3. 역할, 책임, 협력
- 협력: 객체들이 에플리케이션의 기능을 구현하기 위해 수행하는 상호작용
- 책임: 객체가 협력에 참여하기 위해 수행하는 로직
- 객체들이 협력 안에서 수행하는 책임들이 모여 객체가 수행하는 역할을 구성한다.
협력
메시지 전송(message sending) 은 협력을 위해 사용할 수 있는 유일한 커뮤니케이션 수단
객체가 스스로 메시지를 처리할 방법(메서드)을 자율적으로 선택
자율적인 객체가 되기 위해서는 자신이 할 수 없는 일을 다른 객체에게 위임하면 협력에서 전체적인 자율성이 향상
- 가장 기본적인 방법은 캡슐화 이다.
협력이 설계를 위한 문맥을 결정한다
객체의 행동을 결정하는 것은 객체가 참여하고 있는 협력이다.
협력은 객체가 필요한 이유와 객체가 수행하는 행동의 동기를 제공한다.
Movie
의 행동을 결정하는 것은 영화 예매를 위한 협력이다.- 협력이라는 문맥을 고려하지 않고 Moive의 행동을 결정하는 것은 아무런 의미가 없다.
상태는 객체가 행동하는 데 필요한 정보에 의해 결정되고 행동은 협력 안에서 객체가 처리할 메시지로 결정 된다.
객체가 참여하는 협력이 객체를 구성하는 상태와 행동 모두를 결정한다.
- 협력은 설계에 필요한 context(문맥) 을 제공한다.
책임
- 책임이란 객체에 의해 정의되는 응집도 있는 행위의 집합
- 객체의 책임은 ‘무엇을 알고 있는가(knowing)’, ‘무엇을 할 수 있는가(doing)’ 으로 구성 된다.
- 두 개는 밀접하게 연관되어 있다.
- 객체는 책임을 수행하는 데 필요한 정보를 알고 있을 책임
- 할 수 없는 작업을 도와줄 객체를 알고 있을 책임
- 그 책임을 수행하는 데 필요한 정보도 알아야할 책임
- 책임은 메시지 보다 추상적이면서 개념적으로 더 크다.
- 책임은 객체지향 설계의 핵심, 책임을 능숙하게 소프트웨어 객체에게 할당하는 것은 매우 중요하다.
- 객체의 구현 방법은 책임보다 상대적으로 덜 중요하고 책임 이후에 고민해도 늦지 않다.
책임 할당
자율적인 객체를 만드는 가장 기본적인 방법은 책임을 수행하는 데 필요한 정보를 잘 알고 있는 전문가에게 그 책임을 할당하는 것
- 정보 전문가 패턴(Information Expert) 이라 한다.
객체에게 책임을 할당하기 위해서는 협력이라는 문맥을 정의해야 한다.
협력을 설계하는 출발점은 시스템이 사용자에게 제공하는 기능을 시스템이 담당할 하나의 책임으로 바라보는 것
- 객체지향 설계는 필요한 더 작은 책임을 찾아내고,이를 객체들에게 할당하는 반복적인 과정
객체가 책임을 수행하게 하는 유일한 방법은 메시지 전송 이므로, 책임을 할당한다는 것은 메시지의 이름을 결정하는 것과 같다.
- 이렇게 결정된 메시지가 객체의 퍼블릭 인터페이스를 구성한다.
협력을 설계하면서 객체의 책임을 식별해 나가는 과정에서 최종적으로 얻게 되는 결과물은 시스템을 구성하는 객체들의 인터페이스와 오퍼레이션 목록이다.
책임 주도 설계(RDD): 책임을 찾고 책임을 수행할 적절한 객체를 찾아 할당하는 방식으로 협력을 설계하는 방법
- 시스템이 사용자에게 제공해야 하는 기능인 시스템 책임을 파악
- 시스템 채김을 더 작은 책임으로 분할
- 분할된 책임을 수행할 수 있는 적절한 객체 or 역할을 찾아 책임 할당
- 책임을 수행하는 도중 다른 객체의 도움이 필요한 경우 이를 책임질 적잘한 객체 또는 역할을 찾음
- 객체 or 역할에게 책임을 할당함으로써 두 객체가 협력하게 함
메시지가 객체를 결정한다
객체가 메시지를 결정하는 것이 아니라, 메시지가 객체를 선택하게 했다
- 객체가 최소한의 인터페이스를 가질 수 있게 된다.
- 객체는 충분히 추상적인 인터페이스를 가질 수 있게 된다.
- 인터페이스는 what(무엇)을 하는 지 표현해야 하지만, how(어떻게) 수행하는지는 노출하면 안 된다.
메시지(
예매하라
)를 선텍하는 것으로 설계를 시작 그리고, 그 메시지를 수신할 객체를 선택(Screening
)
행동이 상태를 결정한다
객체의 행동은 객체가 협력에 참여할 수 있는 유일한 방법
- 협력에 얼마나 적합한지 결정하는 것은 상태(데이터) 가 아니라 행동이다.
객체의 내부 구현에 초점을 맞춘 설계 방법은 데이터-주도 설계(Data-Driven Design) 이라 한다.
상태는 단지 객체가 행동을 정상적으로 수행하기 위해 필요한 재료일 뿐이다.
역할
객체는 협력이라는 문맥 안에서 특정한 목적을 갖게 된다.
- 목적은 협력 안에서 객체가 맡게 되는 책임의 집합(=역할) 으로 표시
역할은 다른 것으로 교체할 수 있는 책임의 집합이다.
역할은 구체적인 객체를 포괄하는 추상화 이다.
- 추상적인 이름을 부여해야 한다. (Ex.
DiscountPolicy
)
- 추상적인 이름을 부여해야 한다. (Ex.
책임을 수행하는 역할을 기반으로 두 개의 협력을 하나로 통합할 수 있다.
- 역할을 이용하면 불필요한 중복 코드를 제거할 수 있다.
- ‘새로운 할인 정책을 추가하기 위해 새로운 협력을 추가할 필요가 없어짐’
역할을 구현하는 가장 일반적인 방법은 추상 클래스와 인터페이스를 사용하는 것
- 추상 클래스는 책임의 일부를 구현해 놓은것
- 인터페이스는 구현 없이 책임의 집합만을 나열
역할이 다양한 종류의 객체를 수용할 수 있는 슬롯이자 구체적인 객체들의 타입을 캡슐화하는 추상화 이다.
- 협력 안에서 역할이 어떤 책임을 수행해야 하는지 결정하는 것이 중요
객체 대 역할
협력에 참여하는 후보가 여러 종류의 객체에 의해 수행될 필요가 있다면 그 후보는 역할
단지 한 종류의 객체만이 협력에 참여할 필요가 있다면 후보는 객체
역할은 서로 다른 방법으로 실행할 수 있는 책임의 집합
역할을 객체들에 대한 별칭이라고 정의하기도 한다.
- 객체는 클래스를 이용해 구현되고 생성
협력 -
reference->
역할-select from->
객체-instance of->
클래스초기 설계에는 책임과 협력의 큰 그림을 탐색하는게 중요, 역할과 객체를 명확하게 구분하는 것은 그렇게 중요하지 않다.
배우와 배역
연극: 협력
배우: 협력 안에서 역할을 수행하는 객체
극본: 코드
객체의 페르소나: 역할
역할은 모양이나 구조에 의해 정의될 수 없으며 오직 시스템의 문맥 에서만 정의될 수 있다.
배우가 여러 연극에 참여해 여러 배역을 연기할 수 있듯이, 객체는 다양한 역할 수행
- 특정한 협력 안에서는 일시적으로 오직 하나의 역할만이 보여짐
- 참여하는 특정 협력은 객체의 한 가지 역할만 바라 볼 수 있다.
배우는 연극이 끝나면 배역을 잊고 원래의 자기 자신을 되찾는다