Notice
Recent Posts
Recent Comments
끄적끄적
리팩토링 6장 - 메소드 정리 본문
리팩토링의 많은 부분을 차지
Extract Method(v)
- 그룹으로 함께 묶을 수 있는 코드 조각이 있으면, 코드의 목적이 잘 드러나도록 메소드의 이름을 지어 별도의 메소드로 뽑아낸다.
- 동기
- 지나치게 긴 메소드
- 주석이 필요한 코드( 목적을 이해하기 위한 )
- 장점 ( 짧고 이해하기 쉬운 이름으로 메소드를 만들었을 때 )
- 재사용 확률 높아짐
- 메소드를 볼 때 주석을 읽는 것 같은 느낌이 들도록 할 수 있음
- 오버라이드 하기 쉬움
- 절차
- 메소드를 새로 만듦
- 의도를 잘 나타내도록 이름을 정함 ( 어떻게 하는지가 아닌 무엇을 하는지를 나타내도록 )
- 뽑아내고자 하는 부분이 아주 간단한 경우에는 새로운 메소드의 이름이 그 코드의 의도를 더 잘 나타낼 수 있을 때만 뽑아낸다. )
- 뽑아내고자 하는 부분의 코드를 복사하여 새 메소드로 옮김
- 원래 메소드에서 사용되고 있는 지역변수가 뽑아낸 코드에 있는지 확인
- 이 지역변수는 새로운 메소드의 지역변수나 파라미터가 됨
- 뽑아낸 코드 내에서만 사용되는 임시변수가 있는지 본다.
- 있다면 새로 만든 메소드의 임시변수로 선언
- 뽑아낸 코드 내에서 지역변수의 값이 수정되는지 본다.
- 하나의 지역변수만 수정된다면 뽑아낸 코드를 질의(query)로 보고, 수정된 결과를 변수에 대입할 수 있는지 확인 ( ex:) temp = extractMethod(); )
- 두개 이상이면 Split Temporary Variable 사용 후 다시 시도
- 임시변수는 Replace Temp with Query로 제거할 수 있다
- 뽑아낸 코드에서 읽기만 하는 변수는 새 메소드의 파라미터로 넘긴다.
- 지역변수와 관련된 사항을 다룬 후에는 컴파일을 한다.
- 원래 메소드의 뽑아낸 코드 부분에서 새로 만든 메소드를 호출하도록 바꾼다.
- 컴파일과 테스트
Inline Method
- 메소드 몸체가 메소드의 이름만큼이나 명확할 때는, 호출하는 곳에 메소드의 몸체를 넣고, 메소드를 삭제하라
- 동기
- 때론 메소드 몸체가 메소드의 이름만큼 명확할 때가 있다면 메소드를 삭제
- 절차
- 메소드가 다형성을 가지고 있지 않은지 확인
- 서브클래스에서 오버라이드하고 있는 메소드에는 적용 X
- 메소드를 호출하고 있는 부분을 모두 찾는다
- 각각의 메소드 호출을 메소드 몸체로 바꾼다.
- 컴파일과 테스트
- 메소드 정의 제거
Inline Temp
- 간단한 수식의 결과값을 가지는 임시변수가 있고, 그 임시변수가 다른 리팩토링을 하는데 방해가 된다면, 이 임시변수를 참조하는 부분을 모두 원래의 수식으로 바꾸라.
- 예)
- double temp = anOrder.basePrice();
- return (temp > 1000);
- ↓
- return ( anOrder.basePrice() > 1000 );
- 동기
- Replace Temp with Query의 한 부분으로 사용
- 메소드 호출의 결과값이 임시변수에 대입되는 경우
- 절차
- 임시변수를 final로 선언한 다음 커파일
- 임시변수에 값이 단 한번만 대입되고 있는지 확인하기 위해서
- 임시변수를 참조하고 있는 곳을 모두 찾아 대입문의 우변에 있는 수식으로 바꾼다.
- 각각의 변경에 대해 컴파일과 테스트
- 임시변수의 선언과 대입문 제거
- 컴파일과 테스트
Replace Temp with Query(v)
- 어떤 수식의 결과값을 저장하기 위해서 임시변수를 사용하고 있다면, 수식을 뽑아내서 메소드로 만들고, 임시변수를 참조하는 곳을 찾아 모두 메소드 호출로 바꾼다.
- 새로 만든 메소드는 다른 메소드에서도 사용될 수 있다.
- 동기
- Extract Method 적용하기 전의 필수 단계
- 지역변수 또는 임시변수는 메소드 추출을 어렵게 하기 때문에 가능한 많은 지역변수를 질의 메소드로 바꾸는 것이 좋음
- 절차
- 임시변수에 값이 한번만 대입되는지 확인
- 여러번 대입되는 경우 Split Temporary Variable 적용
- 임시변수를 final로 선언
- 컴파일
- 대입문의 우변을 메소드로 추출
- 컴파일과 테스트
- Inline Temp 적용
- 퍼포먼스에 대한 문제
- 약간 느려질지 몰라도 큰 문제가 되진 않을 것
- 문제가 된다면 최적화 단계에서 수정하면 된다.
- 일단 적용하고 나면 최적화를 한다고 해도 코드가 잘 정리되어 있기 때문에 더 좋은 최적화 방법을 찾을 수도 있다.
- 최악의 경우라도, 임시변수를 다시 집어넣는 건 쉽다.
Introduce Explaining Variable(v)
- 복잡한 수식이 있는 경우에는, 수식의 결과나 또는 수식의 일부에 자신의 목적을 잘 설명하는 이름으로 된 임시변수를 사용하라.
- 동기
- 특히 조건문에서 각각의 조건의 뜻을 잘 설명하는 이름의 변수로 만들어 사용할 때 유용
- 긴 알고리즘에서 각 단계의 계산 결과
- 하지만 대부분 Extract Method를 보통 쓰게 된다.
Split Temporary Variable(v)
- 루프 안에 있는 변수나 collecting temporary variable도 아닌 임시변수에 값을 여러 번 대입하는 경우에는, 각각의 대입에 대해서 따로따로 임시변수를 만들어라.
- 동기
- 어떤 변수든 여러 가지 용도로 사용되는 경우에는 각각의 용도에 대해 따로 변수를 사용하도록 바꾸어야 함
- 절차
- 임시변수가 처음 선언된 곳과 임시변수에 값이 처음 대입된 곳에서 변수의 이름을 바꾼다.
- 새로 만든 임시변수를 final로 선언
- 임시변수에 두 번째로 대입하는 곳의 직전까지 원래 임시변수를 참조하는 곳을 모두 바꿈
- 임시변수에 두 번째로 대입하는 곳에서 변수 선언
- 컴파일 & 테스트
Remove Assignments to Parameters(v)
- 파라미터에 값을 대입하는 코드가 있으면, 대신 임시변수를 사용하도록 하라.
- 동기
- 파라미터가 값에 의한 전달(pass by value)이라면 문제 없지만 참조에 의한 전달(pass by reference)일 때는 혼동
- 출력 파라미터를 사용하는 언어는 상관없긴 하지만 출력 파라미터는 가능한 적게 사용하는 것이 좋다.
- 절차
- 파라미터를 위한 임시변수를 만든다.
- 파라미터에 값을 대입한 코드 이후에서 파라미터에 대한 참조를 임시변수로 바꾼다.
- 파라미터에 대입하는 값을 임시변수에 대입하도록 바꾼다.
- 컴파일 & 테스트
Replace Method with Method Object(써보자)
- 긴 메소드가 있는데, 지역변수 때문에 Extract Method를 적용할 수 없는 경우에는,
- 메소드를 그 자신을 위한 객체로 바꿔서 모든 지역변수가 그 객체의 필드가 되도록 한다. 이렇게 하면 메소드를 같은 객체 안의 여러 메소드로 분해할 수 있다.
- 절차
- 메소드의 이름을 따서 새로운 클래스를 만든다.
- 새로운 클래스에 원래 메소드가 있던 객체를 보관하기 위한 final 필드를 하나 만들고, 메소드에서 사용되는 임시변수와 파라미터를 위한 필드를 만들어준다.
- 새로운 클래스에 소스 객체와 파라미터를 취하는 생성자를 만들어준다.
- 새로운 클래스에 compute라는 이름의 메소드를 만들어준다.
- 원래의 메소드를 compute 메소드로 복사한다. 원래의 객체에 있는 메소드를 사용하는 경우에는 소스 객체 필드를 사용하도록 바꾼다.
- 컴파일
- 새로운 클래스의 객체를 만들고 원래의 메소드를 새로 만든 객체의 compute 메소드를 호출하도록 바꾼다.
- 이 후로는 지역변수가 모두 필드로 바뀌었으므로, 파라미터를 넘길 필요 없이 마음대로 메소드를 분해할 수 있다.
Substitute Algorithm
- 알고리즘을 보다 명확한 것으로 바꾸고 싶을 때는, 메소드의 몸체를 새로운 알고리즘으로 바꾼다.
- 절차
- 대체 알고리즘을 적용하여 컴파일
- 알고리즘 테스트, 결과가 같으면 끝
- 결과 같지 않다면, 디버깅
'리팩토링' 카테고리의 다른 글
리팩토링 8장 - 데이터 구성 (0) | 2016.04.02 |
---|---|
리팩토링 7장 - 객체간의 기능 이동 (0) | 2016.03.12 |
리팩토링 4장 - 테스트 만들기 (0) | 2016.02.27 |
리팩토링 3장 - 코드 속의 나쁜 냄새 (0) | 2016.02.21 |
리팩토링 2장 - 리팩토링의 원리 (0) | 2016.02.14 |
Comments