책임 할당 과정은 일종의 트레이드오프 활동이다. 동일한 문제를 해결할 수 있는 다양한 책임 할당 방법이 존재하며, 어떤 방법이 최선인지는 상황과 문맥에 따라 달라진다. 따라서 올바른 책임을 할당하기 위해서는 다양한 관점에서 설계를 평가할 수 있어야 한다. (p. 133)
객체의 행동으로 무게 중심을 옮기기 위해 설계를 위한 질문의 순서를 바꾸자. "이 객체가 수행해야 하는 책임은 무엇인가"를 결정한 후에 "이 책임을 수행하는 데 필요한 데이터는 무엇인가"를 결정한다. 다시 말해 책임 중심의 설계에서는 객체의 행동, 즉 책임을 먼저 결정한 후에 객체의 상태를 결정한다는 것이다. (p. 134)
객체에게 할당된 책임의 품질은 협력에 적합한 정도로 결정된다. 객체에게 할당된 책임이 협력에 어울리지 않는다면 그 책임은 나쁜 것이다. 객체의 입장에서는 책임이 조금 어색해 보이더라도 협력에 적합하다면 그 책임은 좋은 것이다. 책임은 객체의 입장이 아니라 객체가 참여하는 협력에 적합해야 한다. (p. 135)
그러기 위해서는 메세지를 결정한 후에 객체를 선택해야 한다. 메세지가 존재하기 때문에 그 메세지를 처리할 객체가 필요한 것이다. 객체가 메세지를 선택하는 것이 아니라 메세지가 객체를 선택하게 해야 한다.
설계를 시작하기 전에 도메인에 대한 개략적인 모습을 그려 보는 것이 유용하다. 도메인 개념들을 책임 할당의 대상으로 사용하면 코드에 도메인의 모습을 투영하기가 좀 더 수월해진다. 따라서 어떤 책임을 할당해야 할 때 가정 먼저 고민해야 하는 유력한 후보는 바로 도메인 개념이다. 시작 시점에는 도메인 설계를 시작하기 위해 참고할 수 있는 개념들의 모음 정도로 간주하라. (p. 137)
올바른 도메인 모델이란 존재하지 않는다. 필요한 것은 도메인을 그대로 투영한 모델이 아니라 구현에 도움이 되는 모델이다. 다시 말해서 실용적이면서도 유용한 모델이 답이다.
객체는 자신의 상태를 스스로 처리하는 자율적인 존재여야 한다. 객체의 책임과 책임을 수행하는 데 필요한 상태는 동일한 객체 안에 존재해야 한다. 따라서 객체에게 책임을 할당하는 첫 번째 원칙은 책임을 수행할 정보를 알고 있는 객체에게 책임을 할당하는 것이다. GRASP에서는 이를 INFORMATION EXPERT 정보 전문가 패턴이라고 부른다. (p. 139)
여기서 이야기하는 정보는 데이터와 다르다는 사실에 주의하라. 책임을 수행하는 객체가 정보를 '알고'있다고 해서 그 정보를 '저장'하고 있을 필요는 없다. 정보 전문가가 데이터를 반드시 저장하고 있을 필요는 없다는 사실을 이해하는 것이 중요하다.
책임을 할당할 수 있는 다양한 대안들이 존재한다면 응집도와 결합도의 측면에서 더 나은 대안을 선택하는 것이 좋다. 다시 말해 여러 패턴 중에서 높은 응집도와 낮은 결합도를 얻을 수 있는 설계를 선택해야 한다는 것이다. GRASP에서는 이를 LOW COUPLING 낮은 결합도 패턴과 HIGH COHESION 높은 응집도 패턴이라고 부른다.
영화 예매 협력의 최종 결과물은 Reservation
인스턴스를 생성하는 것이다. 이것은 협력에 참여하는 어떤 객체에는 인스턴스를 생성할 책임을 할당해야 한다는 것을 의미한다. GRASP의 CREATOR 창조자 패턴은 이 같은 경우에 사용할 수 있는 책임 할당 패턴으로서 객체 A를 생성해야 할 때 아래 조건을 최대한 많이 만족하는 B에게 객체 생성 책임을 할당할 것을 제안한다. (p. 145)
프로그램을 if ~ else
또는 switch ~ case
등의 조건 논리를 사용해서 설계한다면 새로운 변화가 일어난 경우 조건 논리를 수정해야 한다. 이것은 프로그램을 수정하기 어렵고 변경에 취약하게 만든다. POLYMORPHISM 패턴은 객체의 타입을 검사해서 타입에 따라 여러 대안들을 수행하는 조건적인 논리를 사용하지 말라고 경고한다. 대신 다형성을 이용해 새로운 변화를 다루기 쉽게 확장하라고 권고한다. (p. 158)
코드의 구조가 바뀌면 도메인에 대한 관점도 함께 바뀐다. 도메인 모델은 단순히 도메인의 개념과 관계를 모아 놓은 것이 아니다. 도메인 모델은 구현과 밀접한 관계를 맺어야 한다. 도메인 모델은 코드에 대한 가이드를 제공할 수 있어야 하며 코드의 변화에 발맞춰 함께 변화해야 한다. 도메인 모델을 코드와 분리된 막연한 무엇으로 생각하지 않기 바란다. (p. 165)
이해하기 쉽고 수정하기 쉬운 소프트웨어로 개선하기 위해 겉으로 보이는 동작은 바꾸지 않은 채 내부 구조를 변경하는 것을 Refactoring 리팩터링이라고 부른다. (p. 166)
긴 메서드는 응집도가 낮기 때문에 이해하기도 어렵고 재사용하기도 어려우며 변경하기도 어렵다. 이런 메서드를 Monster Method 몬스터 메서드라고 부른다. 클래스의 응집도와 마찬가지로 메서드의 응집도를 높이는 이유도 변경과 관련이 깊다. 응집도 높은 메서드는 변경되는 이유가 단 하나여야 한다. 클래스가 작고, 목적이 명확한 메서드들로 구성돼 있다면 변경을 처리하기 위해 어떤 메서드를 수정해야 하는지를 쉽게 판단할 수 있다. 또한 메서드의 크기가 작고 분명하기 때문에 재사용하기도 쉽다. 작은 메서드들로 조합된 메서드는 마치 주석들을 나열한 것처럼 보이기 때문에 코드를 이해하기도 쉽다. (p. 168)
이 집 초벌잘하네