아래는 영화 예매 기능을 구현하기 위해 협력하는 객체들의 상호작용을 나타낸 그림이다.

위와 같이 다양한 객체들이 서로 메시지를 주고받으면서 상호작용하는 것을 협력이라고 한다.
객체가 협력에 참여하기 위해 수행하는 로직은 책임이라고 하며, 여러 책임이 모여 객체가 수행하는 역할을 구성한다.
객체의 행동은 그 객체가 참여하고 있는 협력에 따라 결정된다.
자율적인 객체는 자신에게 할당된 책임을 수행하던 중에 도움이 필요한 경우 이를 처리할 수 있는 다른 객체에게 메시지를 전송해서 협력을 요청한다.
메시지를 수신한 객체는 메서드를 이용해 요청에 응답하며, 이는 객체의 행동을 의미한다.
따라서, 협력이 변경되면 객체가 제공해야 하는 행동 역시 변경된다. 협력은 객체가 수행하는 행동의 동기를 제공한다.
객체의 행동을 결정하는 것이 협력이라면, 객체의 상태를 결정하는 것은 행동이다.
객체의 상태는 그 객체가 행동을 수행하는 데 필요한 정보가 무엇인지로 결정된다.
크레이그 라만은 객체의 책임을 하는 것(doing)과 아는 것(knowing)의 두 가지 범주로 나누어 세분화한다.
영화 예매 시스템을 예로 들면,
Screening은 Movie가 영화 요금을 계산하는 것을 요청할 책임이 있으며, 이 행동을 수행하기 위해 Movie에 대해 알고 있다.
자율적인 객체를 만드는 가장 기본적인 방법은 책임을 수행하는 데 필요한 정보를 가장 잘 알고 있는 전문가에게 그 책임을 할당하는 것이다. 이를 책임 할당을 위한 INFORMATION EXPERT(정보 전문가) 패턴이라고 한다.
영화 예매 시스템을 예로 들어 정보 전문가에게 책임을 할당하는 방법을 살펴보자.
시스템이 사용자에게 제공할 기능은 영화를 예매하는 것이고, 이 기능을 시스템이 제공할 책임으로 할당한다.
따라서 “예매하라”라는 이름의 메시지로 협력을 시작한다.
이제 “예매하라”라는 메시지를 수신할 적절한 객체를 선택해야 한다. 영화를 예매하는 책임은 영화 예매와 관련된 정보를 가장 많이 알고 있는 객체에게 할당하는 것이 좋을 듯 하다.
영화를 예매하기 위해서는 상영 시간과 기본 요금을 알아야 하는데, 이 정보를 소유하고 있거나 해당 정보의 소유자를 가장 잘 알고 있는 전문가는 Screening이다. 따라서 수신자로 Screening을 선택한다.
영화를 예매하기 위해서는 예매 가격을 계산해야 한다. 하지만 Screening은 이를 처리하는 데 필요한 정보를 가지고 있지 않다. 따라서 Screening은 예매 가격을 계산할 수 있는 다른 객체에게 “가격을 계산하라”라는 메시지를 전송한다.
이번에도 가격을 계산하는 데 필요한 정보를 가장 많이 알고 있는 정보 전문가를 찾아야 한다.
가격을 계산하기 위해서는 가격과 할인 정책이 필요하다. 이를 가장 잘 알고 있는 전문가는 Movie이므로, 가격을 계산하는 책임을 Movie에게 할당한다.
위 과정을 그림으로 나타내면 다음과 같다.

위와 같이 책임을 수행할 적절한 객체를 찾아 책임을 할당하는 방식으로 협력을 설계하는 방법을 책임 주도 설계(Responsibility-Driven Design)라고 한다.
책임 주도 설계 방법의 과정은 다음과 같다.
객체가 최소한의 인터페이스(minimal inteface)를 가질 수 있게 된다.
필요한 메시지가 식별되기 전까지 객체의 퍼블릭 인터페이스에 어떤 것도 추가하지 않기 때문에 객체는 크지도, 작지도 않은 꼭 필요한 크기의 퍼블릭 인터페이스를 가질 수 있다.
객체는 충분히 추상적인 인터페이스(abstract interface)를 가질 수 있게 된다.
객체의 인터페이스에는 무엇(what)을 하는지는 표현해야 하지만, 어떻게(how) 수행하는지 노출해서는 안 된다. 메시지는 객체가 다른 객체에게 요청하는 무언가를 의미하기 때문에 메시지를 먼저 식별하면 무엇을 수행할지에 초점을 맞추는 인터페이스를 얻을 수 있다.
객체가 충분히 추상적이면서 미니멀리즘을 따르는 인터페이스를 가지게 하고 싶다면 메시지가 객체를 선택하게 하자.
영화 예매 시스템에서 Movie가 전송하는 “할인 요금을 계산하라”라는 메시지를 처리하기에 적절한 객체는 AmountDiscountPolicy가 될 수도 있고, PercentDiscountPolicy가 될 수도 있다. 이러한 경우 두 종류의 객체가 참여하는 협력을 개별적으로 만들어야 할까?
개별적으로 만든다면 대부분의 코드가 중복되고 말 것이므로, 이 방법은 피해야 한다.
문제를 해결하기 위해서는 객체가 아닌 책임에 초점을 맞춰야 한다. 객체라는 존재를 지우고 메시지에 응답할 수 있는 대표자를 생각한다면 두 협력을 하나로 통일할 수 있을 것이다. 이 대표자를 협력 안에서 두 종류의 객체를 교대로 바꿔 끼울 수 있는 슬롯으로 생각할 수 있으며, 이 슬롯이 바로 역할이다.
“역할은 다른 것으로 교체할 수 있는 책임의 집합이다.” - Wirfs-Brock
여기서 역할이 두 종류의 구체적인 객체를 포괄하는 추상화라는 점에서 역할의 이름을 AmountDiscountPolicy와 PercentDiscountPolicy를 포괄할 수 있는 추상적인 이름인 DiscountPolicy로 정할 수 있다.

트리그비 린스카우(Trygve Reenskaug)에 따르면 협력은 역할들의 상호작용으로 구성되고, 협력을 구성하기 위해 역할에 적합한 객체가 선택되며, 객체는 클래스를 이용해 구현되고 생성된다.

설계 초반에 객체와 역할에 대한 결정을 내리기 어렵다면, 단순하게 객체로 시작하고 반복적으로 책임과 협력을 정제해가면서 필요한 순간에 객체로부터 역할을 분리해내는 것이 가장 좋은 방법이다.
역할은 공통의 책임을 바탕으로 객체의 종류를 숨기기 때문에 이런 관점에서 역할을 추상화로 볼 수 있다. 따라서 추상화가 가지는 두 가지 장점(상위 정책 기술, 유연한 설계)은 협력의 관점에서 역할에도 동일하게 적용될 수 있다.
상위 수준에서 협력을 설명하면 구체적인 객체들이 가지는 복잡성을 제거하고 단순화해서 표현할 수 있다.
여기서 구체적인 객체로 대체 가능한 것이 바로 역할이다.
협력 안에서 동일한 책임을 수행하는 객체들은 동일한 역할을 수행하기 때문에 서로 대체 가능하다. 따라서 역할은 협력을 유연하게 만든다.