BackEnd/Refactoring

[Refactoring] 성의없는 요소 (Lazy Element), 추측성 일반화 (Speculative Generality), 임시 필드 (Temporary Field)

샤아이인 2023. 1. 7.

백기선 님의 리팩터링 강의를 들으며 요약한 내용입니다.

 

12. 성의없는 요소

프로그래밍을 하면서 여러 변수, 메서드, 클래스를 만들게 된다.

만들 당시에는 의미를 명확하게 하기 위해서, 또는 중복을 제거하기 위해서 사용했겠지만...

그렇게 예상하고 만들어 놓은 요소들이 기대에 부응하지 못하는 경우가 있는데 그런 경우에 해당 요소들을 제거해야 한다!

 

함수 인라인, 클래스 인라인, 계층 합치기 를 통하여 리팩토링 할 수 있다.

 

13. 추측성 일반화

나중에 이러 저러한 기능이 생길 것으로 예상하여, 여러 경우에 필요로 할만한 기능을 만들어 놨지만 그런 일은 없었고...”결국에 쓰이지 않는 코드가 발생한 경우.

 

XPYAGNI (You aren’t gonna need it) 원칙을 따르자. => 지금 당장 필요한것이 아니라면 만들지 말라!

 

14. 임시 필드

클래스에 있는 어떤 필드가 특정한 경우에만 값을 갖는 경우.

어떤 객체의 필드가 “특정한 경우에만” 값을 가진다는 것을 이해하는 것은 일반적으로 예상하지 못하기 때문에 이해하기 어렵다.

 

예를 들어 다음 코드를 살펴보자.

▶ CustomerService

public class CustomerService {

    public String customerName(Site site) {
        Customer customer = site.getCustomer();

        String customerName;
        if (customer.getName().equals("unknown")) {
            customerName = "occupant";
        } else {
            customerName = customer.getName();
        }

        return customerName;
    }

    public BillingPlan billingPlan(Site site) {
        Customer customer = site.getCustomer();
        return customer.getName().equals("unknown") ? new BasicBillingPlan() : customer.getBillingPlan();
    }

    public int weeksDelinquent(Site site) {
        Customer customer = site.getCustomer();
        return customer.getName().equals("unknown") ? 0 : customer.getPaymentHistory().getWeeksDelinquentInLastYear();
    }

}

위 코드에서 다음 부분이 계속적으로 중복되고 있다.

customer.getName().equals("unknown")

Unknown이라는 케이스가 계속해서 중복되고 있다. 이 특이 케이스를 UnknownCustomer로 추출해보자!

 

추가로, 과연 cutomer에서 getter로 가져와서 동일한지 확인하는 코드가 Service에 있어야 하는 것 일까?

이또한 메서드로 뽑아 Customer로 이동시켜야 할 것 이다.

public class Customer {

    private String name;
    private BillingPlan billingPlan;
    private PaymentHistory paymentHistory;

    public Customer(String name, BillingPlan billingPlan, PaymentHistory paymentHistory) {
        this.name = name;
        this.billingPlan = billingPlan;
        this.paymentHistory = paymentHistory;
    }
    
    // 생략...

    public boolean isUnknown() {
        return false;
    }
}

 

▶ UnknownCustomer

public class UnknownCustomer extends Customer {

    public UnknownCustomer(String name, BillingPlan billingPlan, PaymentHistory paymentHistory) {
        super("unknown", null, null);
    }
    
    @Override
    public boolean isUnknown() {
        return true;
    }
    
    @Override
    public String getName() {
        return "occupant";
    }
}

 

따라서 CustomerService의 코드가 다음과 같이 변경된다.

더이상 타입에 따라서 나누지 않아도 된다.

public class CustomerService {

    public String customerName(Site site) {
        return site.getCustomer().getName();
    }
    
    // 생략...
}

댓글