[리팩토링] 악취 20 : 내부자 거래

 

✍️ 악취 20 : 내부자 거래

어떤 모듈이 다른 모듈의 정보를 지나치게 많이 알고 있다면 혹은 모듈이 지나치게 많은 것을 공개하고 있다면 강한 결합도가 발생할 수 있다. 이 중에서도 다른 모듈의 정보를 지나치게 많이 알고 있는 상황을 '내부자 거래'라고 한다.

 

다른 모듈의 정보를 지나치게 많이 요구한다면 필드나 메서드의 위치가 적절한지 생각해 보고 '함수 옮기기' 혹은 '메서드 옮기기' 리팩토링을 적용할 수 있다. 다른 여러 모듈에서도 동일한 현상이 발생한다면 자주 요구되는 필드와 메서드 혹은 클래스를 '별도의 모듈로 분리' 할 수 있다. 동시에 정보를 최대한 감추기 위해 '위임 숨기기' 도 적용할 수 있다. 

 

여기 내부자 거래 악취를 해결하기 위한 세 가지 리팩토링 기법이 있다.

1. "함수/메서드 옮기기적절한 위치로 옮겨서 캡슐화하기

2. "모듈로 분리하기" 여러 모듈의 참조를 캡슐화된 한곳에서 제공하기 위해

3. "위임 숨기기" 최소한의 정보만을 공개하기 위해

 

본 포스팅에서 관심있게 살펴볼 리팩토링은 "함수/메서드 옮기기"이다.

🍊 함수 옮기기

티켓의 FastPass 조건을 검사할 때 CheckIn이 티켓의 너무 많은 정보를 알아야 한다.

@AllArgsConstructor
@Getter
public class Ticket {

    private DateTime purchasedDate;
    private boolean isPrime;

}

public class CheckIn {

    public boolean isFastPass(Ticket ticket) {
        DateTime earlyBirdDate = new DateTime(2022, 1, 1, 0, 0);
        return ticket.isPrime() && ticket.getPurchasedDate().isBefore(earlyBirdDate);
    }
}

 

클라이언트에 너무 많은 정보를 제공하고 있음은 메서드의 위치가 적절하지 않다는 방증이기도 하다. FastPass 여부를 Ticket의 책임으로 전환하자.

@AllArgsConstructor
public class Ticket {

    public static final DateTime EARLY_BIRD_END_DATE = new DateTime(2000, 1, 1, 0, 0);

    private DateTime purchasedDate;
    private boolean isPrime;

    public boolean isFastPass() {
        return isPrime && purchasedDate.isBefore(EARLY_BIRD_END_DATE);
    }

}