はじめに
「ドメイン駆動設計(DDD)って結局なに?」と聞かれて、一言で答えられますか?
この記事は、DDDを短く・わかりやすく理解することだけを目的にしています。難しい用語は最小限にして、ネット通販の例で最後まで通します。
なお本記事は、Nottaさんの記事 【React】ドメイン駆動設計への道(I):理論編 の内容をベースに、要点だけを絞って再構成したものです。
問題
DDDの解説は、いきなり「エンティティ」「値オブジェクト」「集約」「境界づけられたコンテキスト」といった用語が並びがちで、結局なにがしたいのかが掴めません。
ゴールはシンプルなはずです。まず一言でDDDを言えるようになること。そのうえで、中心にある「ドメインモデル」が何なのかがイメージできること。この2つに絞ります。
解決方法
DDDを一言でいうと
ビジネスの複雑さを、専門家と共通言語(ユビキタス言語)で作ったドメインモデルに落とし込み、それを設計・コードの中心に据えるという考え方。
ポイントは「ドメインモデルを中心に置く」こと。では、そのドメインモデルとは何か?
ドメインモデルとは
一言でいうと、
業務の中に何が登場し、それらがどんなルールや関係で結びついているかを写し取った設計図。
ネット通販なら、現実には「商品」「カート」「注文」があって、「カートに商品を入れる」「注文は合計金額を計算する」といったルールがあります。これをそのままプログラムの中に「商品」「カート」「注文」という部品として作り、現実と同じ役割やルールを持たせます。これがドメインモデルです。
コードで見る
「注文は合計金額を計算する」というルールを、Order という部品の中に持たせるのがポイントです。
// 商品:名前と値段を持つ
class Product {
constructor(
public readonly name: string,
public readonly price: number,
) {}
}
// カート:「カートに入れる」ルールを自分で持つ
class Cart {
private items: { product: Product; quantity: number }[] = [];
addItem(product: Product, quantity: number): void {
this.items.push({ product, quantity });
}
checkout(): Order {
return new Order(this.items);
}
}
// 注文:「合計金額を計算する」ルールを自分で持つ
class Order {
constructor(
private readonly items: { product: Product; quantity: number }[],
) {}
calculateTotal(): number {
return this.items.reduce(
(sum, item) => sum + item.product.price * item.quantity,
0,
);
}
}
使うとこうなります。
const apple = new Product("りんご", 150);
const cart = new Cart();
cart.addItem(apple, 3); // カートにりんごを3個入れる
const order = cart.checkout(); // カートを注文にする
console.log(order.calculateTotal()); // 450
現実で「合計を出すのは注文の役目」なら、コードでも合計計算は Order が担当する。この現実の役割分担をそのまま部品に持たせたものがドメインモデルです。
図で見る(ドメインモデル図)
コードにする前の「業務の模型」を図にすると、UMLのクラス図になります。
各箱が「登場人物(クラス)」で、中は3段に分かれています。上段が名前、中段が属性(持っているデータ)、下段がメソッド(できる操作)。矢印が登場人物どうしの関係です。
先ほどのコードは、この図をそのまま実装に落としたもの、という関係になります。
抽象度の3段階で整理する
DDDまわりは、抽象度で分けると混乱しません。
| 段階 | 中身 |
|---|---|
| DDD | 考え方・思想(「ドメインモデルを中心に据えよう」という方針) |
| アーキテクチャ | 思想を実現する設計方針(層に分け、依存を外→内にする。まだ抽象的) |
| 実装 | 具体化したもの(実際のフォルダ構成やクラス、コード) |
「DDD(概念)→ アーキテクチャ(実現方法だがまだ抽象)→ 実装(具体)」と下りていく関係です。
おまけ:「ドメインモデルを提出して」と言われたら
あくまで個人的見解ですが、ドメインモデルは「整理された業務の模型」なので、相手に応じて形を変えて表現します。
- ドメインモデル図(UML):業務担当者にも見せられる図。最有力
- ユビキタス言語集:図に出てくる用語の定義一覧
-
コード:エンジニア向けの実装(
Product/Cart/Orderなど)
どれも同じ一つのドメインモデルを、別の形で写したものです。
おわりに
DDDを一言でいうと「ドメインモデルを設計・コードの中心に据える考え方」、ドメインモデルとは「業務の仕組みを、登場人物と関係として写し取った設計図」でした。
とはいえ、この感覚は読むだけだと掴みきれません。小さくてもいいので「登場人物を洗い出す→関係を線でつなぐ→コードにする」を一度自分で通すと、言葉が一本につながります。題材は自分がよく知っている業務を選ぶと、ユビキタス言語=ふだん使っている言葉になるので、モデルの良し悪しを判断しやすいです。
参考
- 【React】ドメイン駆動設計への道(I):理論編(本記事のベース)
JISOUのメンバー募集中!
プログラミングコーチングJISOUでは、新たなメンバーを募集しています。
日本一のアウトプットコミュニティでキャリアアップしませんか?
興味のある方は、ぜひホームページをのぞいてみてください!
▼▼▼
https://projisou.jp
