今のプロジェクト「ドメインモデル駆動開発」に、こだわって、やっている。
ドメインモデル駆動開発(DMDD:Domain Model Driven Development) は、モデリングや設計よりも、実際のコードの書き方が、主要な関心事。
具体的、かつ、簡単。
基本のアイデアは、Eclipse プロジェクトを、レイヤごとに、別々に作成すること。
(1)まず、ドメイン層のプロジェクトを作って、ドメインのクラス群を作る
(2)次に、データベースを定義する
(3)次に、データアクセス層の プロジェクトを別に作って、ドメイン層プロジェクトを参照する。
O-R マッピング ( SQL Map ) の仕組みを使って、ドメイン層で宣言した、
Repository インタフェースを、実装する。
(4)次に、サービス層のプロジェクトを、さらに別に作る。
このプロジェクトも、ドメイン層プロジェクトを参照する。
データアクセス層プロジェクトも参照するけど、Spring フレームワークで隠ぺいしてやる。
(5)最後に、Web MVC 用のプロジェクトを作る。
ここは、ドメイン層とサービス層を参照する。
こんな感じ。
プロジェクトに分けているので、参照関係が、一方向に、限定される。
レイヤ構造の概念を、コードの構造として、具体化している。
Java のパッケージは、パッケージ間の参照関係を、明示的に宣言する方法がない。
Eclipse のプロジェクトと、プロジェクトの参照の仕組みを使うことで、構造を、具体的な形にできる。
ドメイン層のモデリングと、設計・実装が、全体を駆動することになる。
概念としての「ドメイン重視」ではなく、作業の順番として、「まずは、ドメイン層」というやり方に、自然になる。
そろそろ開発の中盤から終盤にさしかかっているが、期待どおり、ソフトウェア全体の構造が安定している実感がある。
ドメイン駆動も、概念的な話ではなく、「ドメイン層のクラスから作り始める」という、コードレベル、作業レベルの習慣になっている。発想が、自然にドメイン駆動になる。
ビルディングブロックを作って、それを組み立てていく、というやり方の心地よさを感じている。
コードの全体量が少なかった、開発初期には、オーバーヘッドが目立った感じだが、コードの量が膨らんだ今は、全体の見通しのよさ、安定性、仕様変更への対応のしやすさなど、メリットがいろいろ実感できている。
次の機会でも、まちがいなく、このやり方でやりたいと思う。( keep )
このやり方ができたのは、アーキテクチャを、事前によく検討して、固めておいた効果も大きい。
基本方式は、Spring 3 フレームワーク を全面採用。
「アプリケーション開発者は、ドメイン層に集中してください。それ以外の層は、我々がベストプラクティスをコードで提供しまっせ」という Spring フレームワークの思想が、「ドメインモデル駆動開発」には、ぴったり。
Spring フレームワークのコア以外に使っている、主な仕組み
◎データアクセス層は、iBatis の SQL Map
◎Web MVC は、Spring 3 MVC と Spring Web Flow
◎ビューテクノロジーは、 velocity
◎Validation は、アノテーション式の Bean Validation ( JSR-303 )を全面採用
どの仕組みも、アプリケーション開発者は、ドメインオブジェクトの設計・実装に専念すれば良いようになってきている。
ドメイン層の実装スタイルは、ドメインモデル以外にも、トランザクション・スクリプトやテーブルモジュールがある。( by Martin Fowler PoEAA )
私たちは、いちおう、「ドメインモデル」でやっていると思っているが、この三つの違いは、あまり本質ではないと思っている。
本質は、「ドメイン層」を分離して、実装するか、どうか、という視点。
永続化や、UIの実装と、ドメイン層の実装を、分離したほうが、コードが整理できて、扱いやすくなる。
重要なのは、「ドメイン層」を独立させて、実装する、ということ。
あとは、ドメイン層の中の、関心事の分離や、リファクタリング作業の方向や程度の問題なんじゃないかと思っている。
私自身は、DOA 経由の ドメインモデル派 なので、
トランザクションスクリプト風に書いても、コードの重複が目立ってきて、リファクタリングを始めれば、わりと、ドメインモデルっぽい感じになるんじゃないの?
テーブルモジュールから、データベースアクセスの実装部分を分離すれば、これも、ある意味、ドメインモデルっぽいものになるんじゃないの?
というような、勝手解釈をして、済ませている。
つきつめて考えて、よく比較してドメインモデルを選択したわけではないんですよね。
要件定義は、リレーションシップ駆動分析(RDRA) 、設計は、ICONIX を参考にやっている。ツールは、Enterprise Architect を愛用している。
ICONIX 手法は、ドメインクラスのモデリングと設計・実装で、駆動していくやり方なので、「ドメインモデル駆動開発」そのもの。
RDRA は、上流工程で、ドメインをコンテキストモデルから初めて、モデリングしていくやり方。
必ずしも、ドメインモデル駆動開発ではなく、それぞれの現場のやり方に合わせて使える、わりと、懐の広い手法。
私たちは、初期の段階から、概念クラスモデルを作成し、それを、ドメインクラスの設計・実装まで、成長させつづける、という「ドメインモデル駆動開発」流にアレンジして、使っている。
ツールは、Enterprise Architect を愛用している。
RDRA, ICONIX のテンプレートやマクロが用意されているのが便利。
モデル駆動でやろうと思ったら、Enterprise Architect のように、ダイヤグラムとモデルを明確に区別し、ダイヤグラムは、モデルのビューである、という思想のこのツールは、ほんと使いやすい。
最近は、ステートマシン図と、状態遷移表が、ワンタッチで、表示を切り替えられるのが、ちょっとしたマイブーム。
業務のアプリの場合、結構、状態管理機能の要求が多く、また設計・実装が、いろいろ面倒になりやすい箇所なので、その分析・モデリングツールとして、重宝している。
ドメインモデルは、今回は、Martin Fowler が書いている、 Event Sourcing のスタイルを重視している。
簡単にいえば、「起きたこと(事象)」をソースデータとして、「状態」は、そこから派生させる、というスタイル。
なんてことはない、伝票でまず、事象を記録し、それを、台帳に転記する、という業務の基本シナリオにもっともらしい名前をつけただけ(なんちゃって)。
概念は、単純だけど、設計・実装面では、いろいろ興味深いテーマがたくさんある。
今回も、 Event タイプごとに、異なる処理を、どうやって、整理して記述するかを、いろいろ検討してみた。
結果としては、 Enum の Abstract メソッドの仕組みを使って、タイプごとに、異なる処理を switch 文とか使わずに、うまく表現できたように思う。
あとは、REST スタイルにもこだわった。
単純にいえば、 query 文字列は使わずに、いかに、静的な URI らしく設計するかということ。
Spring 3 MVC が、かなり、 REST スタイルのリクエストマッピングをサポートしているので、こちらも、結構、いい感じになってきている。
( 詳細な検索機能の実装はこれからなので、まだ、紆余曲折があるかもしれない )
今回は、開発環境も本番環境も、全面的にクラウドのインフラを使っている。
これは、技術トレンドというより、
・初期コストを抑えたい
・ビジネスが順調に拡大すれば、ビジネスの成長(収入増)も合わせて、システムも増強していきたい
・もし、ビジネスが振るわなければ、縮小したい。あるいは、徹底もありえる。
という、事業のニーズを素直にインフラに反映するには、クラウドが適切だったということ。
新規事業なので、初期のキャッシュアウトが抑えられて、インフラコストも変動費用として伸縮性があるのは、ほんとうにありがたい。
これも、ドメインモデル(事業モデル)駆動開発の一部だと思っている。
クラウドのインフラにしたことで、「想定障害」「障害時の対処方法」「キャパシティの計画と管理」なども、いろいろ、新しい発想が必要なことを、実感しはじめたところ。
例えば、ディスク障害のためのスタンバイデータベース、というやり方は、意味がなくなってしまった。
DISK は、インフラ側で、冗長構成で、かつ複製して保護してくれているので、データ保護のために、別のハードにスタンバイデータベースを構築して、データを複製しておく、という考え方は、必要ない、ということ。
久しぶりに書き始めたら、いろいろなネタがまざってしました。
いかんなあ、関心事の分離(SoC)に、もっとこだわらないと。
ドメインモデル駆動開発(DMDD:Domain Model Driven Development) は、モデリングや設計よりも、実際のコードの書き方が、主要な関心事。
やり方
具体的、かつ、簡単。
基本のアイデアは、Eclipse プロジェクトを、レイヤごとに、別々に作成すること。
(1)まず、ドメイン層のプロジェクトを作って、ドメインのクラス群を作る
(2)次に、データベースを定義する
(3)次に、データアクセス層の プロジェクトを別に作って、ドメイン層プロジェクトを参照する。
O-R マッピング ( SQL Map ) の仕組みを使って、ドメイン層で宣言した、
Repository インタフェースを、実装する。
(4)次に、サービス層のプロジェクトを、さらに別に作る。
このプロジェクトも、ドメイン層プロジェクトを参照する。
データアクセス層プロジェクトも参照するけど、Spring フレームワークで隠ぺいしてやる。
(5)最後に、Web MVC 用のプロジェクトを作る。
ここは、ドメイン層とサービス層を参照する。
階層構造と参照関係
こんな感じ。
狙い(1) 構造が明確で、安定する
プロジェクトに分けているので、参照関係が、一方向に、限定される。
レイヤ構造の概念を、コードの構造として、具体化している。
Java のパッケージは、パッケージ間の参照関係を、明示的に宣言する方法がない。
Eclipse のプロジェクトと、プロジェクトの参照の仕組みを使うことで、構造を、具体的な形にできる。
狙い(2)開発が、ドメイン駆動になる
ドメイン層のモデリングと、設計・実装が、全体を駆動することになる。
概念としての「ドメイン重視」ではなく、作業の順番として、「まずは、ドメイン層」というやり方に、自然になる。
実践の結果
そろそろ開発の中盤から終盤にさしかかっているが、期待どおり、ソフトウェア全体の構造が安定している実感がある。
ドメイン駆動も、概念的な話ではなく、「ドメイン層のクラスから作り始める」という、コードレベル、作業レベルの習慣になっている。発想が、自然にドメイン駆動になる。
ビルディングブロックを作って、それを組み立てていく、というやり方の心地よさを感じている。
コードの全体量が少なかった、開発初期には、オーバーヘッドが目立った感じだが、コードの量が膨らんだ今は、全体の見通しのよさ、安定性、仕様変更への対応のしやすさなど、メリットがいろいろ実感できている。
次の機会でも、まちがいなく、このやり方でやりたいと思う。( keep )
補足:アーキテクチャ
このやり方ができたのは、アーキテクチャを、事前によく検討して、固めておいた効果も大きい。
基本方式は、Spring 3 フレームワーク を全面採用。
「アプリケーション開発者は、ドメイン層に集中してください。それ以外の層は、我々がベストプラクティスをコードで提供しまっせ」という Spring フレームワークの思想が、「ドメインモデル駆動開発」には、ぴったり。
Spring フレームワークのコア以外に使っている、主な仕組み
◎データアクセス層は、iBatis の SQL Map
◎Web MVC は、Spring 3 MVC と Spring Web Flow
◎ビューテクノロジーは、 velocity
◎Validation は、アノテーション式の Bean Validation ( JSR-303 )を全面採用
どの仕組みも、アプリケーション開発者は、ドメインオブジェクトの設計・実装に専念すれば良いようになってきている。
補足:ドメイン層とドメインモデル
ドメイン層の実装スタイルは、ドメインモデル以外にも、トランザクション・スクリプトやテーブルモジュールがある。( by Martin Fowler PoEAA )
私たちは、いちおう、「ドメインモデル」でやっていると思っているが、この三つの違いは、あまり本質ではないと思っている。
本質は、「ドメイン層」を分離して、実装するか、どうか、という視点。
永続化や、UIの実装と、ドメイン層の実装を、分離したほうが、コードが整理できて、扱いやすくなる。
重要なのは、「ドメイン層」を独立させて、実装する、ということ。
あとは、ドメイン層の中の、関心事の分離や、リファクタリング作業の方向や程度の問題なんじゃないかと思っている。
私自身は、DOA 経由の ドメインモデル派 なので、
トランザクションスクリプト風に書いても、コードの重複が目立ってきて、リファクタリングを始めれば、わりと、ドメインモデルっぽい感じになるんじゃないの?
テーブルモジュールから、データベースアクセスの実装部分を分離すれば、これも、ある意味、ドメインモデルっぽいものになるんじゃないの?
というような、勝手解釈をして、済ませている。
つきつめて考えて、よく比較してドメインモデルを選択したわけではないんですよね。
補足:モデリングと設計手法、ツール
要件定義は、リレーションシップ駆動分析(RDRA) 、設計は、ICONIX を参考にやっている。ツールは、Enterprise Architect を愛用している。
ICONIX 手法は、ドメインクラスのモデリングと設計・実装で、駆動していくやり方なので、「ドメインモデル駆動開発」そのもの。
RDRA は、上流工程で、ドメインをコンテキストモデルから初めて、モデリングしていくやり方。
必ずしも、ドメインモデル駆動開発ではなく、それぞれの現場のやり方に合わせて使える、わりと、懐の広い手法。
私たちは、初期の段階から、概念クラスモデルを作成し、それを、ドメインクラスの設計・実装まで、成長させつづける、という「ドメインモデル駆動開発」流にアレンジして、使っている。
ツールは、Enterprise Architect を愛用している。
RDRA, ICONIX のテンプレートやマクロが用意されているのが便利。
モデル駆動でやろうと思ったら、Enterprise Architect のように、ダイヤグラムとモデルを明確に区別し、ダイヤグラムは、モデルのビューである、という思想のこのツールは、ほんと使いやすい。
最近は、ステートマシン図と、状態遷移表が、ワンタッチで、表示を切り替えられるのが、ちょっとしたマイブーム。
業務のアプリの場合、結構、状態管理機能の要求が多く、また設計・実装が、いろいろ面倒になりやすい箇所なので、その分析・モデリングツールとして、重宝している。
補足:アプリケーション・アーキテクチャのスタイル
ドメインモデルは、今回は、Martin Fowler が書いている、 Event Sourcing のスタイルを重視している。
簡単にいえば、「起きたこと(事象)」をソースデータとして、「状態」は、そこから派生させる、というスタイル。
なんてことはない、伝票でまず、事象を記録し、それを、台帳に転記する、という業務の基本シナリオにもっともらしい名前をつけただけ(なんちゃって)。
概念は、単純だけど、設計・実装面では、いろいろ興味深いテーマがたくさんある。
今回も、 Event タイプごとに、異なる処理を、どうやって、整理して記述するかを、いろいろ検討してみた。
結果としては、 Enum の Abstract メソッドの仕組みを使って、タイプごとに、異なる処理を switch 文とか使わずに、うまく表現できたように思う。
あとは、REST スタイルにもこだわった。
単純にいえば、 query 文字列は使わずに、いかに、静的な URI らしく設計するかということ。
Spring 3 MVC が、かなり、 REST スタイルのリクエストマッピングをサポートしているので、こちらも、結構、いい感じになってきている。
( 詳細な検索機能の実装はこれからなので、まだ、紆余曲折があるかもしれない )
補足:実行環境と運用
今回は、開発環境も本番環境も、全面的にクラウドのインフラを使っている。
これは、技術トレンドというより、
・初期コストを抑えたい
・ビジネスが順調に拡大すれば、ビジネスの成長(収入増)も合わせて、システムも増強していきたい
・もし、ビジネスが振るわなければ、縮小したい。あるいは、徹底もありえる。
という、事業のニーズを素直にインフラに反映するには、クラウドが適切だったということ。
新規事業なので、初期のキャッシュアウトが抑えられて、インフラコストも変動費用として伸縮性があるのは、ほんとうにありがたい。
これも、ドメインモデル(事業モデル)駆動開発の一部だと思っている。
クラウドのインフラにしたことで、「想定障害」「障害時の対処方法」「キャパシティの計画と管理」なども、いろいろ、新しい発想が必要なことを、実感しはじめたところ。
例えば、ディスク障害のためのスタンバイデータベース、というやり方は、意味がなくなってしまった。
DISK は、インフラ側で、冗長構成で、かつ複製して保護してくれているので、データ保護のために、別のハードにスタンバイデータベースを構築して、データを複製しておく、という考え方は、必要ない、ということ。
久しぶりに書き始めたら、いろいろなネタがまざってしました。
いかんなあ、関心事の分離(SoC)に、もっとこだわらないと。