背景
チーム内でドメイン駆動設計(以降、DDDと記述)についてちょっとした勉強会をやることになった際、いわゆる手続き型設計との違いについて、具体的なコード例で説明したいと思い、サンプルコードを用意してみました。チーム内でよく使用されているJavaで記述しています。
勉強会参加者にはプログラミングに疎いメンバもいるので、なるべく理解するのに負担が少ないよう、できる限り単純な例にすることを意識しました。
一方で、実際にはDDDを取り入れるまでもない(むしろ取り入れない方がよい)ほど例が単純すぎることによって、DDDの必要性・効果がうまく伝わらず、むしろ面倒なことをしている印象になってしまう懸念はありますが、概要説明用と割り切っている点はご了承ください。
なお、前提として、そもそもDDDとは何かという部分については、個人的に以下のスライドが内容や流れがわかりやすかったので、勉強会でもそのまま紹介させていただくことにしました。
注意点として、DDDでより本質的なのは、ドメインエキスパートと開発者のコミュニケーション、知識のかみ砕き、モデルへの落とし込み、モデルとコードの一致といった部分だと思っていますが、本記事でこれから紹介するのは、あくまでモデルを実装に落とし込んだコードの例であり、実装手段の一部にすぎません。このような実装手段の部分のみにフォーカスした状態は「軽量DDD」と呼ばれることがあり、賛否両論ある点はご注意ください。
説明の流れ
Javaで書いたごく単純な足し算アプリを例にして説明します。
まずは、DDDとの対比で手続き型設計と呼ばれるような書き方で書いてみます。
public class TransactionAddition01 {
public static void main(String[] args) {
// 引数チェック
if (args.length != 2) {
System.err.println("引数を2つ指定してください");
System.exit(1);
}
int param1 = 0;
int param2 = 0;
try {
param1 = Integer.parseInt(args[0]);
param2 = Integer.parseInt(args[1]);
} catch (NumberFormatException e) {
System.err.println("引数には整数を指定してください");
System.exit(1);
}
// 足し算を実行
int result = param1 + param2;
// 結果を表示
System.out.printf("%s + %s = %s%n", param1, param2, result);
}
}
これを起点として、以下の流れで説明していきます。
-
単純すぎるドメイン駆動設計Javaサンプルコード (1) DDDらしいコード
- まずは、上記コードをDDDらしく修正していきます。
-
ポイント
- ドメインの隔離
- レイヤ化アーキテクチャ
- 値オブジェクト
- ドメインの隔離
-
単純すぎるドメイン駆動設計Javaサンプルコード (2) 仕様追加その1
- 次に、ちょっとした仕様追加が発生した際に、手続き型設計とDDDのそれぞれの場合の対応例を考えます。
-
ポイント
- ドメイン知識の凝集
-
ポイント
- 次に、ちょっとした仕様追加が発生した際に、手続き型設計とDDDのそれぞれの場合の対応例を考えます。
-
単純すぎるドメイン駆動設計Javaサンプルコード (3) 仕様追加その2
- さらに仕様追加が発生し、データの永続化が必要となるケースの対応例を説明します。
-
ポイント
- エンティティ
- リポジトリ
-
単純すぎるドメイン駆動設計Javaサンプルコード (4) テスト
- 最後に、手続き型設計とDDDのそれぞれの場合で、テストがどうなるかを説明します。