오브젝트 3. 역할, 책임, 협력

조현창·2022년 12월 18일
0

오브젝트

목록 보기
3/5

캡슐화

어떤 정보가 필요한 작업을 수행할 때 해당 정보를 가장 잘 아는 정보전문가 클래스에게 위임하고 메세지를 전송하는 방식으로 변경해 캡슐화를 할 수 있다.
예를 들어서 A클래스에 B와 C클래스가 합성돼있으며 B와 C의 상태가 필요한 작업을 수행할 때 getter와 setter를 직접 호출하는 것보다 해당 작업은 각각의 클래스에 메소드화 한 후 만약 다른 클래스가 필요하다면 인자로 인스턴스를 전달한다.
이렇게 하면 불필요한 getter, setter함수를 간소화할 수 있으며 외부에서 추상화단계가 낮은 getter, setter함수를 호출할 이유가 적어진다.

public class Movie {  
private Money fee;  
private DiscountPolicy discountPolicy;

public Money calculateMovieFee(Screening screening) {  
return fee.minus(discountPolicy.calculateDiscountAmount(screening));

} }

Movie는 자기 자신의 요금이 얼마인지 계산할 책임이 있으며 계산을 위해서 fee와 discountPolicy를 상태로 갖는다.
또한 계산 시 상영정보에 있는 시간 등의 정보를 알아야 하므로 Screening 클래스의 인스턴스를 인자로 전달받는다.
할인 요금계산은 영화의 책임과 동떨어져 있으므로 할인요금을 계산하는 메소드가 DiscountPolicy에 위임되어 있는 것은 타당하다.

책임이란

하는 것 메소드

  • 인스턴스를 생성하거나 상태를 이용하여 계산 하는 것
  • 다른 인스턴스에 메세지를 전달하여 동작시키는 것

아는 것 멤버변수, 상태

  • 사적인 정보에 관해 아는 것 (계산 되지 않는 상수, 고유정보 등)
  • 관련된 객체에 관해 아는 것 (인스턴스)
  • 자신이 유도하거나 계산할 수 있는 것에 관해 아는 것(원시타입 등)

CRC

후보: 클래스, 컴포넌트, 역할의 후보가 될 키워드
책임 : 하는 것, 아는 것
협력자: 함께 협력할 후보

책임 주도 설계

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

메세지를 먼저 만들고 적절한 클래스에 배정하므로써 얻는 장점이 있다.

  • 객체가 최소한의 공개된 메소드(인터페이스)를 가지게 된다. 만약 바텀업으로 클래스의 구체적인 사항을 먼저 정하다보면 구현을 먼저하게되므로 어떤 것을 공개해야할지 난감해질 수 있다.
  • 추상적인 인터페이스를 가질 수 있다. : 세부적인 구현은 제쳐두고 메세지를 먼저 식별하므로 어떻게보다 무엇을 하는지 중점적으로 정할 수 있다.

상태보다 메소드를 먼저

만약 상태를 먼저 구현하게 된다면 객체의 내부 구현이 공개된 메소드에 노출되어 캡슐화를 저해한다. 또한 공개된 메소드를 변경하게되면 자연스럽게 의존성을 가진 클래스들도 영향을 받는다. 이런 방식을 데이터 주도 설계라고 한다.
반대로 메세지가 객체를 결정하도록 하는 방식을 책임 주도 설계라고 한다.

할인 정책이 여러가지인 경우 할인된 요금을 계산하라는 책임은 동일하게 부여될 수 있다. 이는 중복된 코드를 유발하므로 역할을 하나 추가하여 상속하여 해결할 수 있다.

이 때 사용할 수 있는 방법이 추상클래스 혹은 인터페이스를 활용하는 것이다. 만약 중복된 부분이 있다면 추상클래스에서 템플릿 패턴등으로 해결하고 메세지는 같으나 구현이 다르다면 인터페이스로 해결한다.

OAuth의 경우 카카오, 애플, 구글이 모두 요청하는 주소도 다르고 반환되는 형태도 다르다. 하지만 OAuth2.0이라는 규격을 구현한 상태이기 때문에 해당하는 인터페이스 API가 마련돼있으므로 템플릿 패턴으로 이를 해결할 수 있을 것이다. 이 때 OAuth를 역할, 나머지 요소를 객체로 구현하면 된다.

만약 위의 사례와 달리 확장될 가능성이 없거나 아직 미정인 상태라면 구체적인 객체를 구현하고 다른 클래스를 단순화하고 합쳐나가다보면 역할이 보일 것이다.

역할 모델링

객체들의 협력패턴을 추상화하여 역할을 얻어냄으로써 재사용 가능한 시스템을 얻을 수 있다.

추상화의 장점

  • 세부 구현에 얽메이지않고 상위 수준의 정책을 간단하고 쉽게 표현할 수 있다. 할인 역시 할인을 수행한다는 추상화를 통해 세부적인 구현으로 내려가지 않고 역할을 얻어낼 수 있었다.
  • 협력을 추상화할 수 있다. 하는 것에서 사용되는 객체 역시 마찬가지로 추상화하여 역할을 얻어낼 수 있다.
  • 협력을 유연하게 만든다. 앞서 본 예시에서 DiscountCondition 혹은 DiscountPolicy는 해당 역할의 하위 객체로 언제든지 교체가 가능하다.

정리

객체는 역할의 구현체이며 언제든 해당 역할인 다른 객체들과 교체될 수 있는 유연한 것이다.
다형적으로 설계가 가능하므로 추상화가 잘 된 역할은 중복된 코드도 적고 유연하게 다른 역할들과 협력할 수 있다.

profile
공부중

0개의 댓글