메시지를 이용해서 객체끼리 통신하면서 이루어지는 활동
협력에 참여하는 객체는 자신이 아는 정보에 관한 행동은 자기가 해야 한다.(자율성)
협력이 객체에게 책임을 부여하기 위한 문맥을 제공한다.
객체의 책임은 결국 협력에 따라 달라진다.
협력은 메시지를 통해 이루어지므로 객체를 선정하기 전에 메시지를 먼저 생각하자.
메시지 => 해당 메시지를 받을 객체 => 메시지 => ....
책임 주도 설계
전체 시스템 책임(시스템의 기능) 파악이 최우선이다.
시스템 책임을 더 작은 책임으로 분할한다.
분할된 책임을 수행할 수 있는 적절한 객체 또는 역할을 찾아 책임을 할당한다.
책임 수행 중 다른 객체의 도움이 필요한 경우 이를 메시지로 만들고 이를 책임질 객체를 만든다.
이 과정을 계속한다.
협력 관계에서 객체를 갈아끼울 수 있는 슬롯이다.
위의 예제에서 DiscountPolicy가 역할이고 그 밑에 객체들로 갈아 끼울 수 있다.
역할은 책임의 추상화, 책임들의 집합이다. 다만 역할과 책임이 일대일인 경우도 많기 때문에(굳이 역할로 추상화 할 필요가 없는 경우도 많다.) 처음부터 역할을 의식하지 말자.
협력(collaboration) => 역할(role) => 객체(object) => 클래스(class)
객체에 들어갈 데이터 => 메서드 => 협력 순으로 이루어짐.
예제 코드 보면 알겠지만 정말 복잡해진다...
DiscountPolicy를 쓸려면 type을 알고 있어야 한다. 이게 캡슐화 측면에서는 DiscountPolicy에 관한 정보가 노출된 셈이고 type으로 빼면서 정책 추가나 변경시 if else문을 건들여야 한다.
핵심은 협력이란 문맥 안에 책임 결정하기(책임 주도 설계), 데이터보다 행동 먼저 결정하기다. 그러나 이는 꽤나 추상적인 조언이기에 좀더 구체적인 GRASP 패턴을 소개하도록 하겠다.
General Responsibility Assignment Software Pattern (일반적인 책임 할당을 위한 소프트웨어 패턴)
책에서는 책 내용 설명에 GRASP 패턴을 첨가하는 방식으로 진행하였다. 그래서 책 내용 기준으로 정리하되 GRASP 패턴인 부분은 따로 표시하겠다.
도메인 개념들을 이용한다면 책임 할당 과정을 시작하기 수월해질 것이다. 다만 도메인 개념을 명확히 정하려 노력할 필요는 없다. 설계를 시작하기 위해 참고하는 용도로 쓰이는게 베스트다.
Information Expert Pattern
특정 책임을 할당할 때 해당 책임에 대해 잘 아는 정보 전문가 객체에게 할당해야 한다.
책임을 할당하다 보면 여러가지 형태의 협력 네트워크가 형성될 것이다. 이들 간의 우열을 가릴 때 결합도와 응집도는 유용한 지표가 될 수 있다.
Low Coupling, High Cohesion
낮은 결합도와 높은 응집도를 가지기 위해 노력하라.
특정 클래스의 객체를 생성하기 위해서는 해당 객체와 관련된 정보를 어느정도 알고 있어야 한다. 즉 생성 또한 정보를 알아야 하는 행위이기 때문에 해당 객체에 대한 의존성이 생긴다.
Create Pattern
B 객체가 A 객체를 생성한다면...
1. B객체는 A 객체를 포함하거나 참조한다.
2. B객체가 A 객체를 기록한다.
3. B객체가 A 객체를 긴밀하게 사용한다.
4. B객체가 A에 대한 정보 전문가다.
Pure Fabrication
정보 전문가에게 책임을 할당했더니 High Cohesion, Low Coupling을 위반한다면 특정 책임을 몰아줄 인위적인 인공물 객체를 만들자. 생성과 관련된 책임을 맡는 factory object도 pure Fabrication중 하나이다.
우선 특정 객체를 분리하기 위해서는 해당 객체가 응집성이 낮다는 것을 느껴야 한다. 이를 느끼기 쉽지 않으니 코드 상으로 드러나는 특징을 잘 보도록 하자.
1) 객체 내 맴버 변수의 초기화 시점이 다르다.
2) 멤버 메서드가 멤버 변수의 일부분만 활용한다.
분리될 때 분리된 객체 각각이 협력의 특정 책임에 대응되어서 협력을 여러 개로 표현해야 한다면 이들을 역할로 묶어버리자.
Polymorphism Pattern
협력 내에서 비슷한 책임을 수행하는 객체들은 다형성을 이용해 코딩하라. 특히 코드 내에 type 변수 + if else 콜라보가 있다면 당장 분리해서 다형성을 이용하자.
Protected Variable Pattern
변화가 다른 곳으로 전이되는 곳에 인터페이스를 이용해서 감싸라
Controller
UI 입력 받아 처리하는 부분은 컨트롤러가 담당하게 하자.
Indirection
두 개의 객체 사이의 결합도를 낮추기 위해 중간 객체를 만들자.
10장 11장 요약서 제대로 배우자... 요약하자면
Movie + 할인 조건인 서브 클래스 만들기는 이해하기는 쉽지만 유연하지 못하다.
Movie에 할인 조건 객체를 맴버 변수로 가지게 하는 방법은 이해하긴 어렵지만 유연하다.
참고 사이트
GRASP 패턴 : https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=kbh3983&logNo=220778008888