기어가더라도 제대로

3. 역할, 책임, 협력 본문

책 리뷰/오브젝트

3. 역할, 책임, 협력

Damagucci-juice 2023. 1. 4. 01:00

조영호 작가님의 전작인 작품에서 언급했던 역할, 책임, 협력에 대해서 이야기 해보는 장입니다. 

왜 이게 중요할까요? 결국 객체지향의 본질을 이해하고 설계를 잘짜기 위함이죠.

객체지향의 본질은 협력하는 객체들의 공동체를 창조하는 것이다.
객체지향 설계의 핵심은 협력을 구성하기 위해 적절한 객체를 찾고 적절한 책임을 할당하는 과정에서 드러난다.
- p.73

각각이 뭔지 살펴보죠!

  • 협력: 객체들이 애플리케이션의 기능을 구현하기 위해 수행하는 상호작용
  • 책임: 객체가 협력에 참여하기 위해 수행하는 로직
  • 역할: 객체들이 협력 안에서 수행하는 책임들이 모여 객체가 수행하는 역할을 구성

1. 협력

영화 예매 시스템에서 "예매하라" 라는 메시지를 수행하기 위해 다양한 객체들이 참여했습니다. 

여기서 볼 수 있듯이 두 객체 사이의 협력은 하나의 객체가 다른 객체에게 도움을 요청할 때 시작됩니다. 이를 메시지 전송이라고 합니다. 

메시지를 받은 객체는 직접 처리 할지 결정하고, 그게 아니면 수행에 필요한 정보를 가지고 있는 객체에게 위임해야합니다. 

이는 객체간 내부 구현을 캡슐화하는 장점도 가지고 있고, 협력 관계를 요청하는 계기를 만들기도 합니다. 

1.1객체 설계시 행동과 상태의 결정 기준 - 문맥

객체의 행동과 상태는 대략적으로 메서드와 변수로 치환할 수가 있습니다. 그렇다면 어떤 기준에서 행동과 상태를 결정할 수 있을까요? 그것을 문맥이 결정한다고 이야기합니다. 좀 더 풀어서 이야기하자면 객체의 행동을 결정하는 것은 객체가 참여하고 있는 협력이라고 할 수 있습니다. 

Movie를 예로 들어 보죠. Movie라는 객체를 떠올릴 때 일반적으로는 play라는 메서드를 들고 있을 것 같습니다.
하지만 영화 예매 시스템을 구현한다는 협력의 문맥안에서는 play 메서드보다는 요금을 계산하는 행동을 하고 있죠. 협력이라는 문맥을 고려하지 않고 Movie의 행동을 결정하는 것은 아무런 의미가 없습니다. 

객체의 행동을 결정하는 것이 협력이라면, 객체의 상태를 결정하는 것은 행동입니다. 결과적으로는 협력이 행동과 상태를 결정한다고 볼 수 있습니다. 

 

2. 책임

협력에 참여하기 위해 객체가 수행하는 행동입니다. 그렇다면 책임은 곧 메서드를 의미하는 것일까요? 꼭 그렇지는 않습니다. 메서드 보다 책임이 훨씬 추상적입니다. 

책임을 좀 더 연구해보면 "하는 것" 과 "아는 것"으로 나눌 수 있습니다. 

하는 것

  • 객체를 생성하거나 계산을 수행하는 등의 스스로 하는 것
  • 다른 객체의 행동을 시작시키는 것
  • 다른 객체의 활동을 제어하고 조절하는 것

아는 것

  • 사적인 정보에 관해 아는 것
  • 관련된 객체에 관해 아는 것
  • 자신이 유도하거나 계산할 수 있는 것에 관해 아는 것

역할과 책임에 대해서  CRC 카드를 만들어 보면 다음과 같이 만들어 볼 수 있습니다. 

위에 굵은 글씨로 쓰여있는 것은 후보자(Candidate)이고 왼쪽 열에 쓰여있는 것이 책임(아는것과 하는것)이며, 오른쪽은 그것을 처리하기에 적절한 협력자를 적어놓았습니다. 사실 협력이 중요한 이유는 객체에게 할달할 책임을 결정할 수 있는 문맥을 제공하기 때문입니다. 

2.1. 책임 할당

자율적인 객체를 만드는 가장 기본적인 방법은 책임을 수행하는 데 필요한 정보를 가장 잘 알고 있는 전문가에게 그 책임을 할당하는 것입니다. 이를 정보 전문가 패턴(Information Expert)이라고 부릅니다.

아마 영화 예매 시스템을 하나의 큰 후보자라고 생각을 해보면, 구체적이진 않지만 이 후보자에게 "예매하라" 라는 메시지로 실행할 수 있습니다. 

1. 예매하라 라는 이름의 메시지로 협력을 시작

2. 정보를 소유하고 있거나 해당 정보의 소유자를 가장 잘 알고 있는 전문가는 누구인가? Screen

3. 가격을 계산하라 라는 이름의 새로운 메시지가 필요

4. 이 정보를 가장 잘 알고 있는 전문가는 누구인가? -> Movie 

...

이런식의 반복입니다.
객체 지향 설계는 협력에 필요한 메시지를 찾고 메시지에 적절한 객체를 선택하는 반복적인 과정을 통해 이뤄집니다. 이를 단순화 하면

  • 시스템이 사용자에게 제공해야하는 기능인 시스템 책임을 파악한다.
  • 시스템 책임을 더 작은 책임으로 분할한다. -> CRC 카드 
  • 분할된 책임을 수행할 수있는 적절한 객체 또는 역할을 찾아 책임을 할당합니다.  -> 정보 전문가 패턴
  • 객체가 책임을 수행하는 도중 다른 객체의 도움이 필요한 경우 이를 책임질 적절한 객체 또는 역할을 찾습니다.  -> 정보 전문가 패턴
  • 해당 객체 또는 역할에게 책임을 할당함으로써 두 객체가 협력하게 합니다. 

2.2. 메시지가 객체를 결정한다.

여기서 가장 중요한 것은 메시지를 먼저 결정하고, 메시지를 처리할 객체를 나중에 선택했다는 것입니다. 이렇게 하면 2가지 장점이 있습니다. 

1. 객체가 최소한의 인터페이스를 가진다. 

2. 객체는 충분히 추상적인 인터페이스를 가질 수 있게 된다. (이후 역할로 세분화됨)

결국 미니멀해진다는 거니까요. 메시지를 먼저 고민해보고 어떤 객체가 이를 처리하면 좋을지 고민해야겠습니다. 

3. 역할

역할이란 객체가 특정한 협력안에서 수행하는 책임의 집합입니다. 

역할은 좀 추상적인데요. 제가 느끼기에 역할이 어려운 이유는 두개의 독립적인 단계가 책임 할당에서 합쳐져서 역할이 부각되지 않기 때문입니다. 

"예매하라"라는 메시지를 처리하기 위한 책임 할당 과정에서 

1. 영화를 예매할 수 있는 적절한 역할이 무엇인가를 찾아야합니다. 

2. 역할을 수행할 객체로 Screening 인스턴스를 선택합니다.

그림에서 보이는 역할이 설계할 때는 잘 눈에 띄지 않기에 어렵게 다가옵니다. 영화도 마찬가지로 역할을 먼저 고민하고 역할을 수행할 객체로 Movie를 선택합니다. 근데 굳이 객체가 있는데 왜 역할을 고민해야할까요?

역할이 유연하고 재사용가능한 협력을 보장하기 때문입니다. 

코드의 중복을 막기 위해 재사용은 아주 관심있게 봐야하는 부분인데요. 위의 메시지 처리 경로와 아래의 경로가 비슷합니다. 서로 하는 일도 거의 같지만,  역할이 없다면. Movie는 두 종류의 객체가 참여하는 협력을 개별적으로 만들어야합니다. 책임의 관점에서 보면 PercentDiscountPolicy와 AmountDiscountPolicy 모두 할인 요금 계산이라는 책임을 수행합니다. "할인 요금을 계산하라"라는 메시지에 응답할 수 있는 대표자를 고려한다면, 여기에 슬롯처럼 특정한 할인 정책을 갈아 끼울 수 있게 됩니다. 이 슬롯이 바로 역할이 되는 것이죠. 

그래서 설계를 하다가 일단은 구체적인 객체로 설계를 하고, 하다보니 비슷해보이는 협력이 여러 갈래로 생길 때 그 부분을 역할로 대체해주는 것이 좋습니다. 평소에 저는 Protocol Oriented Programming 이란 주제를 접할 때 모든 객체에 Protocol 을 달아주어야 하나 고민했었는데, 늘어날 가능성이 적은 객체는 그냥 객체로 쓰고, 늘어날 여지가 있는 객체의 경우 protocol 이란 역할을 생성해주어야하겠습니다. 

또 역할을 쓰다보면 설계를 추상화 할 수 있어서 협력의 흐름을 파악하는데 큰 도움이 됩니다. 

p.93 역할만 슥슥.
p.92 세부사항이 복잡

위의 그림과 아래 그림 중 확연히 흐름이 드러나는 것은 위의 그림인 것 같네요.

4. 갈무리.

3장에서는 역할, 책임, 협력이 무엇이며, 객체 지향 설계를 할 때 어떻게 활용될 수 있는지 알아보았습니다.
POP를 대할 때 조금은 편안해 질 수도 있겠네요. 

'책 리뷰 > 오브젝트' 카테고리의 다른 글

2. 객체지향 프로그래밍  (0) 2022.12.31
1. 객체, 설계  (1) 2022.11.28
Comments