BLOG main image
분류 전체보기 (344)
NWC Consulting (1)
서비스 (173)
출판 (169)
일반 (0)
195,318 Visitors up to today!
Today 34 hit, Yesterday 86 hit
daisy rss
2009.12.14 06:30
6장은 DDD를 가능하게 하는 요소들을 다루는 매우 중요한 장입니다. 제대로 감을 잡기 위해서는 구현을 해 봐야 합니다. DDD를 적용하는 책이나 자료를 찾아서 구현해 보기를 권합니다. 
 
이 장의 여러 곳에서 DDD의 가치를 유감 없이 보여줍니다.  
저는 DDD가 새로운 방법론이나 새로운 명세나 설계 이론을 포함하고 있다라고 평가하지는 않습니다. 하지만 깊이 있게 구현 부분을 포함해서 현실적인 해결책을 제시하려는 시도는 처음이라고 생각합니다. 그리고 DDD의 모든 가치는 여기에 있다고 주장합니다. 


소프트웨어 세계는 복잡한 생명주기를 갖는 객체들이 살아가기엔 불완전한 세계입니다. 갑자기 어떤 객체의 존재도 보장할 수 없는 암흑의 세상이 될 수도 있습니다.
불완전한 세계를 거의 완전한 세계처럼 만드는 것은 큰 도전거리입니다. 저자는 그런 도전거리들을 다음과 같은 두 개의 범주로 구분합니다. 

Maintaining integrity throughout the life cycle.
Preventing the model from getting swamped by the complexity of managing the life cycle.


그리고 이들 도전거리들을 다룰 세 가지 패턴을 제시합니다.
Modeling Aggregates and adding Factories and Repositories to the design gives us the ability to manipulate the model objects systematically and in meaningful units throughout their life cycle.

Aggregates
mark off the scope within which invariants have to be maintained at every stage of the life cycle. Factories and Repositories operate on Aggregates, encapsulating the complexity of specific life cycle transitions.


Aggregates
쉽게 말해서 '서로 연관된 작은 객체들을 묶는 좀 더 큰 객체를 식별하고, 큰 객체 안에 작은 객체들을 캡슐화해서 관리를 편하게 해 보자'라는 것입니다. 이것은 객체보다 더 큰 단위의 재사용을 바랬던 컴포넌트기반개발(Component Based Development)에서 중요하게 다루어졌던 부분입니다.

An Aggregate is a cluster of associated objects that we treat as a unit for the purpose of data changes. Each Aggregate has a root and a boundary. The boundary defines what is inside the Aggregate. The root is a single, specific Entity contained in the Aggregate. The root is the only member of the Aggregate that outside objects are allowed to hold references to, although objects within the boundary may hold references to each other. Entities other than the root have local identity, but that identity needs to be distinguishable only within the Aggregate, because no outside object can ever see it out of the context of the root Entity.
Aggregate
mark off the scope within which invariants have to be maintained at every stage of the life cycle.

p128 마지막 문단에서는 어떻게 Aggregate를 구현해야 하는지를 열거하고 있습니다. 모두 Aggregate의 정의에서 파생한 상식적인 사실들입니다. 


Factories
Creation of an object can be a major operation in itself, but complex assembly operations do not fit the responsibility of the created objects. Combining such responsibilities can produce ungainly designs that are hard to understand. Making the client direct construction muddies the design of the client, breaches encapsulation of the assembled object or Aggregate, and overly couples the client to the implementation of the created object.

A program element whose responsibility is the creation of other objects is called a Factory.


좋은 팩토리는 어떠해야 하나?
Aggregate를 위한 팩토리는 당연히 Aggregate의 정의에 충실해야 합니다.
Each creation method is atomic and enforces all invariants of the created object or Aggregate. A Factory should only be able to produce an object in a consistent state. For an Entity, this means the creation of the entire Aggregate, with all invariants satisfied, but probably with optional elements still to be added. For an immutable Value Object, this means that all attributes are initialized to their correct final state. If the interface makes it possible to request an object that can't be created correctly, then an exception should be raised or some other mechanism should be invoked that will ensure that no improper return value is possible.

The Factory should be abstracted to the type desired, rather than the concrete class(es) created. The sophisticated Factory patterns in Gamma et al. 1995 help with this.

어떻게 팩토리를 선택하고 어디에 두어야 하나?
팩토리로 다루어져야 할 것들에 뭐가 있을까요?
Aggregate가 있습니다.
Aggregate에 포함되는 것들이 있습니다.
Aggregate도 아니고 Aggregate에 포함되지 않는 것들이 있습니다(이게 뭘까요?).

Aggregate가 포함하는 것들은 Aggregate에서 다루어지는 것이니 Aggregate에 둡니다.
Aggregate는 루트에 해당하니 어디에도 포함될 때가 없습니다. 독립적인 팩토리를 만들어야 하는 이유가 됩니다. 
Aggregate도 아니고 Aggregate에 포함되지도 않는 것은 어떻게? 관련성이 깊은 루트에 둡니다.

1. If you needed to add elements inside a preexisting Aggregate, you might create a Factory Method on the root of the Aggregate
2. It would be to place a Factory Method on an object that is closely involved in spawning another object, although it doesn't own the product once it is created. When the data and possibly the rules of one object are very dominant in the creation of an object, this saves pulling information out of the spawner to be used elsewhere to create the object. It also communicates the special relationship between the spawner and the product.
3. A standalone Factory usually produces an entire Aggregate.
If an object interior to an Aggregate needs a Factory, and the Aggregate root is not a reasonable home for it, then go ahead and make a standalone Factory. But respect the rules limiting access within an Aggregate, and make sure there are only transient references to the product from outside the
Aggregate.

팩토리 인터페이스를 설계할 때는
- 팩토리와 한 번의 상호작용으로 완벽한 제품을 생성할 수 있도록 필요한 모든 것을 제공해야 합니다.
- 불변식(invariant)이 만족하지 않을 때 어떻게 할 것인지를 결정해야 합니다.
- 주의 깊게 매개변수를 선택해야 합니다.

생성에 대한 불변식 체크는 제품에 두고 팩토리에서는 대리하는 것이 가장 좋지만 경우에 따라서 팩토리에 둘 수도 있습니다.

엔티티는 정체성을 가지니 팩토리는 id를 다룰 수 있어야 합니다.

생성을 위해서도 팩토리가 필요하지만 데이터베이스와 같은 저장소를 통해 객체를 재구성하기 위해서도 팩토리가 필요합니다.
재구축시에는 당연 저장된 id를 사용할 테니 매개변수로 id를 받아야 합니다. 또한 불변식 체크 방법도 달라집니다. 엔티티가 변경될 때마다 불변식이 체크되어 저장된다면 굳이 체크하지 않을 수도 있습니다.


Repositories

A Repository represents all objects of a certain type as a conceptual set (usually emulated). It acts like a collection, except with more elaborate querying capability. Objects of the appropriate type are added and removed, and the machinery behind the Repository inserts them or deletes them from the database. This definition gathers a cohesive set of responsibilities for providing access to the roots of Aggregates from early life cycle through the end.

Encapsulation of the persistence technology allows the client to be very simple, completely decoupled from the implementation of the Repository.
 
Encapsulation of the persistence technology allows the client to be very simple, completely decoupled from the implementation of the Repository.

Repository를 구현할 때,
타입을 추상화하고, 클라이언트에 트랜잭션 제어를 남겨둡니다.


팩토리와 비교해보면,
팩토리가 객체의 생의 시작을 다룬다면, 레파지토리는 중간과 끝을 다룹니다.
팩토리는 새로운 객체를 만들고, 레파지토리는 오래된 객체들을 찾습니다.


어떻게 팩토리와 레파지토리의 책임을 나눌 것인가? 그림 6.22, 6.23


Designing Objects for Relational Databases에서 여러 가지 이야기를 합니다. 저는 여기서 내용은 여러분에게 맡기고 저의 생각을 좀 이야기 해 보려고 합니다.
누군가의 비판을 받는다고 하더라도 조금은 과격하고 격분된 상태로 이야기 해보려 합니다. 
초등학생, 대학생 언급하는 것은 '객체 모델로 데이터 모델을 만들어야 한다', '데이터 모델을 제발 좀 제대로 만들어야 한다'를 강조하기 위해 충격요법으로 사용한 것입니다. 누구를, 특별한 업역을 낮추어 표현하려는 의도는 없습니다.      


Barker ER과 같은 관계형 모델을 보면, 속성이 단일 값을 갖는 것과 같은 소소한 차이를 제외하곤 객체모델과 거의 유사합니다. 이들 관계형 모델은 관계형 데이터베이스에 매핑 방법을 이미 갖고 있습니다. 따라서 몇 가지 보완할 사항만을 준비한다면 객체모델을 관계형 데이터베이스에 매핑하는 것은 어렵지 않습니다.  
그렇다고 해서 발전된 관계형 모델이 객체 모델을 대체할 수는 없습니다. 여기에서 소소한 차이란 매핑에 있어서의 차이를 이야기하는 것입니다. 모델의 의미를 표현할 때는 이러한 소소한 차이가 큰 차이를 가져옵니다. 그래서 저는 데이터 설계의 논리적 모델은 객체 모델을 사용해야 한다고 주장합니다. 

객체모델링의 진보에도 불구하고 아직까지 많은 프로젝트들에서 관계형 데이터베이스를 기준으로 애플리케이션을 설계하는 모습들을 봅니다. 저는 가끔 이런 모습을 똑똑한 초등학생들이 멍청한 대학생을 회초리로 때려가면서 프로젝트 하는 모습으로 비유합니다. 대학생이 다루는 도구를 가지고 있으면서도 초등학생이 다루는 도구를 가지고 있는 사람보다 더 못한 결과를 만들어 낸다는 것입니다. 회초리 맞는 것을 정당화하는 사람도 있습니다. 원래 그렇게 하는 것이 아니냐고 반문합니다. 왜 여기서는 회초리를 안 맞느냐고 묻습니다. 

설계 능력을 키워야 합니다. DDD를 신봉하든 또 다른 것을 신봉하든 제대로 된 객체모델을 만들 수 있으면 됩니다. 도구만 대학생 것이 아닌 진짜 대학생이 되어야 합니다. 당연 초등학생들의 도구도 알아야겠지요. 대학생 도구를 사용할 수 있는 사람이 초등학생 도구가 어렵다고 해서야 되겠습니까?

모델링을 업으로 삼아 독립된 회사를 차린 이후에 저는 항상 객체모델을 기준으로 관계형 데이터베이스를 설계했습니다. 객체모델은 도메인을 분명하게 투영할 수 있기 때문에 관계형 모델로는 더 많은 노력을 쏟아 부어야만 얻을 수 있는 결과를 쉽게 얻을 수 있었습니다. 물론 이것은 대학생 다운 대학생이 만든 객체모델을 전제로 합니다. 




RSMer's Page

Aggregate는 컴포넌트기반개발의 관리자(Manager)에 해당합니다. 
관리자 식별은 쉽지 않고 실제로 제시된 방법으로 뭘 하려고 하면 모호함에 빠집니다. 이렇게 해도 되고 저렇게 해도 된다고 생각하는 모델러들에게는 문제가 없겠지만 제대로 모델링을 하려고 하는 모델러들에게는 큰 문제가 됩니다. 모델러들에게 근거는 매우 중요한 요소입니다.


본문 내용에서 팩토리 매개변수, 불변식 체크 부분에서 뭘 어떻게 하라는지 명확하게 감이 오지 않을 것입니다. 전체와 부분의 관계에서 컬레보레이션과 부분을 이해하고 그들 사이의 연관을 이해해야 합니다.
RSM에서 전체와 부분, 컬레보레이션, 이들과 관련된 연관을 분명하게 정의하는데 사생결단하고 달려드는 것이 바로 관리자의 식별에 대한 근거를 주기 위해서입니다. 


관리자 컴포넌트를 어떻게 설계해야 할까요?
관리자 컴포넌트는 인터페이스와 인터페이스를 구현하는 focus 클래스가 있어야 합니다. 인터페이스는 역할에 따라 다수개 있을 수 있습니다.
관리자가 포함하는 객체들에 해당하는 클래스들이 있어야 합니다.
본문의 내용과 같이 객체들을 생성할 수 있는 팩토리가 있어야 합니다. 객체들의 영속성을 다루는 레파지토리가 있어야 합니다. 우리는 레파지토리를 데이터모델이라고 부르기도 합니다.
관리자 컴포넌트의 인터페이스의 오퍼레이션들은 실제 객체들을 주고 받지 않는 것을 기본으로 하기 때문에 관리자가 다루어야 하는 객체들에 해당하는 데이터타입들이 있어야 합니다.

정적 행위의 요구정보모델링은 등록에 대한 것으로 팩토리 메소드에 해당합니다. 팩토리 메소드의 매개변수는 요구정보로 작성합니다. 본문의 불변식은 타입불변식으로 요구정보에 대한 선행조건을 체크하는 것입니다.


팩토리 메소드를 어디에 두어야 할까요?
전체와 부분의 관점에서 모델링을 하면 시스템 객체 또한 등장합니다. Aggregate들은 시스템 객체의 부분들입니다. 시스템 객체가 등록해야 합니다.
Aggregate도 아니고 Aggregate에도 포함되지 않는 것은 무엇일까요? 시스템 객체의 컬레보레이션입니다.
전체와 부분의 관점으로 모델링하면 팩토리 메소드를 두어야 하는 곳을 한 가지 방법으로 통일할 수 있습니다.



저자가 아주 당연한 것들을 다 패턴이라고 부르는 것을 보면 저자는 저와 달리 '패턴'이라는 용어를 좋아하는 것 같습니다.
저는 대부분의 설계 패턴들이 대부분은 패턴이 아니고 원래 그래야 했던 것들이라고 주장합니다. 패턴이 될 만큼 자주 등장한 점에 주목합니다. 패턴이라는 현상 뒤에는 숨어 있는 본질이 있습니다. 



저작자 표시 비영리 변경 금지
신고
Name
Password
Homepage
Secret

티스토리 툴바