냄새와 휴리스틱

  • … 여기서 소개한 목록은 가치 체계를 피력할 뿐이다.
    사실상 가치 체계는 이 책의 주제이자 목표다. 일군의 규칙만 따른다고 깨끗한 코드가 얻어지지 않는다. 휴리스틱 목록을 익힌다고 소프트웨어 장인이 되지는 못한다. 전문가 정신과 장인 정신은 가치에서 나온다. 그 가치에 기반한 규율과 절제가 필요하다.

1. 주석

  • 쓸모 없고, 중복된 주석은 지워야 한다.
  • 부적절한 정보과 성의 없는 주석이 없도록 신경써서 작성한다.
  • 코드는 주석 처리하지 않고 지운다.

2. 환경

  • 한 단계로 빌드를 끝내야 한다.
  • 한 명령으로 모든 단위 테스트를 돌려야 한다.

3. 함수

  • 인수는 적을 수록 좋다. 인수의 개수는 3개를 넘지 않도록 한다.
  • 출력 인수 : 상태를 변경해야 한다면 출력 인수를 사용하기보다 함수가 속한 객체의 상태를 변경한다.
  • 플래그 인수(Boolean)는 함수가 여러 기능을 수행한다는 것을 의미하기때문에 피하는 것이 좋다.
  • 아무데서도 호출하지 않는 함수는 죽은 함수다. 지우자.

4. 일반

  • 한 소스 파일에 최대한 한 언어만 사용할 수 있도록 노력한다.
  • 당연한 동작이라고해서 건너뛰지 말고 구독자를 위해 구현해둔다.
  • 모든 경계 조건을 찾아내고, 모든 경계 조건을 테스트하는 테스트 케이스를 작성하라.
  • 실패하는 테스트 케이스를 나중으로 미루지 않는다.
  • 중복
    • 중복을 발견할 때마다 추상화할 기회로 간주하라.
    • 여러 모듈에서 일련의 switch/case나 if/else 문으로 똑같은 조건을 거듭 확인하는 중복은 다형성(polymorphism)으로 대체해야 한다.
    • 알고리즘은 유사하나 코드가 서로 다른 경우 TEMPLATE METHOD 패턴이나 STRATEGY 패턴으로 중복을 제거 한다.
  • 추상화 수준을 맞춘다. (저차원 개념은 파생클래스 / 고차원 개념은 기초 클래스)
  • 기초 클래스는 파생 클래스를 아예 몰라야 마땅하다.
  • 과도한 정보(정보를 제한해 결합도를 낮춰라)
    • 클래스가 제공하는 메서드 수는 작을 수록 좋다. 함수가 아는 변수 수도 작을 수록 좋다. 클래스에 들어있는 인스턴스 변수 수도 적을 수록 좋다.
    • 자료를 숨기고, 유틸리티 함수를 숨기고, 상수와 임시 변수를 숨겨라.
    • 메서드나 인스턴스 변수가 넘쳐나는 클래스는 피해라
    • 인터페이스를 매우 작게 그리고 매우 깐깐하게 만들어라
  • 죽은 코드
    • 불가능한 조건을 확인하는 if문
    • throw문이 없는 try문에서 catch블록
    • 아무도 호출하지 않는 유틸리티 함수
    • switch/case문에서 불가능한 case 조건
  • 일관성만으로도 코드를 읽고 수정하기가 쉬워진다.
  • 사용하지 않는 변수, 호출하지 않는 함수, 쓸모 없는 주석은 제거한다.
  • 인위적인 결합
    • 당장 편한 위치에 변수, 상수, 함수를 넣으면 안된다.
    • 함수, 상수, 변수를 선언할 때는 시간을 들여 올바를 위치를 고민한다.
  • 최대한 분명한 의도를 밝힌다.
  • 코드는 독자가 자연스럽게 기대할 위치에 배치한다. 필요한 영역에 정확한 이름으로 코드를 배치한다.
  • 알고리즘을 이해하라
    • 알고리즘이 올바르다는 사실을 확인하고 이해하려면 기능이 뻔히 보일 정도로 함수를 깔끔하고 명확하게 재구성하는 방법이 최고다.
  • 표준 표기법을 따르라
    • 표준을 설명하는 문서는 코드 자체로 충분해야 하며 별도 문서를 만들 필요는 없는 상태가 최상의 상태다.
  • 매직 숫자는 명명된 상수로 교체하라.
  • 조건
    • 조건을 캡슐화하라. - 조건의 의도를 분명히 밝히는 함수로 표현하라
    • 부정 조건은 피하라.
  • 숨겨진 시간적인 결합
    • 일종의 연결 소자를 생성해 시간적인 결합을 노출한다.
  • 일관성을 유지하라.
    • 코드 구조를 잡을 때는 이유를 고민하라.
    • 구조에 일관성이 없어 보인다면 남들이 맘대로 바꿔도 괜찮다고 생각한다.
  • 함수의 추상화 수준
    • 함수는 추상화 수준을 한 단계만 내려가야 한다.
    • 함수 내 모든 문장은 추상화 수준이 동일해야 한다.
    • 그 추상화 수준은 함수 이름이 의미하는 작업보다 한 단계만 낮아야 한다.
    • 함수에서 추상화 수준을 분리하면 앞서 드러나지 않았던 새로운 추상화 수준이 드러나는 경우가 빈번하다.
  • 한 모듈은 주변 모듈을 모를 수록 좋다.
    • 디미터 법칙(Law of Demeter) / Writing Shy Code
    • 자신이 직접 사용하는 모듈만 알아야 한다.

5. 이름

  • 서술적인 이름 사용
    • 선택한 이름이 올바른지 자주 되돌아 본다.
    • 신중하게 선택한 이름은 추가 설명을 포함한 코드보다 강력하다.
  • 적절한 추상화 수준에서 이름을 선택하라
    • 구현을 드러내는 이름은 피하라.
  • 가능하다면 표준 명명법을 사용하라
    • 흔히 팀마다 특정 프로젝트에 적용할 표준을 나름대로 고안한다. - 프로젝으틔 유비쿼터스 언어(ubiquitous language). 에릭 에반스
  • 목적을 명확히 밝히는 이름을 선택한다.
  • 이름의 길이는 범위 길이에 비례해야 한다.

6. 테스트

  • 테스트 케이스는 잠재적으로 깨질 만한 부분을 모두 테스트해야 한다.
  • 사소한 테스트를 건너뛰지 마라.
  • 무시한 테스트는 모호함을 뜻한다.
  • 경계 조건을 테스트하라.
  • 버그 주변은 철저히 테스트하라.
    • 버그는 서로 모이는 경향이 있어서 버그가 있는 함수를 철저히 테스트 한다면 다른 버그로 발견하게 된다.
  • 실패 패턴을 살펴라.
    • 합리적인 순서로 정렬된 꼼꼼한 테스트 케이스스는 실패 패턴을 드러낸다.
  • 테스트는 빨라야 한다.