FLINTERS Engineer's Blog

FLINTERSのエンジニアによる技術ブログ

コンテキストマップをPlantUMLで書いてみた。

こんにちは。新卒1年目の佐野です。

弊社のほとんどのチームではドメイン駆動設計(以下、DDD)を実践しており、どのチームでもドメインの詳細やドメイン同士の関係性などコンテキストマップを図として可視化させています。Cacooなどのスケッチツールを用いているチームもありますが、僕の所属するチームではPlantUMLを用い、Cacooよりも便利に感じられたので紹介したいと思います。

PlantUMLとはコードから自動でUML図を生成してくれるツールです。

PlantUMLを使用した感想としては、

  • バージョン管理した時の変更点がわかりやすい

  • 図を意識せず、コーディング感覚でバシバシ簡単に書ける

  • epsやpngなどの形式で保存できる などがあるかと思います。

導入方法

IntelliJAtomなどのプラグインとして利用できますが、僕はAtomを使っているのでその導入方法です。

たったこれだけです。

記法

UMLを書くための記法はたくさんありますが、僕のチームで主に用いた記法を紹介したいと思います。

注意としてチーム内で認識の齟齬を生まないためにもUMLの記法にのっとり書いていくべきですが、DDDの文脈では存在しない概念も存在するのでチームとして決めた記法で統一感を持たせることが重要であると思います。

一概に正解とは言えませんが、僕たちのチームで採用している記法を紹介できればと思います。

モデル定義

DDDにおけるモデル定義は、

class エンティティ <<E>> {
  + 属性
  - プライベート属性
  + ふるまい()
  - プライベートふるまい()
}

class 値オブジェクト <<VO>> 

class サービス <<S>> {
  + メソッド(引数): Int
}

のようにclass, object, enum, abstractなど + 名前 + <<モデルの種類>>でモデルを定義しています。

class A <<VO>>のように中括弧を省略してもかけます。 中括弧内では()の有無でメソッドかどうかを判定しているようです。

f:id:m_sano:20170228141927p:plain:w300

モジュール

モジュールの領域はpackageで分割して表現しています。

package モジュール {
  class A
}

f:id:m_sano:20170228115331p:plain:w200

継承

クラス間に継承関係がある場合はclass A extends B でも確かに書けるのですが大量に子クラスが存在している場合、強制的に横一列に並んでしまうので class A -|> B と書くとよいです。 こうすれば、後述のように -u->として矢印の向きを指定できるようになるからです。

abstract Parent
class Child -|> Parent

f:id:m_sano:20170228164931p:plain:w300

集約

DDDでの集約は、UMLでのコンポジションで表しています。

class ルートエンティティ <<E>>
class エンティティID <<VO>>
ルートエンティティ *- エンティティID

f:id:m_sano:20170228142053p:plain:w300


一方UMLでの集約は他のクラスを参照できるがインスタンスは独立して存在できる状態を示していますが、我々は外部の集約の参照を示す時に用いています。 例えば

class 駐車場 {
  駐車してる車: Seq[車ID]
}
class 車ID
車ID -o 駐車場 

f:id:m_sano:20170228115714p:plain:w300

と表しています。

ちょっとした書き方

矢印の細かい設定

ドメインが増えていくにつれ大量の矢印が発生していくので矢印の向きを自分で指定しないと大変なことになってしまいますので、

A -up-> B
A -u-> B
B <-d- A
B <-down- A

のように方向を制御します。(どれも同じ意味です)。同様にleft(l)right(r)も指定することができます。 例えば

A -r-> B
C -up-> A
D -left-> C
B -d-> D

f:id:m_sano:20170228115756p:plain:w300


また矢印の長さも

A -r--> B
C -r-> A

のようにシャフトの部分を伸ばして長さを調整することもできます。 この二つを駆使して見やすい図を心がけましょう。

多重度

矢印にコメントを追加してクラス同士の多重度を表現することもできます。

A "1" -r--> "n" B
A -r-> C : "1対n"

f:id:m_sano:20170228142840p:plain:w300

コメントアウト

シングルクオートで囲むとコメントアウト可能です。

class A
'これはAのクラスです'
定数定義

定数を定義することもできます。

!define E Entity
class A <<E>>

f:id:m_sano:20170228115831p:plain:w200

最後に

今回の記事ではUML記法の一部を用いているにすぎないですが参考になればと思います。細かく多種な記法をとってもメンバー全員にUMLの知識を必要とするため、コンテキストマップの表現したい粒度とその表記記法をチームで決定することが一番重要であると思います。他にもたくさんの記法があるので公式の日本語リファレンスからチームにあった最適なもの選択するとよいと思います。