[Refactoring] 냄새 9. 기능 편애
28 Dec 2022해당 포스트는 inflearn의 백기선님의 강의인 리팩토링 을 듣고 정리한 글입니다.
냄새 9. 기능 편애
- 어떤 모듈에 있는 함수가 다른 모듈에 있는 데이터나 함수를 더 많이 참조하는 경우에 발생한다.
- 예) 다른 객체의 getter를 여러개 사용하는 메소드
- 관련 리팩토링 기술
- “함수 옮기기(Move Function)”를 사용해서 함수를 적절한 위치로 옮긴다.
- 함수 일부분만 다른 곳의 데이터와 함수를 많이 참조한다면 “함수 추출하기 (Extract Function)”로 함수를 나눈 다음에 함수를 옮길 수 있다.
- 만약에 여러 모듈을 참조하고 있다면? 그중에서 가장 많은 데이터를 참조하는 곳으로 옮기거나, 함수를 여러개로 쪼개서 각 모듈로 분산 시킬 수도 있다.
- 데이터와 해당 데이터를 참조하는 행동을 같은 곳에 두도록 하자.
- 예외적으로, 데이터와 행동을 분리한 디자인 패턴 (전략 패턴 또는 방문자 패턴)을 적용할 수도 있다.
예제 코드
- Bill
public class Bill {
private ElectricityUsage electricityUsage;
private GasUsage gasUsage;
public double calculateBill() {
var electicityBill = electricityUsage.getAmount() * electricityUsage.getPricePerUnit();
var gasBill = gasUsage.getAmount() * gasUsage.getPricePerUnit();
return electicityBill + gasBill;
}
}
- ElectricityUsage
public class ElectricityUsage {
private double amount;
private double pricePerUnit;
public ElectricityUsage(double amount, double pricePerUnit) {
this.amount = amount;
this.pricePerUnit = pricePerUnit;
}
public double getAmount() {
return amount;
}
public double getPricePerUnit() {
return pricePerUnit;
}
}
- GasUsage
public class GasUsage {
private double amount;
private double pricePerUnit;
public GasUsage(double amount, double pricePerUnit) {
this.amount = amount;
this.pricePerUnit = pricePerUnit;
}
public double getAmount() {
return amount;
}
public double getPricePerUnit() {
return pricePerUnit;
}
}
Bill 클래스를 살펴본다면 가스나, 전기요금에 대한 영수증을 만드는 클래스이다. 그런데 잘 살펴본다면, 가스사용량과, 전기사용량마저 각자의 모듈에서 계산하는 것이 아닌 Bill 클래스에서 계산하여 측정하고 있다.
각각의 용도에 맞게 메소드들을 옮겨주도록하자.
먼저 가스요금계산과, 전기요금계산을 메소드로 분리해준다.
private double getGasBill() {
return gasUsage.getAmount() * gasUsage.getPricePerUnit();
}
private double getElecticityBill() {
return electricityUsage.getAmount() * electricityUsage.getPricePerUnit();
}
그리고 각각 전기와 가스 사용량을 가져오는 클래스로 메소드를 옮겨 준다.
public class ElectricityUsage {
private double amount;
private double pricePerUnit;
public ElectricityUsage(double amount, double pricePerUnit) {
this.amount = amount;
this.pricePerUnit = pricePerUnit;
}
public double getAmount() {
return amount;
}
public double getPricePerUnit() {
return pricePerUnit;
}
public double getElecticityBill() {
return this.getAmount() * this.getPricePerUnit();
}
}
public class GasUsage {
private double amount;
private double pricePerUnit;
public GasUsage(double amount, double pricePerUnit) {
this.amount = amount;
this.pricePerUnit = pricePerUnit;
}
public double getAmount() {
return amount;
}
public double getPricePerUnit() {
return pricePerUnit;
}
public double getGasBill() {
return this.getAmount() * this.getPricePerUnit();
}
}
이후 Bill클래스의 계산서 계산 메소드를 수정해준다.
public double calculateBill() {
return electricityUsage.getElecticityBill() + gasUsage.getGasBill();
}