17. 냄새와 휴리스틱

리팩터링 책의 저자 마틴 파울러가 언급하는 것과 밥아저씨의 콜라보 냄새 리스트

주석#

C1. 부적절한 정보#

작성자, 최종수정일, Software Problem Report 번호 (이슈번호) 같은 메타정보만 넣자

C2. 쓸모 없는 주석#

오래된, 엉뚱한, 잘못된 주석은 바로 지우자

C3. 중복된 주석#

  • 코드만으로 충분할 때는 주석 X
  • 함수 서명만 있는 Javadoc X

C4. 성의 없는 주석#

최대한 신경써서 정성껏 쓰라는 말

C5. 주석 처리된 코드#

버전 관리로 확인 가능하니 그냥 지우자

환경#

E1: 여러 단계 빌드#

한 명령으로 빌드할 수 있어야 함

E2: 여러 단계 테스트#

한 명령으로 모든 단위테스트가 가능해야 함

함수#

F1: 너무 많은 인수#

작게 작게 (없으면 베스트)

F2: 출력 인수#

츨력인수 X -> 객체 상태를 변경시키는 방향으로

F3: 플래그 인수#

boolean 으로 분기치려는 속셈, 왠만하면 피하자

F4: 죽은 함수#

호출하지 않는 함수는 삭제

일반#

G1: 한 소스 파일에 여러 언어를 사용#

최대한 한 파일 내에 여러 언어가 안 섞이도록 구성

G2: 당연한 동작을 구현하지 않는다#

  • 최소 놀람의 원칙 (The Principle of Least Surprise [Astonishment])에 의거해 당연한 동작은 구현해야 함
  • 예: String to Enum

G3: 경계를 올바로 처리하지 않는다#

모든 경계조건을 최대한 성실하게 찾아내 테스트 하자

G4: 안전 절차 무시#

최대한 안전적으로 개발 할 수 있도록 신경쓰자

  • serialVersionUID 직접 제어 X
  • 컴파일러 경고 무시 X
  • 실패 테스트 케이스 반드시 챙기기

G5: 중복#

가장 중요한 원칙, DRY (Don't Repeat Yourself)

  • 코드 반복은 간단한 함수로 교체
  • switch/case, if/else 문으로 같은 조건을 거듭 확인하면 다형성으로 대체
  • 알고리즘은 유사하나 코드가 서로 다르면 Template Method / Strategy 패턴으로 중복 제거
  • DB 스키마는 BCNF로 중복제거

G6: 추상화 수준이 올바르지 못함#

  • 상수, 변수, 유틸리티는 파생 클래스에 (저차원)
  • 기초 클래스는 구현 정보에 최대한 무지해야 함 (고차원)

G7: 기초 클래스가 파생 클래스에 의존한다#

고차원의 기초 클래스가 저차원 구현체인 파생 클래스에 의존한다는 건 관계가 비틀어진 것임

G8: 과도한 정보#

  • 과도한 정보는 결합도를 증가 시킴
  • 정보 은닉 가이드
    • 클래스와 모듈 인터페이스에 노출할 함수를 제한할 줄 알아야 함
    • 자료를 숨기기
    • 유틸리티 함수 숨기기
    • 상수와 임시 변수 숨기기
    • 메서드와 인스턴스 변수가 넘쳐나는 클래스 피하기
    • 하위 클래스에 필요하다는 이유로 protected 남발 금지
    • 인터페이스는 매우 작게, 매우 깐깐하게 만들기
    • 정보를 제한해 결합도 낮추기

G9: 죽은 코드#

실행되지 않는 코드 제거

G10: 수직 분리#

변수와 함수는 사용되는 위치에 가깝게 정의

  • 지역 변수는 사용하는 곳 가장 가까이에 정의
  • 비공개 함수는 호출한 직후 (호출한 곳의 바로 아래) 정의

G11: 일관성 부족#

  • 어떤 개념을 특정 방식으로 구현했을 때, 이와 유사한 개념을 구현할 때도 해당 방식으로 구현
  • 함수 이름, 변수 이름도 이와 유사
  • 최소 놀람의 원칙에도 부합

G12: 잡동사니#

사용하지 않는 함수/변수, 의미 없는 주석 다 제거

G13: 인위적 결합#

  • enum, 범용 static 함수는 일반적으로 결합할 이유가 없음

G14: 기능 욕심#

다른 클래스의 변수(상태)와 함수에 관심을 최대한 줄여야 함

G15: 선택자 인수#

함수 끝에 달리는 Boolean, enum, int 인수 를 통해 함수의 행동을 컨트롤하는 행위는 바람직하지 않음

  • 가독성을 해침

G16: 모호한 의도#

독자에게 의미를 분명하게 할 수 있도록 고민

G17: 잘못 지운 책임#

최소 놀람의 원칙에 따라 자연스럽게 기대할 위치에 코드를 배치한다

  • 이름에 의도를 분명히하면 위치도 자연스레 배치 가능하다

G18: 부적절한 static 함수#

  • 일반적으로 static 보단 인스턴스 함수로 구현
  • 재정의할 가능성이 있다면 인스턴스 함수

G19: 서술적 변수#

  • 서술적 변수를 잘 배치하면 코드의 가독성이 증감
서술적 변수로 가독성을 높인 예
Matcher match = headerPattern.mathcer(line);
if (match.find()) {
String key = match.group(1); // 서술적 변수 1
String value = mathc.group(2); // 서술적 변수 2
headers.put(key.toLowerCase(), value);
}

G20: 이름과 기능이 일치하는 함수#

Date newDate = date.add(5)

위는 date 인스턴스의 상태도 바뀌는지 아닌지 알 수 없음

  • increase 와같은 단어를 써서 인스턴스 상태도 바뀜을 알릴 수 있음

G21: 알고리즘을 이해하라#

구현이 끝났다고 선언하기 전 함수가 돌아가는 방식을 확실히 이해하는지 확인

  • 확인하면서 리팩터링하면 함수도 훨씬 깔끔해짐

G22: 논리적 의존성은 물리적으로 드러내라#

G23: If/Else 혹은 Switch/Case 문보다 다형성을 사용하라#

G24: 표준 표기법을 따르라#

G25: 매직 숫자는 명명된 상수로 교체하라#

G26: 정확하라#

G27: 관례보다 구조를 사용하라#

G28: 조건을 캡슐화하라#

G29: 부정 조건은 피하라#

G30: 함수는 한 가지만 해야 한다#

Last updated on