해당 포스팅은 인프런 백기선님의 '리팩토링'을 학습 후 정리한 내용입니다.
public class Customer {
private String name;
private double discountRate;
private CustomerContract contract;
public Customer(String name, double discountRate) {
this.name = name;
this.discountRate = discountRate;
this.contract = new CustomerContract(dateToday());
}
public double getDiscountRate() {
return discountRate;
}
public void becomePreferred() {
this.discountRate += 0.03;
// 다른 작업들
}
public double applyDiscount(double amount) {
BigDecimal value = BigDecimal.valueOf(amount);
return value.subtract(value.multiply(BigDecimal.valueOf(this.discountRate))).doubleValue();
}
private LocalDate dateToday() {
return LocalDate.now();
}
}
public class CustomerContract {
private LocalDate startDate;
public CustomerContract(LocalDate startDate) {
this.startDate = startDate;
}
}
discountRate 필드를 CustomerContract 클래스에 있는것이 응집도를 높일 수 있는것 같다.
discountRate 필드를 CustomerContract 클래스로 옮겼다.
import java.math.BigDecimal;
import java.time.LocalDate;
public class Customer {
private String name;
private CustomerContract contract;
public Customer(String name, double discountRate) {
this.name = name;
this.contract = new CustomerContract(dateToday(), discountRate);
}
public double getDiscountRate() {
return this.contract.getDiscountRate();
}
public void becomePreferred() {
this.setDiscountRate(this.getDiscountRate() + 0.03);
// 다른 작업들
}
public double applyDiscount(double amount) {
BigDecimal value = BigDecimal.valueOf(amount);
return value.subtract(value.multiply(BigDecimal.valueOf(this.getDiscountRate()))).doubleValue();
}
private LocalDate dateToday() {
return LocalDate.now();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void setDiscountRate(double discountRate) {
this.contract.setDiscountRate(discountRate);
}
public CustomerContract getContract() {
return contract;
}
public void setContract(CustomerContract contract) {
this.contract = contract;
}
}
import java.time.LocalDate;
public class CustomerContract {
private LocalDate startDate;
private double discountRate;
public CustomerContract(LocalDate startDate, double discountRate) {
this.startDate = startDate;
this.discountRate = discountRate;
}
public LocalDate getStartDate() {
return startDate;
}
public void setStartDate(LocalDate startDate) {
this.startDate = startDate;
}
public double getDiscountRate() {
return discountRate;
}
public void setDiscountRate(double discountRate) {
this.discountRate = discountRate;
}
}
필드를 옮기는데 있어 IDE 의 도움을 받기 힘들어, 안전하게 CustomerContract 생성자에 discountRate 를 넣어 IDE 도움을 받아 옮겼다.
public class Driver {
private int numberOfLateDeliveries;
public Driver(int numberOfLateDeliveries) {
this.numberOfLateDeliveries = numberOfLateDeliveries;
}
public int getNumberOfLateDeliveries() {
return this.numberOfLateDeliveries;
}
}
public class Rating {
public int rating(Driver driver) {
return moreThanFiveLateDeliveries(driver) ? 2 : 1;
}
private boolean moreThanFiveLateDeliveries(Driver driver) {
return driver.getNumberOfLateDeliveries() > 5;
}
}
Rating 클래스의 rating() 함수는 배달기사가 5회 이상 늦게 배달한 경우가 있는지 확인 후 결과 값에 따라 rating 을 반환해주는 함수다.
moreThanFiveLateDeliveries() 함수는 한줄짜리 코드를 단순 위임 해주는 함수이며, 의미를 크게 변환해주지는 않는다.
함수를 인라인하자!
public class Rating {
public int rating(Driver driver) {
return moreThanFiveLateDeliveries(driver) ? 2 : 1;
}
private boolean moreThanFiveLateDeliveries(Driver driver) {
return driver.getNumberOfLateDeliveries() > 5;
}
}
위임의 역할을 하는 함수를 inline 을 해주기 위해 IDE 에서 ctrl + N 을 눌러 함수를 inline 하였다.
public class Shipment {
private TrackingInformation trackingInformation;
public Shipment(TrackingInformation trackingInformation) {
this.trackingInformation = trackingInformation;
}
public TrackingInformation getTrackingInformation() {
return trackingInformation;
}
public void setTrackingInformation(TrackingInformation trackingInformation) {
this.trackingInformation = trackingInformation;
}
public String getTrackingInfo() {
return this.trackingInformation.display();
}
}
public class TrackingInformation {
private String shippingCompany;
private String trackingNumber;
public TrackingInformation(String shippingCompany, String trackingNumber) {
this.shippingCompany = shippingCompany;
this.trackingNumber = trackingNumber;
}
public String display() {
return this.shippingCompany + ": " + this.trackingNumber;
}
public String getShippingCompany() {
return shippingCompany;
}
public void setShippingCompany(String shippingCompany) {
this.shippingCompany = shippingCompany;
}
public String getTrackingNumber() {
return trackingNumber;
}
public void setTrackingNumber(String trackingNumber) {
this.trackingNumber = trackingNumber;
}
}
TrackingInformation 클래스의 역할이 단순 위임으로써 응집도를 높이기 위해 Shipment 클래스에 TrackingInformation 필드와 메소드를 옮기는게 좋을것 같다.
class 를 inline 하자!
public class Shipment {
private String shippingCompany;
private String trackingNumber;
public Shipment(String shippingCompany, String trackingNumber) {
this.shippingCompany = shippingCompany;
this.trackingNumber = trackingNumber;
}
public String getTrackingInfo() {
return this.shippingCompany + ": " + this.trackingNumber;
}
public String getShippingCompany() {
return shippingCompany;
}
public void setShippingCompany(String shippingCompany) {
this.shippingCompany = shippingCompany;
}
public String getTrackingNumber() {
return trackingNumber;
}
public void setTrackingNumber(String trackingNumber) {
this.trackingNumber = trackingNumber;
}
}
TrackingInformation 클래스를 Shipment 클래스로 inline 시켰으며, 필요없어진 TrackingInformation 클래스를 삭제하였다.