14장: 일관성 있는 협력

변경을 분리하고 캡슐화하기

  • 유사한 요구사항에 대해 각 협력이 서로 다른 패턴으로 구현되어 있다면 전체적인 설계의 일관성이 무너지고 비용이 증가한다.

  • 유사한 기능을 구현하기 위해 일관성 있는 유사한 협력 패턴을 사용하면 시스템을 이해하고 확장하기 위해 요구되는 정신적인 부담을 크게 줄일 수 있다.

  • 일관성 있는 설계를 만드려면 다양한 설계 경험을 익히고 널리 알려진 디자인 패턴을 학습하여 적용해보는 것이 필요하다.

  • 늘 강조해왔듯, 변하는 개념과 변하지 않는 개념을 분리하고 변하는 개념은 캡슐화해야 한다. 여기서 캡슐화란 단순히 데이터를 감추는 것이 아니라 소프트웨어 안에서 변할 수 있는 모든 ‘개념’을 감추는 것이다.

  • 캡슐화에는 클래스 내부 데이터를 캡슐화하는 데이터 캡슐화, 클래스의 내부 행동을 캡슐화하는 메서드 캡슐화, 합성을 사용해 객체를 캡슐화하는 객체 캡슐화, 실행 시점에 어떤 객체가 올 지 확인하도록 하는 서브타입 캡슐화가 존재한다.

  • 서브타입 캡슐화와 객체 캡슐화는 다음과 같은 순서로 적용할 수 있다.

    • 변하는 부분을 분리한 후 공통적인 행동을 추상 클래스/인터페이스로 정의하고 이를 상속받도록 한다.

    • 변하지 않는 부분에 타입 계층을 합성(composite)하여 추상화에 의존하게 만든다.

  • 변경의 이유에 따라 캡슐화할 수 있는 다양한 방법을 디자인 패턴에서 제시하므로 공부해보는 게 좋다.

  • 다형성은 조건 로직을 객체 사이의 이동으로 바꾸기 위해 객체지향이 제공하는 설계 기법이다.

협력 패턴 구현하기

요구사항

  • 여러가지 통화 요금 책정 방식이 존재할 수 있다.

  • 아래는 그 중 한 방식인 시간대별 방식을 그림으로 나타낸 것이다. 1월1일 0시부터 1월3일 24시까지 통화가 이뤄졌고, 이 통화 내역을 시간대별로 분리하여 각각 다른 요금을 부과해야 한다.

설계

  • 모든 작업을 객체의 책임으로 생각하고, 아래와 같이 객체를 설계한다.

    • BasicRatePolicy

      • 사용자로부터 통화 목록이 담긴 핸드폰을 전달받으면 해당 핸드폰의 통화 요금을 반환한다.

    • FeeRule

      • 시간대별로 분리된 통화 내역을 기반으로 가격을 계산한다.

    • FeeCondition

      • 적용 조건을 표현하는 인터페이스

      • 통화 내역을 전달받고 적용 조건을 만족하는 기간만 잘라 DateTimeInterval의 List로 반환하는 메서드가 있다.

    • FeePerDuration

      • 특정 기간만큼의 통화 요금을 계산해 반환한다.

구현

  • BasicRatePolicy

    • 하나의 통화 기록 당 통화 내역을 분리해 각각 요금을 계산하여 전체 요금을 반환하도록 한다.

  • FeeCondition

    • 하나의 통화 내역을 전달받고 적용 조건을 만족하는 기간만 잘라 DateTimeInterval의 List로 반환한다.

    • 시간대별 정책, 요일별 정책, 구간별 정책 등이 이 인터페이스를 구현하는 방식으로 표현될 것이다.

  • FeeRule

    • 하나의 통화 내역을 구간별로 잘라 적용 조건에 따른 요금을 계산하여 반환한다.

  • FeePerDuration

    • 얼마동안 통화할경우 얼마만큼의 요금이 나올 지 정의하여

요금 부과 정책 구현

  • FeeCondition을 구현하여 요금 부과 정책 클래스를 만든다.

  • 아래는 시간대별 정책의 적용 조건을 구현하는 클래스로, 시작시간과 종료시간을 담아두고 통화 내역이 입력되면 시작시간과 종료시간에 해당하는 구간만 잘라내 반환한다.

  • 아래는 구간별 정책의 적용 조건을 구현하는 클래스로, 특정 구간을 담아두고 통화 내역이 입력되면 구간에 만족하는 통화 기록 조각을 반환한다.

    • 개념적 무결성을 무너뜨리는 것보다는 약간의 부조화를 수용하는 편이 더 낫다.

    개념적 무결성: 일관성과 유사한 의미로, 시스템이 일관성 있는 몇 개의 협력 패턴으로 구성된다면 이해, 수정, 확장에 필요한 노력과 시간을 아낄 수 있다. 좋은 기능들이 서로 독립적이고 조화되지 못한 아이디어들을 담고 있는 시스템보다는 여러가지 다양한 기능이나 갱신된 내용은 비록 빠졌더라도 하나로 통합된 설계 패턴을 반영하는 시스템이 훨씬 좋다.

  • 협력은 고정된 것이 아니다. 만약 현재의 협력 패턴이 변경을 수용하기 어렵다면 변경의 방향에 맞춰 최선의 협력 패턴을 만들도록 리팩토링해야 한다.

  • 유사한 기능에 대한 변경이 지속적으로 발생하고 있다면 변경을 캡슐화할 수 있는 적절한 추상화를 찾아 반복적으로 적용할 수 있는 협력 구조를 도출하고, 이 추상화에 변하지 않는 공통적인 책임을 할당해야 한다.

Last updated