오브젝트; GRASP와 책임 할당하기

🗓️

  • 데이터를 먼저 결정하고 고립된 객체의 상태에 초점을 맞추면 캡슐화를 위반하기 쉽고, 요소들 사이의 결합도가 높아지며, 코드를 변경하기 어려워진다.
  • 책임에 초점을 맞춰서 설계할 때 어떤 객체에게 어떤 책임을 할당할지를 결정 하는 것이 어렵다.
  • 책임 할당 과정은 트레이드오프 활동이다.

책임 주도 설계를 향해

데이터 중심의 설계에서 책임 중심의 설계로 전환하는 방법

데이터보다 행동을 먼저 결정하라

  • 클라이언트 관점에서 객체가 수행하는 행동이란 곧 객체의 책임을 의미한다.
  • 객체는 협력에 참여하기 위해 존재하며 협렵 안에서 수행하는 책임이 객체의 존재가치를 증명한다.
  • 너무 이른시기에 데이터에 초점을 맞추면 객체의 캡슐화가 약화되기 때문에 낮은 응집도와 높은 결합도를 가진 객체들로 넘쳐나게 된다. 그 결과로 얻게 되는 것은 변경에 취약한 설계다.

데이터 중심의 설계에서는 “이 객체가 포함해야 하는 데이터가 무엇인가”를 결정한 후에 “데이터를 처리하는데 필요한 오퍼레이션은 무엇인가”를 결정한다.” 반면 책임 중심의 설계에서는 “이 객체가 수행하야 하는 책임은 무엇인가”를 결정한 후에 “이 책임을 수행하는데 필요한 데이터는 무엇인가”를 결정한다. 다시 말해 책임 중심의 설계에서는 객체의 행동, 즉 책임을 먼저 결정한 후에 객체의 상태를 결정한다는 것이다.

협력이라는 문맥 안에서 책임을 결정하라

  • 객체에게 할당된 책임이 협력에 어울리지 않는다면 그 책임은 나쁜 것이다.
  • 객체의 입장에서는 책임이 조금 어색해 보이더라도 협력에 적합하다면 그 책임은 좋은 것이다.
  • 책임은 객체의 입장이 아니라 객체가 참여하는 협력에 적합해야 한다.
  • 협력에 적합한 책임을 수확하기 위해서는 객체를 결정한 후에 메시지를 선택하는 것이 아니라 메시지를 결정한 후에 객체를 선택해야 한다. 메시지가 존재하기 때문에 그 메시지를 처리할 객체가 필요한 것이다.
  • 객체가 메시지를 선택하는 것이 아니라 메시지가 객체를 선택해야 한다.

객체에게 적절한 책임을 할당하기 위해서는 협력이라는 문맥을 고려해야 한다. 협력이라는 문맥에서 적절한 책임이란 곧 클라이언트의 관점에서 적절한 책임을 의미한다. 문맥 안에서 메시지에 집중하는 책임 중심 설계는 캡슐화의 원리를 지키기가 훨씬 쉬워진다. 책입 중심의 설계가 응집도가 높고 결합도가 낮으며 변경하기 쉽다고 말하는 이유가 여기 있다.

책임 주도 설계

  • 시스템이 사용자에게 제공해야 하는 기능인 시스템 책임을 파악한다.
  • 시스템 책임을 더 작은 책임으로 분할한다.
  • 분할된 책임을 수행할 수 있는 적절한 객체 똔느 역할을 찾아 책임을 할단한다.
  • 객체가 책임을 수행하는 도중 다른 객체의 도움이 필요한 경우 이를 책임질 적절한 객체 또는 역할을 찾는다.
  • 해당 객체 또는 역할에게 책임을 할당함으로써 두 객체가 협력하게 한다.

협력에 참여하는 객체들의 책임이 어느정도 정리될 때까지는 객체의 내부 상태에 대해 관심을 가지지 않는 것이다.

책임 할당을 위한 GRASP 패턴

GRASP; General Responsibility Assignment Software Pattern

  • INFORMATION EXPERT 패턴
  • LOW COUPLING 패턴
  • HIGH COHESION 패턴
  • CREATOR 패턴
  • PROTECTED VARIATIONS 패턴
  • POLYMORPHISM 패턴

도메인 개념에서 출발하기

  • 설계를 시작하는 단계에서는 개념들의 의미와 관계가 정확하거나 완벽할 필요가 없다.
  • 이 단계에서는 책임을 할당받을 객체들의 종류와 관계에 대한 유용한 정보를 제공할 수 있다면 충분하다.
  • 도메인 개념을 정리하는데 너무 많은 시간을 들이지 말고 빠르게 설계와 구현을 진행하라.
올바른 도메인 모델이란 존재하지 않는다

많은 사람들이 도메인 모델은 구현과는 무관하다고 생각하지만 이것은 도메인 모델의 개념을 오해한 것에 불과하다. 도메인 모델은 개념적으로 표현한 것이지만 그 안에 포함된 개념과 관계는 구현의 기반이 되어야 한다. 이것은 도메인 모델이 구현을 염두해 두고 구조화되는 것이 바람직하다는 것을 의미한다. 반대로 코드의 구조가 도메인을 바라보는 관점을 바꾸기도 한다.
올바른 도메인 모델이란 존재하지 않는다. 필요한 것은 도메인을 그대로 두고 투영한 모델이 아니라 구현에 도움이 되는 모델이다. 다시 말해서 실용적이면서도 유용한 모델이 답이다.

정보 전문가에게 책임을 할당하라

메시지는 메시지를 수신할 객체가 아니라 메시지를 전송할 객체의 의도를 반영해서 결정해야 한다. 따라서 첫번째 질문은 다음과 같다.

  1. 메시지를 전송할 객체는 무엇을 원하는가.

메시지를 결정 했으면 메시지에 적합한 객체를 선택해야 한다. 두번째 질문은 다음과 같다

  1. 메시지를 수신할 적합한 객체는 누구인가?
  • 객체는 상태와 행동을 통합한 캡슐화의 단위다.
  • 객체는 자신의 상태를 스스로 처리하는 자율적인 존재여야 한다
  • 객체의 책임과 책임을 수행하는 데 필요한 상태는 동일한 객체 안에 존재해야 한다.
  • 책임을 수행할 정보를 알고있는 객체에게 책임을 할당하는 것이다.
INFORMATION EXPERT 패턴

책임을 객체에 할당하는 일반적인 원리는 책임 수행하는데 필요한 정보를 가지고 있는 객체에 할당하는 것이다.
INFORMATION EXPERT 패턴은 객체가 자율적인 존재여야 한다는 사실을 다시 한번 상기시킨다. 정보를 알고있는 객체만이 책임을 어떻게 수행할 지 스스로 결정할 수 있기 때문이다. INFORMATION EXPERT 패턴을 따르면 정보와 행동을 최대한 가까운 곳에 위치시키기 때문에 캡슐화를 유지할 수 있다. 필요한 정보를 가진 객체들로 책임이 분산되기 때문에 더 응집력 있고 이해하기 쉬워진다. 따라서 높은 응집도가 가능하다. 결과적으로 결합도가 낮아져서 간결하고 유지보수하기 쉬운 시스템을 구축할 수 있다.

  • INFORMATION EXPERT 패턴은 결국 객체가 자신이 소유하고 있는 정보와 관련된 작업을 수행한다는 일반적인 직관을 표현한 것이다. 여기서 정보는 데이터와 다르다. 정보를 알고 있다고 해서 정보를 저장하고 있을 필요는 없다는 뜻.

높은 응집도와 낮은 결합도

  • 설계는 항상 트레이드오프를 동반한다. 설계를 진행하다 보면 몇 가지 설계 중 한 가지를 선택해야 하는 경우가 빈번하게 발생한다.
  • 책임을 할당할 수 있는 다양한 대안들이 존재한다면 응집도와 결합도의 측면에서 더 나은 대안을 선택하는 것이 좋다.
LOW COUPLING 패턴

어떻게 하면 의존성을 낮추고 변화의 영향을 줄이며 재사용성을 증가시킬 수 있을까? 설계의 전체적인 결합도가 낮게 유지되도록 책임을 할당하라.
낮은 결합도는 모든 설계 결정에서 염두에 둬야 하는 원리다. 다시 말해 설계 결정을 평가할 때 적용할 수 있는 평가원리다. 현재의 책임 할당을 검토하거나 여러 설계 대안들이 있을 때 낮은 결합도를 유지할 수 있는 설계를 선택하라.

HIGH COHESION 패턴

어떻게 복잡성을 관리할 수 있는 수준으로 유지할 것인가? 높은 응집도를 유지할 수 있게 책임을 할당하라.
낮은 결합도 처럼 높은 응집도 역시 모든 설계 결정에서 염두에 둬야 할 원리다. 다시 말해 설계 결정을 평가할 때 적용할 수 있는 평가원리다. 현재의 책임 할당을 검토하고 있거나 여러 설계 대안 중 하나를 선택해야 한다면 높은 응집도를 유지할 수 있는 설계를 선택하라.

창조자에게 객체 생성 책임을 할당하라

CREATOR 패턴

어떤 객체 A를 생성할 때 아래 조건을 최대한 많이 만족하는 객체 B에게 객체 생성 책임을 할당하라.

  • B가 A 객체를 포함하거나 참조한다.
  • B가 A 객체를 기록한다.
  • B가 A 객체를 긴밀하게 사용한다.
  • B가 A 객체를 초기화하는 데 필요한 데이터를 가지고 있다. (이 경우 B 는 A에 대한 정보 전문가다)