14장 일관성 있는 협력

오브젝트의 14장을 요약한 내용 입니다.

객체지향 설계의 목표는 적절한 책임을 수행하는 객체들의 협력을 기반으로 결합도가 낮고 재사용 가능한 코드 구조를 창조하는 것이다. 유사한 요구사항을 계속 추가해야 하는 상황에서 각 협력이 서로 다른 패턴을 다를 경우에는 전체적인 설계의 일관성이 서서히 무너지게 된다.

하지만 재사용은 공짜로 얻어지지 않는다. 재사용을 위해서는 객체 들의 협력 방식을 일관성 있게 만들어야 한다. 특정한 문제를 유사한 방법으로 해결하고 있다는 사실을 알면 문제를 이해하는 것만으로도 코드의 구조를 예상할 수 있게 된다.

대부분의 사람들은 유사한 요구사항을 구현하는 코드는 유사한 방식으로 구현될 것이라고 예상한다. 하지만 유사한 요구사항이 서로 다른 방식으로 구현돼 있다면 요구사항이 유사하다는 사실 자체도 의심하게 될 것이다.

결론은 유사한 기능을 서로 다른 방식으로 구현 해서는 안 된다는 것이다. 일관성 없는 설계와 마주한 개발자는 여러 가지 해결 방법 중에서 현재의 요구사항을 해결하기에 가장 적절한 방법을 찾아야 하는 부담을 안게 된다.

유사한 기능은 유사한 방식으로 구현해야 한다. 객체 지향에서 기능을 구현하는 유일한 방법은 객체 사이의 협력을 만드는 것 뿐이므로 유지보수 가능한 시스템을 구축하는 첫걸음은 협력을 일관성 있게 만드는 것이다.

설계에 일관성 부여하기

일관성 있는 설계를 만드는 데 가장 훌륭한 조언은 다양한 설계 경험을 익히라는 것이다. 두 번째 조언은 널리 알려진 디자인 패턴을 학습하고 변경이라는 문맥 안에서 디자인 패턴을 적용해 보라는 것이다.

디자인 패턴이 반복적으로 적용할 수 있는 설계 구조를 제공한다고 하더라도 모든 경우에 적합한 패턴을 찾을 수 있는 것은 아니다. 따라서 협력을 일관성 있게 만들기 위해 다음과 같은 기본 지침을 따르는 것이 도움이 될 것이다.

  • 변하는 개념을 변하지 않는 개념으로부터 분리하라

  • 변하는 개념을 캡슐화하라

캡슐화 다시 살펴보기

캡슐화란 변하는 어떤 것이든 감추는 것이다. 캡슐화의 가장 대표적인 예는 객체의 퍼블릭 인터페이스와 구현을 분리하는 것이다.

소프트웨어 안에서 변할 수 있는 어떤 '개념'이라도 감추는 것이다. 이 사실을 기억하면서 다음 그림을 살펴보자

위 그림에는 다음과 같은 다양한 종류의 캡슐화가 공존한다.

  • 데이터 캡슐화 : Movie 클래스의 인스턴스 변수 title의 가시성은 private이기 때문에 외부에서 직접 접근할 수 없다. 이 속성에 접근할 수 있는 유일한 방법은 메서드를 이용하는 것뿐이다. 다시 말해 클래스는 내부에 관리하는 데이터를 캡슐화한다.

  • 메서드 캡슐화 : DiscountPolicy 클래스에서 정의돼 있는 getDiscountAmount 메서드의 가시성은 protected다. 클래스의 외부에서는 이 메서드에 직접 접근할 수 없고 클래스 내부와 서브 클래스에서만 접근이 가능하다. 따라서 클래스 외부에 영향을 미치지 않고 메서드를 수정할 수 있다. 다시 말해 클래스의 내부 행동을 캡슐화하고 있는 것이다.

  • 객체 캡슐화 : Movie 클래스는 DiscountPolicy 타입의 인스턴스 변수 discountPolicy를 포함한다. 이 인스턴스 변수는 private 가시성을 가지기 때문에 Movie와 DisvountPolicy 사이의 관계를 변경 하더라도 외부에는 영향을 미치지 않는다. 다시 말해서 객체와 객체 사이의 관계를 캡슐화한다. 눈치가 빠른 사람이라면 객체 캡슐화가 합성을 의미한다는 것을 눈치챘을 것이다.

  • 서브타입 캡슐화 : MovieDiscountPolicy에 대해서는 알고 있지만 AmountDiscountPolicyPercentDiscountPolicy에 대해서는 알지 못한다. 그러나 실제로 실행 시점에는 이 클래스들의 인스턴스와 협력할 수 있다. 이것은 파생 클래스인 DiscountPolicy와의 추상적인 관계가 AmountDiscountPolicyPercentDiscountPolicy의 존재를 감추고 있기 때문이다. 다시 말해 서브타입의 종류를 캡슐화하고 있는 것이다. 눈치가 빠른 사람이라면 서브타입 캡슐화가 다형성의 기반이 된다는 것을 알 수 있을 것이다.

구체적인 협력 구현하기

유사한 기능에 대해 유사한 협력 패턴을 적용하는 것은 객체지향 시스템에서 개념적 무결성(Conceptual Integrity)을 유지할 수 있는 가장 효과적인 방법이다. 시스템이 일관성 있는 몇 개의 협력 패턴으로 구성된다면 시스템을 이해하고, 수정하고, 확장하는 데 필요한 노력과 시간을 아낄 수 있다.

지속적으로 개선하라

협력은 고정된 것이 아니다. 만약 현재의 협력 패턴이 변경의 무게를 지탱하기 어렵다면 변경을 수용할 수 있는 협력 패턴을 향해 과감하게 리팩터링하라. 요구 사항의 변경에 따라 협력 역시 지속적으로 개선해야 한다. 중요한 것은 현재의 설계에 맹목적으로 일관성을 맞추는 것이 아니라 달라 지는 변경의 방향에 맞춰 지속적으로 코드를 개선하려는 의지다.

Last updated