Today I Learned

[도메인 주도 설계] 10. 유연한 설계 (1) 본문

도메인 주도 설계

[도메인 주도 설계] 10. 유연한 설계 (1)

하이라이터 2022. 2. 11. 02:09
728x90
  • 레거시 코드로 인한 중압감에 시달리지 않고 변경을 수용하기 위해 유연한 설계가 필요하다.
  • 과도한 추상 계층과 간접 계층은 오히려 유연성에 방해가 된다.
  • 유연하게 설계를 수정하기 위해서는 설계가 모델을 드러내어 쉽게 이해할 수 있어야 한다.
  • INTENTION-REVEALING INTERFACE(의도를 드러내는 인터페이스)
    • 컴포넌트를 사용하기 위해 컴포넌트의 구현 세부사항을 고려해야한다면 캡슐화의 가치는 사라진다.
    • 인터페이스를 구성하는 각 요소의 이름을 토대로 설계 의도를 드러내야 한다. 
    • 따라서 결과와 목적만을 표현하도록 클래스와 연산의 이름을 부여해야 한다.
    • 방법이 아닌 의도를 표현하는 인터페이스 뒤로 모든 까다로운 메커니즘을 캡슐화해야 한다.

    • 예제 - 리팩터링 : 페인트 혼합 애플리케이션
      • 메서드의 이름에서 의도를 드러내어 클래스의 용도에 대한 실마리를 제공할 수 있다.
      • 테스트로 표현된 예제가 있다면 더 쉽게 실마리를 찾을 수 있다.
  • SIDE-EFFECT-FREE FUNCTION(부수효과가 없는 함수)
    • 연산은 질의를 통해 정보를 얻거나, 명령을 통해 상태를 변경하는 것을 의미한다.
    • 부수효과란 연산에 영향을 미치는 시스템 상태의 변경을 뜻한다.
    • 다수의 규칙에 따라 상호작용하거나 여러가지 계산을 조합하면 결과를 예측하기가 어려워지고 부수효과가 발생하기 쉽다.
    • 함수는 부수효과를 일으키지 않으면서 결과를 반환하는 연산으로써 연산을 사용하는데 따르는 위험을 낮춘다.
    • 부수효과를 낮추는 방법
      1. 명령과 질의를 엄격하게 분리된 연산으로 유지한다. 모든 질의와 계산을 부수효과를 발생시키지 않는 메서드에서 수행한다.
      2. 명령과 질의를 분리하는 대신 연산의 결과를 표현하는 불변객체인 VALUE OBJECT를 생성해서 반환한다. 기존 상태를 변경하는 대신 VALUE OBJECT를 이끌어내거나 전체 책임을 VALUE OBJECT로 옮기는 식으로 부수효과를 제거할 수 있다.
    • 예제 - 페인트 혼합 애플리케이션 다시 리팩터링하기
      • 지식탐구 과정에서 색상 혼합(color mixing)과 페인트(paint)는 다르다는 것을 알게되었다.
      • pigment Color(안료 색소)로 색성과 관련된 데이터를 분리했다. pigment Color는 VALUE OBJECT이므로 불변 객체이다.
      • 따라서 pigment Color를 혼합하는 경우 상태를 변경하는 대신 새로운 색상을 표현하는 pigment Color 객체가 생성된다.또한 mixIn() 메서드 안에서 처리되고 있는 색상과 관련된 행위도 분리되어야 한다.
        public class Paint {
          public void mixIN(paint other) {
            volume = volume + other.getVolume();
            double ratio = other.getVolume() / volume;
            pigmentColor = pigmentColor.mixedWith(other.pigmentColor(), ratio);
          }
        }
  • ASSERTION(단언)
    • 단언은 임의의 연산이 종료된 후에 만족해야 하는 객체의 상태에 관해 개발자가 명시하는 것이다.
    • 불변식을 비롯해 사전조건과 사후조건을 명확하게 명시하면 객체나 연산을 사용한 결과를 이해할 수 있다.
    • "사후조건"은 연산의 부수효과를 의미하며 호출되는 연산에서 보장하는 결과를 기술한다.
    • "사전조건"은 계약에 명시된 단서와 조항과 유사하며 사후조건이 유효하기 위해 충족되어야하는 조건들이다.
    • 연산의 사후조건과 클래스 및 AGGREGATE의 불변식을 명시한다.
    • 프로그램 코드에 직접 ASSERTION을 명시할 수 없다면 자동화된 단위 테스트를 작성해서 내용을 표현한다.

    • 예제 - 다시 페인트 혼합 애플리케이션으로
      • 앞선 예제에서 Paint 클래스의 mixin(paint) 메시지를 수신하는 객체의 용량은 인자로 전달된 객체의 용량만큼 증가한다.
      • 그에 맞춰 인자의 용량도 감소시켜야한다. 하지만 인자를 변경하는 것은 매우 위험한 종류의 부수효과에 해당한다.
      • 인자를 변경하는 것은 좋은 방법은 아니지만 쉽고 직관적이다. 다음과 같은 불변식으로 작성할 수 있다.
        "페인트를 혼합하면 전체 용량은 변하지 않는다"
      • 그런데 프로그램의 목적이 추가된 순수한 페인트의 목록에 관한 보고서를 생성하는 것이라면 어떨까?
      • 논리적으로 일관성있는 페인트 용량 모델을 구축하는 대신 애플리케이션의 요구사항에 맞춰 새로운 모델을 찾을 필요가 있다.
      • Paint의 부여된 두가지 책임을 분리할 수 있다.
      • 명령은 mixIn() 하나 밖에 없으며, mixIn()은 단지 객체를 컬렉션에 추가할 뿐이다.
      • 테스트 메서드는 다음과 같다.
        public void testMixingVolume {
          pigmentColor yellow = new PigmentColor(0, 50, 0);
          pigmentColor blue = new PigmentColor(0, 0, 50);
          
          StockPaint paint1 = new StockPaint(1.0, yellow);
          StockPaint paint2 = new StockPaint(1.5, blue);
          MixedPaint mix = new MixedPaint();
          
          mix.mixIn(paint1);
          mix.mixIn(paint2);
          assertEquals(2.5, mix.getVolume(), 0.01);
        }​
  • SIDE-EFFECT FREE FUNCTION과 ASSERTION의 예측 가능성을 INTENTION-REVEALING INTERFACE의 의사전달력과 결합하면 더 안전한 캡슐화와 추상화가 가능해진다.
728x90
Comments