- 객체지향의 본질은 협력하는 객체들의 공동체를 창조하는 것
- 객체지향 설계의 핵심은 협력을 구성하기 위해 적절한 객체를 찾고 적절한 책임을 할당하는 과정에서 드러남
- 애플리케이션의 기능을 구현하기 위해 어떤 협력이 필요하고 협력을 위해 어떤 역할과 책임이 필요한지를 고민하지 않은 채 너무 이른 시기에 구현에 초점을 맞추는 것은 변경하기 어렵고 유연하지 못한 코드를 낳는 원인이 된다.
협력책임책임할당책임 주도 설계책임을 할당할 때 고려해야 하는 두 가지 요소메시지가 객체를 결정한다행동이 상태를 결정한다 ( 이부분 중요! 내가 자주하는 실수)역할객체 대 역할역할과 추상화배우와 배역
협력

- 다양한 객체들이 영화 예매라는 기능을 구현하기 위해 메시지를 주고받으면서 상호작용함
- 위와 같이 객체들이 애플리케이션의 기능을 구현하기 위해 수행하는 상호작용을
협력
- 객체가 협력에 참여하기 위해 수행하는 로직은
책임
- 객체들이 협력 안에서 수행하는 책임들이 모여 객체가 수행하는
역할
을 구성함
- 객체는 다른 객체의 상세한 내부 구현에 직접 접근할 수 없기 때문에 오직 메시지 전송을 통해서만 자신의 요청을 전달할 수 있음
협력이란 어떤 객체가 다른 객체에게 무엇인가를 요청하는 것. 한 객체는 어떤 것이 필요할 때 다른 객체에게 전적으로 위임하거나 서로 협력한다. 즉, 두 객체가 상호작용을 통해 더 큰 책임을 수행하는 것이다.
객체 사이의 협력을 설계할 때는 객체를 서로 분리된 인스턴스가 아닌 협력하는 파트너로 인식해야 한다.

- Screening이 Movie에게 calculateMovieFee 메시지를 전송하는 이유는, 요금을 계산하는 데 필요한 기본 요금과 할인 정책을 가장 잘 알고 있는 객체가 Movie이기 때문임
- 요금을 계산하는 작업을 Screening이 수행한다면 Movie의 인스턴스 변수인 fee와 discountPolicy에 직접 접근해야 함 ⇒ Screening이 Movie의 내부 구현에 결합됨
책임
객체지향 설계에서 가장 중요한 것은 책임이다. 객체에게 얼마나 적절한 책임을 할당하느냐가 설계의 전체적인 품질을 결정한다.
- 객체를 설계하기 위해 필요한 문맥인 협력이 갖춰졌다고 하면, 다음으로 할 일은 협력에 필요한 행동을 수행할 수 있는 적절한 객체를 찾는 것임
- 협력에 참여하기 위해 객체가 수행하는 행동을
책임
이라고 함
- 객체의 책임은 객체가 ‘무엇을 알고 있는가’ 와 ‘무엇을 할 수 있는가’로 구성된다.
- eg) Screening은 자신이 상영할 영화를 알고 있어야 함. 그리고 영화 예매할 수 있어야 함
- eg) Movie는 가격과 어떤 할인 정책이 적용됐는지 알고 있어야 함. 예매 가격을 계산할 수 있어야 함
- 일반적으로 책임과 메시지의 크기는 다르다. 책임은 객체가 수행할 수 있는 행동을 종합적이고 간략하게 서술하기 때문에 메시지보다 추상적이고 개념적으로도 더 크다. 처음에는 단순한 책임이라고 생각했던 것이 여러 개의 메시지로 분할되기도 하고 하나의 객체가 수행할 수 있다고 생각했던 책임이 나중에는 여러 객체들이 협력해야만 하는 커다란 책임으로 자라는 것이 일반적임
책임할당
- 자율적인 객체를 만드는 가장 기본적인 방법은 책임을 수행하는 데 필요한 정보를 가장 잘 알고 있는 전문가에게 그 책임을 할당하는 것임 ( INFORMATION EXPERT (정보 전문가 패턴) )
- 객체지향 설계는 시스템의 책임을 완료하는 데 필요한 더 작은 책임을 찾아내고 이를 객체들에게 할당하는 반복적인 과정을 통해 모양을 갖춰간다.
- 협력을 설계하면서 객체의 책임을 식별해 나가는 과정에서 최종적으로 얻게 되는 결과물은 시스템을 구성하는 객체들의 인터페이스와 오퍼레이션의 목록이다.
책임 주도 설계
- 시스템이 사용자에게 제공해야 하는 기능인 시스템 책임을 파악
- 시스템 책임을 더 작은 책임으로 분할
- 분할된 책임을 수행할 수 있는 적절한 객체 또는 역할을 찾아 책임을 할당
- 객체가 책임을 수행하는 도중 다른 객체의 도움이 필요한 경우 이를 책임질 적절한 객체 또는 역할을 찾는다.
- 해당 객체 또는 역할에게 책임을 할당 함으로써 두 객체가 협력하게 한다.
- 책임 주도 설계는 자연스럽게 객체의 구현이 아닌 책임에 집중할 수 있게 하고, 그로 인해 유연하고 견고한 객체 지향 시스템을 만들 수 있게 해준다.
책임을 할당할 때 고려해야 하는 두 가지 요소
메시지가 객체를 결정한다
- 객체에게 책임을 할당하는데 필요한 메시지를 먼저 식별하고 메시지를 처리할 객체를 나중에 선택했다는 것이 중요
- 메시지가 객체를 선택하게 해야 하는 두 가지 중요한 이유
- 객체가 최소한의 인터페이스를 가질 수 있음
- 객체는 충분히 추상적인 인터페이스를 가질 수 있음
- 영화 예매 시스템의 경우 예매하라 라는 메시지를 선택하는 것으로 설계를 시작했다는 것을 기억하기. 협력을 위해 예매하라 라는 메시지가 필요하다는 결정을 내린 후에 그 메시지를 수신할 적절한 객체로 Screening을 선택. 그리고 Screening이 가격을 계산하라 라는 메시지를 전송해야 한다는 사실을 결정한 후에 그 메시지를 수신할 수 있는 객체로 Movie를 선택
행동이 상태를 결정한다 ( 이부분 중요!
내가 자주하는 실수)
- 객체를 객체답게 만드는 것은 객체의 상태가 아니라 객체가 다른 객체에게 제공하는 행동이다.
- 객체가 협력에 적합한지를 결정하는 것은 그 객체의 상태가 아니라 행동이다.
- 객체지향 패러다임에 갓 입문한 사람들이 가장 쉽게 빠지는 실수는 객체의 행동이 아니라 상태에 초점을 맞추는 것임. 초보자들은 먼저 객체에 필요한 상태가 무엇인지를 결정하고, 그 후에 상태에 필요한 행동을 결정한다. 이런 방식은 객체의 내부 구현이 객체의 퍼블릭 인터페이스에 노출되도록 만들기 때문에 캡슐화를 저해한다. 객체의 내부 구현을 변경하면 퍼블릭 인터페이스도 함께 변경되고, 결국 객체에 의존하는 클라이언트로 변경의 영향이 전파된다. 레베카 워프스브록은 이와 같이 객체의 내부 구현에 초점을 맞춘 설계 방법을
데이터 주도 설계
라고 부르기도 했다.
캡슐화를 위반하지 않도록 구현에 대한 결정을 뒤로 미루면서 객체의 행위를 고려하기 위해서는 항상 협력이라는 문맥 안에서 객체를 생각해야 한다. 협력 관계 속에서 다른 객체에게 무엇을 제공해야 하고 다른 객체로부터 무엇을 얻어야 하는지를 고민해야만 훌륭한 책임을 수확할 수 있다.
중요한 것은 객체의 상태가 아니라 행동이다. 협력이 객체의 행동을 결정하고 행동이 상태를 결정한다.
역할
- 객체는 협력이라는 주어진 문맥 안에서 특정한 목적을 갖게 된다.
- 객체의 목적은 협력 안에서 객체가 맡게 되는 책임의 집합으로 표시됨
- 이처럼 객체가 어떤 특정한 협력 안에서 수행하는 책임의 집합을
역할
이라고 부름
- 실제로 협력을 모델링할 때는 특정한 객체가 아니라 역할에게 책임을 할당한다고 생각하는 게 좋음
- 예를 들어 영화 예매 협력에서 예매하라 라는 메시지를 처리하기에 적절한 객체로 Screening을 선택할 때, 이 과정은 두 개의 독립적인 단계가 합쳐진 것임
- 영화를 예매할 수 있는 적절한 역할이 무엇인지 찾는 과정
- 역할을 수행할 객체로 Screening 인스턴스를 선택하는 것
- 역할은 다른 것으로 교체할 수 있는 책임의 집합이다. 역할은 여러 종류의 구체적인 객체를 포괄하는
추상화
- 예시로, Movie가 할인요금을 계산하라 라는 메시지를 보낼 때 AmountDiscountPolicy와 PercentDiscountPolicy 각각에게 보낼 수 있음
- 각각은 할인요금을 계산한다(
DiscountPolicy
)는 공통적인 역할을 갖고 있음
- 책임과 역할을 중심으로 협력을 바라보는 것이 바로 변경과 확장이 용이한 유연한 설계로 나아가는 첫걸음이다.
객체 대 역할
- 협력에 적합한 책임을 수행하는 대상이 한 종류라면 간단하게 객체로 간주. 만약 여러 종류의 객체들이 참여할 수 있다면 역할이라고 부르면 됨
- 설계 초반에는 적절한 책임과 협력의 큰 그림을 탐색하는 것이 가장 중요한 목표여야 하고 역할과 객체를 명확하게 구분하는 것은 그렇게 중요하지는 않다는 점. 애매하다면 단순하게 객체로 시작하고 반복적으로 책임과 협력을 정제해가면서 필요한 순간에 객체로부터 역할을 분리해내는 것이 가장 좋은 방법
역할과 추상화
- 협력 안에서 역할이라는 추상화를 이용하면 기존 코드를 수정하지 않고도 새로운 행동을 추가할 수 있다.
배우와 배역
- 배우가 여러 연극에 참여하면서 여러 배역을 연기할 수 있는 것처럼 객체 역시 여러 협력에 참여하면서 여러 역할을 수행할 수 있다
- 객체는 다양한 역할을 가질 수 있다. 객체는 협력에 참여할 때 협력 안에서 하나의 역할로 보여진다. 객체가 다른 협력에 참여할 때는 다른 역할로 보여진다.