ドメインモデルの管理にYAMLを使ってみた
はじめに
皆さんはドメインモデル図を作っていますか?
ドメインモデル図はビジネス要件を整理して、チーム間でのコミュニケーションを円滑にするのに非常に役立つツールです。
Draw.io、Miro、Whimsicalなどのビジュアルツールを利用している方も多いと思います。
そんな中半年ほど前からTechBowlでは外部のビジュアルツールをやめ、YAMLによる構造化テキストでドメインモデルを管理するという取り組みを始めました。この記事ではYAMLで管理するイメージをお伝えできればと思います。
従来のWhimsicalベースの課題
以前TechBowlでは下記記事のようにWhimsicalを活用したモデリングを行っていました。
Whimsicalは確かに優秀なツールですが、開発規模が拡大するにつれて以下の課題が顕在化してきました。
- モデル図とコードの乖離が時間とともに進行してしまう
- ドメイン知識の変更履歴が追跡困難になってしまう
YAMLによる解決アプローチ
ドメインモデルを構造化テキストとして管理することで、先述の課題を解決しました!
YAML構造の設計思想
早速ですが、現状運用しているYAML構造のサンプルを載せます。
サンプルYAML
package: Sample/Sample
entity: Sample
name: サンプル
description: |-
SampleはXXXを判断するために必要なものでXXX業務を行う際に利用します。
aggregateRoot: true
values:
- name: サンプルの識別子
key: id
types:
- SampleId
base: BaseId
- name: サンプルの状態
key: status
types:
- SampleStatus
mutable: true
enum:
- case: Hoge
value: ホゲ
- case: Fuga
value: フガ
- case: Piyo
value: ピヨ
- name: サンプル名
key: name
types:
- SampleName
mutable: true
description: |-
VOの説明
constraints:
- type: max_length
value: 15
- type: required
- name: サンプル所有者
key: owner_id
types:
- null
- UserId
- RecruiterId
packages:
- User
- Recruiter
- name: サンプル付与ラベル
key: label_ids
types:
- array
packages:
- Label/Label
factories:
- category: create
constraints:
- サンプルのXXXがXXXである
- サンプルの所有者がXXXの仕様を満たす
- category: update
constraints:
- サンプルの所有者がXXXの仕様を満たす
events:
- category: created
items:
- name: ユーザーに通知する
nameEn: NotifyToUser
description: |-
サンプルが登録されたことをユーザーに通知する
- name: 採用担当者に通知する
nameEn: NotifyToRecruiter
- category: updated
items:
- name: ユーザーに通知する
nameEn: NotifyToUser
- name: サンプル更新ログをとる
nameEn: CreateSampleLog
specifications:
- name: XXX対象
nameEn: XXXTarget
description: |-
- 紐づくUserが18歳未満である
- 紐づくUserがXXXの条件を満たす
references:
- package: User/User
arrowtail: invodot
- package: Recruiter/Recruiter
arrowtail: invodot
主要なドメインオブジェクトを表す構造を配置しています。
Yamlからモデル図の生成
文字列だけだと認識しづらい点を解決するため、このyamlからdotファイルを生成するようにしています。dotファイルに変換さえすればGraphvizを利用した図の自動生成が可能です。
Graphvizでの表示イメージ

GraphvizではTooltipが利用できるため詳細なドメイン知識については対象の概念にカーソルを合わせて確認できるようにしています。

Yamlからドメインオブジェクトの生成
ドメインオブジェクトの生成もこのyamlから行うようにしています。これまでもコマンドで作成できるようにしていましたが、yamlに書いた通り生成される方がコマンドでの入力よりもミスが少なく、扱いやすくなりました。
生成はLaravelのCommandクラスを利用して実装しており、dotファイルも同様です。
サンプルだと生成されたオブジェクトは以下のように配置されます
(ユースケースは別途作成コマンドを用意しています)
Package/
├── Domain/
│ ├── Model/
│ │ └── {package}/
│ │ ├── {Entity}.php
│ │ ├── {ValueObject}.php
│ │ └── {Entity}Repository.php
│ │
│ ├── Factory/
│ │ └── {package}/
│ │ ├── {Entity}CreateFactory.php
│ │ └── {Entity}UpdateFactory.php
│ └── Specification/
│ └── {package}/
│ └── {Specification}.php
│
├── Adapter/
│ └── Gateway/
│ └── {package}/
│ └── {Entity}Gateway.php
└── Infrastructure/
└── Dao/
└── Eloquent/
└── {package}/
└── Eloquent{Entity}Dao.php
YAMLアプローチの効果
1. 自動コード生成による開発効率化
YAMLからEntity, ValueObject, Repository, Factory, Specificationといったようなドメインオブジェクトの雛形を自動生成することで、ボイラープレートコードの作成時間を大幅に低減させました。
2. ドメイン知識のバージョン管理
Gitによる詳細な変更履歴追跡が可能になりました。また、アプリケーションコードの変更が仕様に則したものか判断しやすくなりました。
3. 管理の内製化
外部サービスを見に行かず、コードベースですぐに確認できるためストレスが減りました。外部サービスの利用にかけていたコストも削減できました。
4. 図生成の自動化
図の元となるdotファイル自体がコマンドにより生成されるため、以前行なっていたモデル同士の配線や整備などの作業をしなくて良くなりました。
おわり
yamlの構造さえ決めてしまえばAIの力を借りて生成処理もすぐに作れるので導入コストは高くないと思います!
現状yamlへの移行が済んでないので、既存の実装済みドメインオブジェクトからyamlを生成するようなアプローチも取れたらいいなと思っている次第です!
皆さんもドメインモデルのyaml化、初めてみませんか?
Discussion
PhpStormにはクラスダイアグラムの生成機能があってな(ry