アクトインディ開発者ブログ

子供とお出かけ情報「いこーよ」を運営する、アクトインディ株式会社の開発者ブログです

PlantUML

morishitaです。

開発の中でドキュメントを書くことがあると思います。
しっかりした仕様書を作成するところもあるでしょうし、重要な部分のみメモ程度ということもあると思います。

ドキュメントでは文章を書くことが多いとは思いますが、文章だけでは説明が難しい場合、図を書いたりすると思います。 システム開発での図というとクラス図やフローチャートなどかと思います。
独自の記法だと見せられる方が困るので、とりあえず厳密でなくても UML を利用しているのではないでしょうか。

今回は UML を描くときに便利な PlantUML について書きます。

UML とは? そして PlantUML とは?

PlantUML の話をする前に UML とは何でしょうか?
システムを開発する場合にはシステム化対象の要件を抽象化して設計に落とし込む必要があります。文章で仕様を記述したりもしますが、モデルとモデルの関係や相互作用を表すには文章よりも図にしたほうがわかりやすい場合が多いです。
また、すでにあるシステムの構造を理解するためにクラス間の関係を図に書いたりすることもあるかと思います。

そんなときによく使われる図の記法が UML です。

UML は Unified Modeling Language の略で、日本語に訳すと「統一モデリング言語」1と呼ばれるものです。
システム構成やソフトウェアの構造や振る舞いを表す図の記法を定めたもので、従来存在していたいくつかの記法の考案者2が協力して 1 つに集約した記法です。 UML の仕様はOMG | Object Management Groupという団体により管理されています。

UML では構造図 (Structure Diagrams) 7 種、振る舞い図 (Behaviour Diagrams) 3 種、相互作用図 (Interaction Diagrams) 4 種の 14 種の図が定義されています。
14 種類の図をすべてを利用する必要はなく、モデル化したい対象を表すのにふさわしいもの必要に応じて選択して利用します。

f:id:HeRo:20220213101902p:plain
UML Overview
(出典:Unified Modeling Language - Wikipedia)

クラス図やシーケンス図などはシステム開発の現場ではよく使われていると思うので見た事あるのではないでしょうか。 また、システム開発だけではなく、ビジネスプロセスのモデリングや組織の構造図を表現するのにUML が使われることもあるようです。

そして PlantUML はこの UML をテキストで記述できるツールです。
独自の記述方法があり、詳しく公式サイトで説明されています。

PlantUML

PlantUML が利用できる環境

公式のオンラインサーバにブラウザでアクセスすればすぐに描くことができます。 公式の Docker イメージplantuml/plantuml-serverを利用すれば、公式のオンラインサーバと同等ものがローカルで動かせます。
そもそも Jar にパッケージされたモジュールなのでそれを利用してPlantUMLを記述したテキストファイルから UML の画像ファイルを出力することもできます3

公式ツールは PlantUML で書いたものを画像として図化してくれるツールですが、 UML の図を単体で描くのではなくドキュメントの中に書きたい場合のほうが多いのではないかと思います。なので手軽に PlantUMLを利用する環境としては VSCode の拡張 Markdown Preview Enhancedがオススメです4。Markdownファイルの中で PlantUMLで書いた図を埋め込めます。
Markdown なメモアプリ Obsidianでもobsidian-plantumlプラグインをインストールすると使えるようになります。

また、Kibelaesaといった Markdown 形式で記述できるドキュメント共有サービスでもサポートされています。文章中に PlantUML で図を入れることができます。
アクトインディではドキュメントの共有に esaを利用しているので私は主にそこで使っています。

PlantUMLで描けるUML

PlantUML がサポートしている UML の図は 9 種類です。 順に見ていきましょう。

ユースケース図

システムが提供するサービスとそれに関係する外部要素(ユーザや外部システム)の関係を表すのがユースケース図です。
楕円でユースケースを人形はそのサービスを利用するアクター(ユーザや外部システム)を表します。 個々のユースケースがどういうことをするのかは表さないので必要ならユースケース記述等で補います。

f:id:HeRo:20220213104656p:plain
ユースケース図の例

上のユースケース図は次のPlantUMLの記述で生成しました。

@startuml
left to right direction
actor "メンバー" as member
actor "イベンター" as eventer

rectangle "いこーよ" {
  usecase "お出かけ先をさがす" as uc1
  usecase "イベントをさがす" as uc2
  usecase "イベントを登録する" as uc3
}

member --> uc1
member --> uc2
eventer -up-> uc3
@enduml

タイトルだけでおおよその内容の見当がつくシンプルなユースケースならユースケース図だけシステムが提供するサービスの全体像を把握するには十分かと思います。

クラス図

モデルの静的な関係を表す図で、問題領域やシステム化対象領域にあるモデル要素の構造を表します。
モデル要素とはクラスです。クラスの構造とクラス間の関係によって問題領域やシステム化対象領域を表現します。
UML の中では最重要かつ最も利用される図であり、他の図はなくてもクラス図だけは書く場合も多いと思います。

f:id:HeRo:20220213104718p:plain
クラス図の例

上のクラス図は次のPlantUMLの記述で生成しました。

@startuml

class User
class Member
class Child
class Eventer
Class Event

Member -up-|> User
Member *--"0..*" Child
Eventer -up-|> User
Eventer --"0..*" Event
@enduml

オブジェクト図

クラス図がクラスの構造、関係を表すのに対して、オブジェクト図はオブジェクトが保持するデータ、オブジェクトの間の関係を表します。
クラスを具象化したものであるオブジェクト(インスタンス)を描くのでシステムのある時点でのスナップショットを表します。

クラスのインスタンスが具体的にどの様な値を持ち、どの様な関連を持つのか理解するのに役立つとは思いますが、わざわざ描くのも面倒なのであんまり使われないと思います。

シーケンス図

問題領域やシステム化対象領域のモデル要素がどのようなやり取りをすのかという振る舞いを表すのがシーケンス図です。

クラス間のメソッドの呼び合いやシステム間のAPIのやり取りなど複数のモデル要素にまたがった処理を時系列順に表すのに便利です。

f:id:HeRo:20220213104739p:plain
シーケンス図の例

上のシーケンス図は次のPlantUMLの記述で生成しました。

@startuml
actor "イベンターA" as user
participant ":イベント登録画面" as form
participant ":イベントコントローラ" as event_ctrl

user -> form: イベント情報を入力
form -> event_ctrl: イベント登録
event_ctrl --> form: 登録情報
form -> form: 登録結果表示

@enduml

アクティビティ図

アクティビティ図では業務や処理の流れを表します。フローチャート呼ばれるものと役割も見た目も近しいかと思います。

f:id:HeRo:20220213104813p:plain
アクティビティ図の例

上のアクティビティ図は次のPlantUMLの記述で生成しました。

@startuml
|イベンター|
start
:イベントを企画する;
:イベントを情報を入力する;
|いこーよ|
:イベントを登録する;
:イベントを表示する;
|参加者|
:イベント情報を見る;
:イベントに参加申込する;
|いこーよ|
:イベント参加登録する;
|イベンター|
:イベントを開催する;
stop
@enduml

コンポーネント図

システム内のコンポーネント構成、関連を表す図がコンポーネント図です。

f:id:HeRo:20220213104556p:plain
コンポーネント図の例

上のコンポーネント図は次のPlantUMLの記述で生成しました。

@startuml
[Webポータル] as web

[チケット販売サブシステム] as ticket
interface "チケットAPI" as ticket_api
ticket_api - ticket

[決済サブシステム] as payment
interface "決済API" as payment_api
payment_api - payment

web -> ticket_api
ticket -> payment_api
@enduml

アプリケーションサーバと DB だけで構成されるようなシンプルなシステムではまあ、必要ないと思います。
モノリスな Rails アプリケーションでも DB 以外に様々なミドルウェア、サービスを利用している場合に全体を俯瞰するには役立つと思います。
マイクロサービスでシステム構築しているところではもっと便利で役立つかもしれません。

配置図

配置図はシステムの物理的な構造を表します。例えばどの様な種類のサーバを立てて、その中でどの様なプロブラムを動かすのかといったことを図示できます。
UML の中でも比較的低レイヤーを表す図です。どのサーバに障害が発生すると何が止まるのかを把握するのに役立つのではないでしょうか。

f:id:HeRo:20220213104852p:plain
配置図の例

上の配置図は次のPlantUMLの記述で生成しました。

@startuml
node UI <<Pod>> {
  artifact クーポンサイト <<nuxt>> as portal
}
node API <<Pod>> {
  artifact クーポンAPI <<rails>> as api
  interface "/coupons" as coupons
  coupons - api 
}
portal -down-> coupons
@enduml

状態遷移図(ステートマシン図)

1 つのオブジェクトの状態変化を表した図です。 Web システムだとできるだけステートレスに設計するのでそれほど複雑な状態を持つオブジェクトの設計はしないと思うのであんまり使わない図だと思います。 組み込み系だとデバイスの動作状況により振る舞いが変わったりするのでよく使うのかもしれません。

f:id:HeRo:20220213104926p:plain
状態遷移図の例

上の状態遷移図は次のPlantUMLの記述で生成しました。

@startuml
state "公開中" as published {
  state "募集中" as recruiting
  state "募集終了" as closed

  recruiting --> closed
  closed --> recruiting
}
state "非公開" as private

[*] --> private
private --> published
published --> private
published --> [*]
private --> [*]
@enduml

タイミング図

多分、電子回路の設計などをするときに有用な図なのだと思うのですが、使ったことがないのでよくわからないです。 「タイミング図は現在作成中です。必要な機能があれば提案してください」とのことなので今後、書き方が変わっていくかもしれないですね。

UML だけでない PlantUML

PlantUML という名称なので描けるのは UML だけかなと思うのですが、そうではありません。 UML にはないけれど、システム開発でよく使われる PlantUML がサポートする図を紹介します。

ER図

データベースのテーブル構成を表す図です。
Rails の様なO/R マッパーを使うフレームワークで開発しているシステムではクラス図 ≒ ER 図なのであんまり使わなくなっているかもしれません。

f:id:HeRo:20220213104955p:plain
ER図の例

上の ER 図は次のPlantUMLの記述で生成しました。

@startuml
entity regions {
  code
  ---
  name
  description
}
entity prefectures {
  code
  ---
  name
  description
}
entity cities {
  code
  ---
  name
  description
}

regions ||--|{ prefectures
prefectures ||--|{ cities
@enduml

ガントチャート

ガントチャートも書けます。

f:id:HeRo:20220213105022p:plain
ガントチャートの例

上のガントチャートは次のPlantUMLの記述で生成しました。

@startgantt
language ja
saturday are closed
sunday are closed
2022-02-11 is closed

Project starts 2022-02-01
-- プロトタイピング --
[プロトタイプを作成] lasts 2 days and starts 2022-02-01
[プロトタイプを評価] lasts 2 days and starts at [プロトタイプを作成]'s end

-- 本開発 --
[設計] lasts 2 days and starts 2022-02-07
[実装] lasts 5 days and starts at [設計]'s end
[テスト] lasts 5 days and starts 2022-02-15
[リリース] happens at [テスト]'s end
@endgantt

最近ではどちらかというと嫌われているようですが、実際にはウォーターフォールプロセスが嫌われていて、それに付き物のガントチャートも嫌われているのかなと思います。 比較的短期だけど関係者が少なくないプロジェクトでは進行状況を把握すのに便利だと思うんですけどね。

WBS図(作業分解図)

比較的大きくて工程が多岐に渡るプロジェクトではタスク分解が重要だったりします。 WBS(Work Breakdown Structure) はプロジェクトを理解し管理する上で、プロジェクトの各工程を各担当者の作業レベルまで展開し木構造に整理した図です。

箇条書き+α な記述を図化してくれるので使いようによっては便利だと思います。
組織図を描くのにも使えますね。

f:id:HeRo:20220213105051p:plain
WBSの例

上のWBS図は次のPlantUMLの記述で生成しました。

@startwbs
+ 新規サイト構築
++ サイト設計
+++ サービス名検討
++++ アイコンデザイン
+++ 運用フロー検討
++++ コンテンツ更新
+++ サイトマップ作成
++++ サービスページ
++++ 管理画面
++ ソフトウェア開発
+++ 設計
++++ アーキテクチャ設計
++++ API設計
++++ クラス設計
+++ 実装
+++ テスト
++ インフラ構築
+++ 設計
+++ サーバ構築
++++ 開発サーバ
++++ 本番環境
+++ CI/CDパイプライン構築
++ テスト
+++ 機能テスト
+++ 負荷テスト
+++ 障害テスト
@endwbs

Network diagram (nwdiag)

ネットワーク構築を含むシステム構築だとネットワーク図も書くと思います。 ケーブリングを含むと工事も発生しますし、関係者の認識合わせが重要です。 ということで次の様にネットワーク図を描くことができます。

f:id:HeRo:20220213105114p:plain
ネットワーク図の例

上のネットワーク図は次のPlantUMLの記述で生成しました。

@startuml
nwdiag {
  network dmz {
    address = "210.x.x.x/24"

    web01 [address = "210.x.x.1"];
    web02 [address = "210.x.x.2"];
  }
}
@enduml

大きい会社で社内ネットワークを管理されている方にも有用かと思います。

マインドマップ

マインドマップも書けます。
例えば次の様なテキストが下のような図になります。 箇条書きで整理したアイデアなどをさっと図化できそうで意外と便利かもと思いました。

f:id:HeRo:20220213105147p:plain
マインドマップの例

上のマインドマップは次のPlantUMLの記述で生成しました。

@startmindmap
+[#White] いこーよ
++[#Orange] お出かけ施設
+++ 動物園
+++ 水族館
+++ 遊園地
++++ テーマパーク
++++ 屋内遊園地
+++ etc
++[#Orange] イベント
+++ オンライン
+++ オフライン
++++ 動物ふれあい
++++ コンサート
++++ アウトドア
++++ etc
--[#Orange] 記事
--- 子育て
--- 健康病気
--- 教育しつけ
@endmindmap

標準ライブラリ

現在のシステムは AWS のクラウドサービスを始め様々なサービスを利用して構築されます。その様なシステムを図示する場合、クラウドサービスのアイコンなどを入れたくなりますよね。 PlantUML ではそれらが標準ライブラリとして用意されています。

主なところでは次の様な標準ライブラリが公開されています。

  • awslib: AWS の各種サービスアイコン
  • kubernetes: k8s の各種リソースアイコン
  • logos: Gil Barbara's logosで公開されている各種サービスのロゴ(ネットサービスやクレジットカードなど)

これらを使ったシーケンス図の例が次の図です。

f:id:HeRo:20220213105213p:plain
標準ライブラリを使った例

上のシーケンス図は次のPlantUMLの記述で生成しました。

@startuml
!include <logos/github-icon>
!include <logos/slack>

!include <awslib/AWSCommon>
!include <awslib/Mobile/APIGateway>
!include <awslib/Compute/Lambda>
!include <awslib/DeveloperTools/CodeBuild>
!include <awslib/Containers/ElasticKubernetesService>

actor Developper as dev
participant "<$github-icon>" as github <<webhook>> #ffffff
APIGatewayParticipant(endpoint, WebhookEndPoint,)
LambdaParticipant(test_trigger,TestTrigger,)
CodeBuildParticipant(codebuild,TestRunner, Rspecを実行)
LambdaParticipant(test_reporter,TestReporter,)
participant "<$slack>" as slack #ffffff

dev -> github: Pull RequestにPush
github -> endpoint: webhook
endpoint -> test_trigger: invoke
test_trigger -> codebuild: startBuild
codebuild -> test_reporter: EventBridge経由でトリガー
test_reporter -> slack: 結果を通知
@enduml

https://plantuml.com/ja/stdlibには他の標準ライブラリも紹介されています。

まとめ

このエントリではシンプルな例を示しましたが、色をつけたり、ノートを付けたり、リンクを張ったりと PlantUML はまあまあ高い表現力も持っています。
使い方は公式サイトに詳しく説明されています。
また、Real World PlantUMLには色々な例を見ることができます。

PlauntUML のメリット・デメリットをまとめると次の様になるかと思います(UML のメリット・デメリットではありません)。

  • メリット
    • テキストだけで UML がかける
    • 図の要素をは自動レイアウトしてくれる
  • デメリット
    • オブジェクトが多すぎると思うようにレイアウトできず見ずらい

メリットで大きいのはなんと言ってもテキストで書けることです。テキストということは Git でバージョン管理も可能ということです。
一方、デメリットがクリティカルといえばクリティカルですが、要素が少ないうちは PlantUML の機能( down、up、right、left による指定など)でまあまあ見やすく配置できます。
要素が多くなってくるとそれも辛いですが、そもそもきれいにレイアウトしたところで要素が多いと見づらくなるかと思うのでシステム内での問題領域毎に分割して見やすい大きさにすればいいのではと思います。
見やすくレイアウトすることが重要な場合には diagrams.netなどの利用を検討してもいいかもしれません5

文章で説明するよりも図を見せたら一発で理解できる、認識が合うことは多いです。 チーム内での認識の共有を助ける図を描くのに PlantUML は便利なツールの 1 つだと思います。

最後に

アクトインディではエンジニアを募集しています。

actindi.net

参考


  1. 会話の中で「とういつもでりんぐげんご」と言っているのは聞いたことは無いですが。

  2. Booch 法の Grady Booch、OMT 法の James Rumbaugh、OOSE 法の Ivar Jacobson。

  3. call it from your script using command line

  4. PlantUML のレンダリングには Java と GraphViz が必要です。

  5. brew cask drawio でローカルアプリもインストールできます。