오브젝트 chapter14

일관성 있는 협력

객체지향 설계의 목표는 적절한 책임을 수행하는 객체들의 협력을 기반으로 결합도가 낮고 재사용 가능한 코드 구조를 창조하는 것이다.

객체지향 패러다임의 장점은 설계를 재사용할 수 있다는 것이다. 재사용을 위해서는 객체들의 협력 방식을 일관성 있게 만들어야 한다. 일관성은 설계에 드는 비용을 감소시킨다. 일관성 있는 설꼐가 가져다 주는 더 큰 이익은 코드가 이해하기 쉬워진다는 것이다.

가능하면 유사한 기능을 구현하기 위해 유사한 협력 패턴을 사용하라.

설계에 일관성 부여하기

일관성 있는 설계를 만드는 데 가장 훌륭한 방법은 다양한 설계 경험을 익히는 것이다. 설계 경험이 풍부할수록 어떤 위치에서 일관성을 보장해야하고 일관성을 제고하기 위해 어떤 방법을 사용해야 하는지 직관적으로 결정할 수 있다.

두번째 방법은 널리 알려진 디자인 패턴을 학습하고 변경이라는 문맥 안에서 디자인 패턴을 적용해 보는 것이다.

협력을 일관성 있게 만들기 위해서는 변하는 개념을 변하지 않는 개념으로부터 분리, 변하는 개념을 캡슐화하는 것이 기본 원칙이다.

바뀌는 부분을 따로 뽑아서 캡슐화한다. 그렇게 하면 나중에 바뀌지 않는 부분에는 영향을 미치지 않은 채로 그 부분만 고치거나 확장할 수 있다.

클래스를 분리하기 위한 가장 중요한 기준은 변경의 이유와 주기다. 클래스는 명확히 단 하나의 이유에 의해서만 변경돼야 하고 클래스 안의 모든 코드는 함께 변경돼야 한다. 단일 책임 원칙을 따르도록 클래스를 분리해야 한다.

일관성 있는 협력을 위한 지침

  1. 변하는 개념을 변하지 않는 개념으로부터 분리하라.
  2. 변하는 개념을 캡슐화하라.

핵심은 훌륭한 추상화를 찾아 추상화에 의존하도록 만드는 것이다. 추상화에 대한 의존은 결합도를 낮추고 결과적으로 대체 가능한 역할로 구성된 협력을 설계할 수 있게 해준다. 추상화의 품질이 캡슐화의 품질을 결정한다.

캡슐화 다시 살펴보기

캡슐화란 변하는 어떤 것이든 감추는 것이다.

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

  • 데이터 캡슐화: 내부에 관리하는 데이터를 캡슐화
  • 메서드 캡슐화: 클래스 외부에서는 이 메서드에 직접 접근할 수 없고 클래스 내부와 서브 클래스에서만 접근이 가능. 클래스 외부에 영향을 미치지 않고 메서드를 수정할 수 있다. 클래스의 내부 활동을 캡슐화

  • 객체 캡슐화: 객체와 객체 사이의 관계를 캡슐화한다. 합성을 의미
  • 서브타입 캡슐화: 다형성의 기반이 됨

코드 수정으로 인한 파급효과를 제어할 수 있는 모든 기법이 캡슐화의 일종.

변경을 캡슐화할 수 있는 다양한 방법이 존재하지만 협력을 일관성 있게 만들기 위해 가장 일반적으로 사용하는 방법은 서브타입 캡슐화와 객체 캡슐화를 조합하는 것이다.

  • 서브타입 캡슐화: 인터페이스 상속을 사용
  • 객체 캡슐화: 합성 사용

변하는 부분을 분리해서 타입 계층을 만든다

  1. 변하지 않는 부분으로부터 변하는 부분을 분리한다.
  2. 변하는 부분들의 공통적인 행동을 추상 클래스나 인터페이스로 추상화한 후 변하는 부분들이 이 추상 클래스나 인터페이스를 상속받게 만든다.
  3. 변하는 부분은 변하지 않는 부분의 서브타입이 된다.

변하지 않는 부분의 일부로 타입 계층을 합성한다

  1. 앞에서 구현한 타입 계층을 변하지 않는 부분에 합성
  2. 변경되는 구체적인 사항에 결합돼서는 안됨. 의존성 주입과 같이 결합도를 느슨하게 유지할 수 있는 방법을 이용해 오직 추상화에만 의존하게 만든다.

일관성 있는 기본 정책 구현하기

변경 분리하기

일관성 있는 협력을 만들기 위한 첫번째 단계는 변하는 개념과 변하지 않는 개념을 분리하는 것이다.

변경 캡슐화하기

협력을 일관성 있게 만들기 위해서는 변경을 캡슐화해서 파급효과를 줄여야 한다. 변경을 캡슐화하는 가장 좋은 방법은 변하지 않는 부분으로부터 변하는 부분을 분리하는 것이다. 변하지 않는 부분이 오직 추상화에만 의존하도록 관계를 제한하면 변경을 캡슐화할 수 있게 된다.

협력 패턴 설계하기

변하는 부분과 변하지 않는 부분을 분리하고, 변하는 부분을 적절히 추상화하고 나면 변하는 부분을 생략한 채 변지 않는 부분만을 이용해 객체 사이의 협력을 이야기할 수 있다.

추상화 수준에서 협력 패턴 구현하기

변하는 것과 변하지 않는 것을 분리하고 변하는 것을 캡슐화한 코드는 오로지 변하지 않는 것과 추상화에 대한 의존성만으로도 전체적인 협력을 구현할 수 있다. 변하는 것은 추상화 뒤에 캡슐화되어 숨겨져 있기 때문에 전체적인 협력의 구조에 영향을 미치지 않는다.

구체적인 협력 구현하기

유사한 기능을 서로 다른 방식으로 구현하면 협력의 일관성을 유지하기 어렵기 때문에 이해하고 유지보수하기 어려운 코드가 만들어질 수밖에 없다.

변하는 부분을 변하지 않는 부분으로부터 분리하면 변하지 않는 부분을 재사용할 수 있다. 새로운 기능을 추가하기 위해 오직 변하는 부분만 구현하면 되기 때문에 원하는 기능을 쉽게 완성할 수 있다.

일관성 있는 협력은 개발자에게 확장 포인트를 강제하기 때문에 정해진 구조를 우회하기 어렵게 만든다. 코드의 형태로 주어진 제약 안에 머물러야 하지만 작은 문제에 집중할 수 있는 자유를 얻는다. 작은 문제에 대한 해결책을 전체 문맥에 연결함으로써 협력을 확장하고 구체화할 수 있다.

일관성 있는 협력을 이해하고 나면 변하는 부분만 따로 떼어내어 독립적으로 이해하더라도 전체적인 구조를 쉽게 이해할 수 있다. 유사한 기능에 대해 유사한 협력 패턴을 적용하는 것은 객체지향 시스템에서 개념적 무결성을 유지할 수 있는 가장 효과적인 방법이다.

지속적으로 개선하라

새로운 요구사항이 추가되는 과정에서 일관성의 벽에 조금씩 금이 가는 경우를 자주 보게 된다. 새로운 요구사항을 수용할 수 있는 협력 패턴을 향해 설계를 진화시킬 수 있는 좋은 신호로 받아들여야 한다. 현재의 협력 패턴이 변경의 무게를 지탱하기 어렵다면 변경을 수용할 수 있는 협력 패턴을 향해 과감하게 리팩터링하라. 요구사항의 변경에 따라 협력 역시 지속적으로 개선해야 한다. 달라지는 변경의 방향에 맞춰 지속적으로 코드를 개선하려는 의지가 중요하다.

패턴을 찾아라

일관성 있는 협력의 핵심은 변경을 분리하고 캡슐화하는 것이다.

유사한 기능에 대한 변경이 지속적으로 발생하고 있다면 변경을 캡슐화할 수 있는 적정한 추상화를 찾은 후, 이 추상화에 변하지 않는 공통적인 책임을 할당하라. 현재의 구조가 변경을 캡슐화하기에 적합하지 않다면 코드를 수정하지 않고도 원하는 변경을 수용할 수 있도록 협력과 코드를 리팩터링하라.

협력을 일관성 있게 만든다는 것은 유사한 변경을 수용할 수 있는 협력 패턴을 발견하는 것과 동일하다.

results matching ""

    No results matching ""