도메인 주도 설계 (에릭 에반스, 2011) 독후감
도메인 주도 설계는 복잡한 도메인을 다뤄야 하는 소프트웨어 프로젝트에 박차를 가하는 것을 목표로 삼는 사고방식이자 우선순위의 모음이다. - 서문 33
도메인 주도 설계(Domain-Driven Design, 이하 DDD)는 기술이 아니라 사고방식이자 우선순위 모음이다. design patterns이 기술 관점으로 패턴을 배운다면 DDD는 설계 관점으로 패턴을 배우는 것이라 할 수 있다.
프로젝트에서 사용하는 언어가 분열되면 심각한 문제가 발생한다. 도메인 전문가는 자신의 전문 용어를 사용하고 기술적인 업무를 맡은 팀원들은 설계 측면에서 도메인에 관한 토론에 적합한 자신들만의 언어를 사용한다. - p25
이렇게 되면 용어와 용어 사이에 번역이라는 비용 발생. 팀에서 쓰는 보편 언어(UBIQUITOUS LANGUAGE)가 중요하다. 책에서도 강조하는데, 중요성을 다시 깨닫는 계기가 됐다. 영향을 받아 요즘 일할 때 용어를 유심히 살펴본다. 다르다면 빨리 조정하고 그 용어가 보편 언어가 되도록 노력한다.
여기에 덧붙여 용어를 만들려는 노력도 필요하다. 내 경험으로는 명확한 특징이 있어도 ’개선된 텍스트 컨트롤’. 뭐 이렇게 부르는 경우가 허다했다. ImprovedTextControl … 뭐 이런 이름 하고 비슷한 클래스가 너무 많아. 그러지 말고 예를 들면 “뱀 스크롤 컨트롤” 뭐 이런 식으로 용어를 만들었으면 좋지 않았을까 생각해 본다. 물론 적절한 비유가 필요. 그리고 보편 언어로 쓰여야 한다. 그리고 기왕 용어를 만드는 김에 영어로도 같이 표기. 주워서 클래스 이름으로 사용.
저자는 도메인을 배울 기회를 중요하게 생각한다. 그래서 외부 전문가에게 일을 맡길 일이 있어도 도메인 지식을 쌓을 수 있는 일감은 맡기지 않는다. 도메인 지식은 프로젝트를 수행하는 모든 사람에게 중요하다. 그런 면에서 게임이 도메인인 나는 행복한 편.
이 책을 통해 가장 많이 배운 건 설계 지식이다. 챕터 중 각종 설계에 대한 팁과 노하우가 담겨 있는 ’10. 유연한 설계’가 가장 도움이 많이 됐다. 큰 그림을 그리는 데 필요한 요소들을 잘 설명해서 설계 내공이 쌓인 느낌.
예제가 많아서 좋다. 초반에 예로 든 대화. 58 페이지에 나온 재미있는 즐겨찾기 구현 이야기. 407 페이지에 나오는 코끼리 예제 등. 제대로 이해 못 하고 넘어갈 뻔했는데, 예제를 보고 이해를 한 경우가 많았다.
하지만 문장이 꽤 어렵다. 잘 안 읽혀. 문장 호흡도 너무 길고. 바로 직구를 팍팍 던져줬음 좋겠는데, 설명을 왜 그리 변화구로 하는지… 답답한 경우가 많았다.
인상적인 문장들
- 이 책의 요점은 하나의 모델이 구현, 설계, 의사소통의 기초가 돼야 한다는 것이다. 이러한 각 목적에 각기 다른 모델을 갖추는 것은 바람직하지 않다. - p41
- 모델이 드러나면 사용자가 소프트웨어의 잠재력을 좀더 많이 접하게 되어 일관성 있고 예상 가능한 행위가 나타날 것이다. -p59
- MODEL-DRIVEN DESIGN에서 코드는 모델의 한 표현으로 볼 수 있다. 코드를 변경하는 것이 곧 모델의 변경에 해당한다. 누가 좋아하건 말건 프로그래머가 곧 모델러다. 그러므로 프로그래머가 훌륭한 모델링 업무를 할 수 있게 프로젝트를 구성하는 것이 바람직하다. - p61
- 도메인 주도 설계는 모델을 동작하게 만들어 애플리케이션의 문제를 해결한다. 지식탐구를 바탕으로 팀은 혼란스러운 정보의 거센 흐름 속에서 정수를 추출해 실제적인 모델로 만든다. MODEL-DRIVEN DESIGN은 모델과 구현을 매우 밀접하게 연결한다. UBIQUITOUS LANGUAGE는 개발자와 도메인 전문가, 소프트웨어 사이에 흐르는 모든 정보의 통로에 해당한다. - p62
- 이 책에서 제시하는 설계 방식은 대부분 ’책임 주도 설계(responsibility-driven design)’ 원칙을 따른다. - p66
- 어떤 프로젝트에서는 사용자 인터페이스와 애플리케이션 계층을 명확히 구분하지 않기도 하며, 여러 개의 인프라스트럭처 계층이 존재하는 프로젝트도 있다. 하지만 MODEL-DRIVEN DESIGN을 가능케 하는 것은 결정적으로 도메인 계층을 분리하는 데 있다. - p72
- 아키텍처에서 응집력 있는 도메인 설계가 시스템의 다른 부분과 느슨하게 결합될 수 있게 도메인 관련 코드를 격리한다면 아마 그러한 아키텍처는 도메인 주도 설계를 지원할 수 있을 것이다. - p81
- 수많은 객체는 본질적으로 해당 객체의 속성이 아닌 연속성과 식별성이 이어지느냐를 기준으로 정의된다. - p91
- 개념적 식별성이 없는 객체도 많은데, 이러한 객체는 사물의 어떤 특징을 묘사한다. - p99
- 모델에 포함된 어떤 요소의 속성에만 관심이 있다면 그것을 VALUE OBJECT로 분류하라. VALUE OBJECT에서 해당 VALUE OBJECT가 전하는 속성의 의미를 표현하게 하고 관련 기능을 부여하라. 또한 VALUE OBJECT는 불변적(immutable)으로 다뤄라. VALUE OBJECT에는 아무런 식별성도 부여하지 말고 ENTITY를 유지하는 데 필요한 설계상의 복잡성을 피하라. - p101
- 설계가 매우 명확하고 실용적이더라도 개념적으로 어떠한 객체에도 속하지 않는 연산이 포함될 때가 있다. 이러한 문제를 억지로 해결하려 하기보다는 문제 자체의 면면에 따라 SERVICE를 모델에 명시적으로 포함할 수 있다. - p107
- 도메인의 중대한 프로세스나 변환 과정이 ENTITY나 VALUE OBJECT의 고유한 책임이 아니라면 연산을 SERVICE로 선언되는 독립 인터페이스로 모델에 추가하라. 모델의 언어라는 측면에서 인터페이스를 정의하고 연산의 이름을 UBIQUITOUS LANGUAGE의 일부가 되게끔 구성하라. SERVICE는 상태를 갖지 않게 만들어라. - p109
- 기술적으로 고려해야 할 여러 사항이 있겠지만 모듈화하는 가장 주된 이유는 바로 인지적 과부하(cognitive overload) 때문이다. - p113
- MODULE로 쪼개지는 것은 코드가 아닌 바로 개념이다. - p113
- 모델 내에서 복잡한 연관관계를 맺는 객체를 대상으로 변경의 일관성을 보장하기란 쉽지 않다. 그 까닭은 단지 개별 객체만이 아닌 서로 밀접한 관계에 있는 객체 집합에도 불변식이 적용돼야 하기 때문이다. - p130
- 루트를 경유하지 않고는 AGGREGATE의 내부를 변경할 수 없다. 이런 식으로 AGGREGATE의 각 요소를 배치하면 AGGREGATE 안의 객체와 전체로서의 AGGREGATE의 상태를 변경할 때 모든 불변식을 효과적으로 이행할 수 있다. - p133
- 도메인 주도 설계의 목표는 기술보다는 도메인에 대한 모델에 집중해 더 나은 소프트웨어를 만들어내는 것이다. - p154
- 클라이언트는 이미 존재하는 도메인 객체의 참조를 획득하는 실용적인 수단을 필요로 한다. … 한편으로는 AGGREGATE 루트에서부터 순회하지 않고 정확히 필요한 데이터를 데이터베이스에서 뽑아내거나 몇 가지 특정한 객체를 가져오는 데 질의를 사용할 수도 있다. 도메인 로직은 질의와 클라이언트 코드로 들어가고, ENTITY와 VALUE OBJECT는 그저 데이터 컨테이너로 전락한다. 대부분의 데이터 접근 인프라스트럭처를 적용하는 데 따르는 급격한 기술적 복잡성으로 클라이언트 코드는 금방 복잡해지고, 이는 도메인 계층에 대한 개발자들의 이해 수준을 낮춰 모델을 도메인 계층과 동떨어진 것으로 만든다. - p154
- 이 경우 REPOSITORY가 데이터를 근거로 객체를 생성하므로 많은 이들이 REPOSITORY를 FACTORY로 생각하는데, 사실 기술적 관점에서는 그렇다고 볼 수 있다. 그러나 모델을 중심에 두는 것이 더 유용하며, 앞에서 언급한 것처럼 저장된 객체를 재구성하는 것이 새로운 개념적 객체를 생성하는 것은 아니다. 설계를 이러한 도메인 주도 관점에서 보면 FACTORY와 REPOSITORY의 책임이 뚜렷이 구분되는데, FACTORY가 새로운 객체를 만들어 내는 데 반해 REPOSITORY는 기존 객체를 찾아낸다. - p163
- 리팩터링의 효과는 선형적으로 증가하지 않는다. - p203
- 도메인 전문가가 사용하는 언어에 귀 기울여라. 복잡하게 뒤얽힌 개념들을 간결하게 표현하는 용어가 있는가? 여러분이 선택한 단어를 (아마도 더 적절하게) 고쳐주는가? 여러분이 특정 문구를 이야기할 때 도메인 전문가의 얼굴에서 곤혹스러운 표정이 사라지는가? 이 모두가 바로 모델에 기여하는 개념의 실마리에 해당한다. - p218
- 제약조건(constraint)은 특별히 중요한 범주의 모델 개념을 형성한다. 흔히 제약조건은 암시적인 상태로 존재하며, 이를 명시적으로 표현하면 설계를 대폭 개선할 수 있다. - p233
- 수행 방법에 관해서는 언급하지 말고 결과와 목적만을 표현하도록 클래스와 연산의 이름을 부여하라. 이렇게 하면 클라이언트 개발자가 내부를 이해해야 할 필요성이 줄어든다. - p262
- 계속적인 리팩터링을 토대로 변경되는 부분과 변경되지 않는 부분을 나누는 중심 축을 식별하고, 변경을 분리하기 위한 패턴을 명확하게 표현하는 CONCEPTUAL CONTOUR를 찾아라. 우선적으로 확실한 지식 영역을 구성하는 도메인의 일관성 있는 측면과 모델을 조화시켜라. - p278
- MODULE 내에서조차 의존성이 증가할수록 설계를 파악하는 데 따르는 어려움이 가파르게 높아진다. 이는 개발자에게 정신적 과부하(mental overload)를 줘서 개발자가 다룰 수 있는 설계의 복잡도를 제한한다. 아울러 명시적인 참조에 비해 암시적인 개념이 훨씬 더 많은 정신적 과부하를 초래한다. - p283
- 정제된 설계에서 흔히 볼 수 있는 일반적인 실천지침으로 ’CLOSURE OF OPERATION’이 있다. 이 명칭은 가장 정교한 개념체계인 수학에서 유래한 것이다. 1 + 1 = 2와 같은 덧셈 연산은 실수 집합에 대해 닫혀 있다. … 하지만 닫힘은 소프트웨어 설계에서도 매우 광범위하게 사용되는 기법이다. 하나의 XML 문서를 다른 XML 문서로 변환할 때 XSLT를 사용하곤 한다. XSLT 연산은 XML 문서 집합에 대해 닫혀 있다. 닫힘의 특성 덕분에 연산을 간단하게 해석할 수 있고 닫힌 연산을 연결하거나 결합하는 것에 관해 쉽게 생각할 수 있다. - p286
- 도메인 주도 설계에서 디자인 패턴을 활용하려면 동시에 두 가지 수준에서 패턴을 바라봐야만 한다. 한 가지 수준은 코드 내에 포함된 기술적인 측면을 다루는 디자인 패턴이다. 다른 수준은 모델 내에 포함된 개념 패턴이다. - p330
- 각 용어가 모호하지 않고 모순되는 규칙이 없는 모델의 내적 일관성을 단일화(unification)라 한다. - p358
- 디스틸레이션(distillation)은 혼합된 요소를 분리해서 본질을 좀더 값지고 유용한 형태로 뽑아내는 과정이다. 모델은 지식의 정수를 추출한 것이다. 더 심층적인 통찰력으로 향하는 모든 리팩터링을 거쳐 우리는 도메인 지식과 우선순위의 일부 중요한 측면을 추상화한다. - p427
Update
표지 사진 교체