[리팩터링 2판] CHAPTER 03. 코드에서 나는 악취 (2)
4 min readJun 18, 2022
리팩터링 2판 책을 읽고 공부한 내용을 기록한다. 2판은 자바스크립트를 기반으로 예시를 제공하지만 저자 마틴 파울러는 리팩터링의 핵심 요소는 언어와 상관없이 동일하다고 이야기한다.
해당 기록에서는 책에서 다루는 예제 코드 대신 개인적으로 작성한 예제 코드를 사용한다. 즉, 책의 모든 내용과 순서를 그대로 담지 않을 수 있다.
각 장/절 별로 작성한 코드는 깃허브 개인 저장소에서 관리한다.
불릿 기호는 책의 내용 중 의미있다고 판단한 것을 옮겨 적은 것이다.
3장의 3.13절부터 3.24절까지 학습한 내용을 기록한다. 코드에서 나는 악취에 대한 저자의 생각 중 공감되는 부분과 나의 의견을 함께 작성한다.
3.13 반복문
- 필터(filter)나 맵(map)같은 파이프라인 연산을 사용하면 코드에서 각 원소들이 어떻게 처리되는지 쉽게 파악할 수 있다.
3.14 성의 없는 요소
- 본문 코드를 그대로 쓰는 것과 진배없는 함수도 있고, 실질적으로 메서드가 하나뿐인 클래스도 있다.
우리는 코드를 구조화하기 위해 함수, 클래스, 인터페이스 등을 사용한다. 하지만, 어떠한 이유로든 구조화할 만큼 충분하지 않은(a.k.a. 책의 표현에 의하면 성의없는) 코드를 구조화로부터 해방시키라는 의미이다.
3.15 추측성 일반화
- ‘나중에 필요할 거야’라는 생각으로 당장은 필요 없는 모든 종류의 후킹(hooking) 포인트와 특이 케이스 처리 로직을 작성해둔 코드에서 풍긴다.
- 미래를 대비해 작성한 부분을 실제로 사용하게 되면 다행이지만, 그렇지 않는다면 쓸데없는 낭비일 뿐이다. 당장 걸리적거리는 코드는 눈앞에서 치워버리자.
3.16 임시 필드
- 임시 필드를 갖도록 작성하면 코드를 이해하기 어렵다. 그래서 사용자는 쓰이지 않는 것처럼 보이는 필드가 존재하는 이유를 파악하느라 머리를 싸매게 된다.
3.17 메시지 체인
- 다른 객체를 요청하는 작업이 연쇄적으로 이어지는 코드를 말한다.
- 가령 getSomething() 같은 게터가 꼬리에 꼬리를 물고 이어지거나 임시 변수들이 줄줄이 나열되는 코드가 있다. 이는 클라이언트가 객체 내비게이션 구조에 종속됐음을 의미한다.
3.18 중개자
- 캡슐화(encapsulation)와 위임(delegation)이 지나치면 문제가 된다. 클래스가 제공하는 메서드 중 절반이 다른 클래스에 구현을 위임하고 있다면 어떤가?
3.19 내부자 거래
- 모듈 사이의 데이터 거래가 많으면 결합도(coupling)가 높아진다고 투덜댄다. 일이 돌아가게 하려면 거래가 이뤄질 수 밖에 없지만, 그 양을 최소로 줄이고 모두 투명하게 처리해야 한다.
3.20 거대한 클래스
- 한 클래스가 너무 많은 일을 하려다 보면 필드 수가 상당히 늘어난다. 그리고 클래스에 필드가 너무 많으면 중복 코드가 생기기 쉽다.
3.21 서로 다른 인터페이스의 대안 클래스들
- 클래스를 사용할 때의 큰 장점은 필요에 따라 언제든 다른 클래스로 교체할 수 있다는 것이다. 단, 교체하려면 인터페이스가 같아야 한다.
3.22 데이터 클래스
- 데이터 클래스란 데이터 필드와 게터/세터 메서드로만 구성된 클래스를 말한다. 그저 데이터 저장 용도로만 쓰이다 보니 다른 클래스가 너무 깊이까지 함부로 다룰 때가 많다.
- 이런 클래스에 public 필드가 있다면 누가 보기전에 얼른 레코드 캡슐화하기로 숨기자.
3.23 상속 포기
- 상속 포기 냄새는 서브클래스가 부모의 동작은 필요로하지만 인터페이스는 따르고 싶지 않을 때 특히 심하게 난다.
- 구현을 따르지 않는 것은 이해할 수 있지만 인터페이스를 따르지 않는다는 것은 상당히 무례한 태도다.
상속 메커니즘을 벗어나야 하는 경우를 의미한다.
3.24 주석
- 주석이 장황하게 달린 원인이 코드를 잘못 작성했기 때문인 경우가 의외로 많다.
- 주석을 남겨야겠다는 생각이 들면, 가장 먼저 주석이 필요 없는 코드로 리팩터링해본다.
각 절에서 언급하는 것을 코드의 안좋은 냄새의 기준으로 삼고 내 코드를 살펴보자. 이 악취를 개선하는 리팩터링 방법은 6장부터 설명한다.