Role & Responsibility & Cooperation(역할 & 책임 & 협력)
객체지향 설계의 핵심은 동적인 객체 간의 협력으로, 협력을 통해 객체의 행동(책임)이 드러나고, 역할이 정의된다.
협력(Cooperation)
협력은 어떤 객체가 다른 객체에게 무언가를 요청할 때 시작되며, 두 객체 사이의 요청과 응답의 연쇄적인 흐름이 모여 애플리케이션의 기능을 구현한다.
협력의 문맥(Context)
객체가 존재하는 이유는 협력에 참여를 목적으로 함
협력은 객체가 필요한 이유와 객체가 수행해야 할 행동의 문맥 제공
요청과 응답
협력은 다수의 요청과 응답으로 구성
특정 요청을 받아들일 수 있다는 것은 그 요청을 처리할 책임이 있음을 의미
책임(Responsibility)
책임은 객체가 협력에 참여하기 위해 수행하는 행동이자, 객체가 유지해야 하는 정보의 집합으로, 크게 두 가지로 분류할 수 있다.
정보(Knowing)
자신의 정보
관련된 객체의 정보
자신이 유도하거나 계산할 수 있는 정보
주로 필드(Field)나 객체 간의 연관 관계(Link)로 구현
서비스(Doing)
객체를 생성하거나 계산을 수행하는 등 스스로 하는 것
다른 객체의 행동을 시작시키거나 제어하는 것
주로 메서드(Method) 호출로 구현
책임은 객체의 공용 인터페이스(Public Interface)를 구성하며, 이는 객체 내부의 구현을 숨기고 외부에는 약속된 동작만 노출하는 캡슐화의 기반이 된다.
인터페이스 설계 원칙
좋은 객체지향 설계를 위해서는 인터페이스를 만들 때 다음 세 가지 원칙을 고려해야 한다.
추상적인 인터페이스
구체적인 방법(How)이 아니라 의도(What)를 명확하게 표현
너무 상세한 메시지는 객체의 자율성을 저해하므로, 추상적인 수준의 메시지를 수신하도록 설계
최소 인터페이스
외부에서 사용할 필요가 없는 인터페이스는 최대한 은닉
인터페이스와 구현의 분리
인터페이스: 객체가 수행해야 할 책임의 목록(외부 공개)
구현: 책임을 수행하기 위한 내부 동작 및 상태(내부 은닉)
변경될 가능성이 높은 구현 부분은 내부에 감추고, 안정적인 인터페이스만 노출
역할(Role)
역할은 객체가 특정한 협력 안에서 수행하는 책임의 집합이다.
동일한 역할을 수행한다면, 이들을 포괄하는 추상적인 개념으로 역할을 정의 가능
이를 확장하여 객체지향 설계의 단순성, 유연성, 재사용성을 뒷받침하는 핵심 개념이 됨
협력의 추상
역할을 사용하면 구체적인 객체가 아니라 추상적인 개념에 의존하게 되므로 협력을 단순화하고 유연하게 만들 수 있다.
구체적인 객체 대신 역할 사용
어떠한 역할이 있다면 그 역할을 수행하는 모든 객체가 협력에 참여 가능
이를 통해 다양한 객체들이 동일한 협력에 참여
대체 가능성
역할은 협력 안에서 구체적인 객체로 대체될 수 있는 추상적인 협력자이므로, 다른 객체에 의해 대체 가능함을 의미한다.
역할을 대체하는 객체는 해당 역할이 가진 모든 책임을 수행 가능
대체하는 객체는 역할이 요구하는 책임 외에 다른 책임을 가질 수 있음
역할의 대체 가능성은 행위의 호환성을 의미하며, 이는 동일한 인터페이스를 구현하는 것으로 기술
객체의 모양을 결정하는 협력
많은 개발자가 데이터(DB 스키마)를 먼저 고민하고 객체를 설계하지만, 데이터는 객체가 행위를 수행하는 데 필요한 재료일 뿐이다.
올바른 설계 순서
객체가 가져야 할 상태나 데이터가 아니라, 객체가 참여해야 할 협력을 먼저 결정
협력이라는 문맥이 객체의 행동을 결정하고, 행동이 객체의 상태를 결정
데이터 중심 설계의 문제점
객체의 행동보다 데이터를 먼저 결정하면 객체의 구현이 인터페이스에 노출
캡슐화를 위반하고 객체 간의 결합도를 높이는 원인
협력을 따라 흐르는 객체의 책임
올바른 객체지향 설계는 적절한 책임을 적절한 객체에게 할당하는 과정이다.
협력이라는 문맥 안에서 객체가 수행해야 할 책임을 먼저 식별
책임을 수행할 적절한 객체를 선택 및 생성
책임을 완수하기 위해 필요한 행동(인터페이스)을 정의
행동을 수행하는 데 필요한 데이터(상태)를 결정
를 클래스와 메서드로 구현
객체지향 설계 기법
역할, 책임, 협력 관점에서 애플리케이션을 설계하기 위해 주로 세 가지 기법이 사용된다.
책임-주도 설계(Responsibility-Driven Design)
시스템의 기능을 더 작은 규모의 책임으로 분할하고, 이를 수행할 적절한 객체에게 할당하는 하향식 설계 방식이다.
설계 흐름
What(무엇을 해야 하는가)을 먼저 결정하고 Who(누가 할 것인가)를 나중에 결정
메시지를 먼저 결정하고 그 메시지를 수신할 객체를 선택
장점
객체의 내부 구현을 먼저 고민하지 않으므로 캡슐화가 자연스럽게 이루어짐
메시지 송신자는 수신자의 구체적인 타입을 알 필요가 없으므로 결합도가 낮아짐
디자인 패턴(Design Pattern)
책임-주도 설계의 결과를 패턴화하여 정리한 것으로, 반복적으로 발생하는 문제 상황에서 역할, 책임, 협력을 어떻게 구성하는 것이 좋은지에 대한 모범 답안이다.
처음부터 패턴을 강제로 적용하는 것이 아니라, 책임 주도 설계를 진행하다가 특정 문제 상황에 직면했을 때 적절한 패턴 참고
각 패턴은 특정한 협력 방식을 제안하며, 이를 통해 설계를 빠르고 안정적으로 진행할 수 있음
테스트-주도 개발(Test-Driven Development)
TDD는 단순한 테스트 기법이 아니라 객체지향 설계를 위한 강력한 도구로, 테스트 코드를 통해 역할, 책임, 협력을 명확히 정의하고 검증하는 방법론이다.
테스트 코드를 먼저 작성하기 위해 테스트 대상 객체가 수행해야 할 행동(책임)과 결과, 그리고 협력하는 객체를 먼저 고민
코드를 작성하기 전에 역할, 책임, 협력을 먼저 생각하게 강제
참고자료
Last updated