現場で役立つシステム設計の原則にあるUMLをPlantUMLで書いてみる

[フューチャーアーキテクト Advent Calendar 2017](https://qiita.com/advent-calendar/2017/future)の2日目です。

# はじめに

システム設計が大好きで大嫌いな皆さん、こんにちは。
突然ですが、皆さんはどのようにシステム設計における **ドキュメント腐る問題** に立ち向かっていますか？
ドキュメント腐る問題とは、設計時に作成した各種ドキュメントがGoogle Driveやファイルサーバ上で陳腐化してしまい、現状の正しい状態を指していないことです。せっかく新規参画者がキャッチアップしようとしてもドキュメントが真実を示していないという怖いやつですよね。

解決策としては、各種ドキュメントを、MarkdownやAsciiDoc、UMLは[PlantUML](http://plantuml.com/)や[mermaid](https://github.com/knsv/mermaid)、ERDはPlantUMLや[erd](https://github.com/BurntSushi/erd)、画面遷移図は[UI Flow](https://qiita.com/hirokidaichi/items/ff54a968bdd7bcc50d42)、REST-API設計は[Swagger](https://swagger.io/)など、なるべくテキストベースで管理し、GitHubなどのリポジトリで管理することで、（レビューフローなどを適切に設定した上で）コードとの乖離を防ぐ、といったことが一案としてあるかと思います。

モデリングツールで行える表現の限界もありますが、コードとパワーポイントやExcelでの同期をとるのは、経験上ですがとてもパワーが必要なことなので、それに比べかなり実現性が高い案だと思います。また、個人的にはパワーポイントなどの資料作成能力は、センスが磨かれるまで時間を要したり、嫌いな人はメンテをとことん嫌がります。その点、テキストベースだと誰が書いても、同じ設計図が出力されるので効率的だし、パワポ図形のポインタがよく見ると微妙に繋がっていないなど、雑に作成されないという安心感があります。

作成においては、例えばPlantUMLであればIntelliJ, VSCode, Vim などでプラグインがあったり簡単にプレビューできる方法が公開されていて、慣れていない人でもすぐに取り掛かれるなど、環境構築も簡単に行え、生産性も高い状態が整っています。
 
では、それらモデリングツールでどういったドキュメントを作成すべきなんだという疑問が出てきます。システムの要件や開発者のスキル次第など本当にケースバイケースだと思いますが、多くは、API定義、ERD、処理シーケンス図は最低限準備する事が多いと思います。

すこし話はそれますが、[現場で役立つシステム設計の原則](https://www.amazon.co.jp/dp/B073GSDBGT) という名著ではいくつかの設計図が示されています。もちろん、同著は設計図を書くことを主眼に置いて説明したものでも何でもないのですが、個人的に示唆に富む内容が多かったので参考にしたいと思います。今回は、同著で出てくる設計図のうち、個人的に特に有用だと感じたものを5種類、PlantUMLで書いてみたいと思います。

もちろん、同著のなかでは、形式的な資料はかえって危険と注意されていますし、ドキュメントをつくること自体がゴールでもなんでもないので、あくまで題材として利用したとだけだと捉えていただければ幸いです。


## 1. 状態遷移図

PlantUMLでは状態遷移図を書く機能が備わっていおり、`state` 宣言を用います。

なるべく、書籍の綺麗な図と寄せようとしましたが、これが限界でした。関係を示す矢印には、`-right->`, `-left->`, `-up->`, `-down->` などを設定できるので、上手くやればさらに綺麗に並べ替えることができるかもしれません。

ちなみに、`skinparam shadowing false` は各オブジェクトに影を無くしフラットな表示にするために宣言しています。

![状態遷移図の例](http://www.plantuml.com/plantuml/png/RP91IyCm5CVlxrFaBEmBU1Zx7kAXqkZAsYfDn7C7Zhau1YBru67WPQYq7eQkMDGFqpRTleKlTcssu2My_D-FVzu_IOznA-2NdWl07UvIKaq-vBNOXAjgaPMFopnCYcy1RE3u5rPWUOJrBVlyol7FoAdbCWfznwR4ezu93HW0kd5AohTdES-ADDxkvStF-cKgqt7JJ-Oo-j9zh6GKwtsvIlBmGOupNBLQlG-Bpn70qS4nwNIw-XHoIAhxvVfLW9OKq1wBG5s3bluScZaGs4IYNA13AocW7Go1kWOjcGxbQ8eci3j4ruoYi1q5pBOH2osRP2Q8Z-0ZNL-AGcTHFfmKgSZ3Ep1o_W_jHzLCSgkkUJzdsrLo_0Im5LGFtmEWHtrR_Q9V)

```text:状態遷移図の例
@startuml

title 状態遷移図の例
skinparam shadowing false

state 審査中
state 承認済
state 実施中
state 中断中
state 差し戻し中
state 終了

[*] --> 審査中 : 申請
審査中 --> 承認済 : 承認
承認済 --> 実施中 : 開始
実施中 --> 中断中 : 中断
中断中 --> 実施中 : 再開

審査中 -> 差し戻し中 : 差し戻し
差し戻し中 -> 審査中 : 再申請
差し戻し中 -down-> 終了 : 取り下げ

承認済 --> 終了 : 取り下げ
実施中 --> 終了 : 完了
中断中 --> 終了 : 中止

終了 --> [*]

@enduml
```

状態遷移の「元」と「先」を表で書くことも多いと思いますが、こういった遷移図も準備するとぐっと直感的に理解できますよね。QiitaやGitHubだとPlantUMLのシンタックスハイライトはしてくれないので、抑揚が無いように見えますが、対応するエディタだともう少し視認性が良いです。


## 2. パッケージ構成図

PlantUMLではパッケージ図そのままは用意されていないようですが、空のパッケージは許容されているようなので、クラス図で代用します。パッケージ同士で依存関係を引いて作成します。

`.>` と `..>` の違いですが、パッケージ間の距離を表現できるので、多少レイアウトは変更できます。なるべく書籍のカッコイイ図に寄せたつもりですが、これまた微妙に異なります。期待された方はすいません..。

![パッケージ構成図](http://www.plantuml.com/plantuml/png/SoWkIImgAStDuIh9BCb9LNZSFF5nS_FZfesFc_SyRjhnTFRcnuqhdkoR-tJjZ9VJ5ZtPtyJ5fQvGa9YSdPYUoWMb5LukNFvqtIA5wbguoDF-wSyshq0HcThsT78ZYiYS5KzthKOHQT_redSxiiYBrTtFDZQXg9azxsb_7qW4w92SpBniBgZjDdfGMxcWLY49G5oZfsS7jHHP2LG0eWGa07O45zHrI08Gnm4588xYWheDf0Bi9Yw7rBmKK4W20000)

```text:パッケージ構成図
@startuml
title パッケージ図と依存関係

' package
package 顧客 {}
package 受注 {}
package 商品 {}
package 在庫 {}
package 出荷 {}
package 請求 {}
package 回収 {}

' link
顧客 <. 受注
商品 <. 受注
受注 ..> 在庫
商品 <. 在庫
受注 <. 出荷
在庫 <. 出荷
出荷 <. 請求
請求 <. 回収
@enduml
```

パッケージ図は意外と盲点で自分は書籍を読むまで書いたことが無かったです。
個人的には、当初の設計では依存しないはずのクラス同士が依存していることをあぶり出したり、再設計のきっかけになるので今後も作成し続けたいと思います。


## 3. 業務フロー図

役職や部門がからむシーケンス図を書く場合はスイムレーン(swimlane)なアクティビティ図で記載することが多いと思います。PlantUMLでも表現できます。これまた、書籍に記載されている図より見にくいのが心苦しいですね。

![業務フロー図](http://www.plantuml.com/plantuml/png/SoWkIImgAStDuUAgYOz_kN3vqtMBukDhk3YjdcrUyMnQ--F6cO-Rkgs1iigEUIMPXQMfuHcP9Qb0jIyshNowUDFBvXKlfpL0T3oTi-BfhjMFcoOzNxJhnQfUc5QWHFkk5xtRCIH0DaAaK4o1A8PfJiiloaOsukc2ZKydTk5srlEjFSydj24R-69rzxEDJSYM8daJP7nYUc9c7iYEgMrF9pU2xEYV_hXnujF-QTXqfEQbA40TzMpA-cUTKnytjX7daAUjIr-sJyGC1WUWaQ0O0000)

レーンを `|hoge|` で表現できます。 `__`で囲んでいるのは下線をつけるためで、色を変えたい場合は、`#AntiqueWhite` などで変更可能です。レーン宣言の後にインデントを下げているのは、見やすさのために付けてみただけで、文法上は不要です。また、`fork`, `forkagein`, `fork end` など見慣れぬ宣言が並んでいますが、これは処理を分岐させるために必要なものです。

定義も見にくいですが、`fork` を使うと出力される図がお世辞にも見やすいとは言い難いのが辛いところですね。どうしても黒いバーが出てしまいます。
これに関しては今のところ回避方法が思いつきませんでした。

```text:業務の流れ（業務フロー図）
@startuml

|__顧客__|
	:注文する;

|#AntiqueWhite|__販売部門__|
	:在庫を確認する;
	:出荷を確認する;

|__出荷部門__|
	:出荷する;
	fork
	:出荷を報告する;

|#AntiqueWhite|__経理部門__|
	:請求する;

|__顧客__|
	forkagain
	:商品を受け取る;

|__顧客__|
	end fork
	:支払う;

|#AntiqueWhite|__経理部門__|
	:入金を確認する;

@enduml
```

あるシナリオに応じた業務フロー図が一つでもあると、初期開発者は非常に喜びますよね。
口頭でユースケースを説明されても、登場人物（レーン）が3つ以上あるとカオス感がありますし。

業務からちょっと遠い人でも、システム間連携やバッチ処理などで複雑なワークフローが存在する場合は、このスイムレーン形式の記載を応用すると、課題をクリアにすることができるかもしれません。


## 4. コンテキスト図

コンテキスト図とは、システムの名前や目的、関係者、外部システムを示した者で、システムの目的となる言葉を探すことで重要なクラスの発見や手がかりにするためのもの、だそうです。

![コンテキスト図](http://www.plantuml.com/plantuml/png/SoWkIImgAStDuU8goIp9ILLutBJvSJCGjJrkMlkuQUVZvewdipTpSJsVkVlfWYrFTkrwthbIGTTEGUDnqtQmTDlZvWLF9_HgSkNbbwGg56McPvGevASfe4ahMA68F6vSztpskkUpMhWmp57GrLM8VZbjqSk6nSXIiLnS3gbvAI270W00)

```text:コンテキスト図
@startuml

title コンテキスト図

登場人物 -> (システム名)
note right of システム名 : システムの目的
(システム名) -- [関連システム]

@enduml
```

DDDを行うと出てくることも多いと思いますが、経験がないので。
ただ、こういう成果物もリポジトリ管理されているプロジェクトは好感が持てそうです。


## 5. 主要クラス図

主要と書いているのがミソで、実際のクラスというよりはより概念的なクラスという意味だと思います。

![主要クラス図](http://www.plantuml.com/plantuml/png/SoWkIImgAStDuU8goIp9ILLuicFtYsMDZvlMFsvU-RXfvzFPcxcuCZ9JKXLoKtEJKekA8PpapABad5GkhkISnE9YXSVDanutTy0uJPkHECsB7ZVtGJdFPZP1MKyNR7dMsS351T6eOAEh2zC6qG0KWGk0AGLTNJkmVXZN3cv6Ndv9ga9HPdf6YK9-6jGf2bOAJnkwd-pQfVziyrGGzR9vnSjf3NfwUZ5vJpkMF9kszd7ZEg1Fd-oTpCNba9gN0Wm00000)

クラス図で、フィールドやクラス記号を記載したくない場合は、`hide menbers`, `hide circle` を宣言します。

```text:主要クラス図
@startuml

title 主要クラス図

hide members
hide circle

class ヒト
class コト
class モノ
class 時
class 場所

ヒト <-- コト
モノ <- コト
コト --> 時
コト -> 場所

note right of ヒト : 個人/法人/部門...\n判断の主体

@enduml
```


クラス設計は頭を捻る必要があり時間がかかる割に、開発者同士の認識レベルに差が出やすいところなので、設計段階で指針となるものがあると、ぐっと開発生産性が上がりそうですね。
もちろん、重要な関心事やその依存関係を明確にする上でも、それらのあぶり出しを行なう上でも有益だと感じます。

# PlantUMLを導入してよく言われたこととその返し

今の開発現場に導入した後に言われたことです。
ドキュメントを増やすこと自体への反対意見はありませんでした。

* 色がダサい、どうにかならないのか
    * 変更もできますが、諦めましょう。開発者なら、開発者自身がこの色合いに慣れるのです
* もう少しレイアウト調整できないのか？
    * 頑張れるところもありますが、それは諦めましょう。がんばるとメンテナンス性が下がります
* この図はコードの自動生成に使えないの？
    * その道は茨なので諦めましょう。UMLを使う人が何度も夢見たので気持ちはわかります
* CIなどで自動出力できないの？
    * できます。PlantUMLはJARで提供されているので、`java`コマンドをCIで実行すればよいです

# まとめ

* [現場で役立つシステム設計の原則](https://www.amazon.co.jp/dp/B073GSDBGT) は尊い
* レイアウト調整には限界があるものの、PlantUMLで大体書ける
* おそらく次はUMLを書くの面倒くさい問題になる