당장 버그는 아니지만 이해나 변경 비용을 높이는 구조적 신호. 리팩터링을 언제 시작하고 멈출지에 정확한 공식은 없어서, 냄새라는 어휘로 직관을 공유한다.
다섯 갈래
냄새를 다섯 갈래로 묶은 것은 Refactoring.Guru의 분류다. 『리팩터링 2판』 3장은 24가지 냄새를 묶지 않고 나열한다.
- 비대해진 것(Bloaters): 긴 함수(Long Function), 거대한 클래스(Large Class), 기본형 집착, 긴 매개변수 목록(Long Parameter List), 늘 함께 다니는 데이터 뭉치(Data Clumps) → 매개변수 객체 만들기
- 객체지향 오용(Object-Orientation Abusers): 반복되는 switch(Repeated Switches, 조건부 로직을 다형성으로 바꾸기), 특정 상황에만 값이 차는 임시 필드(Temporary Field), 물려받고도 안 쓰는 상속 포기(Refused Bequest, 상속보다 위임), 역할은 같은데 인터페이스가 다른 대안 클래스
- 변경 방해꾼(Change Preventers): 산탄총 수술과 뒤엉킨 변경, 한쪽 계층을 늘리면 다른 계층도 늘려야 하는 평행 상속 계층(Parallel Inheritance Hierarchies)
- 없어도 되는 것(Dispensables): 중복 코드(Duplicated Code), 죽은 코드 제거, 하는 일이 거의 없는 요소, 데이터만 있고 행동은 밖에 있는 데이터 클래스(Data Class), 추측성 일반화, 코드를 대신 설명하는 장황한 주석
- 결합 유발자(Couplers): 기능 편애, 서로 속사정을 너무 아는 클래스, 메시지 체인(Message Chains)과 중개자(Middle Man, 디미터 법칙)
냄새에서 기법으로
| 냄새 | 먼저 볼 기법 |
|---|---|
| 긴 함수 | 함수 추출, 임시 변수를 질의 함수로 |
| 긴 매개변수 목록 | 매개변수 객체, 객체 통째로 넘기기, 플래그 인수 제거 |
| 전역·가변 데이터 | 변수 캡슐화, 세터 제거, 질의와 변경 분리 |
| 중복 코드 | 함수 추출, 문장 슬라이드, 메서드 올리기 |
| 주석 | 함수 추출, 이름 바꾸기, 어서션 |
주석을 달고 싶어지면 먼저 주석이 필요 없는 코드로 바꿀 수 있는지 본다. 심플 디자인 관점에서는 냄새 대부분이 "중복"이나 "구성요소가 많음"의 다른 얼굴이다(구성요소 줄이기). 테스트 코드의 냄새는 테스트 냄새에 따로 정리했다.
출처: 『리팩터링 2판』 마틴 파울러 (원서 Refactoring, 2nd Edition) · Refactoring.Guru: Code Smells · Martin Fowler: Code Smell