
좋은 주석 — “읽는 사람에게 감사받는 주석”
주석은 이름으로 의도를 표현할 수 없을 때만 사용해야 한다.
코드가 충분히 명확하다면 주석은 불필요하다.
즉, 주석은 “설명이 필요한 코드”의 대체물이 아니라, 예외적인 보조 장치여야 한다.
// 정규식: MM:DD 형식의 날짜만 허용
Pattern.compile("^(0[1-9]|1[0-2]):(0[1-9]|[12][0-9]|3[01])$");
// TODO: 성능 개선 필요 - 캐시 적용 예정
// i를 1 증가시킨다.
i++;좋은 코드는 이런 주석 없이도 읽히며,
주석이 필요하다면 코드를 개선해야 한다는 신호일 수도 있다.
공백은 코드의 ‘호흡’이다.
적절한 공백은 코드를 덩어리로 나누고, 논리적 관계를 드러낸다.
public과 private 멤버 변수 사이 if, while 블록 전후 int count = 0;
if (isValid()) {
process();
}
return count;
빈 줄 하나로 논리 흐름이 구분되면,
읽는 사람은 더 이상 코드를 ‘해석’하지 않고 ‘이해’하게 된다.
클래스의 핵심은 데이터 보호와 응집된 행동 제공이다.
private 변수는 외부에서 보이지 않아야 하며,
외부에 노출되는 것은 항상 ‘행동’이어야 한다.
class Speaker {
private int volume;
public void increaseVolume() {
if (volume < 100) volume += 10;
}
}
외부에서 speaker.volume = 200 같은 조작이 불가능해야 한다.
이것이 객체의 무결성을 지키는 첫걸음이다.
게터(getter)와 세터(setter)는
클래스를 단순한 데이터 구조로 바꾸며, 응집도를 약화시킨다.
// 데이터 노출형
int getBalance();
void setBalance(int balance);
// 추상화된 행동형
void deposit(int amount);
void withdraw(int amount);
게터세터를 완전히 없앨 수는 없지만, 객체의 행위를 중심으로 설계해야 한다.

응집도가 높은 클래스는 단일한 책임을 가진다.
행동은 관련된 데이터에 직접 작용하며, 내부 구조는 외부에서 보이지 않는다.
추상화는 “무엇을 하는지”에 집중하게 하고, “어떻게 하는지”는 숨긴다.
이 구조 덕분에 클래스는 변경에 강한 단위가 된다.
데이터 구조는 클래스의 반대 개념이다.
행동이 아닌 값 자체를 표현하며, 구현이 노출되어 있다.
| 구분 | 클래스 | 데이터 구조 |
|---|---|---|
| 구성 | private 변수 + 메서드 | public 변수 또는 getter/setter |
| 특징 | 캡슐화 / Tell 가능 | 구현 노출 / Ask만 가능 |
| 장점 | 타입 확장에 강함 | 기능 추가에 강함 |
// 데이터 구조
class PointData {
public int x;
public int y;
}
// 클래스
class Point {
private int x, y;
public double distanceTo(Point other) { ... }
}
데이터 구조는 기능 추가에 유리하지만 타입 추가에 약하고,
클래스는 타입 추가에 강하지만 기능 확장에는 약하다.
→ 즉, 두 개념은 서로 보완적이다.
애플리케이션은 본질적으로 두 계층으로 나뉜다.
의존성의 방향은 항상 추상적인 쪽으로 향해야 한다.
즉, 구체적인 구현이 상위 정책을 의존해서는 안 된다.
// 나쁜 예시
Service service = new JdbcService();
// 좋은 예시
Service service = new DatabaseService(new JdbcRepository());
이 원칙은 IoC(Inversion of Control)와 DI(Dependency Injection)의 기초다.
상위 정책(High-level policy)은 하위 구현(Low-level detail)로부터 보호되어야 한다.
OOP와 RDB는 서로 다른 세계에 존재한다.
ORM은 이 둘을 연결하려 하지만,
본질적으로는 데이터 구조 ↔ 객체 간 불일치 문제(Object-Relational Impedance Mismatch)를 안고 있다.
따라서 Repository, DAO, Service Layer 등을 통해
이 경계를 명확히 분리해야 한다.
@Repository
class UserRepository {
// DB 접근 (데이터 구조)
}
@Service
class UserService {
// 비즈니스 로직 (객체 행동)
}
이렇게 계층을 구분함으로써
객체지향의 유연함과 DB의 안정성을 동시에 얻을 수 있다.
| 항목 | 핵심 개념 |
|---|---|
| 주석 | 이름으로 표현 불가능할 때만, 읽는 사람에게 감사받을 주석 |
| 공란 | 논리 단위 사이의 여백은 코드의 리듬 |
| 클래스 | 행동 중심, 캡슐화, 최소한의 게터세터 |
| 데이터 구조 | 값 중심, 구현 노출, 기능 추가에 강함 |
| 바운더리 | 의존성은 추상 → 구체 방향, IoC·DI 원칙 |
| OOP vs DB | 객체와 테이블은 철학이 다르다 — 계층으로 분리하라 |