double basePrice = _quantity * _itemPrice; if (basePrice > 1000) return basePrice * 0.95; else return basePrice * 0.98;
if (basePrice() > 1000) return basePrice() * 0.95; else return basePrice() * 0.98; ... double basePrice() { return _quantity * _itemPrice; }
동기
- 임시변수는 그것이 사용되는 메소드의 컨텍스트 안에서만 볼 수 있으므로, 임시변수가 사용되는 메소드는 보통 길이가 길어지는 경향이 있다.
- 임시변수를 query method 로 바꿈으로써 클래스 내의 어떤 메소드도 임시변수에 사용될 정보를 얻을 수 있다. 클래스 코드가 더 깔끔해진다.
- Extract Method 적용하기 전의 필수 단계.
- 지역변수는 메소드의 추출을 어렵게 하기 때문에 가능한 많은 지역변수를 query method 로 바꾸는것이 좋다.
절차
- 간단한 경우(임시변수에 값이 한번만 대입되고, 대입문(assignment)을 만드는 수식이 부작용을 초래하지 않는 경우)에 대한 절차는 다음과 같다.
- 임시 변수에 값이 한번만 대입되는지를 확인한다.
- 임시변수를 final 로 선언한다.
- 컴파일 한다.
- 대입분의 우변을 메소드로 추출한다.
- 컴파일과 테스트를 한다.
- Inline Temp를 적용한다.
예제
double getPrice() { int basePrice = _quantity * _itemPrice; double discountFactor; if (basePrice > 1000) discountFactor = 0.95; else discountFactor = 0.98; return basePrice * discountFactor; }
두개의 임시변수(basePrice,discountFactor)를 모두 제거하고 싶다.
임시변수에 값이 한번만 대입되는 것을 확인하기 위해(문제가 있으면 이 리팩토링을 하면 안된다) final 로 선언하여 테스트한다.
double getPrice() {
final int basePrice = _quantity * _itemPrice;
final double discountFactor;
if (basePrice > 1000) discountFactor = 0.95;
else discountFactor = 0.98;
return basePrice * discountFactor;
}
대입문의 우변을 메소드로 뽑아낸다.
double getPrice() {
final int basePrice = basePrice();
final double discountFactor;
if (basePrice > 1000) discountFactor = 0.95;
else discountFactor = 0.98;
return basePrice * discountFactor;
}
private int basePrice() {
return _quantity * _itemPrice;
}
컴파일,테스트후 Inline Temp 를 사용한다.
double getPrice() {
final int basePrice = basePrice();
final double discountFactor;
if (basePrice() > 1000) discountFactor = 0.95;
else discountFactor = 0.98;
return basePrice * discountFactor;
}
컴파일, 테스트후 두번째 참조하는 곳도 바꾸고 basePrice 변수도 삭제한다.(더이상 참조하는 곳이 없으므로)
double getPrice() {
final double discountFactor;
if (basePrice() > 1000) discountFactor = 0.95;
else discountFactor = 0.98;
return basePrice() * discountFactor;
}
discountFactor에 대해서도 위와같이 작업한다.
double getPrice() {
final double discountFactor = discountFactor();
return basePrice() * discountFactor;
}
private double discountFactor() {
if (basePrice() > 1000) return 0.95;
else return 0.98;
}
최종 결과
double getPrice() {
return basePrice() * discountFactor();
}
basePrice() 가 총 두번 호출되므로 이전보다 한번의 계산이 더 늘었다.
- 퍼포먼스에 대해서 걱정이 될 수 있다.
- 당장은 약간 느려질지도 모르나 십중팔구는 문제가 되지 않을것이다.
- 만약 문제가 된다면 최적화 단계에서 수정하면 된다.
- 코드가 잘 분해되어 잇으면 보통 리팩토링을 하지 않았을 때에는 보지 못했을 더 강력한 최적화 방법을 찾을 수 있다.
- 최악의 경우라도, 임시변수를 다시 집어넣는 것은 쉽다.
'프로그램언어 > Refactoring' 카테고리의 다른 글
[ Refactoring ] Split Temporary Variable (2) | 2010.12.01 |
---|---|
[ Refactoring ] Introduce Explaing Variable (0) | 2010.11.29 |
[ Refactoring ] Inline Temp (0) | 2010.11.24 |
[ Refactoring] Inline Method (0) | 2010.11.24 |
[Refactoring] Extract Method (0) | 2010.11.23 |