Chapter 7

냄새와 휴리스틱

  • 7.1 주석
  • 7.2 환경
  • 7.3 함수
  • 7.4 일반
  • 7.5 자바
  • 7.6 이름
  • 7.7 테스트

이 챕터는 책 전체의 총정리야. 코드 냄새(smell)와 휴리스틱을 카테고리별로 정리한 레퍼런스거든. 코드 리뷰할 때 "이건 G14 위반이야" 같은 식으로 참조할 수 있게 만들어놨어.

주석부터 보자. C1: 부적절한 정보 — 변경 이력이나 메타데이터는 소스 코드 관리 시스템에서 관리해야 하니까 주석에 넣지 마. C2: 쓸모 없는 주석은 즉시 삭제하고, C3: 중복된 주석i++; // i를 증가시킨다 같은 건 의미가 없어. C4: 성의 없는 주석 — 쓸 거면 잘 써. C5: 주석 처리된 코드는 즉시 삭제해.

환경 관련해서는 E1: 빌드는 한 단계로, E2: 테스트도 한 명령으로 끝나야 해. 빠르고 쉽고 명확해야 자주 돌리거든.

함수에서 F1: 인수는 적을수록 좋고, F2: 출력 인수는 직관에 어긋나고, F3: 플래그 인수는 함수가 여러 가지를 한다고 선언하는 거야. F4: 죽은 함수는 삭제해.

일반 항목이 가장 길고 가장 중요해. G1: 소스 파일 하나에 언어 하나가 이상적이고. G2: 당연한 동작을 구현하지 않는다 — 이건 최소 놀람의 원칙이야. Day.from("Monday")Day.MONDAY를 반환하리라 기대하는 건 당연하잖아. G3: 경계를 올바로 처리하지 않는다 — 모든 경계 조건을 직접 찾아서 테스트해. 스스로를 믿지 마. G5: 중복 — 이 책에서 가장 중요한 규칙 중 하나야. 코드에서 중복을 발견할 때마다 추상화할 기회지. switch/case, if/else 체인에서 동일 조건이 반복되면 다형성으로 대체하고, 알고리즘이 유사하지만 코드가 다른 경우에는 TEMPLATE METHOD나 STRATEGY 패턴을 고려해.

G6: 추상화 수준이 올바르지 못하다 — 세부 구현은 파생 클래스에, 고차원 개념은 기초 클래스에. G8: 과도한 정보 — 인터페이스를 줄이고 결합도를 낮춰. G9: 죽은 코드는 찾으면 삭제해. G10: 수직 분리 — 변수와 함수는 사용되는 위치에 가깝게 정의해. G11: 일관성 부족 — 어떤 개념을 특정 방식으로 구현했다면 유사한 개념도 같은 방식으로. G14: 기능 욕심 — 다른 객체의 접근자와 변경자를 사용해 그 객체의 내부를 조작한다면, 그 메서드는 그 클래스에 속하는 게 맞아.

G17: 잘못 지운 책임 — 코드는 독자가 자연스럽게 기대할 위치에 놓아. G20: 이름과 기능이 일치해야 한다Date.add(5)가 5일을 더한 건지 5주를 더한 건지 이름만 보고 알 수 있어야 해. G21: 알고리즘을 이해하라 — "돌아가는 코드"와 "올바른 코드"는 달라. G23: if/else, switch/case 대신 다형성을 사용하라. G25: 매직 넘버는 명명된 상수로 교체하라86,400보다 SECONDS_PER_DAY가 명확하지. G26: 정확하라 — 결과가 null일 수 있으면 null을 점검해. G28: 조건을 캡슐화하라if (shouldBeDeleted(timer))if (timer.hasExpired() && !timer.isRecurrent())보다 읽기 쉬워. G29: 부정 조건은 피하라. G31: 숨겨진 시간적 결합 — 한 함수의 결과를 다음 함수의 인수로 넘기는 방식으로 순서를 강제해. G36: 추이적 탐색을 피하라 — 디미터 법칙이야.

자바 관련해서는 J1: 와일드카드 import를 쓰고, J2: 상수는 상속하지 마라import static을 써. J3: 상수 대신 Enum을 써. enum은 메서드와 필드를 가질 수 있고, 타입 안전하거든.

이름에서 N1: 서술적인 이름을 신중하게 고르고, N2: 적절한 추상화 수준에서 이름을 선택해 — Modem 클래스에 dialModem()보다 connect()가 나아. N3: 표준 명칭을 사용하고, N5: 긴 범위에는 긴 이름, N7: 이름으로 부수 효과를 설명해.

테스트에서는 T1: 불충분한 테스트 — 잠재적으로 깨질 만한 것을 모두 테스트해. T2: 커버리지 도구를 사용하고, T3: 사소한 테스트를 건너뛰지 마. T5: 경계 조건을 테스트하고, T6: 버그 주변은 철저히 테스트해 — 버그는 서로 모여드는 경향이 있거든. T9: 테스트는 빨라야 한다 — 느리면 안 돌리게 돼.


정리

7장 읽고 기억할 거 세 가지:

  1. G5: 중복은 모든 악의 근원이다. 코드에서 중복을 발견할 때마다 추상화할 기회다. DRY 원칙을 끊임없이 적용하라
  2. 이름이 곧 설계다. 서술적인 이름, 적절한 추상화 수준의 이름, 부수 효과를 드러내는 이름 — 좋은 이름은 코드의 의도를 전달하는 가장 강력한 도구다
  3. 테스트는 빠르고 충분해야 한다. 경계 조건, 버그 주변, 사소한 케이스까지 꼼꼼히 테스트하라. 커버리지 도구를 활용하라. 느리면 안 돌린다