리팩터링 할 시점 -> 냄새 (smell)
✏️ 코드 악취의 기준
- 기이한 이름
: 코드는 항상 단순하고 명료하게 작성해야 한다.
-> 함수 선언 바꾸기
-> 변수 이름 바꾸기
-> 필드 이름 바꾸기
이름을 쉽게 바꿀 수 없다면 설계에 문제가 있을 수 있다.
- 중복 코드
: 똑같은 구조가 반복된다면 하나로 통합할 수 있음
하지만, 서로 차이점은 없는지 주의 깊게 살펴보면서 적절히 수정해야 함
-> 함수 추출 하기 (내부에서 호출하게끔)
-> 문장 슬라이드 하기 (완전히 같지 않다면)
-> 메서드 올리기 (같은 부모로부터 파생된 서브 클래스들에 코드가 중복되어 있다면)
- 긴 함수
: 짧은 함수로 코드가 끝없이 위임하는 방식으로 작성을 지향 (간접 호출의 효과)
함수를 짧게 구성할 때 이해, 공유, 선택하기 쉬운 코드가 나오게 됨
위임하는 방식의 문제는 함수 이름을 잘 지어서 해소할 수 있도록 함
-> 함수 추출하기
-> 임시 변수를 질의 함수로 바꾸기 (임시 변수가 너무 많을 때 사용)
-> 매개변수 객체 만들기 (매개 변수의 수를 줄이기 위해 사용)
-> 객체 통째로 넘기기 (매개 변수의 수를 줄이기 위해 사용)
-> 함수를 명령으로 바꾸기 (여전히 임시 변수, 매개 변수의 수가 많다면)
코드 단 한줄이어도 따로 설명할 필요가 있다면 함수로 추출하는게 좋음
- 조건문의 경우
-> 조건문 분해하기
-> case문 마다 함수 추출하기
-> 조건부 로직을 다형성으로 바꾸기 (같은 조건으로 switch문이 여러 개라면)
- 반복문의 경우
-> 코드와 함께 추출해서 독립된 함수로 만듬
-> 반복문 쪼개기 (성격이 다른 두 가지 작업이 섞여 있다면)
- 긴 매개변수 목록
: 함수에 필요한 것들을 매개변수로 전달하다보니 목록이 길어져 그 자체로 이해하기 어려울 때가 많아짐
-> 매개변수를 질의 함수로 바꾸기 (다른 매개 변수에서 값을 얻어오는 매개변수 일 경우)
-> 객체 통째로 넘기기 (원본 데이터 구조를 그대로 전달)
-> 매개변수 객체 만들기 (항상 함께 전달되는 매개변수가 있다면)
-> 플래그 인수 제거하기 (동작 방식을 정하는 플래그 변수가 있다면)
-> 여러 함수를 클래스로 묶기 (공통 값들을 클래스의 필드로 정의)
- 전역 데이터
: 전역 데이터 사용 금지 (코드베이스 어디서든 건드릴 수 있고, 값을 누가 바꿨는지 알 수 없음)
- 이 문제가 클래스 변수와 싱글톤에서도 발생됨!
-> 변수 캡슐화 하기 (다른 코드에서 오염시킬 가능성이 있는 데이터를 발견할 때마다 사용 -> 데이터를 수정하는 부분을 쉽게 찾을 수 있고, 접근을 통제할 수 있게 됨)
-> 접근자 함수들을 클래스나 모듈에 넣어서 접근 범위 최소로 줄이기
- 가변 데이터
: 다른 값에서 사용하는지 모르고 데이터를 변경해버려서 발생
-> 변수 캡슐화 하기 (정해놓은 함수를 거쳐야만 값을 수정할 수 있도록 함)
-> 변수 쪼개기 (하나의 변수에 용도가 다른 값들을 저장하느라 값을 갱신하는 경우라면)
-> 문장 슬라이드하기 & 함수 추출 (부작용이 없도록 코드 갱신 가능)
-> 질의 함수와 변경 함수 분리 (꼭 필요한 경우가 아니라면 부작용이 있는 코드를 호출할 수 없게 함)
-> 세터 제거하기 (호출하는 클라이언트를 찾는 것 만으로도 변수의 유효범위 줄일 수 있음)
-> 파생 변수를 질의 함수로 바꾸기
-> 여러 함수를 클래스로 묶기 & 여러 함수를 변환 함수로 묶기 (유효범위 조정 가능)
-> 참조를 값으로 바꾸기 (내부 필드를 직접 수정하지 말고 구조체를 통체로 교체)
- 뒤엉킨 변경
: 코드를 수정할 때 시스템에서 고쳐야 할 군데를 찾아서 그 부분만 수정할 수 있도록
(SRP, 단일 책임 원칙을 제대로 지켜지지 않아서 발생)
한 코드에 섞어들어가서 발생
-> 단계 쪼개기 (순차적으로 데이터가 담긴다면)
-> 함수 옮기기 (처리과정 곳곳에서 각기 다른 맥락의 함수를 호출하는 빈도가 높다면, 관련 함수들을 모음)
-> 함수 추출하기
-> 클래스 추출하기
- 산탄총 수술
: 뒤엉킨 변경과 정반대 (-> 여러 코드에 흩뿌려져서 발생)
-> 함수 옮기기 & 필드 옮기기 (함께 변경되는 대상들을 모두 한 모듈에 묶어둠)
-> 여러 함수를 클래스로 묶기 (비슷한 데이터를 다루는 함수가 많다면)
-> 여러 함수를 변환 함수로 묶기 (데이터 구조를 변환하거나 보강하는 함수)
-> 단계 쪼개기
-> 함수 인라인 & 클래스 인라인 ( 흩어진 코드를 하나로 합침, 비대해질 수는 있지만 나중에 리펙터링으로 다시 추출)
- 기능 편애
: 어떤 함수가 자기가 속한 모듈의 함수나 데이터보다 다른 모듈의 함수나 데이터와 상호작용할 일이 더 많을 때
-> 데이터 옮기기
-> 함수 추출하기 (함수를 여러 조작으로 나눈 후 적절한 모듈로 옮김)
디자인 패턴 중 '전략 패턴' & '방문자 패턴' 사용 가능
- 데이터 뭉치
: 비슷한 성격의 몰려다니는 데이터뭉치는 보금자리를 따로 마련해줘야 함
-> 클래스 추출하기 (하나의 객체로 묶음)
-> 매개변수 객체 만들기 & 객체 통째로 넘기기 (매개변수 수를 줄이기)
간단한 '레코드' 구조가 아닌 '클래스'구조로 만들어야 함
- 기본형 집착
: 기초 타입(화폐, 좌표, 구간 등) 을 직접 정의하지 않고, 기본형만을 사용하려는 경우
일관된 형식으로 출력하지도 않음
-> 기본형을 객체로 바꾸기
->타입 코드를 서브클래스로 바꾸기 & 조건부 로직을 다형성으로 바꾸기 (조건부 동작이 있었다면)
-> 클래스 추출하기, 매개변수 객체 만들기
- 반복되는 switch 문
switch문은 없어져야 할 대상
why? 조건절을 하나 추가 할 때마다 다른 switch문들도 모두 찾아서 함께 수정해야하기 때문
-> 조건부 로직을 다형성으로 바꾸기
'BOOK Review' 카테고리의 다른 글
[클린코드] TIL - 5장 형식 맞추기 (0) | 2024.06.30 |
---|---|
[클린코드] TIL - 2장 의미있는 이름 (0) | 2024.06.25 |
[클린코드] TIL - 4장 주석 (0) | 2024.06.25 |
[클린 코드] TIL - 3장 함수 (0) | 2024.06.25 |
[클린 코드] TIL - 1장 깨끗한 코드 (0) | 2024.06.22 |