011. (Objects) 4. 설계 품질과 트레이드오프

4. 설계 품질과 트레이드오프

거듭 강조하지만 객체지향 설계의 핵심은 역할, 책임, 협력이다.

협력은 애플리케이션의 기능을 구현하기 위해 메시지를 주고받는 객체들 사이의 상호작용이며,

책임은 객체가 다른 객체와 협력하기 위해 수행하는 행동이고,

역할은 대체 가능한 책임의 집합이다.

참고 001. (The Essence of Object-Orientation) 1. 협력과 역할 그리고 책임

객체지향 설계란 올바른 객체에게 올바른 책임을 할당하면서 낮은 결합도와 높은 응집도를 가진 구조를 창조하는 활동이다.

이 정의에는 객체지향 설계에 핵심은 책임이라는 것과 책임을 할당하는 작업이 응집도와 결합도 같은 설계 품질과 깊이 연관되어있음이 내포되어있다.

설계는 변경을 위해 존재하고 변경에는 어떤 식으로든 비용이 발생한다.

따라서 훌륭한 설계란 합리적인 비용 안에서 변경을 수용할 수 있는 구조를 만드는 것이다.

그렇다면 결합도와 응집도를 합리적인 수준으로 유지하려면 어떻게 해야할까?

바로 객체의 상태가 아니라 객체의 행동에 초점을 맞추는 것이다.

객체를 단순한 데이터의 집합으로 바라보는 시각은 객체의 내부 구현을 공개된 인터페이스에 노출시키는 결과를 낳기 때문이다.

따라서 객체의 책임을 초점을 맞추어 책임은 객체의 상태에서 행동으로, 나아가 객체와 객체 사이의 상호작용으로 설계 중심을 이동시켜야 한다.

이는 결과적으로 결합도가 낮고 응집도가 높으며 캡슐화를 잘 한 객체들을 창조할 수 있게 해준다.

이번 포스팅에서는 상태를 표현하는 데이터 중심의 설계를 살펴보고 객체지향적으로 설계한 구조와 어떤 차이점이 있는지 살펴본다.

1.1. 데이터 중심의 설계

데이터 중심의 관점에서 객체는 자신이 포함하고 있는 데이터를 조작하는 데 필요한 오퍼레이션을 정의한다.

객체의 상태를 구현에 속하며, 구현은 불안정하고 변동성이 크다.

즉, 상태를 객체 분할의 중심으로 삼으면 구현에 관한 세부사항이 객체의 인터페이스에 노출되어 캡슐화가 깨지게 된다.

데이터 중심의 설계를 위해 객체가 내부에 저장해야하는 데이터가 무엇인지를 고민해보자.

필요한 데이터가 주어졌다면 캡슐화를 위해 Getter/Setter 등을 작성하여 접근자와 수정자를 제공해야할 것이다.

1.2. 설계 트레이드오프

캡슐화
상태와 행동을 하나의 객체안에 모으는 이유는 객체의 내부 구현을 외부로부터 감추기 위해서다.

여기서 구현이랑 변동성이 높은 부분을 의미하며, 반대로 안정성이 높은 부분은 인터페이스라고 볼 수 있다.

객체지향의 장점 중 하나는 객체의 수정이 시스템 전체에 미치는 영향도를 조절할 수 있기 때문이며,

적절한 캡슐화를 통해 영향도를 조절할 수 있다.

따라서 변경의 관점에서 캡슐화는 설계의 품질을 판단하기 위한 기준이 될 수 있다.

응집도

응집도는 모듈에 포함된 내부 요소들이 연관되어있는 정도를 나타낸다.

모듈 내의 요소들이 하나의 목적을 위해 긴밀하게 협력한다면 그 모듈은 높은 응집도를 가진다.

객체지향의 관점에서 응집도는 객체 또는 클래스에 얼마나 관련 높은 책임들을 할당했는지를 나타낸다.

결합도

결합도는 의존성의 정도를 나타내며 다른 모듈에 대해 얼마나 많은 정보를 가지고 있는지를 나타낸다.

어떤 모듈이 다른 모듈에 대해 너무 자세한 부분까지 알고 있다면 두 모듈은 높은 결합도를, 반대로라면 낮은 결합도를 가지게 된다.

관심사의 분리(Separation of concerns)

소프트웨어를 잘 개발하기 위해 지켜야할 원칙 중 하나는 관심사의 분리(Separation of concerns) 라는 개념이다.

흔히 복잡성을 극복하기 위해 여러가지 디자인 패턴을 적용하여 View와 Controller를 분리하기 위해 애쓰는 사람들이 많은 것도 결국 프로덕트의 복잡성을 (완전히 없앨 수는 있을까?) 최소화하기 위해서이다.

따라서 설계를 적용하면서 계속 머릿속에 캐시해두어야할 개념은 CouplingCohesion 이다.

흔히들 커플링이 심하다라고 표현하긴 하는데, 굳이 한글로 번역하자면 각각, 어떠한 컴포넌트들간의 결속 과 분리된 각 모듈 내부의 응집 을 뜻한다고 볼 수 있다.

출처 How Cohesion and Coupling Correlate

위의 세 그림을 아래 개념을 뜻한다.

  • A : Low cohesion, tight coupling
  • B : High cohesion, tight coupling
  • C : High cohesion, loose coupling

결국 관심사를 잘 분리했다는 것은 개발하려는 프로덕트가 C의 구조가 되게끔 작성하는 것이다.

1.2. 책임 중심의 설계

책임 중심의 설계를 위해서는 자율적인 객체를 구현해야 한다.

특히 캡슐화는 설계의 제 1원칙으로 가져가야한다.

낮은 응집도와 높은 결합도는 결국 캡슐화를 위반했기때문에 발생한 것이기 때문이다.

따라서 객체는 스스로의 상태를 책임져야 하며 외부에서는 인터페이스를 통해서만 상태에 접근하도록 해야 한다.

우리가 상태와 행동을 하나의 단위로 묶는 이유는 객체 스스로 자신의 상태를 처리할 수 있게 하기 위해서이다.

객체는 단순히 데이터를 제공하는 것이 전부가 아니며, 객체 내부에 저장되는 데이터보다 객체가 협력에 참여하면서 수행할 책임을 정의하는 오퍼레이션이 더 중요하다.

따라서 객체를 설계할 때는 이 객체가 어떤 데이터를 포함할지와 함께 이 객체가 데이터에 대해 수행해야하는 오퍼레이션은 무엇인지도 고민해야한다.