[DDD] DDD 입문에 좋은 글

여기에 왕창있더군요. 사부님이 읽고 공부하라고 적극 추천해주는 바람에 출근해서 지금까지 모두 정독해버렸습니다. 개념 설명도 충분하고 중간 중간 코드도 같이 주셔서 이해하기가 더 좋았습니다. TDD까지 권하시는 센스.. 캬~~ 읽으면서 많이 감탄했네요.

이터니티님 감사합니다. 잘 읽었습니다~ 계속해서 연재해 주세요~

2009/03/25   Domain-Driven Design의 적용-4.ORM과 투명한 영속성 4부 [1]
2009/02/27   Domain-Driven Design의 적용-4.ORM과 투명한 영속성 3부
2009/02/23   Domain-Driven Design의 적용-4.ORM과 투명한 영속성 2부
2009/02/15   Domain-Driven Design의 적용-4.ORM과 투명한 영속성 1부
2009/01/18   Domain-Driven Design의 적용-3.Dependency Injection과 Aspect-Oriented Programming 7부 [2]
2009/01/02   Domain-Driven Design의 적용-3.Dependency Injection과 Aspect-Oriented Programming 6부
2008/12/24   Domain-Driven Design의 적용-3.Dependency Injection과 Aspect-Oriented Programming 5부 [2]
2008/12/17   Domain-Driven Design의 적용-3.Dependency Injection과 Aspect-Oriented Programming 4부
2008/12/13   Domain-Driven Design의 적용-3.Dependency Injection과 Aspect-Oriented Programming 3부
2008/12/09   Domain-Driven Design의 적용-3.Dependency Injection과 Aspect-Oriented Programming 2부
2008/12/05   Domain-Driven Design의 적용-3.Dependency Injection과 Aspect-Oriented Programming 1부
2008/11/30   Domain-Driven Design의 적용-2.AGGREGATE와 REPOSITORY 5부
2008/11/27   Domain-Driven Design의 적용-2.AGGREGATE와 REPOSITORY 4부
2008/11/25   Domain-Driven Design의 적용-2.AGGREGATE와 REPOSITORY 3부
2008/11/23   Domain-Driven Design의 적용-2.AGGREGATE와 REPOSITORY 2부
2008/11/20   Domain-Driven Design의 적용-2.AGGREGATE와 REPOSITORY 1부
2008/11/17   Domain-Driven Design의 적용-1.VALUE OBJECT와 REFERENCE OBJECT 4부
2008/11/17   Domain-Driven Design의 적용-1.VALUE OBJECT와 REFERENCE OBJECT 3부
2008/11/16   Domain-Driven Design의 적용-1.VALUE OBJECT와 REFERENCE OBJECT 2부
2008/11/15   Domain-Driven Design의 적용-1.VALUE OBJECT와 REFERENCE OBJECT 1부 [2]

파트 3: Refactoring Toward Deeper Insight

리팩터링 수준

다른 책들은 너무 로우 레벨로 얘기하는데 그 보다는 도메인에 대한 통찰을 통한 또는 모델이 말하고자 하는 바를 분명하게 하는 것이 시스템의 실용성에 더 지대한 영향을 주는 리팩터링 이라는 이야기..

The refactorings that have the greatest impact on the viability of the system are those motivated by new insights into the domain or those that clarify the model’s expression through the code.

Deep Model

모델을 좀 더 심도있게 바라보도록.. 피상적인 모습으로만 축출한 모델이 다가 아니라는거…

A deep model provides a lucid expression of the primary concerns of the domain experts and their most relevant knowledge while it sloughs off the superficial aspects of the domain.

Supple Design

변경을 반영할 수 있는 설계가 되어야 한다.

In a process of constant refactoring, the design itself needs to support change.

Deep Model과 Supple Design은 Model-Driven Design을 뒷받침하는 두 개의 축이다.

A MODEL-DRIVEN DESIGN stands on two legs. A deep model makes possible an expressive design. At the same time, a design can actually feed insight into the model discovery process when it has the flexibility to let a developer experiment and the clarity to show a developer what is happening.

The Discovery Process

좋은 모델을 찾아가는 과정은 개인의 창의성에 달려있기도 하지만, 여러 패턴을 따를 수도 있겠다.

You will usually depend on creativity and trial and error to find good ways to model the concepts you discover, but sometimes someone has laid down a pattern you can follow.

가끔은 이론적인 얘기로 머리를 환기시키는 것도 좋네요.

Factories

Entity와 Aggregate는 보통 생성자에서 만들기는 너무 복잡해질 정도로 커지는 경향이 있다.

보통 객체를 요구하는 쪽에서 여러 인자들과 함께 생성자를 호출한다. 이러면 객체를 생성할 때 너무 많은 정보들을 알게 된다. 즉, 객체에 대한 클라이언트들이 객체 생성에 관한 정보를 알게 되는 것이고, 이 것은 도메인 객체와 Aggregate에 대한 Encapsulation을 깨트린다.

실제에서도 플라스틱, 고무, 철, 실리콘 등으로 프린터를 직접 만들진 않는다. 이런 복잡한 것들을 포함시키면 이해하기 어려운 설계가 된다. 따라서 복잡한 객체 생성 과정을 캡슐화하는 새로운 개념이 필요하다. 그게 바로 Factory다.

객체 생성 과정을 원자화Atomic하는 것은 중요하다. 그렇지 않으면, 만들다 만 객체를 생성할 수도 있다. 특히 Aggregate의 경우에 그렇다. 객체 생성이 실패하면, 예외를 발생시켜서 잘못된 값이 전달되지 않도록 해야한다.

따라서 복잡한 객체나 Aggregate 객체를 생성하는 책임을 별도의 객체로 위임하는 것이 좋다. 인터페이스를 제공하여 클라이언트가 구현 클래스에 직접 접근할 필요가 없도록 하라.

Factory와 관련된 GoF의 Design Pattern 중에 Factory Method 패턴과 Abstract Factory 패턴이 있다. 디자인 관점이 아니라 도메인 모델링 관점에서 살펴보겠다.

사용자 삽입 이미지참조 : http://en.wikipedia.org/wiki/Factory_method_pattern

Factory Method는 다른 객체를 생성하는데 필요로 하는 정보를 가지고 숨겨둔 객체 메소드이다. 이것은 클라이언트가 Aggregate에 속한 객체를 얻고 싶을 때 유용하다. Aggregate 루트에 객체 생성을 책임지는 메소드를 추가하면 된다.

사용자 삽입 이미지참조 : http://www.dofactory.com/Patterns/PatternAbstract.aspx

Abstract Factory는 객체 생성이 더 복잡하거나 객체 생성이 여러 개의 객체 생성을 포함하고 있는 경우에 사용한다. 예를 들어, Aggregate를 생성할 때, 그에 대한 책임을 별도의 Factory 객체에게 위임할 수 있다. Factory를 만드는 것은 객체 캡슐화를 위배하기 때문에 주의깊게 사용해야 한다.

Entity Factory와 Value Object Factory의 차이점. Value Object는 변하지 않는immutable 객체기 때문에, 한 번 만들어 지면 변하지 않아야 한다. Entity 는 immutable하지 않다. 매번 변하며, 식별성identity을 가지고 있다.

다음의 경우 Factory보다는 생성자를 사용하는게 좋다.

  • 객체 생성이 복잡하지 않을 때.
  • 객체 생성이 다른 객체 생성 과정을 포함하고 있지않으며, 오로지 인자로 넘어온 값들만 필요로 할 때.
  • 클라이언트가 구현 과정에 관심이 있을 때.
  • 계층구조가 없는 단순한 타입일 때. 어떤 구현체를 제공해야 할지 선택할 필요가 없기 때문에..

Entity 객체를 가져올 때 주의해야 할 것은 DB의 identity와 객체의 identity를 맞춰주어야 한다는 것이다.

Aggregates

Aggregate는 객체의 소속Ownership과 경계Boundary를 정의하기 위해 사용하는 도메인 패턴이다.

모델은 많은 도메인 객체들을 포함하고 있을 것이며, 이 도메인 객체들은 서로 거미줄처럼 연결되어 있을 것이다. 실제 도메인에서의 연관 관계는 코드와 DB에도 그대로 반영되어야 한다. 마치 한 사람의 고객이 계좌 하나를 가지고 있을 때 Customer와 Account 테이블처럼 말이다.

모델이 복잡해지는 것을 막기 위해서 최대한 간단하고 이해 가능한 수준으로 작성하려 할 것이다. 그러기 위해서 많은 시간을 모델들 사이의 관계를 제거하거나 단순화 하는데 소비한다. 하지만 1:1, 1:다, 다:다 등의 관계를 단순화하는 작업이 그리 간단하지 않은 것 같다.

Invariant도 마찬가지로 신경써야한다. Invariant는 데이터가 변경되더라도 유지되어야 할 규칙을 이야기한다. 하지만 복잡한 관계에서 변경은 도메인 객체에 해를 끼칠 수도 있다. 그래서 신중한 롹킹으로 여러 사용자들이 데이터를 동시에 사용할 수 있도록 한다.

그래서 Aggregate가 필요하다.

사용자 삽입 이미지
Aggregate는 데이터 변경에 영향을 받는 객체들을 하나의 유닛으로 묶어놓은 그룹이다. Root에 해당하는 Entity 객체를 통해서 외부와 내부의 객체들 사이를 경계짓고 있다. 경계 내부에 또 다른 Entity가 있을 때 해당 Entity의 identity는 aggregate 내부에서만 통용되는 지역적인 identity이다.

이렇게 되어있을 때 무경성을 지키는것이 훨씬 편하다. 외부에서 내부에 있는 객체들에 바로 접근할 수 없으며, 최상위 Entity 객체를 통해서 조작되기 때문이다.

또한 내부의 객체에 대한 복사본을 외부로 전달하는 것이 가능하다. 이렇게 되면, 외부에서 해당 객체를 지지고 볶아서 구워 삶아 먹든 별 문제가 없을 것이다.

내부의 객체들은 외부에 있는 다른 Aggregate의 Entity를 참조할 수 있다.
최상위 Entity는 Gloval Identity를 가지고 있다.

Modules

크고 복잡한 애플리케이션에서 모델은 갈수록 커지는 경향이 있다. 그러다가어느 시점에 도달하면 더이상 전체를 파악하기도 힘들고 그들의 관계를 이해할 수도 없을 만큼 복잡해진다.

모듈은 관련된 개념과 작업들을 묶어서 복잡도Complexity를 줄이기 위해 사용한다.

모듈을 사용하는 또 다른 이유는 코드의 품질과 관련이 있다. 높은 응집도Cohesion와 낮은 결합도Coupling을 유지하는 코드가 좋은 코드다.  모듈을 사용하면 응집도를 높이고 결함도를 떨어트린다. 왜냐면 모듈화 함으로써 기능적으로나 논리적으로 관련된 녀석들을 묶어주기 때문에 응집도는 높아지며, 모듈들은 모두 잘 정의된 인터페이스를 가지고 있기 떄문에 결함도를 낮춰준다.

사용자 삽입 이미지
모듈 이름은 유비쿼터스 언어의 일부에서 발췌해야 한다.

모듈을 한 번 만들고 그 역할을 정해두면, 그 내부에 많은 변화가 생기더라도 보통 모듈을 자주 변경하지 않는다. 하지만 프로젝트를 진행하면서 모듈을 얼려두지 말고 진화시키는 것을 권장한다. 모듈을 리팩토링하는 비용이 엄청나다는 것을 알지만 그래도 모듈을 유지하기 위해 돌아가는 방법을 선택하는 것 보다는 모듈을 변경하는게 좋다.