7장

Move Method(v)

메소드가 자신이 정의된 클래스보다 다른 클래스의 기능을 더 많이 사용하고 있다면
이 메소드를 가장 많이 사용하고 있는 클래스에 비슷한 몸체를 가진 새로운 메소드를 만들어라. 
그리고 이 전 메소드는 간단한 위임으로 바꾸거나 완전히 제거하라.

동기

자신이 속해 있는 클래스보다 다른 클래스를 더 많이 참조하는 메소드가 있는지 확인

절차

소스 클래스에 정의된 소스 메소드에 의해 사용되는 모든 부분을 조사
소스 클래스의 서브클래스나 슈퍼클래스에서 옮기려고 하는 메소드에 대한 다른 선언이 있는지 확인
타겟 클래스에 메소드를 정의
소스 메소드에서 타겟 메소드로 코드를 복사. 그리고 그 메소드가 타겟 클래스에서 동작하도록 적절히 수정
타겟 클래스 컴파일
소스 클래스에서 적절한 타겟 객체를 참조하는 방법 결정
소스 메소드를 위임 메소드로 바꾼다.
컴파일, 테스트 한다.
소스 메소드를 제거할지 위임 메소드로 남겨둘지 결정

Move Field(v)

필드가 자신이 정의된 클래스보다 다른 클래스에 의해서 더 많이 사용되고 있다면
타겟 클래스에 새로운 필드를 만들고 기존 필드를 사용하고 있는 모든 부분을 변경하라.

동기

어떤 Field가 자신이 속한 Class보다 다른 Class의 Method에서 더 많이 사용되고 있을 때
get/set으로 다른 곳에서 많이 쓰고 있을 거 같으면 Method를 옮기는 게 좋다.
그러나 Method의 위치가 적절하다면 필드를 옮긴다.
Extract Class를 할 땐 Field를 먼저 옮기고 Method를 옮긴다.

절차

Field가 public으로 선언되어 있으면 Encapsulate Field를 사용
Compile, Test
Target Class에 Field와 그 Field에 대한 get/set method를 만든다.
Compile Target Class 
Source Class에서 Target 객체를 참조하는 방법 결정
Source Class에 있는 Field 제거
Source Field를 참조하고 있는 모든 부분을 Target Class에 있는 적당한 Method를 참조하도록 바꾼다.
Compile, Test

Extract Class(v)

두 개의 Class가 해야 할 일을 하나의 Class가 하고 있는 경우
새로운 Class를 만들어서 관련 있는 Field와 Method를 예전 Class에서 새로운 Class로 옮겨라

동기

Class가 많은 Method, Data를 가지고 있고, 너무 커서 쉽게 이해하기 어려운 경우
어떤 Data의 부분 집합과 Method의 부분 집합이 같이 몰려다니는 경우
만약 일부 Data나 Method를 제거한다면 다른 Field나 Method가 의미 없는 것이 될지를 물어보는 것은 편리한 테스트 방법

절차

Class의 책임을 어떻게 나눌지 결정
분리된 책임을 떠맡을 새로운 Class 생성
이전 클래스에서 새로 만든 클래스에 대한 링크를 만든다.
옮기고자 하는 각각의 Field에 대해 Move Field 사용
각각의 Field를 옮길 때마다 Compile, Test
Move Method를 사용해서 이전 Class에서 새로 만든 Class로 Method를 옮긴다.
저수준 Method(호출하기보다 호출되는 Method) -> 고수준 Method 순서로
각각의 Method 옮길 때마다 Compile, Test
각 Class를 검토하고, Interface를 줄인다.
새로운 Class를 공개할지 결정

Inline Class

Class가 하는 일이 많지 않은 경우에는
그 Class에 있는 모든 변수와 메소드를 다른 클래스로 옮기고 그 클래스를 제거하라.

동기

Extract Class와 반대
Refactoring으로 그 Class의 책임을 대부분 다른 곳으로 옮기고 남은 것이 거의 없는 경우

절차

흡수하는 Class에 Source Class의 public Field와 Method를 선언
Source Class를 참조하고 있는 모든 부분을 흡수하는 Class를 참조하도록 변경
Compile, Test
Move Method와 Move Field를 사용하여 Source Class에 있는 모든 Field와 Method를 흡수하는 Class로 옮김

Hide Delegate

Client가 객체의 위임 Class를 직접 호출하고 있는 경우
서버에 Method를 만들어서 대리객체(delegate)를 숨겨라

Remove Middle Man

Class가 간단한 위임을 너무 많이 하고 있는 경우에는
Client가 대리객체(delegate)를 직접 호출하도록 하라.

Introduce Foreign Method

사용하고 있는 서버 Class에 부가적인 Method가 필요하지만 Class를 수정할 수 없는 경우에는 
첫 번째 인자로 서버 Class의 인스턴스를 받는 Method를 클라이언트에 만들어라

동기

모든 서비스를 제공하는 정말로 멋진 Class를 사용하고 있다.
그러나 꼭 필요하지만 그 Class가 제공하지 않는 서비스가 하나 있다. 
그런데 소스 코드를 변경할 수 없다면 클라이언트에서 외래 메소드(Foreign Method)로 만들어주는 방법밖에 없다. 
Foreign Method는 임시방편일 뿐

절차

필요한 작업을 하는 Method를 클라이언트 Class에 만든다.
 ㄴ이 Method는 클라이언트 Class의 어떤 부분에도 접근해선 안 됨
 ㄴ값이 필요하다면 값을 Parameter로 넘겨야 함
첫 번째 Parameter로 서버 Class의 인스턴스를 받도록 함
Method에 "외래 메소드, 원래 서버 클래스에 있어야 한다."와 같은 주석을 달아 놓는다.

Introduce Local Extension(v)

사용하고 있는 서버 Class에 여러 개의 Method를 추가할 필요가 있지만 서버 Class를 수정할 수 없는 경우
필요한 추가 Method를 포함하는 새로운 Class를 만들어라.
이 확장 Class를 원래 Class의 서브클래스 또는 래퍼 클래스로 만들어라.

Introduce Foreign Method만으로는 감당이 안 될 만큼 Method가 많은 경우

Last updated