Ch3 역할, 책임, 협력

본문


들어가며

앞선 챕터에서는 간단한 영화 예매 코드를 통해서 구현 관점의 객체지향 설계에 대해서 배웠다. 캡슐화, 상속, 합성, 다형성, 추상화, 메시지와 메서드의 개념을 확인하고 컴파일 타임 의존성런타임 의존성을 다르게 함으로써 보다 유연하고 변경하기 쉬운 설계가 무엇인지에 대해 감을 잡았다.

이번 장에서는 구현 관점에 앞서 객체지향 설계에 있어 본질이며 중점이 되어야 하는 역할, 책임, 협력에 대해서 학습한다.

클래스, 상속, 지연 바인딩이 중요하지 않은 것은 아니지만 구현 측면에 치우쳐저 있기 때문에 객체지향 패러다임의 본질과는 거리가 멀다.

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

클래스와 상속은 객체들의 책임과 협력이 어느정도 자리를 잡은 후에 사용할 수 있는 구현 메커니즘일 뿐이다.

애플리케이션의 기능을 구현하기 위해 어떤 협력이 필요하고 어떤 역할과 책임이 필요한지를 고민하지 않은 채 너무 이른 시기에 구현에 초점을 맞추는 것은 변경하기 어렵고 유연하지 못한 코드를 낳는 원인이 된다.


핵심

  • 객체가 메시지를 처리할 방법을 스스로 선택한다.

  • 객체를 자율적으로 만드는 가장 기본적인 방법은 내부 구현을 캡슐화하는 것이다.

  • 객체의 행동을 결정하는 것은 객체가 참여하고 있는 협력이다.

  • 책임이란 객체가 유지해야 하는 정보객체가 수행할 수 있는 행동에 대해 개략적으로 서술한 문장이다.

  • 객체의 책임하는 것(Doing)아는 것(Knowing)으로 세분화 할 수 있다.

  • 협력 안에서 객체에게 할당한 책임이 외부의 인터페이스와 내부의 속성을 결정한다.

  • 일반적으로 책임메시지의 크기는 다르다. 책임은 객체가 수행할 수 있는 행동을 종합적이고 간략하게 서술하기 때문에 메시지보다 추상적이고 개념적으로도 더 크다.

  • 책임의 관점에서 아는 것하는 것은 밀접하게 연관되어 있다.

  • 어떤 책임을 수행하기 위해서는 그 책임을 수행하는 데 필요한 정보도 함께 알아야 할 책임이 있는 것이다.

  • 객체지향에서 가장 중요한 것은 책임이다.

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

  • 시스템의 책임을 완료하는 데 필요한 더 작은 책임을 찾아내고 이를 객체들에게 할당하는 반복적인 과정을 통해 객체지향 설계가 진행된다.

  • 객체가 책임을 수행하게 하는 유일한 방법은 메시지를 전송하는 것이므로 책임을 할당한다는 것은 메시지의 이름을 결정하는 것과 같다.

  • 메시지객체의 퍼블릭 인터페이스를 구성한다

  • 협력을 설계하면서 객체의 책임을 식별해 나가는 과정에서 최종적으로 얻게 되는 결과물은 시스템을 구성하는 객체들의 인터페이스와 오퍼레이션 목록이다.

  • 정보 전문가에게 책임을 할당하면 행동상태를 함께 갖는 자율적인 객체를 만들 가능성이 높아진다.

  • 메세지객체를 결정한다.

  • 필요한 메시지를 먼저 식별하고 메시지를 처리할 객체를 나중에 선택함으로써 최소한의 인터페이스충분히 추상적인 인터페이스 (How가 아닌 What을 표현하는 인터페이스)를 얻을 수 있다.

  • 객체가 어떤 특정한 협력 안에서 수행하는 책임의 집합을 역할이라고 부른다.

  • 실제로 협력을 모델링 할때는 특정한 객체가 아니라 역할에게 책임을 할당한다고 생각하는게 좋다.

  • 역할은 다른 것으로 교체할 수 있는 책임의 집합이다.

  • 역할은 다양한 종류의 객체를 수용할 수 있는 일종의 슬롯이자 구체적인 객체들의 타입을 캡슐화하는 추상화이다.

  • 추상화상위 정책의 흐름을 표현하고 구체적인 구현체들은 상위 정책의 흐름을 그대로 따라가기 때문에 재사용 가능한 협력을 표현할 수 있다. 따라서 역할추상화로써 유연하고 재사용 가능한 협력을 표현할 수 있다.

  • 설계 초반에는 적절한 책임과 협력의 큰 그림을 탐색하는 것이 가장 중요한 목표여야 하고 역할과 객체를 명확하게 구분하는 것은 그렇게 중요하지 않다는 점을 기억하자.

  • 중요한 것은 협력을 구체적인 객체가 아니라 추상적인 역할의 관점에서 설계하면 협력이 유연하고 재사용 가능해진다는 것이다. 따라서 역할의 가장 큰 장점은 설계의 구성 요소를 추상화할 수 있다는 것이다.

  • 역할공통의 책임을 바탕으로 객체의 종류를 캡슐화하기 때문에 이런 관점에서 역할객체의 추상화로 볼 수 있다.

  • 추상화를 적절히 이용하면 불필요한 세부사항을 생략하고 핵심적인 개념을 강조할 수 있다.

  • 역할이 중요한 이유는 동일한 행동을 수행하는 객체들을 추상화할 수 있기 때문이다.

  • 추상화를 적절히 이용하면 설계를 유연하게 만들 수 있다. 협력 안에서 동일한 책임을 수행하는 객체들은 동일한 역할을 수행하기 때문에 서로 대체 가능하다.

  • 협력 안에서 역할이라는 추상화를 이용하면 기존 코드를 수정하지 않고도 새로운 행동을 추가(AnotherDiscountPolicy)할 수 있다.


협력

협력

객체지향 원칙을 따르는 애플리케이션의 제어 흐름은 어떤 하나읜 객체에 의해 통제되지 않고 다양한 객체들 사이에 균형있게 분배되는 것이 일반적이다. 객체들은 요청의 흐름을 따라 자신에게 분배된 로직을 실행하면서 애플리케이션의 전체 기능을 완성한다.

여기서 중요한 것은 다양한 객체들이 기능을 구현하기 위해 메시지를 주고받으면서 상호작용 한다는 점이다. 이처럼 객체들이 애플리케이션의 기능을 구현하기 위해 수행하는 상호작용협력이라고 한다.

객체가 협력에 참여하기 위해 수행하는 로직을 책임이라고 부른다.

객체들이 협력 안에서 수행하는 책임들이 모여 객체가 수행하는 역할을 구성한다.

협력은 객체지향의 세계에서 기능을 구현할 수 있는 유일한 방법이다. 두 객체 사이의 협력은 하나의 객체가 다른 객체에게 도움을 요청할 때 시작된다. 메시지 전송은 객체 사이의 협력을 위해 사용할 수 있는 유일한 커뮤니케이션 수단이다.

협력이란 어떤 객체가 다른 객체에게 무엇인가를 요청하는 것이다.

메시지를 수신한 객체는 메서드를 실행해 요청에 응답한다. 객체가 메시지를 처리할 방법을 스스로 선택한다는 점이 중요하다.

외부의 객체는 오직 메시지만을 전송할 수 있을 뿐이며 메시지를 어떻게 처리할지는 메시지를 수신한 객체가 직접 결정한다.

이것은 객체가 자신의 일을 스스로 처리할 수 있는 자율적인 존재라는 것을 의미한다. 자율적인 객체자신의 상태를 직접 관리하고 스스로의 결정에 따라 행동하는 객체다.

객체의 자율성을 보장하기 위해서는 ‘필요한 정보’와 ‘정보에 기반한 행동’을 같은 객체 안에 모아놓아야 한다.

Movie가 자율적인 존재가 되기 위해서는 자신이 알고 있는 정보를 이용해 직접 요금을 계산해야 한다.

자신이 할 수 없는 일을 다른 객체에게 위임하면 협력에 참여하는 객체들의 전체적인 자율성을 향상시킬 수 있다.

결과적으로 객체를 자율적으로 만드는 가장 기본적인 방법은 ‘내부 구현을 캡슐화’하는 것이다. 캡슐화를 통해 변경에 대한 파급효과를 제한할 수 있기 때문에 자율적인 객체는 변경하기도 쉬워진다.

자율적인 객체는 자신에게 할당된 책임을 수행하던 중에 ‘필요한 정보’를 알지 못하거나 외부의 도움이 필요한 경우 적절한 객체에게 ‘메시지를 전송’해서 협력을 요청한다.

이처럼 객체들 사이의 협력을 구성하는 일련의 요청과 응답의 흐름을 통해 애플리케이션의 기능이 구현된다.

협력이 설계를 위한 문맥을 결정한다.

객체가 가질 수 있는 상태와 행동을 어떤 기준으로 결정해야 할까?

객체를 설계할 때 어떤 행동과 상태를 할당했다면 그 이유는 무엇인가?

객체가 협력에 필요한 적절한 행동을 보유하고 있기 때문이다. 결론적으로 객체의 행동을 결정하는 것은 객체가 참여하고 있는 협력이다. 예를들어 Movie의 행동(요금 계산)을 결정하는 것은 영화 예매를 위한 협력이다. 협력이라는 문맥을 고려하지 않고 Movie의 행동을 결정하는 것은 아무런 의미가 없다. 협력이 존재하기 때문에 객체가 존재하는 것이다.

객체의 행동을 결정하는 것이 협력이라면 객체의 상태를 결정하는 것은 행동이다.

객체의 상태는 그 객체가 행동을 수행하는 데 필요한 정보가 무엇인지로 결정된다.

상태는 객체가 행동하는데 필요한 정보에 의해 결정되고 행동은 협력 안에서 객체가 처리할 메시지로 결정된다. 결과적으로 객체가 참여하는 협력이 객체를 구성하는 행동상태 모두를 결정한다. 따라서 협력은 객체를 설계하는 데 필요한 일종의 문맥(Context)를 제공한다.

책임

책임이란 무엇인가.

객체를 설계하기 위해 필요한 협력이 갖추어졌다면 다음으로 할 일은 협력에 필요한 행동을 수행할 수 있는 적절한 객체를 찾는 것이다. 이때 협력에 참여하기 위해 객체가 수행하는 행동책임이라고 부른다.

책임이란 객체가 유지해야 하는 정보객체가 수행할 수 있는 행동에 대해 개략적으로 서술한 문장이다. 객체의 책임은 객체가 무엇을 알고있는가(무엇을 알아야 하는가)무엇을 할 수 있는가(무엇을 해야하는가)로 구성된다. 이러한 분류 체계에 따라 객체의 책임을 크게 하는 것(Doing)아는 것(Knowing)의 두 가지 범주로 나누어 세분화 할 수 있다.

  • 하는 것(Doing)
    • 객체를 생성하거나 계산을 수행하는 등의 스스로 하는 것
    • 다른 객체의 행동을 시작시키는 것
    • 다른 객체의 활동을 제어하고 조절하는 것
  • 아는 것(Knowing)
    • 사적인 정보에 관해 아는 것
    • 관련된 객체에 관해 아는 것
    • 자신이 유도하거나 계산할 수 있는 것에 관해 아는 것

Movie예매 가격을 계산할 책임을 진다. 이것은 하는 것(Doing)과 관련된 책임이다. 또한 영화 가격과 어떤 할인 정책이 적용됐는지도 알고 있어야 한다. 이것은 아는 것(Knowing)과 관련된 책임이다.

MoviecalculateMovieFee 메시지를 수신할 수 있고 feediscountPolicy를 속성으로 갖는 이유는 협력 안에서 가격을 계산할 책임을 할당받아기 때문이다. 이처럼 협력 안에서 객체에게 할당한 책임이 외부의 인터페이스와 내부의 속성을 결정한다.

일반적으로 책임메시지의 크기는 다르다. 책임은 객체가 수행할 수 있는 행동을 종합적이고 간략하게 서술!!!하기 때문에 메시지보다 추상적이고 개념적으로도 더 크다. 처음에는 단순하게 책임이라고 생각했던 것이 여러개의 메시지로 분할되기도 하고 하나의 객체가 수행할 수 있다고 생각했던 책임이 나중에는 여러 객체들이 협력해야만 하는 커다란 책임으로 자라는 것이 일반적이다.

책임의 관점에서 아는 것하는 것은 밀접하게 연관되어 있다. 객체는 자신이 맡은 책임을 수행하는 데 필요한 정보를 알고있을 책임이 있다. 또한 객체는 자신이 할 수 없는 작업을 도와줄 객체를 알고있을 책임이 있다.

어떤 책임을 수행하기 위해서는 그 책임을 수행하는 데 필요한 정보도 함께 알아야 할 책임이 있는 것이다.

객체지향에서 가장 중요한 것은 책임이다. 객체에게 얼마나 적절한 책임을 할당하느냐고 설계의 전체적인 품질을 결정한다.

책임 할당.

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

여기서 잠깐. 정보 전문가에게 책임을 할당한다고 하였는데 그렇다면 어떤 객체가 정보 전문가인지는 어떻게 알 수 있을까?

start1

정보 전문가에 대한 판단은 도메인에 대한 정확한 이해직관이 필요하다. 더불어 객체는 스스로를 책임지는 자율적인 존재라는 기본적인 개념을 적용해보면 누가 정보 전문가인지는 생각보다 판단하기가 수월해 지는 경우가 많다.

이런 고민에도 누가 정보 전문가인지 판단하기 쉽지 않다면 짐작되는 객체 후보들에게 책임을 할당해보고 응집도, 결합도 측면에서 더욱 적절한 객체에게 할당하는 것도 경험적으로 나쁘지 않은 선택이었다.

예를 들어 MovieScreening할인 정책에 대해 알고있을 책임이 있는 정보 전문가가 누구인지 헷갈렸다.

  • 영화 요금 계산을 위해 영화 요금에 대한 정보를 가장 잘 알고 있는 객체는 Movie이다.
    1. 영화 요금 계산 책임을 수행하기 위해서는 할인 정책에 대한 정보가 필요하므로 Movie할인 정책에 대한 정보를 알고있어야 할 책임을 할당한다.
    2. Movie로 부터 영화 기본 요금만 계산하도록 하고 할인 적용 요금 계산Screening에 할당한다.

위에서와 같이 1번(Movie에 할당)과 2번(Screening에 할당)이 헷갈렸다. 물론 처음부터 도메인에 대한 정확한 이해가 있었다면(할인 정책은 영화 별 적용) 좀 더 쉽게 책임을 할당할 수 있었겠지만 그렇지 않은 경우 2번에 대한 고민도 함께 해볼 수 있다.

만일 2번과 같이 Screening할인 적용 요금 계산 책임을 할당한다면 우선 응집도가 낮아진다. Screening영화 요금 계산의 책임 일부를 떠안게 되는 셈이다. 이에 따라 Screening할인 정책에 대해서도 알고 있어야 하므로 결합도 역시 높아진다. 따라서 1번과 같이 Movie에 할당하는 것이 더 좋은 설계라고 볼 수 있다.

end1

start2

학습을 진행하던 중 위의 MovieScreening의 책임 할당 과정에서 떠오른 것이 있어서 덧붙인다. 생각해보면 상당히 간단하다.

먼저 책임과 관련하여 머릿속에 염두해야할 것이 있다.

  1. 알아야 할 책임이란 맡은 책임을 수행하는 데 필요한 정보에 대해 알아야 할 책임을 의미한다.
  2. 필요한 정보란 자신이 직접 유도하거나 계산할 수 있는 것에 대해 아는 것도 있지만 필요한 정보와 관련된 객체에 대해 아는 것도 필요한 정보를 알아야 할 책임에 해당한다.
  3. 책임은 시스템의 책임인 큰 책임(추상적)에서 시작하여 각 객체들에게 적절히 분배 및 할당되며 조금씩 작아진다(세분화)

자. 그렇다면 다시 MovieScreening으로 돌아와서 Screening의 책임은 보다 추상적이고 큰 책임인 예매하다.이다. 그리고 이 예매 책임을 수행하기 위해서 요금을 계산할 수 있어야 하는데, 이 책임을 우리는 Movie에게 할당하였다.

  • Screening의 책임 : 예매하다.
  • Movie의 책임 : 요금을 계산하다.

그리고 Movie요금을 계산하기 위한 책임을 수행하기 위해서는 할인 요금에 대한 정보가 필요하다. 즉, Movie할인 요금과 관련된 정보에 대해 알아야 할 책임이 존재한다. 위에서는 할인 요금과 관련된 정보를 할인 정책으로 표현하였으므로 할인 요금과 관련된 정보인 할인 정책에 대해서 알아야 할 책임은 자연스럽게 Movie에게 있는것이다.

정리하자면 예매하다라는 보다 추상적이고 큰 책임에서 시작하여 요금을 계산하다라는 작은 책임이 Movie에게 할당되었고. 이 요금을 계산하는 책임을 수행하기 위해서는 할인 요금에 대한 정보를 알아야 했다. 그리고 할인 요금과 관련된 정보가 바로 할인 정책이므로, 결과적으로 Movie가 책임을 수행하기 위해서 알아야 할 정보가 할인 정책인 것이다.

end2

start3

조금 더 나아가서 할인 요금 계산은 변경되는 부분(가변적)이므로 캡슐화/추상화의 대상이 된다. 사람에 따라 할인 정책 타입을 캡슐화 하여 합성 관계로 설계(현재의 설계)하는 사람이 있을 것이고 Movie 타입을 추상화 하여 할인 요금 계산이라는 추상 메서드를 사용하는 메서드 추상화를 사용하는 사람도 있을 것 같다.

end3

객체지향 설계는 시스템의 책임을 완료하는 데 필요한 더 작은 책임을 찾아내고 이를 객체들에게 할당하는 반복적인 과정을 통해 모양을 갖춰간다.

이처럼 객체지향 설계는 협력에 필요한 메시지를 찾고 메시지에 적절한 객체를 선택하는 반복적인 과정을 통해 이뤄진다. 그리고 이런 메시지메시지를 수신할 객체의 책임을 결정한다.

이렇게 결정된 메시지객체의 퍼블릭 인터페이스를 구성한다는 것 역시 눈여겨 보자. 협력을 설계하면서 객체의 책임을 식별해 나가는 과정에서 최종적으로 얻게 되는 결과물은 시스템을 구성하는 객체들의 인터페이스와 오퍼레이션 목록이다.

모든 책임 할당 과정이 이렇게 단순한 것은 아니다. 위에서 언급했듯 어떤 경우에는 응집도결합도 관점에서 정보 전문가가 아닌 다른 객체에게 책임을 할당하는 것이 더 적절한 경우도 있다. 하지만 기본적인 전략은 책임을 수행할 정보 전문가를 찾는것이다. 정보 전문가에게 책임을 할당하는 것만으로도 상태행동을 함께 가지는 자율적인 객체를 만들 가능성이 높아지기 때문이다.

책임 주도 설계

  • 시스템이 사용자에게 제공해야 하는 기능인 시스템 책임을 파악한다.

  • 시스템 책임더 작은 책임으로 분할한다.

  • 분할된 책임을 수행할 수 있는 적절한 객체 또는 역할을 찾아 책임을 할당한다.

  • 객체가 책임을 수행하는 도중 다른 객체의 도움이 필요한 경우 이를 책임질 적절한 객체 또는 역할을 찾는다.

  • 해당 객체 또는 역할에게 책임을 할당함으로써 두 객체가 협력하게 한다.

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

객체에게 책임을 할당하는 데 필요한 메시지를 먼저 식별하고 메시지를 처리할 객체를 나중에 선택한다는 것이 중요하다. 다시 말해 객체가 메시지를 선택하는 것이 아니라. 메시지가 객체를 선택하게 한다. 이와 같이 메시지가 객체를 선택하게 해야 하는 두 가지 중요한 이유가 있다.

  1. 객체가 최소한의 인터페이스를 갖게 된다. 필요한 메시지가 식별될 때 까지 객체의 퍼블릭 인터페이스에 어떤 것도 추가하지 않아도 된다.

  2. 객체는 충분히 추상적인 인터페이스를 갖게 된다. 객체의 인터페이스는 무엇(What)을 표현해야 하지만 어떻게(How) 수행하는지를 노출해서는 안된다. 메시지는 외부의 객체가 요청하는 무엇인가를 의미하기 때문에 메시지를 먼저 식별하면 무엇을 ㅅ구행할지에 초점을 맞추는 인터페이스를 얻을 수 있다.

행동이 상태를 결정한다.

객체가 존재하는 이유는 협력에 참여하기 위해서다. 객체는 협력에 필요한 행동을 제공해야 한다. 객체를 객체답게 만드는 것은 객체의 상태가 아니라 객체가 다른 객체에게 제공하는 행동이다.

객체의 행동은 객체가 협력에 참여할 수 있는 유일한 방법이다. 상태행동을 결정하고 나서야 비로소 결정할 수 있다.

역할

역할과 협력

객체의 목적은 협력 안에서 객체가 맡게되는 책임의 집합으로 표시된다. 이처럼 객체가 어떤 특정한 협력 안에서 수행하는 책임의 집합을 역할이라고 부른다.

실제로 협력을 모델링 할때는 특정한 객체가 아니라 역할에게 책임을 할당한다고 생각하는게 좋다.

유연하고 재사용 가능한 협력

역할이 중요한 이유는 역할을 통해 유연하고 재사용 가능한 설계를 얻을 수 있기 때문이다. 여기서 DiscountPolicyAmountDiscountPolicy, PercentDiscountPolicy로 대체 가능한 역할로써 할인 요금 계산이라는 동일한 책임을 수행하는 구체적인 객체들의 추상화이다.

앞선 챕터에서 언급했던 것 처럼 추상화상위 정책의 흐름을 표현하고 구체적인 구현체들은 상위 정책의 흐름을 그대로 따라가기 때문에 재사용 가능한 협력을 표현할 수 있다. 따라서 역할추상화로써 유연하고 재사용 가능한 협력을 표현할 수 있다.

역할은 다른 것으로 교체할 수 있는 책임의 집합이다.

역할의 구현

추상화라는 말에서 예상했겠지만 역할을 구현하는 가장 일반적인 방법은 추상 클래스인터페이스를 사용하는 것이다. 협력의 관점에서 추상 클래스와 인터페이스는 구체 클래스들이 따라야 하는 책임의 집합을 서술한 것이다.

여기서 중요한 것은 역할이 다양한 종류의 객체를 수용할 수 있는 일종의 슬롯이자 구체적인 객체들의 타입을 캡슐화하는 추상화라는 것이다.

객체 vs 역할

역할객체가 참여할 수 있는 일종의 슬롯이다. 하지만 대부분의 경우 어떤 것이 역할이고 어떤 것이 객체인지가 또렷하게 드러나지는 않을 것이다. 특히나 명확한 기준을 세우기 어렵고 정보가 부족한 설계 초반에는 결정을 내리기가 더욱 어려울 것이다. 도메인 모델 안에는 개념과 객체와 역할이 어지럽게 뒤섞여 있다.

혼란을 덜기 위해서 설계 초반에는 적절한 책임과 협력의 큰 그림을 탐색하는 것이 가장 중요한 목표여야 하고 역할과 객체를 명확하게 구분하는 것은 그렇게 중요하지 않다는 점을 기억하자.

따라서 애매하다면 단순하게 객체로 시작하고 반복적으로 책임협력을 정제해 나가면서 필요한 순간에 객체로부터 역할을 분리해내는 것이 가장 좋은 방법이다.

처음에 특정 시나리오에 대한 협력을 구상할 때는 아마도 도메인 모델에 있는 개념들을 후보로 선택하여 직접 책임을 할당할 것이다. 다양한 시나리오를 설계로 옮기면서 협력을 지속적으로 정제하다 보면 두 협력(AmountDiscountPolicy와의 협력, PercentDiscountPolicy와의 협력)이 거의 유사한 구조를 보인다는 것을 발견하게 될 것이다. 이 경우 두 협력을 하나로 합치면서 두 객체를 포괄할 수 있는 역할을 고려해서 객체를 역할로 대체(DiscontPolicy라는 역할로 대체)할 수 있다.

중요한 것은 협력을 구체적인 객체가 아니라 추상적인 역할의 관점에서 설계하면 협력이 유연하고 재사용 가능해진다는 것이다. 따라서 역할의 가장 큰 장점은 설계의 구성 요소를 추상화할 수 있다는 것이다.

역할과 추상화

역할공통의 책임을 바탕으로 객체의 종류를 캡슐화하기 때문에 이런 관점에서 역할객체의 추상화로 볼 수 있다.

추상화의 첫 번째 장점은 세부 사항에 억눌리지 않고도 상위 수준의 정책을 쉽고 간단하게 표현할 수 있다는 것이다. 추상화를 적절히 이용하면 불필요한 세부사항을 생략하고 핵심적인 개념을 강조할 수 있다.

협력이라는 관점에서는 세부적인 사항을 무시하고 추상화에 집중하는 것이 유용하다.

객체들에게 중요한 것은 행동이라는 것을 기억하자. 역할이 중요한 이유는 동일한 행동을 수행하는 객체들을 추상화할 수 있기 때문이다.

추상화의 두 번째 장점은 설계를 유연하게 만들 수 있다는 것이다. 협력 안에서 동일한 책임을 수행하는 객체들은 동일한 역할을 수행하기 때문에 서로 대체 가능하다.

협력 안에서 역할이라는 추상화를 이용하면 기존 코드를 수정하지 않고도 새로운 행동을 추가(AnotherDiscountPolicy)할 수 있다.

프레임워크나 디자인 패턴과 같이 재사용 가능한 코드설계 아이디어를 구성하는 핵심적인 요소가 바로 역할이다.

참고 및 출처

  • 오브젝트