ドメイン駆動設計
ドメイン駆動設計とは、Eric Evans氏が提唱するソフトウェア設計手法です。[Domain-driven design | DDD]
参考書籍:「エリック・エヴァンスのドメイン駆動設計」- 翔泳社 (ISBN 9784798121963) ※以下DDD本と表記します。
参考情報: DomainDrivenDesignQuicklyOnline_JP.pdf。要約版のようです。 A4 90ページ程で、日本語が分かり易いです。
ドメイン駆動設計の基本
DDD本には多くの事が書かれています。 最初から多くのプラクティスを取り入れて、うまく実践できたという事例は稀でしょう。
本記事では、DDD本の内容を網羅することよりも、 まず、主要なキーワードを辿りながら、ドメイン駆動設計の基本について考えたいと思います。
ドメイン駆動設計の基本は、(後述する) ドメイン知識から導き出されたユビキタス言語とドメインモデルです。
開発チームは、 ドメインモデルを中心にリファクタリング (洗練) を重ね、モデルの完成度を上げ、深化させていきます。 アプリケーションの本質はドメインモデルであり、ドメインモデルを中心に据えてアプリケーションを構築するという考え方が、ドメイン駆動設計の基本です。
ドメイン駆動設計は、その設計活動に有用なモデリングパターンや深い考察、指針を示しています。
ドメインとは
ドメインとは、システム化対象領域を指します。例えば、在庫管理業務などです。
多くの業務アプリケーションでは、ビュー層、ドメイン層、永続化層の3層構造が採用されています。 実装寄りの観点では、ドメインは、このドメイン層に相当します。 ただし、「ドメイン欠乏症」と言われるような、アンチパターンの構成を想像してはいけません。 このようなアプリケーションのドメイン層には、まともなオブジェクトは存在していません。 あるのは、ビュー層と永続化層の間でデータのバケツリレーをするだけのクラスです。 ドメイン駆動設計のドメインは、アプリケーションの本質的な責務を持ったオブジェクトの集まりを意味します。
開発チーム
チームは、ユーザ、ドメインエキスパート (業務の専門知識をもつ人) 、ソフトウェア技術者で構成されます。
チーム内では、(後述の) ユビキタス言語を使ってコミュニケーションをとります。
実践的モデラ
実践的モデラとは、 分析、モデリング、設計、プログラミングというように、過度に役割を分離しないで、 メンバー全員が、モデラであり、プログラマであることです。
実践的モデラが困難な場合にも、全員がモデルと実装コードを理解し、関心と責任を持つことが重要です。 モデリングとプログラミングを分離すると、モデルと実装の不一致など、ドメイン駆動設計はうまくいきません。
例えば、モデリング時に何か気づいてモデルを変更した場合には、 それは、ユビキタス言語と実装コードに、正確に反映されなければなりません。
また、実装時に気づいた問題も、ドメインモデルとユビキタス言語に反映されなければなりません。
同様に、コミュニケーション中に気づく問題もあるでしょう。それも、ドメインモデルと実装コードに反映されなければなりません。
ユビキタス言語に変更 (用語の意味の変更など) があった場合には、会話の中に反映されなければなりません。
従って、(少なくとも主要なメンバーは) 実践的モデラであることが求められます。
ユビキタス言語
※DDD本から引用:ここから
モデルを言語の骨格として使用すること。
チーム内のすべてのコミュニケーションとコードにおいて、その言語を厳格に用いることを、チームに約束させること。
図やドキュメント、そして何より会話の中では同一の言語を使用すること。
言語を使う上で問題があれば、代わりの表現を用いて実験することで、問題を取り除くこと。
そうした表現は代りとなるモデルを反映している。
そこで、新しいモデルに合わせてコードをリファクタリングし、クラス、メソッド、モジュールの名前を変更すること。
会話の中で用語が混同されていたら、普通の単語の意味について認識を合わせるのと同じやり方で解決すること。
ユビキタス言語における変更は、モデルに対する変更であると認識すること。
※DDD本から引用:ここまで
ソフトウェア技術者はクラスやメソッドなどに関心があり、それらを実世界の概念と結び付けて思考し、会話します。 一方、ユーザやドメインエキスパートには、クラスなど知識はありません。 例えば「クラス」という単語を使っていたとしても、多分それば、ソフトウェア技術者が使うクラスとは別の何かだと思われます。 ドメインモデルを作成するときは、チーム内でのコミュニケーションがとても重要です。 ドメイン駆動設計では、このコミュニケーションを正確にするための共通言語として「ユビキタス言語」という言語を、明確に位置づけて、コミュニケーションするようにします。
ユビキタス言語の語彙は、クラス名、メソッド名などと双方向に追跡可能 (紐付けられる) であることが求められます。 例えば、実装レベルで問題点が発見されたり、新たな知見が得られた場合は、ユビキタス言語にも反映しなければなりません。 ドメインモデルはイテレーションを重ねる度に深化していきますが、それと同時にユビキタス言語も深化させていきます。 ユビキタス言語をメンテナンスするだけではなく、関係者の会話においても、必ず反映されるようにしなければなりません。
ドメインモデル
あるドメイン (アプリケーション領域、業務領域) におけるドメイン知識から導き出したユビキタス言語は、 そのアプリケーション開発に関わる全ての人 (開発者、ユーザ、ドメインエキスパートなど) たちの共通言語となります。 ユビキタス言語の語彙はドメインモデルのオブジェクト群のクラス名/オブジェクト名やメソッド名に双方向で対応付けられます。 ユビキタス言語もコード (ソフトウェアで表現されたモデル : クラス、メソッド、モジュール) も、リファクタリング (洗練) と検証を繰り返して完成度を上げ、深化させていきます。 本記事では、ドメインモデルを定めるものは、ユビキタス言語、UML図などのモデリング言語や記法で表現されたモデル、ソフトウェアで表現されたモデルと考えています。
ソフトウェアで表現されたドメインモデルを構成するオブジェクトのパターンには、エンティティ、値オブジェクト、サービスがあります。
エンティティ
ドメインモデル内のオブジェクト。連続性と識別性 (同一性と同値は区別される) を持ちます。
ドメイン駆動設計はオブジェクト指向モデリングを前提とはしませんが、多くのチームが、オブジェクト指向モデリングを採用するでしょう。
そこで、エンティティの見つけるときのヒントとして、 少々、古典になりますが、 「オブジェクト指向システム分析」シュレイアー、メラー著 にクラスの候補として以下が挙げられています。
- 有形物
- 人、商品、伝票
- 役割
- 人や構成により演じられる役割
- 医師、患者、顧客、従業員
- 医師は患者にもなる
- 出来事
- 飛行、事故、故障、サービス要求
- 相互作用
- 買い入れ、結婚
- 仕様
- 製品などの仕様
また、DOA (データ中心アプローチ) になれている方の場合、1つのテーブルとして抽出した概念やモノは、多くの場合、エンティティとして適切か、有力な候補になるはずです。
値オブジェクト
識別性を持ちません。変更不可の不変 (immutable) オブジェクトです。多くの場合、エンティティオブジェクトの状態を記述する属性として振る舞ういます。
例として、図形処理アプリケーションで良く見かける座標点クラス (Point) があります。 多くの場合、エンティティの属性の状態を現すクラスは値オブジェクトとなります。 値オブジェクトには一意性は必要なく、同値性が重要です。 エンティティの属性の状態を示すためには、使用するプログラミング言語のプリミティブ型で十分なケースも多くありますが、 Pointクラスのような値オブジェクトをドメインモデルに追加することで、ドメインモデルがより洗練されます。 ただし、過度に追加するとクラスの爆発と言われるような状況に陥ることもあります。
サービス
ドメインには、エンティティや値オブジェクトとして扱うには不自然なものが存在します。GRASPパターンの純粋人工物 (Pure Fabrication)です。 ドメインには実在しないオブジェクトであり、サービスという形でユビキタス言語に組み込みます。サービスは基本的に状態を持ちません。 エンティティや値オブジェクトではなく、アクションや操作といった概念として存在します。
モジュール
パッケージと同義です。モジュール名もユビキタス言語に含まれる名前です。モジュール名、モジュール構成もリファクタリングの対象です。 モジュール間は低結合、モジュール内は高凝集にします。
ドメイン駆動設計の立ち位置
ドメイン駆動設計では、新しいモデリング技術や特別な設計プロセスは提唱していません。 ドメイン駆動設計は、アプリケーション構築において最も重要なものはドメインモデルであるとし、ドメインモデルを中心に置く設計手法です。 ドメインモデリングには、モデル駆動設計 (MDD) や、オブジェクト指向 (OO) の世界で培われてきた技法・手法を最大限適用します。 ドメイン駆動設計は、モデル駆動設計やオブジェクト指向技術と協調します。 モデル中心の考え方はモデル駆動設計から取り入れ、 そのモデルを表現する手段として (必須ではありませんが多くの場合) オブジェクト指向のパラダイムを使用します。 モデル駆動設計やオブジェクト指向はモデル化する対象を特に限定していませんが、ドメイン駆動設計はアプリケーションのドメインを中心に置きます。 例えば、MVCモデルのビュー層や永続化層は主要な関心事ではありません。 ドメイン駆動設計では、開発プロセスとしてアジャイル開発が基本です。 (本記事では、アジャイル開発とイテレーティブ開発を区別しないで混用します)
モデリングパラダイム
ドメイン駆動設計、モデル駆動設計では、モデリングパラダイムを限定しませんが、 実際に主流となっているのは、オブジェクト指向パラダイムです。 DDD本以外にも、ドメインモデル作成の最初の取っ掛かりや、その後のリファクタリングに役立つモデリング手法があります。 参考になりそうな手法を次に挙げてみます。
アナリシスパターン
マーチン・ファウラー氏の著書「アナリシスパターン」には、再利用可能なオブジェクトモデルがパターンとして示されています。 これらのオブジェクトモデルは、著書の中の特定の業務 (ドメイン) だけでなく、他のドメインにも適用できるものです。 自分たちのアプリケーションのドメインモデルとして、そのまま適用できるケースは少ないかもしれませんが、 ドメインモデルを作成するときの貴重な手本になると思われます。 アナリシスパターンで示されているパターンは、よく洗練されたものであり、深いモデルです。 時として、深すぎて難しく感じるものも少なくないかもしれません。 しかし、深さのレベルを少し落として取り入れたり、ドメインモデリングを始めるときのヒントにするだけでも、とても有益なパターン集だと思います。
デザインパターン
GoFと呼ばれる4人による共著「オブジェクト指向における再利用のためのデザインパターン」では、 オブジェクト指向設計、実装に関する23個のパターンを示しています。 各パターンは主に次の4つに分類されます。
(1) 生成に関するパターン
(2) 構造に関するパターン
(3) 振る舞いに関するパターン
(4) マルチスレッドプログラミングに関するパターン
実装の観点からの設計パターンです。ドメイン駆動設計のドメインモデルを作成する際や、リファクタリングする際の有用な指針となるでしょう。そのまま適用できるケースも少なくないと思われます。 GoFとは、エーリヒ・ガンマ、リチャード・ヘルム、ラルフ・ジョンソン、ジョン・ブリシディースの4人です。
CRC (Class Responsibility Collaborator) (クラス 責務 協調者)
ドメイン駆動設計とは直接関係しませんが、オブジェクト指向分析ツールにCRCカードがあります。 CRCカードは、オブジェクトの発見ツールとして使用されます。また、オブジェクト指向の初学者のための演習用としても良く使用されます。 CRCは同じ大きさの小さなカードを使用します。 1枚のカードにオブジェクトの候補を1つ記入し、クラス名、責務、協調者を記入します。 実際にオブジェクトの候補を挙げながら、その責務や、(責務を果たすために) 相互作用すべき協調者 (他のオブジェクト) を実際に書いてみることが、 オブジェクトの発見や、発見するためのアプローチを理解するのに効果があるからです。 CRCでは分析チームのメンバーや演習の参加者同士が机上と口頭で相互作用してみて、候補に挙げたオブジェクトに正しい責務が割り当てられ、 期待する振る舞いを実現できるか等を検証します。 ドメイン駆動設計においても、もし、ドメインオブジェクトの見つけ方で悩まれているならば、CRCカードを使ってみる価値があると思います。
Naked Objects パターン
ここで、ドメイン駆動設計に通じるコンセプトを持つ Naked Objects パターンを紹介します。 Naked Objects パターンでは、ドメイン駆動設計と同様にドメインモデルに重点を置きます。 アプリケーションを開発する時には、ドメインオブジェクトだけを作成します。 ユーザインタフェース層やデータアクセス層は、ドメインオブジェクトから自動で作成します。 十分に洗練され深化したドメインモデルがあれば、 ドメインモデルの各インタフェース (サービスやクラスのメソッド、プロパティ) をビューとしてユーザに公開 (画面など) するだけで、 アプリケーションとして機能する、という考えです。 大きなアプリケーションでの事例もあるようです。 本記事で紹介するドメイン駆動設計をサポートするソフトウェアツールは、Naked Objects パターンにインスパイア (触発) されたものです。
ドメインモデル中心の反復型開発
ドメイン駆動設計では反復型開発が基本です。リファクタリング (洗練) と検証を繰り返し、段階的にモデルの完成度を上げていく手法です。
開発プロセスの中で繰り返す単位をイテレーションと呼び、1回のイテレーションのなかで、分析から設計、実装、検証までを完結させます。
ドメインモデルと実装を常に結びつけて繰り返すことが重要です。
[反復型開発の流れ]
ドメインモデルを常に動かすことの重要性
例えば、UMLで表現されたドメインモデルは、そのままでは動かしてみることはできません。
ソフトウェアで表現されたドメインモデル (例: Javaで実装されたドメインモデル) も、実際に動かすためには単体テストコードやドライバのようなものが必要です。 ここでは「動くソフトウェアモデル」とは、「ソフトウェアで表現されたドメインモデル」のサービスやメソッドを実行できる画面を持った「Webアプリケーション」を指すこととします。
動くソフトウェアモデル (動くアプリケーション) は次のような観点で必要です。
- 動くソフトウェアモデルは、各イテレーションの成果物のひとつです。
- 実際に動かすことで、ドメインモデルの検証をより正確に、具体的にできます。
- 開発チーム (ユーザ、ドメインエキスパート、技術者など) 内でのドメインモデルに対する知識や理解のバラつきを抑止します。
- 過剰な机上分析状態に陥ることを予防します。
- ドメイン駆動設計の用語やパターン名に拘り過ぎて、理解しにくいドメインモデルになることを抑止します。
- 技術寄りではないメンバーであっても、Webアプリケーションとして操作することで深く理解し検証できます。
もしも、動くソフトウェアモデルを作らずに、机上のUML図や単体テストレベルのテストコードだけでドメインモデルを検証しようとすると、 検証の精度や手間、メンバー間の齟齬の発生などが課題となるでしょう。
また、技術寄りではないメンバーにとって検証作業は難しくなります。
質の高いイテレーション
イテレーションは反復型開発のコアプロセスです。 動くソフトウェアモデルで検証すればイテレーションの品質・精度が上がります。 イテレーションを軽快に繰り返すことができれば、チーム (ユーザ、ドメインエキスパート、技術者など) の関心事をドメインモデルに集中できます。
ただ現実には、イテレーションを何度も繰り返すなかで、動くソフトウェアモデルを ”いつでも動く状態” に維持することは、簡単ではありません。 ドメインモデルを動かすために、想定以上に時間を要するケースが多いからです。 例えば、ドメインモデルをWebアプリケーションで動かそうとする場合、イテレーションの度に、即ちドメインモデルをリファクタリングする度に、ユーザインタフェース層やインフラストラクチャ層などの更新も必要になるからです。 イテレーションの本来の目的はドメインモデルのリファクタリング (洗練) です。しかし、動くソフトウェアモデルの維持に手間がかかって、簡単には繰り返せなくなることがあります。 1回1回のイテレーションが重くて手間がかかるようでは、反復型開発の効果は得られません。 この問題を解決するためには、開発プロセスの一部を自動化するなど、何らかの対策が必要です。
アプリケーション自動生成の効果
次のような効果が期待できます。- イテレーションを軽量化し、短いサイクルで何度でも繰り返せる。
- リファクタリング (洗練) したドメインモデルを、素早く検証し結果を得られる。
- 開発チーム (ユーザ、ドメインエキスパート、技術者など) がドメイン以外の問題に煩わされないで、ドメインモデルに集中できる。
- ドメインモデルをJavaで実装すれば、すぐに動かしてみることができるので、入門や学習にも役立ちます。
各イテレーションで何をどのように行うかは、開発の成否において重要なファクターになります。
もし、イテレーションの中でやらなくてはいけない「ドメイン以外の作業」が多いと、開発プロセスの速度と質は低下します。
例えば、イテレーションサイクルが長いと、ドメインモデルのリファクタリング (洗練) に集中できなくなる、などです。
実際、このような速度と質の低下が発生しがちです。
後述のDDBuilderは、ドメインモデルから「動くソフトウェアモデル」 を自動生成することで、 イテレーションに含まれるドメイン以外の問題から開発チームを開放し、開発プロセスに生じる速度や質の低下など、開発実践時の現実的な問題の解消を助けます。
【補足】ドメインモデル以外の作業とは
ドメインモデルのサービスやメソッドを検証するためのインタフェース画面やテストコードの実装作業、 ドメインモデルの永続化の実装作業などのリファクタリング (洗練) に伴う作業です。
ドメイン駆動設計をサポートするソフトウェアツール
ダウンロードページへ...
■ DDBuilderは、
ネクストデザイン有限会社が公開する無料・無保証のソフトウェアツールです。
■ サポートとソースコード公開について
■ お問合せ
DDBuilderとは
DDBuilderを活用すると、ドメインモデリングを Java コードファーストでイテレーティブに実践できます。 この記事でのコードファーストとは、モデル図を必要としないという意味ではありません。 モデル図で検証する方が良いと思われる部分は、コードよりも先にモデル図を作成するべきです。 ただし、そのモデル図はスケッチの方が良いかもしれません。 正確なモデル図は、UMLツール等でコードから生成するようにしないと、モデル図と実装を一致させることは困難です。なによりツール無しでは工数がかかるからです。 ドメインモデルからアプリケーションを自動生成するソフトウェアツールがあれば、ドメインモデルの リファクタリング → 動くソフトウェアモデルで検証 → リファクタリング → … という繰り返しがスムーズに実践できます。
ドメイン駆動設計では反復型開発が基本です。リファクタリング (洗練) と検証を繰り返し、段階的にモデルの完成度を上げていく手法です。 反復型ではイテレーションの速度と質が重要です。
DDBuilderは、ドメインモデルから「動くソフトウェアモデル」を自動生成することで、イテレーションを軽量化・高速化し、 反復サイクルを短くします。 開発者はドメイン以外の問題から解放され、本来のドメインに集中できるようになり、イテレーションの質を向上できます。
DDBuilderのポイントは、入力がJavaで実装されたドメインモデル、出力が「動くソフトウェアモデル」のJava Webアプリケーションであることです。
開発者はドメインモデルをJavaで実装し、 DDBuilderは、ドメインモデル (Javaソースコード) を読込み、Java Webアプリケーション (Javaソースコード) を生成します。
【役割】
DDBuilderはドメインモデルからWebアプリケーションを自動生成することで繰り返し (反復、イテレーション) を軽量化します。
上図に示すように、開発チーム が設計し、Javaで実装したドメインモデル から、検証可能な動くソフトウェアモデル (Java Webアプリケーション) を生成することで、動くソフトウェアモデルの実装時間と手間を軽減します。
イテレーションの度に行っていたユーザインタフェース層やインフラストラクチャ層の実装作業がドメイン中心になり、開発チーム (ユーザ、ドメインエキスパート、技術者など) はドメインモデルの分析・設計・実装・評価に集中できるようになります。 単純な実装ミスも減少します。
ドメインモデルからJava Webアプリケーションを自動生成
ただし、DDBuilderが生成するWebアプリケーションに縛られる必要はありません。
本当の成果物は、「ソフトウェアで表現されたドメインモデル」です。
ここでは、その表現手段としてJava言語、検証手段としてWebアプリケーション型を使用したにすぎません。
Webアプリケーションはドメインモデルを評価するための入れ物にすぎません。
従って、DDBuilderは、Webアプリケーション自動生成というよりも、ドメインモデルのインキュベータ (孵化器) と考えた方がより適切です。
もちろん、そのまま実運用することもできます。
ドメインモデルをコードファーストでリファクタリング
[DDBuilderとEclipseの関係]
[1]生成/読込み更新
生成は、初回に実行します。
読込み更新は、[3]で更新されたドメイン実装を読取り、Webアプリケーションに反映します。
主に、WebアプリケーションのUI層が更新されます。
この処理は、DDBuilder画面のボタン押下で実行されます。
[2]インポート/リフレッシュ
インポートは、初回に実行します。
リフレッシュは[1]の更新結果をEclipseに通知・反映するために行います。
この処理は、Eclipseの操作で行います。
[3]ドメインモデルの実装
モデル図などをもとにEclipseでJavaプログラミングします。
これは、開発チームのタスクです。
期待できる効果
- イテレーションを軽量化(工数削減・期間短縮)できます。
- 手組み実装によるミスとロスを排除できます。
- 開発チームは、非本質的な作業から解放されます。
- コード中心・実装一致で実践できます。
求められる知識
関連する知識
パターンという観点で簡単に区別してみます。
- アナリシスパターンは、実際のドメインモデルの具体例、パターンです。他のドメインでも参考になるようなドメインモデルの構造、パターンを示しています。一方、ドメイン駆動設計は、モデリングについてのパターンや指針を示しています。
- デザインパターンは、オブジェクト指向設計パターン、実装パターンです。
- ドメイン駆動設計は、モデリングのパターンです。
ユーザガイド
ユーザガイド [PDF][2.5MB]
入門や学習用に活用
DDBuilderは、実際の開発プロセスだけではなく、入門や練習にも効果的です。 例えば、実際にドメインモデルをJavaで実装してみて、アプリケーションとしての振る舞いを、あまり手間をかけずに、具体的に試してみることができます。 そうすれば、トランザクションスクリプトとの違いを具体的に見て頂けると思いますし、ドメイン駆動設計のドメインモデルとは何かも、ざっと見てみることができます。
また、トランザクションスクリプトの利点とされている 開発着手時の生産性の問題の解消策にもなります。
もちろん前提として、ドメインモデルの位置付けや役割についての (ある程度の) 理解や、オブジェクト指向によるモデリングやプログラミングのスキルは必要ですが、 まずは、実際に試してみることも効果的ではないでしょうか。
オブジェクト指向、モデル駆動設計、アジャイル開発、ドメイン駆動設計などを、これから始めるという入門者にとって、 文献だけでドメインモデルを理解したり、イメージしたりすることは、難しく、時間がかかるかもしれません。 実際に実装し動かしてみることができれば、理解もしやすいと考えます。
ドメイン駆動設計が示す内容は広く深いです。 しかし、その (少し深い) 内容に拘りすぎて、実際に何も手を動かせないといった状況も、とても残念な状況です。 例えば、オブジェクト指向の基礎とDDD本の第5章位までを読み、 後は、実際に試しながら理解を深めていくといった方法も検討してみてはいかがでしょうか。
書籍など
・「エリック・エヴァンスのドメイン駆動設計」- 翔泳社
・「Domain-Driven Design Quickly 日本語版」
動作確認済み環境
- Java 8
- Windows7 pro 32bit/64bit, Windows10 pro 64bit
- Eclipse IDE for Java EE Developers 4.4, 4.3
- Apache Tomcat 7.0, 8.0, 8.5, 9.0
インストール・アンインストール
DDBuilderはスタンドアロンのJavaデスクトップアプリケーションです。
インストールは、ダウンロードしたzipファイルを適当な場所に解凍してください。
アンインストールは、 解凍結果をエクスプローラなどで削除してください。
※ ダウンロードしたファイルを解凍すると次の説明ファイルが含まれていますので、参考にしてください。
「はじめにお読みください(使い方).txt」
「DDBuilder_Guide_Ver2.pdf」
謝辞
DDBuilderは次のソフトウェアを利用しています。- Apache Wicket 7.4.0
- hibernate-entitymanager4.3.6.Final
- Derby10.10.2.0
- log4j2.5
- Eclipse jdt3.9.1
サポートとソースコードの公開について
使いはじめで、ご不明な点がありましたら「お問合せフォーム」からご連絡ください。
弊社の都合で返信が遅くなる場合がありますが、ご了承ください。
また、有料でのサポートも別途用意しております。
DDBuilderのソースコードは、準備が整い次第、公開する方向です。
関連ツール
参考例
例1 利口なUI (アンチパターン) の罠
Eric Evans氏の著書「エリック・エヴァンスのドメイン駆動設計」(以下「DDD本」と略記します) は、
オブジェクト指向技術やモデル駆動設計を多少とも学習したり実践してきた技術者にとっては、
ツボを得た考察やモデリングパターンがたくさんあり、次に向かうべき方向を示してくれる心強い指南書となるでしょう。
一方、「オブジェクト思考」ではなく「手続き思考」の技術者にとっては、500頁を超える分厚いDDD本を地道に読んで理解していくのは、相当の時間を要するかもしれません。
念のためですが、オブジェクト指向言語を使っていても、オブジェクト思考になっているとは限りません。
ドメイン駆動設計を始めるためには、最小限、DDD本に示されている「利口なUI」パターンのメリットとデメリットを理解しておく必要があると思います。
例えば、Struts系のフレームワークを使って作成したWebアプリケーションが、次のような構造になっているとすれば、オブジェクト思考になっているとは言えないでしょう。 DDD本に「利口なUI アンチパターン」という記述があります。 ドメイン駆動設計的にはアンチパターンですが、実際の開発では多く使われているのが現実のようです。 また、よく似たパターンにトランザクションスクリプトと呼ばれるものがあります。 トランザクションスクリプトは、マーチン・ファウラー氏の著書「エンタープライズアプリケーションアーキテクチャパターン」に示されています。 DDD本では、利口なUI とトランザクションスクリプトは違うものとされていますが、 どちらもドメイン駆動設計の考えを適用できないという意味で、ここでは、同類のアンチパターンと考えます。 下図のようなアプリケーション構造は、利口なUI やトランザクションスクリプトの例です。
上図の (A) や (B) では、JSPやアクションの中にSQL文が固定の文字列、または動的に構築される形で組込まれていて、そのSQL文で多くの業務ロジックを実現します。 そして、同じような、あるいは全く同じSQL文が、JSPやアクションの中に散在しています。 (C) ではModelと称するクラスがありますが、実態はDAOのような役割しか持ちません。 (A)(B)と同様にSQL文が重複したり散在します。 ドメイン駆動設計をはじめるに際しては、これらがアンチパターンであるという認識が必要です。
しかし、利口なUI には悩ましい利点もあります。
利口なUI の利点
※引用:ここから (同じくDDD本の第4章から引用)
● 単純なアプリケーションの場合、生産性が高く、すぐに作れる。
● それほど有能でない開発者でも、この方法ならほとんど訓練しないで仕事ができる。
※引用:ここまで (引用元には箇条書きで他に5点示されています)
なぜ悩ましいかというと、この利点が (少数派とは言えないほどの数の) プロジェクト管理者や開発者を縛り付けていて、 オブジェクト思考へのパラダイムシフトを妨げているケースに何度も直面したからです。 大量の開発者を一時的に集めて作業をするようなスタイルの開発プロジェクトにとっては都合の良いことかもしれません。 ただし、プロジェクトの後半や保守・改修の局面で、これらの利点が効果を出しているケースは皆無に近いのではないでしょうか。 分析・設計やアーキテクチャのリファクタリング (洗練) 不足が表面化するのは、開発の初期局面ではなく後半だからです。
ちなみに、経験上「生産性が高く、すぐに作れる」というのは、初期段階だけに限られます。
本記事内の「オブジェクト指向やドメイン駆動設計を導入する時の傾向」を参考ください。
ドメイン駆動設計を習得し実践に移していくためには、トランザクションスクリプトの課題を理解しておくことが最低限必要かと思います。
トランザクションスクリプトの欠点については、下に引用を示しましたが、これだけではすこし分かり難いかもしれません。 しかし、トランザクションスクリプトに起因するであろう問題点を実際に経験されている方も多いのではないでしょうか。 特に開発工程の後半や、保守や改修作業において、所謂エントロピーの増大に悩まされた方は少なくないでしょう。
利口なUI の欠点
※引用:ここから (同じくDDD本の第4章から引用)
● アプリケーションの統合は困難で、データベースを経由させるしかない。
● ふるまいが再利用されことも、ビジネスの問題が抽象化されることもない。ビジネスルールは、適用先の操作それぞれで複製されることになる。
※引用:ここまで (引用元には箇条書きで他に2点示されています)
例2 レイヤ化アーキテクチャ Java Web
DDBuilderが自動生成する Web アプリケーションの構成図です。
DDD本に示されているレイヤ化アーキテクチャを参考にしています。
「開発者作成」の部分は、開発者によって、ドメイン駆動設計でモデリングされ、Javaで実装されたものになります。DDBuilderはこのJavaクラス群を読み込みビュー層などを生成します。
DDBuilderが生成する「動くソフトウェア」は、Java Web アプリケーションです。
Eclipseのプロジェクト形式になっていますので、Eclipseにインポートして、編集・実行できます。
DDBuilder固有のコンテナなどはなく、フレームワークとして次を使用しています。
ビュー層: Apache Wicket
永続化層 (インフラストラクチャ層): Java EE JPA/ Hibernate
※上図中の「DDBuilder基底」部分に、いくつかの簡単な基底クラスを含んでいます。
ロックインフリー
利用者チームは、開発時でも実行時でも、いつでもDDBuilderを切り離すことができます。
DDBuilderにロックインされることはありません。
ドメインモデルがある程度安定し、頻繁な繰り返しが必要ない段階になれば、DDBuilderは必要なくなるかもしれません。
そして、ドメインモデルを他の言語やアプリケーションフレームワークに移植することもあるでしょう。
DDBuilderはドメインモデルのインキュベータ (孵化器・育成器) です。
もちろん、そのまま運用することもできます。
自作ページの追加
自動生成されたWebアプリケーションに自作のページを追加できます。
DDBuilderは自作ページを上書きしません。
自作ページの作成は、自動生成されたページクラスを参考にすれば、効率よく自作できるでしょう。
Java について
リファクタリングの中で、クラス名を変えたり、メソッド名を変えることは頻繁にあります。 Javaのような強い静的型付けの言語であれば、Eclipseなどのリファクタリング機能で期待通りに簡単に変更できます。 しかし (筆者の勉強不足かもしれませんが) 動的型付け言語では期待する結果を得られないのではないでしょうか。 予期せぬ名前まで置換えられたりしないでしょうか。
Apache Wicket について
Wicketは、Java Webアプリケーションフレームワークです。
Struts系と違い、 オブジェクト指向プログラミングモデルを前提としたフレームワークです。
HTMLとの独立性が高く、基本的にすべてをJavaコードで実装するアーキテクチャは、 自動生成機能を実現するうえでも好都合で相性がよいと言えます。
ドメインモデルは利用者が実装しますが、Wicketを意識することはありません。
Wicketを意識するのは自作ページを追加する場合です。
Java JPA Hibernate について
HibernateはJavaEE JPA実装の1つです。
DDBuilderが生成する動くソフトウェアは、デフォルトではJava標準のJavaDBを使用します。
Hibernateは、 PostgreSQL, MySQL, Oracle, SQLServer, DB2など代表的なデータベースをサポートしており、設定変更だけで他のデータベースに変更できます。
動くソフトウェアは、Hibernateを「Javaアプリケーションのスタンドアロン型」で使用し、Springなどのコンテナは前提としません。
ドメインモデル層のクラスを実装するときには、JPA / Hibernateの知識が必要になります。
主に、関連を定義するためのアノテーションの書き方などの知識が必要になります。
[ 戻る]
例3 クラス図
DDBuilderにはクラス図をサポートする機能はありませんが、ドメイン駆動設計を実践するうえで、クラス図やそれに相当するものは必要です。
本記事では、分析時のクラス図は手書きラフスケッチとし、正式なクラス図はUMLツールなどで Java ソースからリバースエンジニアリングされることを推奨します。リバースエンジニアリングであれば常に実装と一致させることができます。もしも、表計算ソフトなどで作成すると不一致が起き、イテレーションが回らなくなる原因にもなると思います。
また当社では、
JavaクラスレポートというJavaソースからメトリクスなどの情報抽出を行うツールも公開[無料]していますのでご参考ください。
[ 戻る]
例4 オブジェクト指向やドメイン駆動設計を導入する時の傾向
プロジェクトをドメイン駆動設計やオブジェクト指向で始めても途中で断念したり、方針変更を余儀なくされた、という経験はないでしょうか。
そのような結果を生む原因の1つに、下図に示すような「立ち上がり期」の停滞感があると思います。 そのために、オブジェクト指向やドメイン駆動設計で始めたけれど、進捗が遅い、先が不安などと判断され、過去の手法に戻すことになったりします。 原因としては、パターン名や用語に振り回されて空転しているようなケースもありますが、やはり、トランザクションスクリプト型などの方が、とりあえず何らかの進捗が出やすいというのも事実でしょう。
※注意:上のグラフは感覚的なものです。
この立ち上がり期を乗り越えないと、その効果が見える前に従来型に戻されてしまいます。この停滞感を、手法に対する想いや熱意だけで乗り越えるのも難しいでしょう。
DDBuilderを利用することで、この停滞感を少しでも解消できればと思います。
机上だけではなく、実際に動くソフトウェアを素早く試すことができれば、プロジェクトに存在する不安を払しょくし、技術やドメイン知識の習得スピードも上がると思います。
DDD本には考えるべきことが多く書かれています。しかし、最初から多くの指針やパターンを取り入れようとすると、なかなか前には進まないでしょう。 ソフトウェア設計は最終的には自分流です。ただし基本を学んだ上の自分流と、まったくの我流は違います。 DDD本の少しだけでも実践できれば、実践する前に比べて、遥かに良いものになると思います。
[ 戻る]
例5 DDBuilderを活用したイテレーション
ドメイン駆動設計では反復型開発が基本です。
反復型開発プロセスの最も重要な要素はイテレーションです。
イテレーションに自動生成ツール DDBuilder を利用したイテレーションの流れを具体的に示します。
ここでは、ドメインとして在庫管理業務を想定して、倉庫、製品、在庫、在庫管理サービスといったドメインモデルを作り上げていく流れを説明します。
すこし長くなりますので、まず、説明 (概要) を述べた後で、説明 (詳細) を続けます。
すでに上で述べました「 ドメインモデルをコードファーストでリファクタリング」も参考にしてください。
要は、
・ ドメインモデルを作成・修正 (Javaプログラミング)
・ DDBuilderで更新 (自動生成/更新)
・ Eclipseで検証
の繰り返しです。
では、説明を始めます。
説明 (概要)
■ STEP1 DDBuilderをインストール
・ 以下の通りにDDBuilderをPCにインストールします。
・ ダウンロードページからダウンロードしてください。
・ ダウンロードしたファイルを適当な場所に解凍します。
・ 解凍すると次の説明ファイルが含まれていますので、参考にしてください。
「はじめにお読みください(使い方).txt」、「DDBuilder_Guide_Ver2.pdf」
■ STEP2 インストールの確認
・ 正しくインストールされたことを確認するために、DDBuilderを起動します。
・ 作成するWebアプリケーションの名前などの基本情報を設定します。
・ Webアプリケーションを生成してみます。 (自分たちが作成したドメインクラスが1つもない状態)
・ 生成されたWebアプリケーションをEclipseにインポートします。
・ Eclipse上で (動的Webプロジェクト) Webアプリケーションを実行します。
・ ブラウザで動作を確認します。
■ STEP3 1回目のイテレーション
・ 最初のドメインクラスとして「製品」クラスをEclipseで1つだけ作成します。
・ DDBuilderでWebアプリケーションを更新します。
(DDBuilderは「製品」クラス (Javaソースファイル) などを読み込みWebアプリケーションを更新します)
・ WclipseからWebアプリケーションプロジェクトをリフレッシュします。
(EclipseにDDBuilderが行った変更を通知するため)
・ Eclipse上でWebアプリケーションを実行します。
・ ブラウザから動作を確認します。
・ Eclipseの準備方法は他のサイトをご参考ください。
■ STEP4 2回目のイテレーション
・ 次に倉庫、製品、在庫、在庫管理サービスをEclipseで作成します。
・ Eclipse上でWebアプリケーションを実行します。
・ ブラウザから動作を確認します。
説明 (詳細)
まず、DDBuilderを起動すると下図の画面が表示されます。
※DDBuilderはJavaで作成されたスタンドアロンアプリケーションです。Eclipseのプラグインではありません。Eclipseとは関係なく独立して動作します。
起動したらまず、Webアプリケーションの作成場所やアプリケーション名などの基本情報を入力します。
この基本情報は、生成されたJava Web アプリケーションの画面ラベル等にも反映されます。
より詳細な設定は、「他の設定」ボタンを押してから設定してください。
下図は入力例です。
基本情報を入力し、作成/更新ボタンを押下するとWebアプリケーションの基本形が作成されます。
この時点ではドメインモデルはひとつも定義されていませんので、
生成されたWebアプリケーションは最小限の画面 (トップ画面など) を含むだけです。
次に、生成されたWebアプリケーションを編集できるように、Eclipseにインポートします。
ここでの編集とは、ドメインモデルを Java で実装したり、Web アプリケーションとしてデバッグ実行して、ドメインモデルを検証することを指します。
※Webアプリケーションは、インポート可能なEclipseプロジェクトとして生成されています。
インポートが完了すると、上図のように「プロジェクトエクスプローラ」ビューに表示されます。
確認のために、EclipseでWebアプリケーションを実行してみます。
この時点では、ドメインモデルは1つもありませんが、基本的な画面遷移の動作確認はできます。
下図はEclipse内で実行した時の例です。
上図はEclipse内蔵のブラウザで表示された状態ですが、Eclipse外のブラウザからもアクセスしてテストできます。
下図はChromeからアクセスした例です。例:http://localhost:8080/zaiko/
ここまでで、Webアプリケーションの基本動作ができました。(ドメインモデルが無い空のアプリケーション)
この先は、ドメイン駆動設計による分析、ドメインモデルの抽出、設計、実装、検証する作業の繰り返しが始まります。
つまり、初回のイテレーションの開始です。
一気にドメイン全体をカバーしようとするのではなく、1週間程度で行える範囲や優先度の高いユースケースが通る範囲などをイテレーションのゴールとして設定します。(1週間が妥当かどうかは要検討です)
期間の目安や、ユースケースの優先度などはプロジェクトによって違ってくるでしょう。
反復型開発プロセスやアジャイルなどの手法解説を参考にしてください。
まず、もっとも簡単な例として、下図のProductオブジェクトを1つだけ作成してみます。
つまり、イテレーションのゴールは、以下の製品Productクラスの初版を実装し、Webアプリケーションの形で振る舞いを検証することです。
エンティティ
/**
* 製品
*/
@Entity <------------- JPAアノテーション
public class Product extends DdBaseEntity { <------------- DDBuilderエンティティ基底クラス
private static final long serialVersionUID = 1L;
/**
* 製品名
*/
private String name;
/**
* コンストラクタ
*/
public Product(){
super();
this.name = "";
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
実装作業は、下図のように、EclipseでProductクラスを実装します。
domainパッケージの直下にProduct.javaを追加します。サブパッケージを追加することもできます。
これで、Productクラスは追加できました。
ただし、Productクラスのインスタンスを登録したり、表示したりするためのビュー層 (ユーザインタフェース層) や永続化層 (インフラストラクチャ層) はありません。
これらは、DDBuilderが自動生成します。
そのために、DDBuilderでWebアプリケーションを更新します。
DDBuilderはProduct.javaファイルを読み込み、ビュー層のクラスなどを追加します。v
※なお、前回入力されたDDBuilder画面の基本情報は維持されています。
作成/更新ボタンを押下し、完了ダイアログが表示されたら、Webアプリケーションの中に必要なjavaファイルが追加されています。しかし、Eclipseは、追加されたファイルを感知していません。そのために必ず、Eclipse側でプロジェクトをリフレッシュしてください。(忘れがちです)
リフレッシュしたら、再度Webアプリケーションを起動してテストします。
下図はChromeからアクセスした例です。
ここで、ドメインクラス一覧ボタンをクリックすると次画面に遷移します。
次に、製品Productリンクをクリックすると次画面に遷移します。
次に、新規作成リンクをクリックすると次画面に遷移します。
次に、製品名を入力し保存ボタンを押下すると、Productインスタンスが永続化され、次画面に遷移します。
1件登録され、一覧に追加されています。
次に、編集リンクをクリックすると次画面に遷移します。
次に、製品名を変更すると次画面に遷移します。
次に、保存すると次画面に遷移します。
ここまではProductクラスだけでしたが、下図のようにドメインモデルに1つのサービスと2つのエンティティを追加します。
値オブジェクト (バリューオブジェクト) はこの例では登場しません。
Productを追加した時と同様の手順で、Webアプリケーションを更新し、テスト実行します。
ドメインクラス一覧ボタン → 製品Productリンクをクリックします。
なお、ここでは説明を省略しますが、以降の説明での中では、下図のようにテストデータが作成済みとします。
テストデータの作成については ユーガイド(PDF)を参照ください。
ドメインクラス一覧ボタンを押下します。
製品 Productリンクをクリックします。
例として、2行目の編集リンクをクリックします。
編集して保存するか、キャンセルで戻ります。
次に、サービスメソッドを実行してみます。
このサービスは、ある倉庫から別の倉庫に在庫を移動させる業務を実現します。
サービス一覧またはホーム → サービス一覧で下図の画面が表示されます。
実行リンクをクリックします。
下図の画面が表示されたら、このサービスメソッドに渡す引数を指定します。
from移動元倉庫:選択ボタンを押下します。
例として「福岡センター」を選択します。
仮決定ボタンを押下します。
同様に移動先の倉庫と移動する製品と数量を指定します。
サービス実行を押下するとお下図の完了画面が表示されます。
倉庫間移動メソッドの詳細は実装していませんので、戻り値としてtruetrueが表示されています。
DDBuilder ドメインモデルの実装コード例(例:StockService, Warehouse, Stock)を表示する
詳細は ユーザガイド(PDF)をご覧ください。
[ 戻る]例6 DDBuilderがサポートする関連タイプと属性型
このドメインモデルは、DDBuilderがサポートする関連の種類、インスタンス属性型の種類を確認するためのサンプルです。 ドメイン駆動設計的にはあまり参考になりません。 [ コードをダウンロード]
UMLクラス図
DDBuilder 関連タイプと属性型のコードサンプルを表示する
[ 戻る]