개발하다보면 유사한 요구사항을 반복적으로 추가하거나 수정하게 되는 경우가 있다. 이 때 객체들의 협력 구조가 서로 다른 경우에는 코드를 이해하기도 어렵고 코드 수정으로 버그가 생길 위험성도 높아진다. 이런 상황에서 각 협력이 서로 다른 패턴을 다를 경우에는 전체적인 설계의 일관성이 서서히 무너지게된다.
설계의 재사용을 위해 객체들의 협력 방식을 일관성있게 만들어야 한다. 일관성있는 설계는 코드를 이해하기 쉽게 만들어준다. 가능하면 유사한 협력 패턴을 사용하자. 이해하기 쉬운게 최고다.
핸드폰 과금 시스템의 요금 정책을 수정해야 한다고 가정하자. 지금까진 기본에 일반 + 심야 할인만 있었다. 이를 다음과 같이 확장할 것이다.
유형 | 형식 | 예 |
---|---|---|
고정요금 | A초당 B원 | 10초당 18원 |
시간대별 방식 | A시부터 B시 까지 C초당 D원 | |
B시부터 C시까지 C초당 E원 | ||
요일별 방식 | 평일엔 A초당 B원 | |
공휴일에는 A초당 C원 | ||
구간별 방식 | 초기 A분 간 B초당 C원 | |
A~D분간 얼마 | ||
D 초과시 얼마 |
고정요금의 경우 기존의 RegularPolicy의 일듬을 FixedFeePolicy로 수정하자.
시간대별 방식을 구현할 때 0~19시에 대해서는 10초당 18원의 요금을 부과하고, 19~24시는 10초당 15원을 부과한다고 가정하자. 이 때 3일에 걸쳐 통화를 한다면? 어떤 규칙에 따라 통화 시간을 분리해야 할까? 이를 위해 기간을 편하게 관리할 수 있는 DateTimeInterval 클래스를 추가한다.
또, from, to만 가지고 있는 Call 클래스가 있는데 이 두 필드를 하나로 묶은 DateTimeInterval로 변경하자.
이제 요금 계산을 한다. 계산은 두 단계로 나눌 수 있다.
두 작업을 객체의 책임으로 할당할 것이다. 책임을 할당하는 기본 원칙은 해당 정보를 가장 잘 알고 있는 전문가에게 할당하는 것이다.
첫 번째로 통화 기간에 대해 잘 알고 있는 객체는 Call이다. 하지만 기간 자체를 처리하는 방법에 대해서는 잘 알지 못한다. 고로 기간을 나누는 책임은 DateTimeInterval에게 할당하고 Call이 DateTimeInterval에게 분할을 요청하는 것이 적절할 것이다.
두 번째 작업은 누가 해야할까? 시간대별 기준을 잘 알고 있어야한다. 이를 TimeOfDayDiscountPolicy라는 이름의 클래스로 구현할 것이다.