객체지향의 본질은 협력하는 객체들의 공동체를 만드는 것이다.
객체지향 설계의 핵심을 협력을 구성하기 위해 적절한 객체를 찾고
적절한 책임을 할당하는 과정에서 드러난다.
애플리케이션 기능에만 몰두하여, 협력,역할,책임을 고려하지 않은 채
구현에만 초점을 맞추는 것은 유연하지 못한 코드를 낳는 원인이 된다.
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
: 협력에 참여하는 후보가 여러 객체일때 => 역할 고려
: 협력에 참여하는 후보가 오직 하나일 때 => 객체 고려
트리그비 린스카우의 협력-역할-객체-클래스의 관계
=> 협력은 상호작용 문맥에서 필요한 역할을 식별하게 해준다
=> 역할에 알맞는 객체를 선택한다
=> 객체를 클래스로 구현한다
그러나, 사람들은 세상을 이해할 때 무의식적으로 개념, 객체, 역할을 명확히 구분하지 못한다
중요한 것은 적절한 책임과 협력의 큰 그림을 탐색하는 것이다.
객체를 명확하게 구분하는 것은 그렇게 중요하지 않다
단순한 객체로 시작하고 반복적으로 책임/협력을 정제해가면서
필요한 순간에 객체로부터 역할을 분리하는 것이 중요하다
배우와 배역
배역을 역할로, 배우를 객체로 비유해보자
- 서로 다른 배우들이 동일한 배역을 연기할 수 있다
== 서로 다른 객체들이 동일한 역할을 수행할 수 있다
- 하나의 배우가 여러 배역을 연기할 수 있다
== 하나의 객체가 여러 역할을 수행할 수 있다
정리
- 객체는 다양한 역할을 가질 수 있다
- 객체는 협력에 참여할 때 협력 안에서 하나의 역할로 보여진다
- 객체가 다른 협력에 참여할 때는 다른 역할로 보여질 수 있다
- 협력 안에서 동일 역할을 수행하는 객체 간에는 대체가능하다
- 역할은 특정 객체 종류를 캡슐화하기 때문에 동일 역할을 수행하는 객체들은 다형적이다
'기술 서적' 카테고리의 다른 글
[오브젝트] ch5. 책임 할당하기 (0) | 2024.04.13 |
---|---|
[오브젝트] ch4. 설계 품질과 트레이드 오프 / 데이터 중심 설계의 문제점 (0) | 2024.04.11 |
[오브젝트] ch2. 객체지향 프로그래밍 (0) | 2024.04.09 |
[오브젝트] ch1. 객체, 설계 (0) | 2024.04.07 |
[스터디] 이펙티브 자바 - item4. 인스턴스화를 막으려거든 private 생성자를 사용하라 (0) | 2024.03.12 |