본문 바로가기

기술 서적

[오브젝트] ch3. 역할, 책임, 협력

객체지향의 본질은 협력하는 객체들의 공동체를 만드는 것이다.

 

객체지향 설계의 핵심을 협력을 구성하기 위해 적절한 객체를 찾고

적절한 책임을 할당하는 과정에서 드러난다.

 

애플리케이션 기능에만 몰두하여, 협력,역할,책임을 고려하지 않은 채

구현에만 초점을 맞추는 것은 유연하지 못한 코드를 낳는 원인이 된다.


1. 협력

 

영화 예매 시스템 돌아보기

영화 예매 기능을 구현하기 위한 객체 간의 상호작용

 

=> 객체끼리 영화 예매라는 기능을 구현하기 위해 메시지를 주고받으며 상호작용한다

 

협력 애플리케이션 기능을 구현하기 위해 수행하는 상호작용
책임 객체가 협력에 참여하기 위해 수행하는 로직
역할 협력 안에서 수행하는 밀접한 책임의 집합

 

 

협력

- 메세지 전송 : 객체끼리 협력을 위해 사용하는 유일한 소통수단

- 메시지를 수신한 객체는 메서드를 실행해 요청에 응답 

=> 외부 객체는 메세지만을 전송 / 메세지 처리 방식은 객체가 자율적으로 결정

 

협력이 설계를 위한 문맥을 결정한다

애플리케이션의 객체가 필요하다 == 객체가 어떤 협력에 참여한다(협력에 필요한 적절한 행동을 보유한다)

=> 객체의 행동을 결정하는 것은 객체가 참여하는 협력

 

ex) Movie 객체의 [행동] 결정과정

> 협력을 고려하지 않았을 때
: 영화가 상영되는 play라는 행동을 생각

> 협력을 고려했을 때
: 예매라는 협력에 참여하고 있고 요금 계산의 책임을 짐

=> Movie 객체의 행동을 결정하는 것은 '예매를 위한 협력'

 

ex2) Movie 객체의 [상태] 결정과정

- 객체의 상태를 결정하는 것은 행동이다
- 1인당 요금을 계산할 책임(행동) =>  기본 요금인 fee와 할인 정책인 discountPolicy가 필요하겠구나!

=> Movie 객체의 상태를 결정하는 것은 "요금 계산이라는 행동"

 

상태는 객체 행동에 필요한 정보로 결정되고 / 행동은 협력에 필요한 객체가 처리할 메시지로 결정된다

=> 따라서 객체가 참여하는 협력이 객체를 구성하는 행동과 상태를 모두 결정한다


2. 책임

: 협력에 참여하기 위해 객체가 수행하는 행동

 

책임의 분류

- 책임의 관점에서 '아는 것'과 '하는 것'은 밀접하게 관련 있다

- 객체는 자신이 맡은 책임을 수행하는데 필요한 정보를 알고 있을 책임이 있다

- 객체는 자신이 할 수 없는 작업을 도와줄 객체를 알고 있을 책임이 있다

하는 것 - 객체 생성, 계산 등 스스로 하는 것
- 다른 객체의 행동을 시작시키는 것
- 다른 객체의 활동을 제어하는 것
아는 것 - 사적인 정보에 관해 아는 것
- 관련된 객체에 관해 아는 것
- 자신이 유도되거나 계산할 수 있는 것에 아는 것

 

ex) 

> Screening(상영)

- 하는 것 : 영화 예매

- 아는 것 : 자신이 상영할 영화

 

> Movie(영화)

- 하는 것 : 요금 계산

- 아는 것 : 기본요금과 할인 정책

 

책임 할당 : 정보 전문가 패턴

 

정보 전문가 패턴 
: 책임을 수행하는데 필요한 정보를 가장 잘 알고 있는 전문가에게 책임을 할당
: 정보를 안다 != 정보를 저장한다

 

 

ex) 정보 전문가 패턴을 사용한 책임 할당의 방식

 

1) 메세지 선택 : 예매

- 시스템의 전체적 기능을 책임으로 메세지 선택 => 예매하라

- 영화를 예매하라 라는 이름의 메시지로 협력 시작

2) 객체 선택 => Screening

- 예매에 필요한 정보 => 상영시간, 기본 요금

- 예매에 필요한 정보를 가장 많이 아는 객체 => Screening

 

3) 메세지 선택 : 영화가격 계산

- Screening은 영화 자체의 가격을 알 수 없음

- 새로운 메세지 : 가격을 계산하라

 

4) 객체 선택  => Movie

- 가격계산에 필요한 정보  => 영화가격 / 할인 정책

- 영화가격을 알고 있는 정보전문가  => Movie

 

 

정보전문가 패턴 결론

- 협력에 필요한 메세지 <-> 메세지에 적절한 객체선택 반복

=> 시스템을 구성하는 객체들의 인터페이스와 오퍼레이션 목록을 구성

 

책임 주도 설계(RDD)

: 책임을 찾고 책임을 수행할 적절한 객체를 찾아 책임을 할당하는 방식으로 협력 설계

 

1) 시스템 책임 파악 : 시스템이 사용자에게 제공하는 기능 파악
2) 책임 분할 : 시스템 책임을 더 작은 책임으로 분할
3) 책임 할당 : 분할된 책임을 적절한 객체/역할에 할당
4) 책임 할당 : 책임 수행 도중 다른 객체의 도움이 필요한 경우 이를 책임질 객체/역할 파악
5) 협력 구성 : 객체/역할에 책임을 할당함으로써 객체 협력 구성

=> 협력이 책임을 식별하고, 책임이 협력에 참여할 객체를 결정


책임 할당시 고려해야할 2가지

 

1. 메세지가 객체를 결정한다

- 필요한 메시지를 먼저 식별하고, 메세지를 처리할 객체를 나중에 선택

이유1. 최소한의 인터페이스 : 꼭 필요한 메시지만 식별

이유2. 추상적인 인터페이스 : how? 가 아닌 what?에 초점이 맞춰진 메세지

 

2. 행동이 상태를 결정한다

> 데이터 주도 설계 : 상태에 초점

- 캡슐화 저해

- 내부 구현이 인터페이스에 스며듬 => 내부 구현 변경 시 퍼블릭 인터페이스 변경 => 변경의 영향이 전파

 

=> 객체가 가질 수 있는 상태는 행동을 결정하고 나서야 비로소 결정가능하다



3. 역할

: 어떤 특정한 협력 안에서 수행하는 책임의 집합

 

유연하고 재사용 가능한 협력

 

- 역할은 유연하고 재사용가능한 협력을 얻을 수 있게 해준다

 

ex) 영화의 금액 할인 정책/ 기간 할인 정책의 협력을 각각 만들 때

 

금액 할인 정책 사용 시 협력 모델
기간 할인 정책 사용시 협력 모델

 

- 두 할인 정책에 대해 협력 구조가 굉장히 유사하다!

- 이는 코드 중복을 예상할 수 있으며, 코드 중복은 모든 악의 근원이다

 

=> 객체가 아닌 책임에 초점을 맞추자

- 할인 정책에게 필요한 책임 : 할인 요금을 계산하라!

- 협력 안에서 이 책임을 수행가능한 대표자를 생각할 수 있다

- 이 대표자를 협력 안에서 객체를 바꾸어 낄 수 있는 슬롯처럼 생각할 수 있다

- 이 슬롯이 바로 역할이다

 

 

=> 이제 동일책임을 수행하는 역할을 기반으로 두개의 협력을 하나로 통합가능하다

=> 중복 코드 제거가 가능하다

 

객체 대 역할

 

만약, 협력에 참여하는 객체가 오직 한 종류라면 역할을 고려하는 것이 옳을까?

A
: 협력에 참여하는 후보가 여러 객체일때 => 역할 고려
: 협력에 참여하는 후보가 오직 하나일 때 => 객체 고려

 

 

트리그비 린스카우의 협력-역할-객체-클래스의 관계

=> 협력은 상호작용 문맥에서 필요한 역할을 식별하게 해준다

=> 역할에 알맞는 객체를 선택한다

=> 객체를 클래스로 구현한다

 

그러나, 사람들은 세상을 이해할 때 무의식적으로 개념, 객체, 역할을 명확히 구분하지 못한다

 

중요한 것은 적절한 책임과 협력의 큰 그림을 탐색하는 것이다.

객체를 명확하게 구분하는 것은 그렇게 중요하지 않다

 

단순한 객체로 시작하고 반복적으로 책임/협력을 정제해가면서

필요한 순간에 객체로부터 역할을 분리하는 것이 중요하다

 

배우와 배역

 

배역을 역할로, 배우를 객체로 비유해보자

- 서로 다른 배우들이 동일한 배역을 연기할 수 있다

== 서로 다른 객체들이 동일한 역할을 수행할 수 있다

 

- 하나의 배우가 여러 배역을 연기할 수 있다

== 하나의 객체가 여러 역할을 수행할 수 있다

 

정리

- 객체는 다양한 역할을 가질 수 있다

- 객체는 협력에 참여할 때 협력 안에서 하나의 역할로 보여진다

- 객체가 다른 협력에 참여할 때는 다른 역할로 보여질 수 있다

- 협력 안에서 동일 역할을 수행하는 객체 간에는 대체가능하다

- 역할은 특정 객체 종류를 캡슐화하기 때문에 동일 역할을 수행하는 객체들은 다형적이다