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->클래스초기 설계에는 책임과 협력의 큰 그림을 탐색하는게 중요, 역할과 객체를 명확하게 구분하는 것은 그렇게 중요하지 않다.
배우와 배역
연극: 협력
배우: 협력 안에서 역할을 수행하는 객체
극본: 코드
객체의 페르소나: 역할
역할은 모양이나 구조에 의해 정의될 수 없으며 오직 시스템의 문맥 에서만 정의될 수 있다.
배우가 여러 연극에 참여해 여러 배역을 연기할 수 있듯이, 객체는 다양한 역할 수행
- 특정한 협력 안에서는 일시적으로 오직 하나의 역할만이 보여짐
- 참여하는 특정 협력은 객체의 한 가지 역할만 바라 볼 수 있다.
배우는 연극이 끝나면 배역을 잊고 원래의 자기 자신을 되찾는다