ContractS開発者ブログ

契約マネジメントシステム「ContractS CLM」の開発者ブログです。株式会社HolmesはContractS株式会社に社名変更しました。

PlantUMLでドメイン駆動設計のモデリングを実装する(Nizi Project編)

こんにちは!株式会社Holmesでエンジニアをしている平田です。

Holmesでは、現在、プロダクト開発にドメイン駆動設計を取り入れようと、社内で勉強会の開催や各メンバーが勉強したことを共有しあったりしています。
ドメイン駆動設計に取り組むにあたって、大切なことのことの一つにより良いモデルを作成する、モデリングがあります。
今回はそんなモデリングをPlantUMLで行う方法について、一例をご紹介できればと思います。

※本記事のモデリング手法は以下の書籍を参考に行なっております。

PlantUMLとは

PlantUML(github)とは、オープンソースUMLダイアグラム作成用の言語です。
本記事ではVisual Studio Code拡張機能を用いています。(PlantUMLのセットアップは拡張機能の説明をご覧ください)

なぜPlantUMLを用いるのか

モデリングを行う方法はオンライン・オフライン問わずいくらでも存在すると思います。
弊社でも、オンラインホワイトボードのmiroを使ったりしています。
その中で、PlantUMLを使う利点としては、プレーンテキストで記述できるため、Gitなどのバージョン管理システムで管理できることではないでしょうか。 PlantUMLで記述したモデルをバージョン管理することによって、コードレビューのプロセスに乗せたり、変更を追っていくことができるようになります。

ユースケース

まずはユースケースを作成します。
今回は、Nizi Projectドメインとして作成します。

Nizi Project(ニジプロジェクト)は、韓国大手事務所JYPエンターテイメントとソニーミュージックによる共同ガールズグループプロジェクトである。

(Wikipediaより)

このオーディションに合格したメンバーはNiziUとして2020/12/02にデビューします。(ついでに覚えて帰ってね)

全体像

f:id:k-hirata:20201007012400p:plain
ユースケース

@startuml NiziProject
actor プロデューサー
left to right direction
rectangle {
    プロデューサー -- (キューブをあげる)
    プロデューサー -- (テストを進める)
    プロデューサー -- (パート1脱落者を決める)
    プロデューサー -- (パート2脱落者を決める)
    プロデューサー -- (合格者を決める)
}
@enduml

たったこれだけでユースケース図を作成することができます。
記述内容の詳細を説明します。

@startuml,@enduml

これは開始と終了をそれぞれ表しています。

@startuml
@enduml
actors
f:id:k-hirata:20201008223846p:plain
actor プロデューサー

actor プロデューサーで人の形をした図が表示されラベルを設定することができます。
:プロデューサー:と記述することもできます。

usecases
f:id:k-hirata:20201008223950p:plain
:プロデューサー: -- (キューブをあげる)
f:id:k-hirata:20201008224037p:plain
left to right direction

プロデューサー -- (キューブをあげる)ではユースケースとactorとの関連を表現しています。--と記述することで関連を線でつなぐことができます。
ユースケースusecase キューブをあげると書くこともできますが、今回は定義と関連付けを同時に行いたかったので(キューブをあげる)と記述しています。
left to right directionは関連の方向を指定しています(作成したい図に合わせて調整してみてください)。

rectangle
f:id:k-hirata:20201008231932p:plain
rectangle { :プロデューサー: -- (キューブをあげる) }

rectangle {}はブロック内に記述することで枠に囲われたように表現することができます。見た目やスコープのために記述しています。

ドメインモデル図

ドメインモデル図は冒頭に紹介した書籍に沿ったルールで作成します。

  • ルールを吹き出しに記述する
  • オブジェクトの関連を記述する
  • 多重度を記述する
  • 集約の範囲を記述する
全体像

f:id:k-hirata:20201008011105p:plain
ドメインモデル図

@startuml NiziProject
skinparam PackageStyle rectangle

package 候補者集約 {
    object 候補者 {
        候補者ID
        パート1脱落
        パート2脱落
        合格
        オーディションID
    }
    object 名前 {
        姓
        名
        ニックネーム
    }
    object ペンダント {
        パート1キューブ
        パート2キューブ
    }
    object キューブ {
         キューブ名
    }
}

note left of ペンダント
    * ペンダントにはそれぞれ4つのキューブをはめることができる。
    * パート1用キューブは重複できず決められた4種類、
      パート2用キューブは最大4つはめることができる。
end note

note bottom of キューブ
    * キューブは5種類存在する。
    * パート1キューブ(「ダンス」「ボーカル」「スター性」「人柄」)
    * パート2キューブ
end note

note right of 候補者
    * パート1で脱落した候補者はパート2キューブを獲得できない
    * パート2で脱落した候補者も以降、パート2キューブを獲得できない
end note

名前 "1" -left-* "1" 候補者
ペンダント "1" -down-* "1" 候補者
キューブ "0..8" -down-* "1" ペンダント

package オーディション集約 {
    object オーディション {
        オーディションID
        オーディション名
        現在テスト
    }
    object テスト {
        テスト名
        パート
        順序
    }
}

note right of オーディション
    * テストの順番は決められている。
end note

note right of テスト
    * テストは1オーディションにつき、パート1に4回、パート2に4回ある
    * テストで獲得可能なキューブは決められている。
    * パート1テスト1~3は決められたパート1キューブを1つ、
      テスト4ではパート1キューブ最大4つ獲得できる。
    * パート2テスト1~3まではパート2キューブ1つ、
      テスト4ではパート2キューブ最大4つ獲得できる。
end note

候補者 "1..n" -down-> "1" オーディション
テスト "8" -down-* "1" オーディション
テスト "1..4" -down-> "1..4" キューブ

@enduml

記述内容の詳細を説明します。

packages
f:id:k-hirata:20201008233415p:plain
package 候補者集約 {}
f:id:k-hirata:20201008233433p:plain
skinparam PackageStyle

skinparam PackageStyle rectangleはパッケージのスタイルを変更するために記述しています。様々なスタイル変更を施すことができるので、興味がある人は調べてみてください。

package 候補者集約 {}集約を表現しています。ブロック内に記述することで集約内であることを表現できます。

objects
f:id:k-hirata:20201008233704p:plain
object 候補者 { 候補者ID }
f:id:k-hirata:20201008234121p:plain
package 候補者集約 { object 候補者 }

object 候補者 {}はオブジェクトです。ブロック内には属性を記述することができます。

notes
f:id:k-hirata:20201008235304p:plain
note left of ペンダント: コメント
f:id:k-hirata:20201008235322p:plain
改行できる

吹き出しでルールを記述することができます。以下は改行の表現で、end noteまでの間に文章を記述し、改行が反映されます。また、インデントが揃っていれば、吹き出しはインデントされませんが、インデントがずれている場合、最もインデントが少ない行をスタートとしてインデントが反映されます。改行が不要な場合、note left of ペンダント: コメントと簡潔に記述することもできます。

note left of ペンダント
  改行
  できる
end note
direction
f:id:k-hirata:20201008235710p:plain

left吹き出しをオブジェクトに対してどの方向に表示するかを指定できます。(left、right、top、bottom)

relations
f:id:k-hirata:20201009000912p:plain
名前 "1" -left-* "1" 候補者
f:id:k-hirata:20201009002700p:plain
名前 "1" -right-* "1" 候補者

名前 "1" -left-* "1" 候補者は多重度とオブジェクト間の関連を表現しています。
-left-*は関連になりますが、--の間にleftと入れることで関連を表示する方向を決めることができます。(left、right、up、down)

label

f:id:k-hirata:20201009002806p:plain
候補者 "0..n" -down-> "1" オーディション
終端の*はいくつかの種類があり、始端と終端両方に記述が可能です。ドメインモデル図では*または>しか登場しません。
関連付けるオブジェクトと関連付けの間に""(ダブルクォート)で囲んで文字を記述することで多重度の表現ができます。

振り返り

私自身、この記事で初めてモデリングを行いました。

ドメインモデル図を見ていただらいたらわかるように、テストのルールが多かったり、キューブがテスト・候補者の双方に深く関連しているように見えます。
今回は、「キューブをあげる(候補者がキューブを受け取る)」ユースケースを鑑みてこのようなモデリングを行いましたが、ユースケースや今後の展開によっては、キューブ集約やテスト集約といった形に変更していくことも考えられます。

モデリングは最初に作成したら終わりではなく、コード同様、常に変更し、より良いモデルに改善していくことが重要です。
モデルをPlantUMLで記述してバージョン管理していくメリットが活きてきますね!

最後に

いかがでしたでしょうか。
PlantUMLを用いたドメイン駆動設計のモデリングが容易にできることがわかっていただけたと思います。
是非活用していただければ幸いです。

Holmesではエンジニア・デザイナーを募集しております。ご興味がある方はこちらからご連絡ください。

lab.holmescloud.com

lab.holmescloud.com