PlantUML で UML お絵描き生活

## はじめに

今回は [PlantUML](https://plantuml.com/ja/)について紹介します。PlantUMLは最近連携ツールが増えつつある特定の記法のテキストからUMLを生成するツールです。本記事は9月15日、オンラインで社内勉強会を開催した際の資料を元に書いたものです。

この記事の対象者は、

- UMLってなんか聞いたことある人
- UML知ってるけど描くのにいいツールないかなぁと思ってる人
- UMLがGitで管理できたら最高じゃんと思う人

を想定しています。

## 1. ゆーえむえるってなぁに？

### 統一モデリング言語

> 統一モデリング言語（とういつモデリングげんご、UML、英: Unified Modeling Language）は、主にオブジェクト指向分析や設計のための、記法の統一がはかられた（Unified）モデリング言語（Modeling Language）である。

出典: フリー百科事典『ウィキペディア（Wikipedia）』

つよそう

### こういう図のこと

![sample1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326401/ec303f01-2eaa-7308-91ab-e1a789ffbefc.png)
![sample3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326401/8bb68e00-3149-4d34-dcb2-b49cc1e4603e.png)
![sample4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326401/65878203-4184-2488-6b32-d8b950d6fd41.png)
※以上PlantUML公式から引用

![sample2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326401/acbf4481-8941-df15-e3c1-3929da97dcd2.png)

色々あるけど全部UML。UMLは色んな図の書き方のルールをまとめたもの。


## 2. どんな風に使うの？

### シーケンス図

![sequence1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326401/7cbc4a30-7603-208d-1360-b2232cff0371.png)

複数のオブジェクトの間のメッセージのやり取りと、それぞれのオブジェクトの活性・非活性を時系列で描くための図。


### ユースケース図

![usecase1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326401/cfce0e95-b89e-8bc2-0aa6-931a37d22648.png)

ユーザ視点でのシステムの利用例を表す図。顧客への説明で使うことを想定している。

### アクティビティ図

![activity1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326401/362c7729-24de-45b4-1f2b-21e58045be03.png)

フローチャートを発展させた図。フローチャートと違ってハードウェアを直接表すような記号は無い。並列処理・例外にも対応している。

現在はステートメントを一つ一つ記述するフローチャートはナンセンスとされている。そのためアクティビティ図では概念的な処理の流れを記述する。

### 状態遷移図

![statemachine1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326401/25b6936f-1192-451c-6b1a-38434028eb75.png)

状態の移り変わりを表す図。システムがどんな振る舞いをするのかを表す。queue構造と相性がいい。

### 配置図

![deployment1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326401/bf1a0d70-a410-3501-8da1-1ab167ee5ca4.png)

システムの物理的な構成を表す図。ネットワーク図もここに含まれる。

### ほかにもいろんな図がある

- クラス図
- コンポーネント図
- タイミング図
- まだ見ぬ強敵達...

その時々の用途に合わせて使おう。

## 3. UMLってどうやって描くの？

### UMLを描くツール

デファクトスタンダードと言えるようなツールは無いみたい。
完全にUMLのみのツールというのはあまりない。

- **draw.io**
  最近人気が高いドローイングツール。Webサービスなのでブラウザで使う。
  色んな図が描ける。

- **Microsoft Visio**
  昔からあるドローイングツール。
  Microsoftに買収されてからはOfficeの一つとして扱われている。でも別売り。

- **パワポ**
  パワポさえあればなんでもできるぞ！！

## 4.PlantUML ってなんですの？

PlantUMLはテキストをUMLに変換するコンポーネント。
テキストなので他のツールに組み込みやすい。テキストなのでバージョン管理もできる。Markdownに組み込めるツールも結構ある。
Visual Studio Codeでもプラグイン入れればMarkdownにUMLを埋め込んだ文書を作れる。

https://plantuml.com/ja/

### 今回使う環境

今回は社内勉強会のために用意したCodiMD環境を使います。
CodiMDにPlantUMLでUMLを描くにはサーバ側で設定ができていれば以下の記述で表示されるはずです。

![version.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326401/4462e723-4bea-84ae-6322-272e58e5750c.png)


### 最も簡単に使うには

最もかんたんで素早く PlantUML を使いたい方には、[PlantUML オンラインサーバ](http://www.plantuml.com/plantuml/uml/SyfFKj2rKt3CoKnELR1Io4ZDoSa70000) がおすすめです。


## 5. 今回描く図

今回は

- シーケンス図
- アクティビティ図
- 状態遷移図

を描いていきます。

## 6. PlantUMLでシーケンス図を描く

### さっきのはこう書いてた

```=
@startuml
Activate 母
母 ->> 息子: おきなさい！
母 ->> 息子: おきなさい！
母 ->> 息子: おきなさい！
Activate 息子
息子 ->> 母: おきたー
Deactivate 息子
母 ->> 息子: 二度寝するな！
@enduml
```

![sequence1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326401/3e1aed67-21b0-f342-e808-94b00ede536d.png)


### 図の意味は？

矢印はメッセージ。太線になっている部分はアクティブな状態。
アクティブな状態を維持している期間を表すことができる。

```=
@startuml
A -> B: 塗りつぶし実線矢印は同期呼び出し
activate B
B --> A: 点線はレスポンス
A ->> B: 線だけ実線矢印は非同期呼び出し
B -->> A: 非同期のレスポンス
deactivate B
@enduml
```

![sequence2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326401/d058f92e-f441-0c1b-7d76-ebbd2fd3c212.png)

### もちろん3つ以上でも

```=
@startuml
activate A
A -> B: 起動
activate B
B ->> C: 起動
activate C
C -->> B: 起動完了
B --> A: Cの起動完了
deactivate B
C -->> A: 処理完了
deactivate C
@enduml
```

![sequence3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326401/c11bac75-6752-d480-2701-982a398a44df.png)

### 分岐とループ

分岐は`alt`、ループは`loop`で記述する。
他にも色々定義されている。

```=
@startuml
A ->> B: 起動

loop 起動完了まで
  A ->> B: 起動チェック
end

alt 正常起動
  B ->> A: 正常
else 異常
  B ->> A: エラー
end
@enduml
```

![sequence4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326401/8134e01c-d836-2449-cb32-48abcba2dad9.png)

### 見やすくする

オブジェクトがたくさんある時は分類したり境界線を入れたりすると見やすいかもしれません。

```=
@startuml
box 社内
  participant A
  participant B
end box
box 客先
  participant C
end box

A -> B: 社内接続
== ここから危ない処理 ==
B -> C: 客先接続
@enduml
```

![sequence5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326401/b1c008e6-cb58-fd91-f764-2a300c086373.png)

## 7. PlantUMLでアクティビティ図を描く

### さっきのはこう書いてた

```=
@startuml
start
if (おなかすいた？) then (すいた)
  :おやつたべる;
endif
end
@enduml
```

![activity1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326401/69c8b4a3-ce42-2cb6-de03-21e9422cbcb9.png)

### 開始と停止・終了

`start`は任意の範囲内での始端。
`stop`は任意の範囲内での終端。
`end`はプロセスとかの全体の終了位置。

```=
@startuml
start
stop

start
end
@enduml
```

![activity2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326401/692dc76b-eeb8-4c84-7564-538e9f795737.png)
![](activity2.png)

### 単純なアクティビティの遷移

`:`と`;`の間に書いていくだけ。

```=
@startuml
start
:起きる;
:ご飯食べる;
:寝る;
stop
@enduml
```

![activity3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326401/6acf5c0b-06f2-5861-68be-127e4d865a87.png)

### 条件分岐（if）

`if` `then` `else` `endif`で条件分岐。
`then` `else`の後の条件は省略可能。

```=
@startuml
start
if (今日のご飯は？) then (肉がいいな)
  :しょうが焼き定食;
else (魚がいいな)
  :サバの味噌煮定食;
endif
stop
@enduml
```

![activity4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326401/8f8eedec-65bc-57e5-db5b-e6810de04cb7.png)

### 3つ以上への条件分岐（elseif）

`elseif`で3つ以上のルートへの分岐ができる。

```=
@startuml
start
if (今朝はご飯だった) then (Yes)
  :お昼はパンにしよう;
elseif (今朝はパンだった) then (Yes)
  :お昼はご飯にしよう;
else (No)
  :お昼は豪勢にしよう;
endif
stop
@enduml
```

![activity5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326401/afc632f7-69d3-7b9e-ba07-9dda3d92a924.png)

### 前判定のループ処理

`while` `endwhile`で繰り返し処理を表現する。

```=
@startuml
start
while (お腹いっぱい？) is (まだいける)
  :食べる;
endwhile (もう食べられないよぉ)
stop
@enduml
```

![activity6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326401/486a5bb8-052b-554c-6a5f-ce839e40fbd9.png)

### 後判定のループ処理

後判定では`repeat` `repeat while`を使う。
`backward`で繰り返し処理を継続する場合のみの処理を記述できる。

```=
@startuml
start
repeat :ご飯が来る;
  :食べる;
backward :「おかわり！」;
repeat while (足りた？) is (まだまだ)
stop
@enduml
```

![activity7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326401/1d124ce9-56d4-c10d-2c0f-7a731e4cc16c.png)

### 並列処理

`fork` `fork again` `end fork`で
並列処理を表現する。

```=
@startuml
start
fork
  :食べる;
fork again
  :飲む;
end fork
stop
@enduml
```

![activity8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326401/26dfc54f-d2f6-f18b-982e-227e09e55c94.png)

## 8. PlantUMLで状態遷移図を描く

### さっきのはこう書いてた

```=
@startuml
hide empty description
state 出社 {
  仕事 -> 休憩
  休憩 -> 仕事
}
state 退社 {
  呑む -> 寝る
}
出社 -d-> 退社
退社 --> 出社
@enduml
```

![statemachine1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326401/eab69840-5697-aacb-8189-2190985e33c6.png)

### 図の意味は？

枠内は状態、矢印は状態の遷移を表す。

```=
@startuml
state 状態1: 状態1の解説
state 状態2: 状態2の解説

状態1 --> 状態2: 状態1から2への\n遷移条件
状態2 --> 状態1: 状態2から1への\n遷移条件
@enduml
```

![statemachine2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326401/244b4be3-8420-ba40-dc5c-b606ba6c318f.png)


### 始点と終点

`[*]`で始点または終点を表す。

```=
@startuml
[*] -> 状態
状態 -> [*]
@enduml
```

![statemachine3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326401/cb87bd27-da8d-cc19-f234-63cb183d2a75.png)

### 状態を列挙する

`state`で状態をあらかじめ定義しておく。単純な図であれば省略できる。

状態遷移図は記法が似ているのでシーケンス図と認識されてしまう事が多い。`state`で一つでも状態を作っておけば正しく認識される。

```=
@startuml
state A: Aの解説
state B
C: Cの解説
@enduml
```

![statemachine4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326401/8efce794-7e19-3a3e-dff1-29bcb415d6cb.png)


### 矢印の書き方

矢印は`-`の数を増やすと長くなる。
矢印の途中に`up` `down` `right` `left`あるいは`u` `d` `r` `l`のいずれかを入れると矢印の向きをある程度制御できる。

```=
@startuml
state A
A -> B
B --> C
A ---> D

V -u-> W
V -r-> X
V -d-> Y
V -l-> Z
@enduml
```

![statemachine5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326401/ede64e1f-a584-ebf0-14f7-4cecea49e769.png)

### 複合状態

状態の中に複数の状態がある場合は状態の中に状態を描く。

```=
@startuml
hide empty description
state 画面A {
    [*] -> 設定画面
    設定画面 --> 確認画面: 確認ボタン
    確認画面 --> 設定画面: 戻るボタン
}
state 画面B {
    [*] -> 実行中画面
    実行中画面 -> 実行結果画面
}

[*] --> 画面A
確認画面 --> 画面B: 実行ボタン
実行結果画面 --> [*]
@enduml
```

![statemachine6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326401/cc9f3ecd-38d6-f148-b3c7-23df9dc69e27.png)


## 9. みんな上手く描けた？

### そんなにたくさん覚えられない・・・

私も覚えて使ってるわけじゃないです。
毎回公式サイトを見ながら描いてます。見ながらでいいのよ。

https://plantuml.com/ja/

PlantUMLはまだまだいろんな記法があります。
UML以外にも対応しているので興味があれば使ってみてください。



Ditaaとかね・・・！

```=
@startuml
ditaa
+-----+-----+   +----+
|     | bbb |-->|    |
| aaa +-----+   | dd |
|     | ccc |...|    |
+-----+-----+   +----+
@enduml
```

![ditaa.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326401/7fa24f15-1ce9-0868-d0d1-e5e8fa1abcb5.png)


## 終わりに

俺たちの戦いはこれからだ！
おしまい。


*本記事はクオリティアの中の一人、中本さんに書いていただきました。