PlantUMLの現場活用例

# はじめに
この記事では私が本業（老舗メーカー）でPlantUMLを現場に導入した経験をもとに、環境構築手順や開発チーム内でのルール作り、使用した便利機能を紹介します。PlantUMLの書き方は公式ドキュメントに記載されているため、それぞれの機能をどう組み合わせたかを中心に記載します。PlantUMLでは様々な種類のUML図を書くことができますが、私が今回紹介するのはシーケンス図です。

一例として参考にして頂ければと思います。

# PlantUMLとは？
PlantUMLはUML図をテキストベースで作成することができるツールです。
フリーソフトウェアとなっており、無料で使用することができます。
> githubリポジトリはこちら
> https://github.com/plantuml/plantuml

### メリット
・行間の調整など余計なところに時間を使わなくて良く、設計作業に集中することができます。
・テキストベースのため、git等でドキュメントの差分管理ができます。
・誰が作っても同じようにレンダリングされるので開発の標準化を行うことができます。
・無料で使用できます。


### デメリット
・記法に慣れる必要があります。（ただしそこまで難しくはないです。）
・環境構築が少し面倒です。（現場に導入したとき環境構築が大変だと言われました。ツール導入になれている人であれば問題ないですが不慣れな人だと手順がやや多いかもしれません。

# 環境構築
PlantUMLの環境構築について説明します。

PlantUMLを使用するために必要な手順は以下です。

1. VSCodeのインストール
2. Java(OpenJDK)のインストール
3. Graphvizのインストール
4. PlantUMLのプラグイン導入
5. PlantUMLプラグインの設定変更

## 1. VSCodeのインストール
プラグインが頻繁に更新されている、という観点でVSCodeを使用することをお勧めします。
VSCodeを以下よりダウンロードし、インストールします。
https://azure.microsoft.com/ja-jp/products/visual-studio-code

## 2. Javaのインストール

JavaにはOpenJDKを使用します。
昔のPlantUML導入記事ではOracle Javaが使用されているものもありますが、2019年4月16日から有償化されているため商用利用では使用できません。

以下よりOpenJDKをインストールします。
https://jdk.java.net/

任意の場所に配置してパスを繋ぎます。
コマンドプロンプトで「java --version」を入力し、OpenJDKのバージョン情報が出力されたらインストール成功です。

## 3. Graphvizのインストール

Graphvizは描画のためのツールです。

以下よりGraphvizをインストールします。
https://www.graphviz.org/

## 4. PlantUMLプラグインのインストール
VSCodeにPlantUMLプラグインをインストールします。
<img width="600" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/314894/78e88dd5-df3d-9837-e546-af69ae478f02.png">

## 5. PlantUMLプラグインの設定変更

settings.jsonを変更します。
右下の歯車ボタンを押し、`拡張機能の設定`を選択します。
以下の画面が表示されるので`setting.jsonで編集`を選択します。
<img width="800" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/314894/155ec53a-a86b-d9ec-0c37-fa5300fb19b4.png">

`plantuml.commandArgs`に以下を設定します。
プレビューが表示できない場合を防ぐためです。

``` setting.json
    "plantuml.commandArgs": [
        "-Xmx2g", 
        "-DPLANTUML_LIMIT_SIZE=16384"
    ],
``` 

`拡張機能の設定`画面で、Renderがlocalになっていることを確認します。
<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/314894/7199deb3-439d-7974-9e26-4c7f65320a24.png">

以上でplantUMLを動作させるためのローカル環境構築手順は完了です。

## 動作確認
1. VSCodeを開きます。
2. 新規でファイルを作成します。（拡張子は.pu）
3. テキストを書きます。
シンプルなシーケンス図を出力するテキストです。
4. `alt+d`押下でプレビューを表示します。  
※ プレビューが表示されない場合はショートカットキーが競合している可能性があります。VSCodeのショートカット設定を変更して競合を解消してください。



```test.pu
@startuml

test1 -> test2
test2 -> test1

@enduml
```
<img width="800" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/314894/fcaf6d44-9857-6232-bd5b-3d4aa943a732.png">


# シーケンス図

本記事では具体的なPlantUMLの記法については解説しません。 
チームで開発するための可読性向上のために行ってる取り組みやよく使用する機能について紹介します。

> PlantUMLの公式レファレンスに詳細に記載されているため以下を参考にしてください。
> http://plantuml.com/ja/guide

## 基本的な書き方

私が良く使用するキーワードを使ったシーケンス図は以下です。

<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/314894/1f42b6a3-15f1-e9f3-1dcf-ff5d884ed56b.png">

このシーケンス図はこちらのテキストから生成されています。

```sample.pu
@startuml

title Step1:シーケンス図を書き始める

participant TestModule1
participant TestModule2
participant TestModule3

== 処理を区切る区切り線 ==

TestModule1 -> TestModule2 : 同期処理
activate TestModule1
   note over TestModule1
       注釈
   end note
   activate TestModule2
       TestModule2 ->> TestModule3 : 非同期処理
       activate TestModule3
       TestModule1 <-- TestModule2 : 同期処理の応答
   deactivate TestModule2
deactivate TestModule1


== 処理を区切る区切り線 ==

TestModule3 ->> TestModule1 : 非同期処理からの応答
deactivate TestModule3

activate TestModule1

break エラー発生

   TestModule1 ->> TestModule3 : 強制終了
   activate TestModule3
       TestModule3 -> TestModule3 : 強制終了処理
   destroy TestModule3

end break

@enduml
```

### よく使用するキーワードの紹介

- **title**  
titleを設定します。
- **participant**  
ライフラインの線を表示します。粒度は用途によって色々あるかと思いますが、例えばモジュールなどがここに来ます。定義した順番に右から表示されるので、並べたい順番で記載します。participantを定義しなくても図は書けますが、図内で使用するライフラインは必ずここで定義しておくと運用時に並び替える作業が楽です。
- **== ~~~ ==**  
区切りを表示します。見やすさを向上させるために処理の区切りで入れています。
- **->, <--,  ->>**  
-> でparticipant間を繋ぐと線が現れます。テキストの書き方によって表示される線が変わります。->を同期処理、<--を同期処理の戻り、->>を非同期処理として使用しています。メッセージは：で繋いで右側に記載します。
- **activate, deactivate**  
activateでライフラインを活性化します。deactivateで非活性化します。
- **note**  
注釈をつけます。注釈を表示する場所によって`note left`、`note right`、`note over "participant名"`と種類があります。
- **break**  
エラー時の処理を記載しています。他にもloopやopt、altなどが同じ記法で使用できます。

### テキストの記述ルール
PlantUMLはインデントなしで記述しても正常にレンダリングされますが、修正するときに追いにくくなるため簡単な記述ルールを設定しています。
私が設定しているルールは以下です。

1. `activate`-`deactivate`ごとにインデントを一段下げる。（ただし非同期処理は除く）
2. `break`、`alt`、`loop`-`end xxx`ごとインデントを一段下げる。
3. noteの内容を記述する場合はインデントを一段下げる。
4. ライフライン線を追加する場合は必ずparticipantとしてファイル上部で定義する。
5. コメントは入れない。  
※ puファイルではテキストにコメントを記載できますが、必要なことはすべて図に入れるべき、の精神から禁止しています。

簡単なルールではありますが、インデントを入れるだけでだいぶ可読性が向上します。

## procedureの活用
複数のシーケンスで共通した処理を何回も書いていると、コードのように共通化できたら良いのに・・と思うときがあります。
そこで使用するのがprocedure機能です。ひとつのまとまりをメソッドのように名前を付けて使いまわしすることができます。

<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/314894/d9e25461-a3cf-cb2a-e9c6-0831c901c442.png">

```procedure.pu
@startuml

participant sample
participant sample1
participant sample2

!procedure sample1()

sample->sample1 : sample1
activate sample1
	sample<-- sample1
deactivate sample1

!endprocedure 

!procedure sample2()

sample->sample2 : sample2
activate sample2
	sample<-- sample2
deactivate sample2

!endprocedure 

activate sample
	sample2()
	sample1()
deactivate sample

@enduml
```

## 設定ファイルの活用
色の設定など、全ファイルに共通して使用したい定義は設定ファイルに書き出すことができます。

``` color_setting.pu
/'カラー定義'/
!define C_MODULE1        #peachpuff
!define C_MODULE2        #pink
!define C_MODULE3        #LightGreen

/' スキン定義 '/
skinparam RoundCorner 8
skinparam ArrowColor Black
skinparam Shadowing false
skinparam ArrowFontSize 15

skinparam SequenceLifeLineBackgroundColor DodgerBlue
skinparam SequenceParticipant Black
skinparam SequenceLifeLineBorderColor DarkGray
skinparam SequenceLifeLineBorderThickness 2
skinparam SequenceGroupFontSize 12
skinparam SequenceGroupBorderThickness 1

skinparam participant {
   BackgroundColor whitesmoke
   BorderColor Black
   FontColor Black
   FontSize 15
}
skinparam note {
   BackgroundColor whitesmoke
   BorderColor gray
   FontColor Black
   FontSize 12
}
```

設定ファイルはincludeを使用して他のファイルから呼び出すことができます。
procedureも別ファイルとして定義して、includeすることができます。  

<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/314894/84626adb-5aa3-8ce4-2673-751a7e247a50.png">

``` include.pu
@startuml

!include ./color_setting.pu

participant TestModule1
participant TestModule2
participant TestModule3

== 処理を区切る区切り線 ==

TestModule1 -> TestModule2 : 同期処理
activate TestModule1
   note over TestModule1
       注釈
   end note
   activate TestModule2
       TestModule2 ->> TestModule3 : 非同期処理
       activate TestModule3
   TestModule1 <-- TestModule2 : 同期処理の応答
   deactivate TestModule2
deactivate TestModule1


== 処理を区切る区切り線 ==

TestModule3 ->> TestModule1 : 非同期処理からの応答
deactivate TestModule3

activate TestModule1

break エラー発生

   TestModule1 ->> TestModule3 : 強制終了
   activate TestModule3
       TestModule3 -> TestModule3 : 強制終了処理
   destroy TestModule3

end break
@enduml
```

## 画像のエクスポート
VSCode拡張機能にも画像のエクスポートはあるのですが、まとめて複数の図を出力したいときなどは不便です。私はコマンドラインを使用してフォルダ構成に合わせてsvgファイルを吐き出すようにしています。

platuml.jarは以下からダウンロードできます。
https://plantuml.com/ja/starting

コマンドラインの仕様は以下です。
https://plantuml.com/ja/command-line

以下はwindowsでsvgファイルとして出力する例です。

```output.bat
@echo off
java -jar plantuml.jar -tsvg -charset UTF-8 -o (画像ファイル出力ディレクトリパス) (puファイルのディレクトリパス）

echo 処理が完了しました。
pause
```

# 最後に

現場で活用するために色々試した中で、実際に私がよく使用している機能について紹介させて頂きました。
設定ファイルやprocedureファイルを別ファイルとして定義することで、フォルダ構成も整理できメンテナンスが楽になります。

是非試してみてください！