[리팩터링 2판] CHAPTER 03. 코드에서 나는 악취 (1)
리팩터링 2판 책을 읽고 공부한 내용을 기록한다. 2판은 자바스크립트를 기반으로 예시를 제공하지만 저자 마틴 파울러는 리팩터링의 핵심 요소는 언어와 상관없이 동일하다고 이야기한다.
해당 기록에서는 책에서 다루는 예제 코드 대신 개인적으로 작성한 예제 코드를 사용한다. 즉, 책의 모든 내용과 순서를 그대로 담지 않을 수 있다.
각 장/절 별로 작성한 코드는 깃허브 개인 저장소에서 관리한다.
불릿 기호는 책의 내용 중 의미있다고 판단한 것을 옮겨 적은 것이다.
3장의 3.1절부터 3.12절까지 학습한 내용을 기록한다. 코드에서 나는 악취에 대한 저자의 생각 중 공감되는 부분과 나의 의견을 함께 작성한다.
- 리팩터링을 언제 시작하고 언제 그만할지를 판단하는 일은 리팩터링의 작동 원리를 아는 것 못지않게 중요하다.
3.1 기이한 이름
- 코드는 단순하고 명료하게 작성해야 한다.
- 이름만 잘 지어도 나중에 문맥을 파악하느라 헤매는 시간을 크게 절약할 수 있다.
- 이름 바꾸기는 단순히 이름을 다르게 표현하는 연습이 아니다. 마땅한 이름이 떠오르지 않는다면 설계에 더 근본적인 문제가 숨어 있을 가능성이 높다. 그래서 혼란스러운 이름을 잘 정리하다 보면 코드가 훨씬 간결해질 때가 많다.
내가 작성한 코드를 동료가 무리없이 읽어 내려가고 이해할 수 있도록 개선하는 일을 자주 한다. 그 일에는 변수의 이름이 모호하지는 않은지 함수나 클래스의 이름이 명확한지 확인하고 개선하는 일이 빠질 수 없다.
3.2 중복 코드
- 코드가 중복되면 각각을 볼 때마다 서로 차이점은 없는지 주의 깊게 살펴봐야 하는 부담이 생긴다. 그중 하나를 변경할 때는 다른 비슷한 코드들도 모두 살펴보고 적절히 수정해야 한다.
3.3 긴 함수
- 코드를 이해하고, 공유하고, 선택하기 쉬워진다는 장점은 함수를 짧게 구성할 때 나오는 것이다.
- 짧은 함수로 구성된 코드를 이해하기 쉽게 만드는 가장 확실한 방법은 좋은 이름이다. 함수 이름을 잘 지어두면 본문 코드를 볼 이유가 사라진다.
- 코드가 단 한 줄이어도 따로 설명할 필요가 있다면 함수로 추출하는 게 좋다.
내 코드를 확인할 때도 동료의 코드를 리뷰할 때도 하나의 함수를 읽어 내려가는 호흡이 길다 싶으면, 이 함수가 여러개의 목적을 갖고 있지는 않은지 확인하고 쪼개는 일을 먼저한다.
3.4 긴 매개변수 목록
- 매개변수 목록이 길어지면 그 자체로 이해하기 어려울 때가 많았다.
매개변수 목록이 길어지면 꼭 필요한 데이터인지, 혹 그렇다면 객체로 넘기는 것이 명확하지는 않을지 고민한다.
3.5 전역 데이터
- 전역 데이터는 코드베이스 어디에서든 건드릴 수 있고 값을 누가 바꿨는지 찾아낼 메커니즘이 없다는 게 문제다.
- 전역 데이터가 가변이라면 특히나 다루기 까다롭다.
3.6 가변 데이터
- 코드의 다른 곳에서는 다른 값을 기대한다는 사실을 인식하지 못한 채 수정해버리면 프로그램이 오작동한다.
- 변수의 유효범위가 단 몇 줄뿐이라면 가변 데이터라 해도 문제를 일으킬 일이 별로 없다.
- 변수를 갱신하는 코드들의 유효범위를 제한한다.
3.7 뒤엉킨 변경
- 코드를 수정할 때는 시스템에서 고쳐야 할 딱 한 군데를 찾아서 그 부분만 수정할 수 있기를 바란다.
- 뒤엉킨 변경은 단일 책임 원칙이 제대로 지켜지지 않을 때 나타난다.
- 예컨데 지원해야 할 데이터베이스가 추가될 때마다 함수 세 개를 바꿔야 하고, 금융 상품이 추가될 때마다 또 다른 함수 네 개를 바꿔야 하는 모듈이 있다면 뒤엉킨 변경이 발생했다는 뜻이다.
3.8 산탄총 수술
- 이 냄새는 코드를 변경할 때마다 자잘하게 수정해야 하는 클래스가 많을 때 풍긴다. 변경할 부분이 코드 전반에 퍼져 있다면 찾기도 어렵고 꼭 수정해야 할 곳을 지나치기 쉽다.
3.9 기능 편애
- 기능 편애는 흔히 어떤 함수가 자기가 속한 모듈의 함수나 데이터보다 다른 모듈의 함수나 데이터와 상호작용할 일이 더 많을 때 풍기는 냄새다.
3.10 데이터 뭉치
- 데이터 항목 서너 개가 여러 곳에서 항상 함께 뭉쳐 다니는 모습을 흔히 목격할 수 있다. 클래스 두어 개의 필드에서, 혹은 여러 메서드의 시그니처에서 함께 발견되기도 한다. 이렇게 몰려다니는 데이터 뭉치는 보금자리를 따로 마련해줘야 마땅하다.
3.11 기본형 집착
- 프로그래머 중에는 자신에게 주어진 문제에 딱 맞는 기초 타입(화폐, 좌표, 구간 등)을 직접 정의하기를 몹시 꺼리는 사람이 많다.
- 그래서 금액을 그냥 숫자형으로 계산하거나, 물리량을 계산할 때도 밀리미터나 인치 같은 단위를 무시하고, 범위도 if (a < upper && a > lower)처럼 처리하는 코드를 수없이 봤다.
3.12 반복되는 switch문
- 중복된 switch문이 문제가 되는 이유는 조건절을 하나 추가할 때마다 다른 switch문들도 모두 찾아서 함께 수정해야 하기 때문이다. 이럴 때 다형성은 반복된 switch문이 내뿜는 사악한 기운을 제압하여 코드베이스를 최신 스타일로 바꿔주는 세련된 무기인 셈이다.
각 절에서 언급하는 것을 코드의 안좋은 냄새의 기준으로 삼고 내 코드를 살펴보자. 이 악취를 개선하는 리팩터링 방법은 6장부터 설명한다.