"매개변수를 질의 함수로 바꾸기(Replace Parameter with Query)"는 함수의 매개변수(parameter)를 함수 안에서 계산하는 쿼리(query)로 대체하는 리팩터링 기법입니다.
함수의 매개변수 목록은 함수의 변동요인을 나타내고, 짧을수록 이해 가기가 쉽습니다.
함수의 매개변수를 사용하여 함수 내부에서 계산이 이루어지는 경우, 이는 함수 내부와 외부의 결합도를 높일 수 있습니다.
즉, 함수의 입력값이 변할 때마다 함수 내부에서 처리하는 방식이 달라져야 한다면, 이를 유지보수하기 어려워집니다.
어떤 매개변수를 다른 매개변수를 통해 알아낼수 있다면 "중복 매개변수"라고 생각할 수 있습니다.
매개변수를 줄이면 책임 주체가 달라집니다.
매개변수가 있다면 호출하는 쪽에 책임이 있고, 매개변수가 없다면 피호출함수가 책임이 있습니다.
가능하면 호출하는 쪽에 책임을 간소하게 만드는 것을 권장합니다.
매개변수를 질의 함수로 바꾸면 함수 내부와 외부의 결합도가 낮아지며, 함수의 유지보수성이 향상됩니다.
다음은 물건의 가격을 할인하는 예제 코드입니다.
double finalPrice()
{
double basePrice = this.quantity * this.itemPrice;
int discountLevel;
if(this.quantity > 100)
{
discountLevel = 2;
}
else
{
discountLevel = 1;
}
return this.discountedPrice(basePrice, discountLevel);
}
double discountedPrice(double basePrice, int discountLevel)
{
switch (discountLevel)
{
case 1: return basePrice * 0.95;
case 2: return basePrice * 0.9;
}
}
물건(this)의 퀄리티(quantity)를 확인하여 할인 레벨(discountLevel)을 결정하여 할인된 가격(discountedPrice())을 계산합니다.
임시 변수를 질의 함수로 바꾸기 로 다음과 위 코드를 아래 코드로 리팩터링 합니다.
double finalPrice()
{
double basePrice = this.quantity * this.itemPrice;
return this.discountedPrice(basePrice, this.discountLevel());
}
int discountLevel()
{
return (this.quantity > 100) ? 2 : 1;
}
double discountedPrice(double basePrice, int discountLevel)
{
switch (discountLevel)
{
case 1: return basePrice * 0.95;
case 2: return basePrice * 0.9;
}
}
할인 레벨(discountLevel) 임시 변수를 질의 함수(discountLevel())로 바꾸었습니다.
double discountedPrice(double basePrice, int discountLevel) 해당 함수의 2번째 매개변수를 없애고 함수에서 직접 호출합니다.
double finalPrice()
{
double basePrice = this.quantity * this.itemPrice;
return this.discountedPrice(basePrice);
}
int discountLevel()
{
return (this.quantity > 100) ? 2 : 1;
}
double discountedPrice(double basePrice)
{
switch (this.discountLevel())
{
case 1: return basePrice * 0.95;
case 2: return basePrice * 0.9;
}
}
이렇게 "매개변수를 질의 함수로 바꾸기"를 사용하여 리팩터링을 할 수 있습니다.
할인 레벨(discountLevel)를 계산하는 책임 주체가 호출자인 finalPrice()에서 피 호출자인 discountedPrice()로 변경된 것을 확인할 수 있습니다.
다음은 또 다른 예제 코드입니다.
double calculatePrice(double price, double discountRate) {
double discountedPrice = price - (price * discountRate);
if (discountedPrice < 0) {
return 0;
} else {
return discountedPrice;
}
}
이 함수는 가격(price)과 할인율(discountRate)을 받아서, 할인된 가격을 계산하여 반환합니다.
이때, 할인된 가격이 음수가 되지 않도록 하기 위해 0과 비교하는 로직이 포함되어 있습니다.
이 함수의 매개변수인 discountRate를 대체하기 위해 다음과 같이 리팩터링 할 수 있습니다.
double calculatePrice(double price) {
double discountRate = getDiscountRate();
double discountedPrice = price - (price * discountRate);
if (discountedPrice < 0) {
return 0;
} else {
return discountedPrice;
}
}
double getDiscountRate() {
// 할인율을 계산하는 로직
// ...
return discountRate;
}
getDiscountRate() 함수를 호출하여 할인율을 계산하도록 변경하였습니다.
이렇게 변경하면, calculatePrice() 함수를 호출할 때 할인율을 전달할 필요가 없어지며, calculatePrice() 함수는 단순화되고 유연성이 향상됩니다.
또한, 할인율을 계산하는 로직이 중복되는 것을 방지할 수 있습니다.
매개변수를 질의 함수로 바꾸지 말아야 할 경우도 있습니다.
이 경우는 매개변수를 제거함으로써 피 호출자가 해당 함수에 의존성이 생길 때입니다.
'리팩터링 > 리팩터링 기법' 카테고리의 다른 글
리팩터링. Use a Configuration File (0) | 2023.02.27 |
---|---|
리팩터링. Use a Builder (0) | 2023.02.26 |
리팩터링. 조건문을 다형성으로 바꾸기(Replace Conditional with Polymorphism) (0) | 2023.02.23 |
리팩터링. 반복문 쪼개기 (Split Loop) (0) | 2023.02.22 |
리팩터링. 조건문 분해하기 (Decompose Conditional) (0) | 2023.02.21 |