火曜日 3 13, 2007

Domain-Driven Design Quickly

dddq-small.jpg

Domain-Driven Design (DDD)は、複雑なビジネス要件を持つシステムの設計に対して、どのようなアプローチや戦略で望むべきかについて、筆者Eric Evansの経験からまとめたものです。左の"Domain-Driven Design Quickly"は、オリジナルの"Domain Driven Design"(2003)の内容を104ページにまとめた簡略版で、InfoQのサイトでフリーのpdfとして公開されているものです。

DDD Quicklyを読むと、全体的にはビジネス・モデリングを重視した開発方法論であるということができます。本の内容は、アプリケーション設計上重要と考えられるプラクティスを説明したもので、個々のパターンの関係をダイアグラムで表した図は本の表紙にもなっています。本の前半は、このダイアグラムの要素を一つずつ説明した内容になっています。

DDDのもっとも基本的なところでは、「階層化アーキテクチャを採用する」や「アプリケーションをサービス(service)、エンティティ(entity)、バリュー・オブジェクト(value object)でモデル化する」など、統一開発方法論(UP)やJ2EEパターンを学んで実践しているエンジニアの方には、一見新しい考え方ではないように捉えられてしまいそうです。しかし、注意深く読むと微妙にJ2EEパターンの考え方とは異なることが分かります。

アプリケーション・レイヤはビジネス層ではない

まず、DDDにおける階層化アーキテクチャを見ていきましょう。DDDにおけるレイヤの定義は以下は以下の通りです。

User Interface (Presentation Layer) Responsible for presenting information to the user andinterpreting user commands.
Application Layer This is a thin layer which coordinates the application activity. It does not contain business logic. It does not hold the state of the business objects, but it can hold the state of an application task progress.
Domain Layer This layer contains information about the domain. This is the heart of the business software. The state of business objects is held here. Persistence of the business objects and possibly their state is delegated to the infrastructure layer.
Infrastructure Layer This layer acts as a supporting library for all the other layers. It provides communication between layers, implements persistence for business objects, contains supporting libraries for the user interface layer, etc.
(Domain-Driven Design Quickly, pp.38)

レイヤの名前だけを見ると、DDDのApplication LayerはJ2EEパターンのビジネス層に対応し、Domain/Infrastructure Layerはインテグレーション層に対応するかのように見えますが、これは正しくありません。上記の定義によれば、Application Layerにはビジネスロジックは含まれないのであって、アプリケーションの動作をコーディネートするだけの薄い層であるという定義になっています。そう考えると、J2EEパターンにおけるビジネス層とインテグレーション層の多くはDDDではDomain Layerに属するものと考える必要があります。逆に言えば、従来のビジネス層とインテグレーション層はDDDのレイヤリングの観点からは区別すべきものではないという考え方であることが分かります。

ちょっと正確ではないかもしれませんが、DDDのレイヤは、Pragmatic SOAのレイヤリングに似ています。DDDの4層をPragmatic SOAの4層にそのままマッピングすると、Application Layer(DDD)がProcess Layer(Pragmatic SOA)に、Domain Layer(DDD)がService Layer(Pragmatic SOA)になりますが、J2EEパターンのレイヤよりも素直なマッピングに思えます。仮にこのマッピングが正しいと仮定して、DDDの原則をSOAに適用すると、BPELなどで定義されることが想定されるProcess Layerは、可能な限り薄くしなければならないとなります。個人的にはこの仮定に基づく原則は納得です。

サービスが属するのはドメイン・レイヤか?

Domain Layerの議論を進める前に、DDDのもう一つの考え方、サービス、エンティティ、バリュー・オブジェクトの分類について考えます。エンティティは、何らかの識別子によって区別され、アプリケーション内のある特定の状態を保持しているオブジェクトです。バリュー・オブジェクトはエンティティに似ていますが、大きな違いは識別子を持たず、レイヤ間あるいはアプリケーション間でpass-by-valueによるデータの受渡しを行なうためのオブジェクトということになります。DDDにおけるバリュー・オブジェクトはJ2EEパターンにおけるトランスファー・オブジェクト(かつてはJ2EEパターンでも同じようにバリュー・オブジェクトと呼ばれていた)と同じ概念です。モデリングの過程で、名詞として抽出されたものはエンティティかバリュー・オブジェクトのどちらかにマッピングされると考えてよいでしょう。

サービスは、モデリングの過程で動詞として抽出されたものの内、特定のオブジェクトに属することができない、ドメインの振舞を表します。ここで注意しなければならないのは、ビジネス・ロジックと考えられる振舞であっても、特定のオブジェクトに属することが相応しいと考えられるのであれば、エンティティであってもビジネス・メソッドを定義して良いという考え方です。従来、J2EEパターンに忠実なアーキテクトは(私も含めて)、ビジネスロジックはセッション・ファサードに定義し、エンティティには属性を表すプロパティだけを定義する傾向がありました。エンティティにもロジックを含めることはありましたが、せいぜい姓+名や日付のフォーマット変換を提供するpseudoプロパティ・メソッドのようなものぐらいでした。しかしながら、オブジェクト指向設計の本来のメリットはデータとオペレーションのカプセル化が基本であり、エンティティにオペレーションを持たせないという考え方は、手続き型プログラミングとあまり変わりはないという批判があって然りです。この辺りは、全体のバランスを考えながら、私自身考え方を変えていかなければいけない点だと思います。

それでは、サービスはどのレイヤに属するものでしょうか。DDD Quicklyの説明では、サービスは、Domain Layer、Infrastructure Layer、Application Layerのいずれにも属することがあり得るが、それがどのレイヤに属するべきかを判断するのは難しい、となっています。簡略版のDDD Quicklyではこの判断基準の記述が十分ではありません。このあたりは、オリジナルのDDD本を参照する必要がありそうです。

また、DDDではサービスはステートレスであることが条件となっています。個人的にはこれは少し古い考え方ではないかと思います。ここ最近のJava EE技術の動向を見てみれば明らかなように、JBoss Seamによるconversational stateの実現や、JAX-WS 2.1RIではステートフルなWebサービスを実現できるようになりつつある現状においては、ステートレスであることに固執するよりは、ステートフルなサービスを定義した方が自然なアーキテクチャとなる場面が多々あるように思われます。実は、Martin Fowlerがこの件に関してEric Evansに確認したところ、サービスがステートレスであることは必須ではないと言っていたそうです(martinfowler.comのDesign bliki EvansClasificationを参照)。

DDDとアジャイル開発の関係

DDD Quicklyの後半の内容は、複数の開発プロジェクト・チームが協力して実現しなければならないような巨大なシステム開発において、顧客と開発者との共通言語(Ubiquitous Language)として築き上げたモデルを、開発フェーズ以降も一貫して維持していくためにはどうすればよいかという課題に対して、10のプラクティスを提案しています。

一般には、システムがソフトウェアとして出来上がってくるに従って、多かれ少なかれ設計の見直しが発生します。このとき多くの場合、見直された設計は初めにソースコードに反映され、次に設計書やモデルに反映されます。もし、システムの規模が大きかったり、設計見直しの量が大きいと、なかなかドキュメントに新しい設計が反映されず、モデルと実装の乖離が顕著になります。これがひどくなると、顧客と開発者の認識のずれが大きくなり、プロジェクトは悪い方向に転げ落ちていく可能性が高くなります。

DDDが効果的に機能するためには、以下の図に示すように、ビジネス要件とモデルの同期、モデルとソースコードの同期が、システムのリリースまで一貫して保たれる必要があるということになります。

これを実現するためのそれぞれのプラクティスの説明は納得できるものもありますが、全体的に具体例が少ないため、個人的には正しく理解できていないものもあります。この点に関しても、オリジナルのDDD本を確認する必要がありそうです。

それよりも注目すべきは、筆者であるEric Evansはアジャイル開発の推進派であるという点です。一般にモデルやアーキテクチャ重視はUPにはうたわれていますが、XPやアジャイル開発では、モデルよりもソースコードに重きを置いています。アジャイル開発では厳密な設計を端折ってでも早く最初のリリースを迎え、そのフィードバックを顧客からもらうことで、変化するビジネス要件とソースコードの同期を維持できるという考え方に基づいています。

しかし、一般には、XPは大規模開発には向かないとされています。これは実装と同時に設計を行うことは規模が小さいうちは巧く機能するが、規模が多くなると間違った方向に進みやすくなり、事前設計をしなかったことによって貯金した工数より後戻りによる実装のやり直しの工数が上回ってしまう現象が起こるためです。DDDはアジャイル開発に設計としてのモデルへの視点と重みを加えることで、大規模開発に対しても立ち向かえる可能性があることを示唆しているということができます。

一方で、UPは大規模案件に強く、変化を許容する開発手法であると言われていますが、コンストラクション・フェーズに入ってからのモデルとソースの同期問題は開発規模が大きくなるにつれて、UPでも無視できない問題になります。そのため、UPの変化に対する許容量は、XPに較べて圧倒的に小さいのは確かです。その意味では、UPもアジャイルな要素を少しずつ取り入れることで、より変化に対する許容量を大きくできるのではないかと期待しています。

UPもXPもそれぞれに欠点があります。DDDはUP派とXP派それぞれの欠点を補うことができる共通のアイデアなのではないかと想像します。実際のところ本当にそうなのかは簡略版のDDD Quicklyを一度読んだだけでは判断できませんが、560ページあるオリジナルのDDD本を読んでみようかと、思わせる内容ではありました(おっと、Eric Evansのマーケティング戦略に乗ってしまったかな)。

About

Takashi Nishigaya
Principal Consultant
Technology Solution Consulting
Oracle Consulting Services

Search

Categories
Archives
« 4月 2014
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
今日