코딩으로 학습하는 리팩토링
깔끔한 코드에서 가장 중요한 것 하나가 바로 "좋은 이름"
사용할 수 있는 리팩토링 기술
• 함수 선언 변경하기 (Change Function Declaration): 함수명으로만 이해 가능
• 변수 이름 바꾸기 (Rename Variable): 많이 사용되는 변수 일수록 더 고민하여 이름 짓기
• 필드 이름 바꾸기 (Rename Field): Record 자료구조의 필드 (자바14 버전부터 지원)
비슷한지 완전히 동일한 코드 인지, 코드 변경시 모든 곳을 변경
사용할 수 있는 리팩토링 기술
• 동일한 코드를 여러 메소드에서 사용하는 경우, 함수 추출하기 (Extract Function): "의도"와 "구현" 분리하기
• 코드가 비슷하게 생겼지만 완전히 같지는 않은 경우, 코드 분리하기 (Slide Statements)
• 여러 하위 클래스에 동일한 코드가 있다면, 메소드 올리기 (Pull Up Method)
함수가 길 수록 더 이해하기 어렵다
작은 함수에 좋은 이름을 사용하면 이해가 쉽다
주석 대신 함수의 이름으로 의도를 표현
• 임시 변수를 질의함수로 바꾸기
• 매개변수 객체만들기
• 객체 통째로 넘기기
• 반복문 쪼개기
• 조건문 분해하기
• 조건문 다형성으로 바꾸기
매개변수가 많을 수록 함수의 역할을 이해하기어려움
• 매개변수를 질의 함수로 바꾸기
• 매개변수를 플래그 인수 제거하기: 매개변수가 플래그로 사용하는 경우
• 여러 함수를 클래스로 묶기: 여러 함수가 일부 매개변수를 공통적으로 사용하는 경우
전역데이터는 아무곳에서나 변경되는 문제, 어던 코드로 값이 바뀐지 파악이 어려움
• 변수 캡슐화하기 (Encapsulate Variable)를 통해 접근 제어, 사용파악
데이터 변경 시 발생할 수 있는 리스크를 관리하는 것이 좋음
• 변수쪼개기: 가독성 향상
• 질의 함수와 변경 함수 분리하기: 사이드이펙트가 있는/없는 코드 분리
• 세터제거하기: 변경될 여지를 제거
• 파생변수를 질의함수로 바꾸기
• 참조를 값으로 바꾸기
소프트웨어는 변경에 유연하게 대처할 수 있어야하고, 서로 다른 문제는 서로 다른 모듈에서 해결해야함
• 단계 쪼개기(Split Phase)
• 함수 옮기기(Move Function)
• 클래스 추출하기(Extract Class)
변경 사항이 생길 때 여러 모듈(함수, 클래스)을 손봐야하는 경우
• 필드 옮기기: 필요한 변경내역을 하나의 클래스로
• 함수 인라인: 흩어진 로직 한곳으로
• 클래스 인라인: 흩어진 로직 한곳으로
어떤 모듈에 있는 함수가 다른 모듈에 있는 데이터나 함수를 더 많이 참조하는 경우에 발생
• 함수 옮기기
항상 뭉쳐 다니는 데이터는 한 곳으로 모아두기
• 클래스 추출하기
• 매개변수 객체 만들기
프로그래밍 언어가 제공하는 기본 타입보다 도메인에 필요한 기본타입사용
• 기본형을 객체로 바꾸기
• 타입 코드를 서브클래스로 바꾸기
• 조건부 로직을 다형성으로 바꾸기
동일한 switch문이 반복되는 경우
동일한 switch문이 반복되는 경우
예상하고 만들어 놓은 요소들이 기대에 부응하지 못하는 경우 제거 불필요한 상속 구조는 "계층합치기"
지금 당장 필요하지 않으면 만들지 않기
• 죽은 코드 제거하기
어떤 필드가 특정한 경우에만 값을 갖는 경우 ex) NULL
• 특이 케이스 추가하기
레퍼런스를 따라 계속 메소드 호출이 이어지는 코드
• 위임 숨기기(Hide Delegate)
중재자 제거로 필요한 클래스 직접 사용하기
• 중재자 제거: 위임 숨기기와 반대
• 슈퍼클래스를 위임으로 바꾸기: 대체하더라도 잘 동작해야함(리스코프 치환 원칙)
상속을 적용한 이후에, 적절치 않다고 판단된다면 적용
서브클래스를 위임으로 바꾸기 > 인터페이스로 의존성을 줄일 수 있음
어떤 모듈이 다른 모듈의 내부 정보를 지나칙 많이 알고 있는 경우(지나치게 강한 결합도)
어떤 클래스가 하는일이 많은 경우 (중복코드)
• 클래스 추출하기를 사용해 관련있는 필드를 한 곳으로 • 슈퍼클래스 추출하기 or 타입 코드를 서브클래스로 교체하기
비슷한 일을 여러 곳에서 서로 다른 규약을 사용해 지원
public 필드를 가지고 있다면 "레코드 캡슐화하기(Encapsulate Record)"를 사용해 게터 세터를통해 접근하도록
서브클래스가 슈퍼클래스에서 제공하는 메소드나 데이터를 잘 활용하지 않는다는 것은 상속 구조에 문제 슈퍼클래스 또는 서브클래스를 위임으로 교체
주석을 남겨야 할 것 같다면 먼저 코드를 리팩토링 함수 추출하기, 함수 선언부 변경, 어셔선 추가하기
• Assertion은 항상 True이길 기대하는 조건으로
카탈로그 1. 기본기술
함수 추출하기
함수 인라인하기
변수 추출하기
변수 인라인하기
함수 선언 변경하기
변수 캡슐화하기
변수 이름바꾸기
매개변수 객체만들기
여러 함수를 클래스로 묶기
여러함수를 변환 함수로 묶기
단계 쪼개기
카탈로그 2. 캡슐화
레코드 캡슐화하기
컬렉션 캡슐화하기
기본형을 객체로 바꾸기
임시 변수를 질의 함수로 바꾸기
클래스 추출하기
클래스 인라인하기
위임하기
중재자 제거하기
알고리듬 교체하기
카탈로그 3. 기능 옮기기
함수 옮기기
필드 옮기기
문장을 함수로 옮기기
문장을 호출한 곳으로 옮기기
인라인 코드를 함수 호출로 바꾸기
문장 슬라이드하기
반복문 쪼개기
반복문을 파이프라인으로 바꾸기
죽은 코드 제거하기
카탈로그 4. 데이터 조직화
변수 쪼개기
필드 이름 바꾸기
파생 변수를 질의 함수로 바꾸기
참조를 값으로 바꾸기
값을 참조로 바꾸기
카탈로그 5. 조건부 로직 간소화
조건문 분해하기
조건식 통합하기
중첩 조건문을 보호 구문으로 바꾸기
조건부 로직을 다형성으로 바꾸기
특이 케이스 추가하기
어서션 추가하기
카탈로그 6. API 리팩토링
질의 함수와 변경 함수 분리하기
함수 매개변수화하기
플래그 인수 제거하기
객체 통째로 넘기기
매개변수를 질의 함수로 바꾸기
질의 함수를 매개변수로 바꾸기
세터 제거하기
생성자를 팩토리 함수로 바꾸기
함수를 명령으로 바꾸기
명령을 함수로 바꾸기
카탈로그 7. 상속 다루기
메소드 올리기
필드 올리기
생성자 본문 올리기
메서드 내리기
필드 내리기
타입 코드를 서브클래스로 바꾸기
서브클래스 제거하기
슈퍼클래스 추출하기
계층 합치기
서브클래스를 위임으로 바꾸기
슈퍼클래스를 위임으로 바꾸기