코드에서 나는 악취 목록
13. Loops
반복문은 프로그래밍 언어가 등장할 때부터 함께 한 핵심 프로그래밍 요소다. 지금은 일급 함수(First-class function)를 지원하는 언어가 많아졌기 때문에 반복문을 파이프라인으로 바꾸는 등 시대에 걸맞지 않은 반복문을 제거할 수 있게 됐다. 필터나 맵 같은 파이프라인 연산을 사용하면 코드에서 각 원소들이 어떻게 처리되는지 쉽게 파악할 수 있다.
14. Lazy Element
우리는 코드의 구조를 잡을 때 프로그램 요소를 이용하는 것을 좋아한다. 그렇지만 그 구조가 필요 없을 때도 있다. 본문 코드를 그대로 쓰는 것과 진배없는 함수도 있고, 실질적으로 메서드가 하나뿐인 클래스도 있다. 이런 프로그램 요소는 고이 보내드리는 게 좋다. 이 제거 작업은 함수를 인라인 하거나 클래스를 인라인 하여 처리한다. 상속을 사용했다면 계층을 합칠 수 있다.
15. Speculative Generality
이 냄새는 '나중에 필요할 거야'라는 생각으로 당장은 필요 없는 모든 종류의 후킹(Hooking) 포인트와 특이 케이스 처리 로직을 작성해둔 코드에서 풍긴다. 그 결과는 이해하거나 관리하기 어려워진 코드다. 당장 걸리적거리는 코드는 눈앞에서 치워버리자.
하는 일이 거의 없는 추상 클래스는 계층 합치기로 제거한다. 쓸데없이 위임하는 코드는 함수를 인라인 하거나 클래스를 인라인 하여 삭제한다. 본문에서 사용되지 않는 매개변수는 함수 선언을 바꾸어서 없앤다.
16. Temporary Field
간혹 특정 상황에서만 값이 설정되는 필드를 가진 클래스도 있다. 하지만 객체를 가져올 때는 당연히 모든 필드가 채워져 있으리라 기대하는 것이 보통이다. 이렇게 임시 필드를 갖도록 작성하면 코드를 이해하기 어렵다.
이렇게 덩그러니 떨어져 있는 필드들을 발견하면 클래스를 추출하여 제 살 곳을 찾아준다. 그런 다음 함수를 옮겨 임시 필드들과 관련된 코드를 모조리 새 클래스에 몰아넣는다. 또한 특이 케이스를 추가하여 필드들이 유효하지 않을 때를 위한 대안 클래스를 만들어서 제거할 수 있다.
17. Message Chains
메시지 체인은 클라이언트가 한 객체를 통해 다른 객체를 얻은 뒤 방금 얻은 객체에 또 다른 객체를 요청하는 식으로, 다른 객체를 요청하는 작업이 연쇄적으로 이어지는 코드를 말한다. 이는 클라이언트가 객체 내비게이션 구조에 종속됐음을 의미한다. 그래서 내비게이션 중간 단계를 수정하면 클라이언트 코드도 수정해야 한다.
이 문제는 위임을 숨겨서 해결한다. 이 리팩터링은 메시지 체인의 다양한 연결점에 적용할 수 있다. 원칙적으로 체인을 구성하는 모든 객체에 적용할 수 있지만, 그러다 보면 중간 객체들이 모두 중개자가 돼버리기 쉽다. 그러니 최종 결과 객체가 어떻게 쓰이는지부터 살펴보는 게 좋다.
18. Middle Man
객체의 대표적인 기능 하나로, 외부로부터 세부사항을 숨겨주는 캡슐화가 있다. 캡슐화하는 과정에서 위임이 자주 활용된다. 예를 들어 여러분이 팀장에게 미팅을 요청한다고 해보자. 팀장은 자신의 일정을 확인한 후 답을 준다. 이러면 끝이다.
하지만 지나치면 문제가 된다. 클래스가 제공하는 메서드 중 절반이 다른 클래스에 구현을 위임하고 있다면 어떤가? 이럴 때는 중개자를 제거하여 실제로 일을 하는 객체와 직접 소통하게 하자. 위임 메서드를 제거한 후 남은 일이 거의 없다면 호출하는 쪽으로 인라인 하자.