객체지향 패러다임의 관점에서 핵심은 역할(role), 책임(responsibility), 협력(collaboration) 이다.
객체지향 설계의 핵심은 협력을 구성하기 위해 적쩔한 객체를 찾고 적절한 책임을 할당하는 과정에서 드러난다.
역할
- 객체들이 협력 안에서 수행하는 책임들이 모여 객체가 수행하는 역할을 구성. 책임
- 객체가 협력에 참여하기 위해 수행하는 로직. 협력
- 애플리케이션의 기능을 구현하기위해 수행하는 상호작용.
협력
객체들은 혼자서 존재할 수 없다. 다른 객체와의 협력을 통해 기능을 구성한다. 다른 객체와의 협력할 수 있는 유일한 수단은 메시지 전송(message sending) 뿐이다.
객체는 다른 객체의 상세한 내부 구현에 접근할 수 없기 때문에 오직 메시지 전송을 통해 자신의 요청을 전달한다.
메시지를 수신한 객체는 메시지에 응답하기 위해 알아서 실행할 메서드를 골라 수행한다.
협력은 객체를 설계하는데 필요한 일종의 문맥(context) 를 제공한다.
객체가 참여한ㄴ 협력이 객체를 구성하는 행동과 상태를 모두 결정한다.
책임
협력에 참여하기위해 객체가 수행하는 행동을 책임이라 한다. 책임은 객체에 의해 정의되는 응집도 있는 행위의 집합이다.
크게 하는 것(doing) 과 아는 것(knowing) 의 두가지로 나누어 세분화 할 수 있다 [크레이그 라만]
하는 것
- 객체를 생성하거나 계산을 수행 하는 등의 스스로 하는 것.
- 다른 객체의 행동을 시작시키는 것.
- 다른 객체의 활동을 제어하고 조절하는 것.
아는 것
- 사적인 정보에 관해 아는 것.
- 관련된 객체에 관해 아는 것.
- 자신이 유도하거나 계산할 수 있는 것에 관해 아는 것.
일반적으로 책임과 메시지의 크기는 다르다. 책임은 객체가 수행해야 할 행동을 종합적이고 더 간략하게 서술하기 때문에 더 추상적이고 개념적으로도 더 크다.
책임의 관점에서 아는 것과 하는 것이 밀접하게 연관되어있다. 어떤 책임을 수행하기 위해서는 그 책임을 수행하는데 필요한 정보도 함께 알아야 하기 때문이다.
책임 할당
INFORMATION EXPERT PATTERN (정보 전문가 패턴)
책임을 수행하는 데 필요한 정보를 가장 잘 알고 있는 전문가에게 그 책임을 할당하는 방법이다. 이는 일상상활에서 어떤 문제를 해결하기 위해 그 분야의 전문가에게 도움을 구하는 것과 같다.
그 전문가 객체는 자율적으로 자신이 가장 잘 알고있는 정보와 방법을 이용해 문제를 해결하고 메시지에 응답한다.
책임 주도 설계 (RDD - Responsibility driven design)
어떤 책임을 선택하느냐가 전체적인 설계의 방향과 흐름을 결정한다. 먼저 책임을 먼저 찾고 책임을 수행할 적절한 객체를 찾아 책임을 할당하는 방식으로 협력을 설계하는 방식이다.
- 시스템이 사용자에게 제공해야 하는 기능인 시스템 책임을 파악한다.
- 시스템 책임을 더 작은 책임으로 분할한다.
- 분할된 책임을 수행할 수 있는 적절한 객체 또는 역할을 찾아 책임을 할당한다.
- 객체가 책임을 수행하는 도중 다른 객체의 도움이 필요한 경우 이를 책임질 적절한 객체 또는 역할을 찾는다.
- 해당 객체 또는 역할에게 책임을 할당함으로써 두 객체가 협력하게 한다.
책임을 할당할 때에 고려해야 하는 두가지
- 메시지가 객체를 결정한다.
- 행동이 상태를 결정한다.
메시지가 객체를 결정한다.
메시지가 객체를 선택헤야하는 두 가지 중요한 이유.
- 객체가 최소한의 인터페이스를 가질 수 있게 된다.
필요한 메시지가 식별될 때까지 퍼블릭 인터페이스에 어떤 것도 추가하지 않기 때문에 필요한 크기의 인터페이스를 갖게 된다. - 객체는 충분히 추상적인 인터페이스를 가질 수 있게 된다.
메시지는 외부의 객체가 요청하는 무언가를 의미하기 때문에 메시지를 먼저 식별하면 무엇을 수행할지에 초점을 맞추는 인터페이스를 얻을 수 있다.
협력을 구성하는 객체들의 인터페이스는 충분히 추상적인 동시에 최소한의 크기를 유지할 수 있다.
행동이 상태를 결정한다.
객체의 행동은 협력에 참여할 수 있는 유일한 방법이다. 객체가 협력에 적합한지를 결정하는 것은 객체의 상태가 아닌 행동이다.
Data-Driven Design (데이터 주도 설계)
객체의 내부 구현에 초점을 맞춘 설계 방법으로 책임 주도 설계와는 반대로 객체 내부의 상태를 우선 생각하고 인터페이스를 구성하는 방법이다.
DDD의 문제는 내부 구현이 퍼블릭 인터페이스로 노출된다는 것에 있다. 객체 내부의 상태를 컨트롤하기 위해 getter, setter가 퍼블릭 인터페이스로 노출이되어 결국 캡슐화를 저해한다.
캡슐화를 위반하지 않도록 구현에 대한 결정을 뒤로 미루면서 객체의 행위를 고려하기 위해서는 항상 협력이라는 문맥 안에서 객체를 생성해야 한다.
상태는 단지 객체가 행동을 정상적으로 수행하기 위해 필요한 재료일 뿐이다.
역할
역할과 협력
객체가 어떤 특정한 협력 안에서 수행해야할 책임의 집합을 역할이라 한다. 협력을 모델링 할때는 특정한 객체가 아니라 역할에게 책임을 할당한다 생각하는게 좋다.
유연하고 재사용 가능한 협력
역할이 중요한 이유는 역할을 통해 유연하고 재사용 가능한 협력을 얻을 수 있기 때문이다. 객체가 아닌 책임에 초점을 맞추면 만들어야할 객체의 추상화된 개념을 알 수 있다.
이를 통해 설계단계에서 효과적으로 중복을 제거할 수 있다. 역할은 동일한 역할을 하게 될 다른 객체를 포괄하는 추상화라는 점을 주목해야한다.
객체 대 역할
역할은 객체가 참여할 수 있는 일종의 슬롯이다. 협력에 오직 한 가지의 객체만 참여한다면 역할을 고려해야 할까?
협력에 참여하는 후보가 여러 종류의 객체에 의해 수행 될 필요가 있다면 그 후보는 역할이 되지만, 단지 한 종류의 객체만이 협력에 참여할 필요가 있다면 후보는 객체가 된다.
-- 레베카 워프스브록 --
즉 협력에 적합한 대상이 한 종류라면 간단히 개게로 간주하고, 대상이 여러 종류라면 역할로 간주하면 된다.
협력은 역할들의 상호작용으로 구성되고, 협력을 구성하기 위해 역할에 적합한 객체가 선택되며, 객체는 클래스를 이용해 구현되고 생성된다. -- 트리그비 린스카우
협력(Collaboration) -- referene --> 역할(Role) -- select from --> 객체(Object) -- instance of --> 클래스(Class)
역할과 추상화
추상화는 세부 사항에 억눌리지 않고도 상위 수준의 정책을 쉽고 간단하게 표현할 수 있다. 불필요한 세부 사항을 생략하고 핵심적인 개념을 강조할 수 있다.
협력이라는 관점에서는 세부적인 사항을 무시하고 추상화에 집중하는 것이 유리하다.
또한 추상화는 설계를 유연하게 만들수 있다. 역할을 다양한 종류의 객체가 놓일 수 있는 슬롯이라 생각할 수 있다. 컴파일 타임과 런타임의 의존성을 다르게 할 수 있다. 협력안에서 동일한 책임의 다른 객체는 서로 대체될수 있다. 역할은 다양한 환경에서 다양한 객체들을 수용할 수 있게 해주므로 협력을 유연하게 만든다.