포스트

5장. 책임 할당하기

오브젝트 읽기6 / 13편 · 목차
  1. 들어가며...
  2. 1장. 객체, 설계
  3. 2장. 객체지향 프로그래밍
  4. 3장. 역할, 책입, 협력
  5. 4장. 설계 품질과 트레이드오프
  6. 5장. 책임 할당하기
  7. 6장. 메시지와 인터페이스
  8. 7장. 객체 분해
  9. 8장. 의존성 관리하기
  10. 9장. 유연한 설계
  11. 10장. 상속과 코드 재사용
  12. 11장. 합성과 유연한 설계
  13. 12장. 다형성
5장. 책임 할당하기


❐ 1. 책임 주도 설계를 향해


데이터 중심 설계에서 책임 중심의 설계로 전환되기 위해서는 다음의 두 원칙을 따라야 한다.

  • 데이터보다 행동을 먼저 결정하라
  • 협력이라는 문맥 안에서 책임을 결정하라


1-1. 데이터 보다 행동을 먼저 결정하라

객체를 설계하기 위한 질문 순서

  • 객체가 수행해야 하는 책임에 대해서 먼저 고민하고, 그 책임을 수행하는 데 필요한 데이터가 무엇인지 고민하라.


1-2. 협력이라는 문맥 안에서 책임을 결정하라

협력을 시작하는 주체는 메시지 전송자

  • 협력에 적합한 책임이란, 메시지 전송자에게 적합한 책임을 의미한다.
  • 즉, 객체가 메시지를 선택하는 것이 아니라 메시지가 객체를 선택하게 해야 한다.
  • 객체를 가지고 있기 때문에 메시지를 보내는 것이 아니고, 메시지를 전송하기 때문에 객체를 갖게 된 것이다.



❐ 2. 책임 할당을 위한 GRASP 패턴


GRASP(General Responsibility Assignment Software Pattern) 패턴

  • 일반적인 책임할당 소프트웨어 패턴의 약자
  • 객체에게 책임을 할당할 때 지침으로 삼을 수 있는 원칙들의 집합을 패턴 형식으로 정리한 것


2-1. 도메인 개념에서 출발하기

도메인 개념

  • 설계를 시작하기 전에 도메인에 대한 개략적인 모습을 그려 보는 것이 유용하다.
  • 어떤 책임을 할당해야 할 때 가장 먼저 고민해야 하는 유력한 후보는 바로 도메인 개념이다.
  • 시작하는 단계에서는 개념들의 의미와 관계가 정확하거나 완벽할 필요는 없다.
  • 도메인 개념을 정리하는데 너무 많은 시작을 들이지 말고 빠르게 설계와 구헌을 진행하라.


올바른 도메인은 존재하지 않는다.

  • 2장과 5장에서 보여주는 도메인 모델은 다르다.
    • 2장 : 할인 정책이라는 개념이 하나의 독립적인 개념으로 분리돼 있음.
    • 5장 : 할인 정책이라는 개념이 영화의 종류로 표현되어 있음.
  • 그렇다면 어느 쪽이 올바른 도메인 모델일까?
    • 정답 : 둘 다 (두 도메인 모두 올바른 구현을 이끌어낼 수만 있는 경우에만)


도메인 모델과 구현

  • 도메인 모델과 구현은 무관하지 않다.
  • 도메인 모델은 도메인을 개념적으로 표현한 것이지만, 그 안에 포함된 개념과 관계는 구현의 기반이 돼야 한다.


2-2. 정보 전문가에게 책임을 할당하라.

GRASP 첫 번째 원칙 : INFORMATION EXPERT(정보 전문가) 패턴

  • 책임을 수행할 정보를 가지고 있는 객체에게 책임을 할당하라.
    • 정보 ≠ 데이터
    • 정보를 알고 있다고 해서 저장할 필요까진 없기 때문
  • 이 패턴을 따르면
    • 정보와 행동을 최대한 가까운 곳에 위치시키기 때문에 캡슐화를 유지할 수 있다.
    • 필요한 정보를 가진 객체들로 책임이 분산되기 때문에 더 응집력 있고, 이해하기 쉬워진다.
    • 결과적으로 결합도가 낮아져서 간결하고 유지보수하기 쉬운 시스템을 구축할 수 있다.


2-3. 높은 응집도와 낮은 결합도

GRASP 두 번째 원칙 : LOW COUPLING 패턴 & HIGH COHESION 패턴

  • 이 원칙은 설계를 진행하면서 책임과 협력의 품질을 검토하는데 사용할 수 있는 중요한 평가 기준


LOW COUPLING 패턴

  • 설계의 전체적인 결합도가 낮도록 설계하라.
  • 현재의 책임 할당을 검토하거나, 여러 설계 대안들이 있을 때 낮은 결합도를 유지할 수 있는 설계를 선택하라.


HIGH COHESION 패턴

  • 높은 응집도를 유지할 수 있게 책임을 할당하라
  • 현재의 책임 할당을 검토하거나, 여러 설계 대안들이 있을 때 높은 응집도를 유지할 수 있는 설계를 선택하라.


2-4. 창조자에게 객체 생성을 할당하라

GRASP 세 번째 원칙 : CREATOR 패턴

  • 객체를 생성할 책임을 어떤 객체에게 할당할지에 대한 지침을 제공한다.
  • 이미 존재하는 객체 사이의 관계를 이용하기 때문에 설계가 낮은 결합도를 유지할 수 있게 한다.


예제. Reservation의 creator ‘Screening’

1
2
3
4
5
6
7
8
9
10
11
public class Screening {
    private Movie movie;
    private int sequence;
    private LocalDateTime whenScreened;

    public Reservation reserve(Customer customer, int audienceCount) {
        return new Reservation(customer, this, calculateFee(audienceCount), audienceCount);
    }
    
    //...
}
  • Screening은
    • 예매 정보를 생성 하는데 필요한 영화, 상영 시간, 상영 순번 등의 정보에 대한 전문가이다.
    • 예매 요금을 계 하는 데 필수적인 Movie에 알고 있다.
  • Reservation의 creator로 Screening을 선택하는 것이 적절해 보인다.



❐ 3. 구현을 통한 검증


3-1. 변경의 이유는 하나여야 한다.

코드를 통해 변경의 이유를 파악할 수 있는 방법

  1. 인스턴스 변수가 초기화되는 시점을 잘 확인하라.
    • 응집도가 낮은 클래스는 일부는 초기화되고, 일부는 초기화 되지 않는다.
    • 함께 초기화되는 속성을 기준으로 코드를 분리해야 한다.
  2. 메서드들이 인스턴스 변수를 사용하는 방식을 살펴보는 것이다.
    • 메서들이 사용하는 속성에 따라 그룹이 나뉜다면 클래스의 응집도가 낮다고 볼 수 있다.
    • 속성 그룹과 해당 그룹에 접근하는 메서드 그룹을 기준으로 코드를 분리해야 한다.


GRASP 네 번째 원칙 : POLYMORPHISM(다형성) 패턴

  • 객체의 타입에 따라 변하는 행동이 있다면 타입을 분리하고 변화하는 행동을 각 타입의 책임으로 할당하라
  • 하나의 클래스가 여러 타입의 행동을 구현하고 있는 것처럼 보인다면
    클래스를 분해하고 이 패턴에 따라 책임을 분산하라.


GRASP 다섯 번째 원칙 : PROTECTED VARIATION(변경 보호) 패턴

  • 변화가 예상되는 불안정한 지점들을 식별하고 그 주위에 안정된 인터페이스를 형성하도록 책임을 할당하라.
  • 예측 가능한 변경으로 인해 여러 클래스들이 불안정해진다면
    이 패턴에 따라 안정적인 인터페이스 뒤로 변경을 캡슐화하라.


도메인 구조가 코드의 구조를 이룬다.

  • 도메인 모델은 단순히 설계에 필요한 용어를 제공하는 것을 넘어 코드의 구조에도 영향을 미친다.
  • 여기서 강조하는 것은 변경 역시 도메인 모델의 일부라는 것
  • 따라서 구현을 가이드 할 수 있는 모델을 선택하라.


3-2. 변경과 유연성

변경에 대비할 수 있는 두 가지 방법

  1. 코드를 이해하고 수정하기 쉽도록 최대한 단순하게 설계하는 것
    • 대부분의 경우 좋은 방법
  2. 코드를 수정하지 않고도 변경을 수용할 수 있도록 코드를 더 유연하게 만드는 건
    • 유사한 변경이 반복적으로 발생하고 있다면 이 방법이 더 좋음


의존성은 유연성 관리의 문제

  • 요소들 사이의 의존성 정도가 유연성의 정도를 결정한다.
  • 유연성의 정도에 따라 결합도를 조절할 수 있는 능력은 개발자가 갖춰야하는 중요한 기술 중 하나.



❐ 4. 책임주도 설계의 대안


4-1. 메서드 응집도

응집도가 낮은 메서드는…

  • 로직의 흐름을 이해하기 위해 주석이 필요한 경우가 대부분


응집도가 높은 메서드는…

  • 전체적인 흐름을 이해하기 쉽워진다.
  • 변경 가능한 설계를 이끌어 내는 기반이 된다.


4-2. 객체를 자율적으로 만들자

  • 자신이 소유하고 있는 데이터를 자기 스스로 처리하도록 만드는 것이 자율적인 객체를 만드는 지름길이다.
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.