📘

ドメインモデルの管理にYAMLを使ってみた

に公開1件

はじめに

皆さんはドメインモデル図を作っていますか?
ドメインモデル図はビジネス要件を整理して、チーム間でのコミュニケーションを円滑にするのに非常に役立つツールです。
Draw.io、Miro、Whimsicalなどのビジュアルツールを利用している方も多いと思います。
そんな中半年ほど前からTechBowlでは外部のビジュアルツールをやめ、YAMLによる構造化テキストでドメインモデルを管理するという取り組みを始めました。この記事ではYAMLで管理するイメージをお伝えできればと思います。

従来のWhimsicalベースの課題

以前TechBowlでは下記記事のようにWhimsicalを活用したモデリングを行っていました。
https://zenn.dev/techtrain_blog/articles/334ac36e79d946

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を利用した図の自動生成が可能です。

https://graphviz.org

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化、初めてみませんか?

TechTrainテックブログ

Discussion

horie-thorie-t

PhpStormにはクラスダイアグラムの生成機能があってな(ry

1