Refactoring 03 코드에 나는 악취
03 코드에서 나는 악취
기이한 이름
- 함수 선언 바꾸기 (이름바꾸기)
- 변수 이름 바꾸기
- 필드 이름 바꾸기
- 마땅히 이름이 떠오르지 않는다면 설계에 더 근본적인 문제가 숨어있을 가능성이 높다.
중복코드
- 함수 추출하기
- 문장 슬라이드하기 (비슷한 부분만 모아서)
- 메서드 올리기 (서브클래스에서 중복이라면)
긴 함수
- 주석이 달릴만한 부분은 함수로
- 함수 추출하기
- 임의 변수를 질의함수로 바꾸기 (임시 변수 줄이기)
- 매개변수 객체 만들기, 객체 통째로 넘기기 (매개변수 수 줄이기)
- 함수를 명령으로 바꾸기
- 조건문 분해하기
- 조건부 로직을 다형성으로 바꾸기 (switch문이 여러개라면)
- 반복문 쪼개기 (반복문을 메서드로 분리후 메서드명이 떠오르지 않는다면)
긴 매개변수 목록
- 매개변수 객체 만들기
- 함수 동작방식을 정하는 플래그 인수 제거하기
- 여러 함수를 클래스로 묶기
- 매개변수를 질의함수로 바꾸기 (다른 매개변수에서 값을 얻어올 수 있는 매개변수가 있을때)
- 객체 통채로 넘기기
전역 데이터
- 변수 캡슐화하기
가변 데이터
- 변수 캡슐화하기
- 변수 쪼개기
- 질의함수와 변경함수 분리하기
- setter 제거하기
- 파생변수를 질의함수로 바꾸기
- 여러 함수를 클래스로 묶기, 변환함수로 묶기.
- 참조를 값으로 바꾸기. 내부 필드를 직접 수정하지않고 구조체를 통채로 교체하자.
뒤엉킨 변경
- SRP가 잘 지켜지지 않을때 나타난다.
- 한 코드에 섞여들어감 - 맥락별로 분리
- 단계쪼개기
- 함수 옮기기 (처리과정의 맥락이 보이도록)
- 함수 추출하기 (여러 맥락에 관여하는 함수라면)
- 클래스 추출하기 (모듈이 클래스라면)
산탄총 수술 (shotgun surgery)
- 여러코드에 흩뿌려짐 -> 맥락별로 모음
- 코드 변경시 수정해야할 클래스가 많을때.
- 함수 옮기기, 필드옮기기
- 여러 함수를 클래스고 , 변환함수로 묶기
- 함수, 클래스 인라인하기
- 리팩터링 당시에는 커질 수 있으나, 중간과정일뿐 나중에는 리팩터링으로 더 좋은 형태로 분리할 수 있다.
기능 편애
- 함수가 속한 모듈보다 다른 모듈과의 상호작용이 더 많을때
- 함수 옮기기, 추출하기
데이터 뭉치
- 항상 같이다이는 데이터세트가 있는경우
- 클래스 추출하기
- 매개변수 객체만들기
- 객체 통채로 넘기기
- 데이터 뭉치인지 판별하려면 값 하나를 삭제해보자. 그랬을 때 나머지 데이터만으로는 의미가 없다면 데이터 뭉치라는것.
기본형 집착
- 화폐,좌표,구간 등을
if(a < uppper && a > lower)
처럼 단위를 무시하고 처리하는 경우가 생길수있음.
- 기본형을 객체로 바꾸기.
- 타입코드를 서브클래스로 바꾸기(12.6절)
- 조건부로직을 다형성으로 바꾸기
반복되는 스위치문
- 조건절을 추가할때마다 다른 switch문도 챙겨 수정해야하기때문에, 반복되는경우 코드스멜이다.
- 조건부 로직을 다형성으로 바꾸기.
반복문
- 반복문을 파이프라인으로 바꾸기. (stream)
성의없는 요소
- 메서드가 하나뿐인 클래스
- 구조가 필요없어 보일때
- 함수 인라인하기, 클래스 인라인하기
- 계층 합치기
추측성 일반화
- 나중에 필요할거라는 생각으로 처리 로직을 작성한 경우.
- 테스트코드말고는 사용하는 곳이 없는 함수나 클래스, 테스트먼저 제거하고 죽은코드 제거하기
- 하는일이 없는 추상클래스는 계층 합치기
- 함수 인라인하기. 클래스 인라인하기
- 보눔ㄴ에서 사용되지않는 매개변수는 함수선언 바꾸기
임시 필드
- 특정 상황에서만 값이 설정되는 필드
- 클래스 추출하기
- 함수 옮기기
- 특이케이스 추가하기 (필드들이 유효하지 않을때는 대안클래스로 제거하자)
메시지 체인
- 한 객체를 통해 다른 객체를 요청하는 작업이 연쇄적으로 발생하는 경우. getter의 연속
- 위임 숨기기
- a.manager.name -> a.managerName
- 함수 추출하기
- 함수 옮기기
중재자
- 클래스가 제공하는 메서드중 절반이 다른 클래스에 구현을 위임하고있다면, 중재자 제거하기.
내부자 거래
- 클래스끼리 교류가 많다면, 함수 옮기기, 필드 옮기기
- 3의 모듈을 만들어 위임 숨기기
- 상속구조에서 부모클래스를 이상으로 알려고 하고 부모품을 떠나야할때? 서브/슈퍼클래스를 위임으로 바꾸기
거대한 클래스
- 클래스 추출하기
- 상속이 유리하다면, 슈퍼클래스 추출하기, 타입코드를 서브클래스로 바꾸기
서로 다른 인터페이스의 대안 클래스들
- 동일한 인터페이스를 추출하기위해
- 함수선언 바꾸기
- 함수 옮기기
- 슈퍼클래스 추출하기
데이터 클래스
- 게터와 세터 메서드로만 구성된 클래스.
- public 필드는 레코드캡슐화하기, setter 없애기
- 필요한 동작이 엉뚱한곳에 있을수도 있다.
- 데이터가 모두 불변일 경우 캡슐화하지 않아도 좋다.
상속 포기
- 서브클래스가 부모의 동작은 필요로 하지만, 인터페이스는 따르지 않을때
- 서브/슈퍼클래스를 위임으로 바꾸기
주석
- 주석이 많으면 코드스멜이 나기 쉽다.
- 주석을 남겨야겠다는 생각이 들면, 가장 먼저 주석이 필요없는 코드로 리팩터링 해본다.
- 함수 추출하기
- 함수 선언 바꾸기
- 선행조건 assertion 추가하기
- 코드를 작성한 이유에 대한 히스토리는 좋은 주석.