Ch3 역할, 책임, 협력
들어가며
앞선 챕터에서는 간단한 영화 예매
코드를 통해서 구현 관점
의 객체지향 설계에 대해서 배웠다. 캡슐화
, 상속
, 합성
, 다형성
, 추상화
, 메시지와 메서드
의 개념을 확인하고 컴파일 타임 의존성
과 런타임 의존성
을 다르게 함으로써 보다 유연하고 변경하기 쉬운 설계가 무엇인지에 대해 감을 잡았다.
이번 장에서는 구현 관점
에 앞서 객체지향 설계
에 있어 본질
이며 중점이 되어야 하는 역할
, 책임
, 협력
에 대해서 학습한다.
클래스, 상속, 지연 바인딩이 중요하지 않은 것은 아니지만 구현 측면에 치우쳐저 있기 때문에 객체지향 패러다임의 본질과는 거리가 멀다.
객체지향의 본질은 협력하는 객체들의 공동체를 창조하는 것이다. 객체지향 설계의 핵심은 협력을 구성하기 위해 적절한 객체를 찾고 적절한 책임을 할당
하는 과정에서 드러난다.
클래스와 상속은 객체들의 책임과 협력이 어느정도 자리를 잡은 후에 사용할 수 있는 구현 메커니즘
일 뿐이다.
애플리케이션의 기능을 구현하기 위해 어떤 협력이 필요하고 어떤 역할과 책임이 필요한지를 고민하지 않은 채 너무 이른 시기에 구현에 초점을 맞추는 것은 변경하기 어렵고 유연하지 못한 코드를 낳는 원인이 된다.
핵심
-
객체가 메시지를 처리할 방법을 스스로 선택한다.
-
객체를 자율적으로 만드는 가장 기본적인 방법은
내부 구현을 캡슐화
하는 것이다. -
객체의 행동을 결정하는 것은 객체가 참여하고 있는 협력이다.
-
책임
이란객체가 유지해야 하는 정보
와객체가 수행할 수 있는 행동
에 대해개략적으로 서술한 문장
이다. -
객체의
책임
은하는 것(Doing)
과아는 것(Knowing)
으로 세분화 할 수 있다. -
협력 안에서 객체에게 할당한 책임이 외부의 인터페이스와 내부의 속성을 결정한다.
-
일반적으로
책임
과메시지
의 크기는 다르다.책임
은 객체가 수행할 수 있는 행동을종합적이고 간략하게 서술
하기 때문에메시지
보다추상적이고 개념적으로도 더 크다.
-
책임의 관점에서
아는 것
과하는 것
은 밀접하게 연관되어 있다. -
어떤
책임
을 수행하기 위해서는 그책임을 수행하는 데 필요한 정보
도 함께 알아야 할 책임이 있는 것이다. -
객체지향에서 가장 중요한 것은
책임
이다. -
자율적인 객체
를 만드는 가장 기본적인 방법은 책임을 수행하는 데필요한 정보를 가장 잘 알고있는 전문가에게 그 책임을 할당
하는 것이다. 이를 책임 할당을 위한정보 전문가 패턴
이라고 부른다. -
시스템의 책임을 완료하는 데 필요한
더 작은 책임
을 찾아내고 이를 객체들에게 할당하는 반복적인 과정을 통해 객체지향 설계가 진행된다. -
객체가 책임을 수행하게 하는 유일한 방법은 메시지를 전송하는 것이므로 책임을 할당한다는 것은 메시지의 이름을 결정하는 것과 같다.
-
메시지
가객체의 퍼블릭 인터페이스를 구성
한다 -
협력을 설계하면서 객체의 책임을 식별해 나가는 과정에서 최종적으로 얻게 되는 결과물은 시스템을 구성하는 객체들의 인터페이스와 오퍼레이션 목록이다.
-
정보 전문가
에게 책임을 할당하면행동
과상태
를 함께 갖는자율적인 객체
를 만들 가능성이 높아진다. -
메세지
가객체
를 결정한다. -
필요한 메시지를 먼저 식별
하고메시지를 처리할 객체를 나중에 선택
함으로써최소한의 인터페이스
와충분히 추상적인 인터페이스 (How가 아닌 What을 표현하는 인터페이스)
를 얻을 수 있다. -
객체가 어떤 특정한 협력 안에서 수행하는 책임의 집합을 역할이라고 부른다.
-
실제로 협력을 모델링 할때는 특정한
객체
가 아니라역할
에게책임을 할당
한다고 생각하는게 좋다. -
역할은 다른 것으로 교체할 수 있는 책임의 집합이다.
-
역할은 다양한 종류의 객체를 수용할 수 있는 일종의 슬롯이자
구체적인 객체들의 타입을 캡슐화하는 추상화
이다. -
추상화
는상위 정책의 흐름
을 표현하고 구체적인 구현체들은 상위 정책의 흐름을 그대로 따라가기 때문에재사용 가능한 협력
을 표현할 수 있다. 따라서역할
은추상화
로써유연하고 재사용 가능한 협력
을 표현할 수 있다. -
설계 초반에는 적절한 책임과 협력의 큰 그림을 탐색하는 것이 가장 중요한 목표여야 하고 역할과 객체를 명확하게 구분하는 것은 그렇게 중요하지 않다는 점을 기억하자.
-
중요한 것은
협력
을 구체적인 객체가 아니라추상적인 역할
의 관점에서 설계하면협력이 유연하고 재사용 가능
해진다는 것이다. 따라서역할
의 가장 큰 장점은설계의 구성 요소를 추상화
할 수 있다는 것이다. -
역할
은공통의 책임
을 바탕으로객체의 종류를 캡슐화
하기 때문에 이런 관점에서역할
을객체의 추상화
로 볼 수 있다. -
추상화
를 적절히 이용하면불필요한 세부사항을 생략
하고핵심적인 개념을 강조
할 수 있다. -
역할
이 중요한 이유는동일한 행동을 수행하는 객체들을 추상화
할 수 있기 때문이다. -
추상화
를 적절히 이용하면 설계를 유연하게 만들 수 있다. 협력 안에서 동일한 책임을 수행하는 객체들은 동일한 역할을 수행하기 때문에 서로 대체 가능하다. -
협력
안에서역할
이라는추상화
를 이용하면 기존 코드를 수정하지 않고도새로운 행동을 추가(AnotherDiscountPolicy)
할 수 있다.
협력
협력
객체지향 원칙을 따르는 애플리케이션의 제어 흐름은 어떤 하나읜 객체에 의해 통제되지 않고 다양한 객체들 사이에 균형있게 분배
되는 것이 일반적이다. 객체들은 요청의 흐름을 따라 자신에게 분배된 로직을 실행하면서 애플리케이션의 전체 기능을 완성한다.
여기서 중요한 것은 다양한 객체들이 기능을 구현하기 위해 메시지를 주고받으면서 상호작용 한다는 점이다. 이처럼 객체들이 애플리케이션의 기능을 구현하기 위해 수행하는 상호작용
을 협력
이라고 한다.
객체가 협력
에 참여하기 위해 수행하는 로직을 책임
이라고 부른다.
객체들이 협력
안에서 수행하는 책임
들이 모여 객체가 수행하는 역할
을 구성한다.
협력
은 객체지향의 세계에서 기능을 구현할 수 있는 유일한 방법
이다. 두 객체 사이의 협력은 하나의 객체가 다른 객체에게 도움을 요청할 때 시작된다. 메시지 전송
은 객체 사이의 협력을 위해 사용할 수 있는 유일한 커뮤니케이션 수단
이다.
협력이란 어떤 객체가 다른 객체에게 무엇인가를 요청하는 것이다.
메시지
를 수신한 객체는 메서드
를 실행해 요청에 응답한다. 객체가 메시지를 처리할 방법을 스스로 선택한다는 점이 중요하다.
외부의 객체는 오직 메시지만을 전송할 수 있을 뿐이며 메시지를 어떻게 처리할지는 메시지를 수신한 객체가 직접 결정한다.
이것은 객체가 자신의 일을 스스로 처리할 수 있는 자율적인 존재라는 것을 의미한다. 자율적인 객체
란 자신의 상태를 직접 관리하고 스스로의 결정에 따라 행동
하는 객체다.
객체의 자율성을 보장하기 위해서는 ‘필요한 정보’와 ‘정보에 기반한 행동’을 같은 객체 안에 모아놓아야 한다.
Movie
가 자율적인 존재가 되기 위해서는 자신이 알고 있는 정보를 이용해 직접 요금을 계산
해야 한다.
자신이 할 수 없는 일을 다른 객체에게 위임하면 협력에 참여하는 객체들의 전체적인 자율성을 향상시킬 수 있다.
결과적으로 객체를 자율적으로 만드는 가장 기본적인 방법은 ‘내부 구현을 캡슐화’하는 것이다. 캡슐화
를 통해 변경에 대한 파급효과를 제한할 수 있기 때문에 자율적인 객체는 변경하기도 쉬워진다.
자율적인 객체는 자신에게 할당된 책임을 수행하던 중에 ‘필요한 정보’를 알지 못하거나 외부의 도움이 필요한 경우 적절한 객체에게 ‘메시지를 전송’해서 협력을 요청한다.
이처럼 객체들 사이의 협력을 구성하는 일련의 요청과 응답
의 흐름을 통해 애플리케이션의 기능이 구현된다.
협력이 설계를 위한 문맥을 결정한다.
객체가 가질 수 있는 상태와 행동을 어떤 기준으로 결정해야 할까?
객체를 설계할 때 어떤 행동과 상태를 할당했다면 그 이유는 무엇인가?
객체가 협력에 필요한 적절한 행동을 보유하고 있기 때문이다. 결론적으로 객체의 행동을 결정하는 것은 객체가 참여하고 있는 협력이다. 예를들어 Movie
의 행동(요금 계산)을 결정하는 것은 영화 예매를 위한 협력
이다. 협력
이라는 문맥을 고려하지 않고 Movie
의 행동을 결정하는 것은 아무런 의미가 없다. 협력이 존재하기 때문에 객체가 존재하는 것이다.
객체의 행동을 결정하는 것이 협력이라면 객체의 상태를 결정하는 것은 행동이다.
객체의 상태는 그 객체가 행동을 수행하는 데 필요한 정보가 무엇인지로 결정된다.
상태는 객체가 행동하는데 필요한 정보에 의해 결정되고 행동은 협력 안에서 객체가 처리할 메시지로 결정된다. 결과적으로 객체가 참여하는 협력
이 객체를 구성하는 행동
과 상태
모두를 결정한다. 따라서 협력은 객체를 설계하는 데 필요한 일종의 문맥(Context)를 제공한다.
책임
책임이란 무엇인가.
객체를 설계하기 위해 필요한 협력
이 갖추어졌다면 다음으로 할 일은 협력에 필요한 행동을 수행할 수 있는 적절한 객체를 찾는 것이다. 이때 협력에 참여하기 위해 객체가 수행하는 행동
을 책임
이라고 부른다.
책임
이란 객체가 유지해야 하는 정보
와 객체가 수행할 수 있는 행동
에 대해 개략적으로 서술한 문장
이다. 객체의 책임
은 객체가 무엇을 알고있는가(무엇을 알아야 하는가)
와 무엇을 할 수 있는가(무엇을 해야하는가)
로 구성된다. 이러한 분류 체계에 따라 객체의 책임
을 크게 하는 것(Doing)
과 아는 것(Knowing)
의 두 가지 범주로 나누어 세분화 할 수 있다.
하는 것(Doing)
- 객체를 생성하거나 계산을 수행하는 등의 스스로 하는 것
- 다른 객체의 행동을 시작시키는 것
- 다른 객체의 활동을 제어하고 조절하는 것
아는 것(Knowing)
- 사적인 정보에 관해 아는 것
- 관련된 객체에 관해 아는 것
- 자신이 유도하거나 계산할 수 있는 것에 관해 아는 것
Movie
는 예매 가격을 계산할 책임
을 진다. 이것은 하는 것(Doing)
과 관련된 책임이다. 또한 영화 가격과 어떤 할인 정책이 적용됐는지
도 알고 있어야 한다. 이것은 아는 것(Knowing)
과 관련된 책임이다.
Movie
가 calculateMovieFee
메시지를 수신할 수 있고 fee
와 discountPolicy
를 속성으로 갖는 이유는 협력 안에서 가격을 계산할 책임을 할당받아기 때문이다. 이처럼 협력 안에서 객체에게 할당한 책임이 외부의 인터페이스와 내부의 속성을 결정한다.
일반적으로 책임
과 메시지
의 크기는 다르다. 책임
은 객체가 수행할 수 있는 행동을 종합적이고 간략하게 서술!!!
하기 때문에 메시지
보다 추상적이고 개념적으로도 더 크다.
처음에는 단순하게 책임
이라고 생각했던 것이 여러개의 메시지로 분할
되기도 하고 하나의 객체가 수행할 수 있다고 생각했던 책임
이 나중에는 여러 객체들이 협력
해야만 하는 커다란 책임
으로 자라는 것이 일반적이다.
책임의 관점에서 아는 것
과 하는 것
은 밀접하게 연관되어 있다. 객체는 자신이 맡은 책임을 수행하는 데 필요한 정보를 알고있을 책임이 있다. 또한 객체는 자신이 할 수 없는 작업을 도와줄 객체를 알고있을 책임이 있다.
어떤 책임을 수행하기 위해서는 그 책임을 수행하는 데 필요한 정보도 함께 알아야 할 책임이 있는 것이다.
객체지향에서 가장 중요한 것은 책임
이다. 객체에게 얼마나 적절한 책임을 할당하느냐고 설계의 전체적인 품질을 결정한다.
책임 할당.
자율적인 객체
를 만드는 가장 기본적인 방법은 책임을 수행하는 데 필요한 정보를 가장 잘 알고있는 전문가에게 그 책임을 할당하는 것이다. 이를 책임 할당을 위한 정보 전문가 패턴
이라고 부른다.
여기서 잠깐. 정보 전문가에게 책임을 할당한다고 하였는데 그렇다면 어떤 객체가 정보 전문가인지는 어떻게 알 수 있을까?
start1
정보 전문가
에 대한 판단은 도메인에 대한 정확한 이해
와 직관
이 필요하다. 더불어 객체는 스스로를 책임지는 자율적인 존재
라는 기본적인 개념을 적용해보면 누가 정보 전문가
인지는 생각보다 판단하기가 수월해 지는 경우가 많다.
이런 고민에도 누가 정보 전문가
인지 판단하기 쉽지 않다면 짐작되는 객체 후보들
에게 책임을 할당해보고 응집도
, 결합도
측면에서 더욱 적절한 객체에게 할당하는 것도 경험적으로 나쁘지 않은 선택이었다.
예를 들어 Movie
와 Screening
중 할인 정책
에 대해 알고있을 책임이 있는 정보 전문가
가 누구인지 헷갈렸다.
영화 요금 계산
을 위해영화 요금
에 대한 정보를 가장 잘 알고 있는 객체는Movie
이다.영화 요금 계산
책임을 수행하기 위해서는할인 정책
에 대한 정보가 필요하므로Movie
가할인 정책
에 대한 정보를 알고있어야 할 책임을 할당한다.Movie
로 부터영화 기본 요금
만 계산하도록 하고할인 적용 요금 계산
은Screening
에 할당한다.
위에서와 같이 1번(Movie에 할당
)과 2번(Screening에 할당
)이 헷갈렸다. 물론 처음부터 도메인에 대한 정확한 이해가 있었다면(할인 정책은 영화 별 적용) 좀 더 쉽게 책임을 할당할 수 있었겠지만 그렇지 않은 경우 2번에 대한 고민도 함께 해볼 수 있다.
만일 2번과 같이 Screening
에 할인 적용 요금 계산
책임을 할당한다면 우선 응집도
가 낮아진다. Screening
이 영화 요금 계산
의 책임 일부를 떠안게 되는 셈이다. 이에 따라 Screening
이 할인 정책
에 대해서도 알고 있어야 하므로 결합도
역시 높아진다. 따라서 1번과 같이 Movie
에 할당하는 것이 더 좋은 설계라고 볼 수 있다.
end1
start2
학습을 진행하던 중 위의 Movie
와 Screening
의 책임 할당 과정에서 떠오른 것이 있어서 덧붙인다. 생각해보면 상당히 간단하다.
먼저 책임과 관련하여 머릿속에 염두해야할 것이 있다.
- 알아야 할 책임이란 맡은 책임을 수행하는 데 필요한 정보에 대해 알아야 할 책임을 의미한다.
- 필요한 정보란
자신이 직접
유도하거나 계산할 수 있는 것에 대해 아는 것도 있지만필요한 정보와 관련된 객체에 대해 아는 것
도 필요한 정보를 알아야 할 책임에 해당한다. - 책임은 시스템의 책임인 큰 책임(추상적)에서 시작하여 각 객체들에게 적절히 분배 및 할당되며 조금씩 작아진다(세분화)
자. 그렇다면 다시 Movie
와 Screening
으로 돌아와서 Screening
의 책임은 보다 추상적이고 큰 책임인 예매하다.
이다. 그리고 이 예매
책임을 수행하기 위해서 요금을 계산
할 수 있어야 하는데, 이 책임을 우리는 Movie
에게 할당하였다.
- Screening의 책임 : 예매하다.
- Movie의 책임 : 요금을 계산하다.
그리고 Movie
가 요금을 계산
하기 위한 책임을 수행하기 위해서는 할인 요금
에 대한 정보가 필요하다. 즉, Movie
는 할인 요금과 관련된 정보에 대해 알아야 할 책임
이 존재한다. 위에서는 할인 요금과 관련된 정보를 할인 정책
으로 표현하였으므로 할인 요금과 관련된 정보인 할인 정책
에 대해서 알아야 할 책임은 자연스럽게 Movie
에게 있는것이다.
정리하자면 예매하다
라는 보다 추상적이고 큰 책임에서 시작하여 요금을 계산하다
라는 작은 책임이 Movie
에게 할당되었고. 이 요금을 계산
하는 책임을 수행하기 위해서는 할인 요금
에 대한 정보를 알아야 했다. 그리고 할인 요금
과 관련된 정보가 바로 할인 정책
이므로, 결과적으로 Movie
가 책임을 수행하기 위해서 알아야 할 정보가 할인 정책
인 것이다.
end2
start3
조금 더 나아가서 할인 요금 계산
은 변경되는 부분(가변적)이므로 캡슐화/추상화
의 대상이 된다. 사람에 따라 할인 정책 타입
을 캡슐화 하여 합성 관계로 설계(현재의 설계)하는 사람이 있을 것이고 Movie 타입을 추상화
하여 할인 요금 계산
이라는 추상 메서드
를 사용하는 메서드 추상화
를 사용하는 사람도 있을 것 같다.
end3
객체지향 설계는 시스템의 책임
을 완료하는 데 필요한 더 작은 책임
을 찾아내고 이를 객체들에게 할당
하는 반복적인 과정을 통해 모양을 갖춰간다.
이처럼 객체지향 설계는 협력에 필요한 메시지를 찾고 메시지에 적절한 객체를 선택하는 반복적인 과정을 통해 이뤄진다. 그리고 이런 메시지
가 메시지를 수신할 객체의 책임을 결정
한다.
이렇게 결정된 메시지
가 객체의 퍼블릭 인터페이스를 구성
한다는 것 역시 눈여겨 보자. 협력을 설계하면서 객체의 책임을 식별해 나가는 과정에서 최종적으로 얻게 되는 결과물은 시스템을 구성하는 객체들의 인터페이스와 오퍼레이션 목록이다.
모든 책임 할당 과정이 이렇게 단순한 것은 아니다. 위에서 언급했듯 어떤 경우에는 응집도
와 결합도
관점에서 정보 전문가
가 아닌 다른 객체에게 책임을 할당하는 것이 더 적절한 경우도 있다. 하지만 기본적인 전략은 책임을 수행할 정보 전문가를 찾는것이다. 정보 전문가
에게 책임을 할당하는 것만으로도 상태
와 행동
을 함께 가지는 자율적인 객체
를 만들 가능성이 높아지기 때문이다.
책임 주도 설계
-
시스템이 사용자에게 제공해야 하는 기능인
시스템 책임
을 파악한다. -
시스템 책임
을더 작은 책임
으로 분할한다. -
분할된 책임을 수행할 수 있는 적절한 객체 또는 역할을 찾아
책임을 할당
한다. -
객체가 책임을 수행하는 도중 다른 객체의 도움이 필요한 경우 이를 책임질 적절한 객체 또는 역할을 찾는다.
-
해당 객체 또는 역할에게 책임을 할당함으로써 두 객체가 협력하게 한다.
메시지가 객체를 결정한다.
객체에게 책임을 할당하는 데 필요한 메시지를 먼저 식별
하고 메시지를 처리할 객체를 나중에 선택
한다는 것이 중요하다. 다시 말해 객체가 메시지를 선택하는 것이 아니라. 메시지가 객체를 선택
하게 한다. 이와 같이 메시지가 객체를 선택하게 해야 하는 두 가지 중요한 이유가 있다.
-
객체가
최소한의 인터페이스
를 갖게 된다. 필요한 메시지가 식별될 때 까지 객체의퍼블릭 인터페이스
에 어떤 것도 추가하지 않아도 된다. -
객체는
충분히 추상적인 인터페이스
를 갖게 된다. 객체의 인터페이스는무엇(What)
을 표현해야 하지만어떻게(How)
수행하는지를 노출해서는 안된다.메시지
는 외부의 객체가 요청하는 무엇인가를 의미하기 때문에 메시지를 먼저 식별하면 무엇을 ㅅ구행할지에 초점을 맞추는 인터페이스를 얻을 수 있다.
행동이 상태를 결정한다.
객체가 존재하는 이유는 협력
에 참여하기 위해서다. 객체는 협력에 필요한 행동
을 제공해야 한다. 객체를 객체답게 만드는 것은 객체의 상태
가 아니라 객체가 다른 객체에게 제공하는 행동
이다.
객체의 행동
은 객체가 협력
에 참여할 수 있는 유일한 방법이다. 상태
는 행동
을 결정하고 나서야 비로소 결정할 수 있다.
역할
역할과 협력
객체의 목적은 협력
안에서 객체가 맡게되는 책임
의 집합으로 표시된다. 이처럼 객체가 어떤 특정한 협력 안에서 수행하는 책임의 집합을 역할이라고 부른다.
실제로 협력을 모델링 할때는 특정한 객체
가 아니라 역할
에게 책임을 할당
한다고 생각하는게 좋다.
유연하고 재사용 가능한 협력
역할
이 중요한 이유는 역할
을 통해 유연하고 재사용 가능한 설계
를 얻을 수 있기 때문이다. 여기서 DiscountPolicy
는 AmountDiscountPolicy
, PercentDiscountPolicy
로 대체 가능한 역할
로써 할인 요금 계산
이라는 동일한 책임
을 수행하는 구체적인 객체들의 추상화
이다.
앞선 챕터에서 언급했던 것 처럼 추상화
는 상위 정책의 흐름
을 표현하고 구체적인 구현체들은 상위 정책의 흐름을 그대로 따라가기 때문에 재사용 가능한 협력
을 표현할 수 있다. 따라서 역할
은 추상화
로써 유연하고 재사용 가능한 협력
을 표현할 수 있다.
역할은 다른 것으로 교체할 수 있는 책임의 집합이다.
역할의 구현
추상화
라는 말에서 예상했겠지만 역할
을 구현하는 가장 일반적인 방법은 추상 클래스
와 인터페이스
를 사용하는 것이다. 협력
의 관점에서 추상 클래스와 인터페이스는 구체 클래스들이 따라야 하는 책임의 집합을 서술
한 것이다.
여기서 중요한 것은 역할이 다양한 종류의 객체를 수용할 수 있는 일종의 슬롯이자 구체적인 객체들의 타입을 캡슐화하는 추상화라는 것이다.
객체 vs 역할
역할
은 객체
가 참여할 수 있는 일종의 슬롯
이다. 하지만 대부분의 경우 어떤 것이 역할이고 어떤 것이 객체인지가 또렷하게 드러나지는 않을 것이다. 특히나 명확한 기준을 세우기 어렵고 정보가 부족한 설계 초반에는 결정을 내리기가 더욱 어려울 것이다. 도메인 모델 안에는 개념과 객체와 역할이 어지럽게 뒤섞여 있다.
혼란을 덜기 위해서 설계 초반에는 적절한 책임과 협력의 큰 그림을 탐색하는 것이 가장 중요한 목표여야 하고 역할과 객체를 명확하게 구분하는 것은 그렇게 중요하지 않다는 점을 기억하자.
따라서 애매하다면 단순하게 객체
로 시작하고 반복적으로 책임
과 협력
을 정제해 나가면서 필요한 순간에 객체
로부터 역할
을 분리해내는 것이 가장 좋은 방법이다.
처음에 특정 시나리오에 대한 협력
을 구상할 때는 아마도 도메인 모델에 있는 개념들을 후보로 선택하여 직접 책임을 할당
할 것이다. 다양한 시나리오를 설계로 옮기면서 협력을 지속적으로 정제하다 보면 두 협력(AmountDiscountPolicy와의 협력, PercentDiscountPolicy와의 협력
)이 거의 유사한 구조를 보인다는 것을 발견하게 될 것이다. 이 경우 두 협력을 하나로 합치면서 두 객체를 포괄할 수 있는 역할을 고려해서 객체를 역할로 대체(DiscontPolicy라는 역할로 대체
)할 수 있다.
중요한 것은 협력
을 구체적인 객체가 아니라 추상적인 역할
의 관점에서 설계하면 협력이 유연하고 재사용 가능
해진다는 것이다. 따라서 역할
의 가장 큰 장점은 설계의 구성 요소를 추상화
할 수 있다는 것이다.
역할과 추상화
역할
은 공통의 책임
을 바탕으로 객체의 종류를 캡슐화
하기 때문에 이런 관점에서 역할
을 객체의 추상화
로 볼 수 있다.
추상화
의 첫 번째 장점은 세부 사항에 억눌리지 않고도 상위 수준의 정책을 쉽고 간단하게 표현할 수 있다는 것이다. 추상화
를 적절히 이용하면 불필요한 세부사항을 생략
하고 핵심적인 개념을 강조
할 수 있다.
협력
이라는 관점에서는 세부적인 사항을 무시하고 추상화
에 집중하는 것이 유용하다.
객체들에게 중요한 것은 행동
이라는 것을 기억하자. 역할
이 중요한 이유는 동일한 행동을 수행하는 객체들을 추상화
할 수 있기 때문이다.
추상화
의 두 번째 장점은 설계를 유연하게 만들 수 있다는 것이다. 협력 안에서 동일한 책임을 수행하는 객체들은 동일한 역할을 수행하기 때문에 서로 대체 가능하다.
협력
안에서 역할
이라는 추상화
를 이용하면 기존 코드를 수정하지 않고도 새로운 행동을 추가(AnotherDiscountPolicy)
할 수 있다.
프레임워크나 디자인 패턴과 같이 재사용 가능한 코드
나 설계 아이디어를 구성
하는 핵심적인 요소가 바로 역할
이다.
참고 및 출처
- 오브젝트