フューチャー技術ブログ

チームで機能設計するためのPlantUML標準化

はじめに

現在所属しているプロジェクトではWebAPIやバッチ処理の設計の一環としてPlantUMLを利用しています。効率よく品質高くアウトプットを出すためには、プログラミング言語に対してコーディング規約があるように、UMLに対してもチームで設計するにあたり一定のルールを決める必要があります。
そこでプロジェクト内のPlantUMLを使用するうえでのガイドラインやルールをまとめる機会があり、せっかくなのでそれを記事化します。

記事のゴール

  • シーケンス図設計におけるPlantUMLの標準化
  • 必要最低限のルールだけに絞ってチーム設計の生産性と品質を上げる

記事の前提

  • ルールの想定の利用シーン:
    チームで大量生産する業務機能の処理フローを表現するために使う場合を想定。
    また、この記事に記載されているルールはRDBを中心的に使用したAPI処理やバッチ処理等を念頭に置き決められたものです。
  • ルールの想定の効果:
    PlantUMLを標準化/シンプル化することで設計者も、レビュアも少ないインプットで品質高く設計/レビュできようになる想定。
  • ルールがカバーしている図の種類:
    PlantUMLで様々な種類の図が作成できますがこの記事のスコープはシーケンス図に限った話になります。
  • ルールに沿って作成されるシーケンス図に期待される最低限の役割:
    • 一目で機能全体の流れと大まかなロジックがわかる。
    • デバッグ、障害対応やパフォーマンスチューニングの第一ステップとして即座に調査ターゲットを絞り、問題の詳細設計やソースコードに導くヒントを与えてくれる。

書いてない内容

書いてる内容

  • このルールに沿ってPlantUMLでシーケンス図を楽しく書いていきましょう!

puファイルの基本

PlantUMLのファイル(pu)の中身は大体こんな感じです。
大きく、色等といった見た目を決める部分(L39より上)と、実際のシーケンスのフローを示す部分(L39より下)に分けられます。

なお、見た目を決める部分は別のコードは一つのconfigファイルに統一させることもできますが、ここはチームの管理の仕方に合わせてやりましょう。

上記のコードをレンダリングすると下記のような綺麗な図になります。

基本的な処理の書き方

矢印

処理が発生する箇所は矢印で表します。

  • シングルヘッド - 処理がアクターを跨いで一方的になっているもの
    (例:リクエスト送信、Queueに詰める処理等)
single_head_example.pu
Client -> Backend: Request
  • ダブルヘッド - 処理がアクターを跨いで双方的になっているもの

    (例:マスターチェック、DBアクセス処理等)
double_head_example.pu
Backend <-> RDB: Master Check\n[Store Control Master]
  • リターニング - 処理がアクターを跨がないもの

    (例:DBにアクセスせずJava内で完結するチェック処理等)
returning_example.pu
Backend -> Backend: Add select result into Error List

イベント

  • note - 大きなイベントごとにnote毎で分けて見やすくします
    (例:Parameter Check > Update t_status_history

    Process End)

note_example.pu
note over Backend: 1. Parameter Check

分岐

シーケンス図内で分岐や条件付き処理を表したい場合は分岐の処理毎にAltで囲みます。

  • alt - いわゆるifのような条件付き処理
Backend->Backend: Check A and B
alt If A
Backend -> Backend: Add x to Error List
end
alt If B
Backend <-> RDB: Insert x to A table
end
  • alt - else ① - いわゆるif-elseのような分岐処理
alt_else_example.pu
Backend->Backend: Check A and B
alt If A
Backend -> Backend: Add x to Error List
else
Backend <-> RDB: Insert x to A table
end
  • alt - else ② - いわゆるif-else if-elseのような分岐処理
alt_else_ifexample.pu
Backend -> Backend: Check something
alt If A
Backend -> Backend: Add x to Error List
else If B
Backend <-> RDB: Insert x to A table
else
Backend -> Client: Response status code 422
end

ループ

loopが発生した場合はloopで囲みます。
loopの右にはループを回す単位をFor Eachで記載する

  • loop
loop_example.pu
loop for each EPC
Backend <-> RDB: Insert\n[t_sales]
end

その他

  • 採番のルール
    殆どの場合、シーケンス図はスタンドアロンではなく、一つ一つの処理の詳細(データアクセス定義、チェック定義、DB変更定義等)を図以外の場所に記載しますよね。そういった設計書内の詳細の記載とマッピングするために一個一個のフローステップにプロセスIDを付けます。プロセスIDの採番は下記のルールで実施します:
    • 処理が複数あった場合、階層が同じ処理は処理が発生する順に番号を振っていく
    • 直前の処理からaltで階層が深くなるたびにIDの桁に1を足し、1から始める
    • 直前の処理からaltで階層が深くなると同時に、その階層に複数処理があった場合、IDの桁に2桁足す(深くなった理由での一桁と複数処理を分けるためのもう一桁)
id_example.pu
note over Backend: 2. Update Family Tree
loop for each New Member
alt If Update Pattern = Any member
Backend -> Backend: 2.1. Check DNA
alt If DNA test returns success
Backend <-> RDB: 2.1.1.1. Update\n[t_parent]
Backend <-> RDB: 2.1.1.2. Update\n[t_child]
Backend <-> RDB: 2.1.1.3. Update\n[t_grand_child]
end
alt If DNA test returns failure
Backend -> Backend: 2.1.2. Add Member into Error List
end
end
end
  • 改行
    文字の記載等で改行したい場合は\nを使いましょう。
return_example.pu
loop for each EPC
Backend <-> RDB: Insert\n[t_sales]
end
  • テーブル名
    DBアクセスが発生した場合はできる限り対象テーブルやデータを記載しましょう。

    テーブル名は[ ]に入れましょう。
table_example.pu
loop for each EPC
Backend <-> RDB: Insert\n[t_sales]
end
  • エラー
    エラーやエクセプションはAltで表現しましょう。
error_example.pu
alt Error
Backend -> Client: 1.4. Response status code 402
end
  • ロック
    ロックする場合は下記のようにSelect Lock for [ロック解除の処理] [ロックするテーブル]と記載する。
    ただロックに関してはプロジェクトのロック方式などにもよるのでここはフレキシブルに。
lock_example.pu
Backend <-> RDB: 2.2.1. Select\nLock for Update at 2.2.4\n[t_sales_header]
  • インデント
    インデントは基本しなくてもコードはレンダリングされるが、他の言語同様読みやすいように入れましょう。


  • 余談ですがPlantUMLのデフォルトカラーって良いと思う人、世の中あまりいないですよね。
    これはもう、目に良いビジュアルに自分で変えていくしかないです。
    色を変えるだけでだいぶ印象も変わってきます。ちなみに私のお気に入りは:

    • パレット①:
      「puファイルの基本」で使ったサンプル図で使っているものです。グレーをベースにカラフルなアクセント、トイライクで見やすい(個人的な意見)パレットを作りました。
      • #FFFFFF(font1)
      • #DDDDDD(background)
      • #454645(font2、line)
      • #FF6F61(participant)
      • #98DDDE(database)
      • #FFDA29(entity)
      • #98FB98(note)
    • パレット②:
      「基本的な処理の書き方」で使ったサンプル図で使っているものです。使用する色が少ないなためシンプルでクリーンな資料と相性が良いです。バックグラウンドも白く、シーケンス図をWeb等に埋め込んで使う場合に適しており、ページと一体化して見えるので統一感があっておすすめです。
      • #FFFFFF(font1, background)
      • #696969(line)
      • #454645(font2)
      • #FF6347(participant)
      • #00FFFF(database)
      • #7FFFD4(note)
    • デフォルト:
      もちろん、カラーにこだわりのない方はデフォルトでトラディショナルな白黒黄のコーディネートにすることができます。

(左から右:デフォルト、パレット②、パレット①)

コピペ用のテキストはこちらです。

🎨パレット1

パレット1のplantumlスニペット
@startuml Sample Diagram

skinparam BackgroundColor DDDDDD
skinparam shadowing false
skinparam RoundCorner 7
skinparam ArrowColor 454645
skinparam FontColor 454645
skinparam SequenceLifeLineBorderColor 454645
skinparam SequenceGroupHeaderFontColor 454645
skinparam SequenceGroupFontColor 454645
skinparam SequenceGroupBorderColor 454645
skinparam SequenceGroupBorderThickness 1
skinparam participant {
BackgroundColor FF6F61
BorderColor FF6F61
FontColor White
}
skinparam database {
BackgroundColor 98DDDE
BorderColor 454645
FontColor 454645
}
skinparam entity {
BackgroundColor FFDA29
BorderColor 454645
FontColor 454645
}
skinparam note {
BackgroundColor LightGreen
BorderColor LightGreen
FontColor 454645
}

entity Client
participant Backend
participant Queue
database RDB
entity "External"

@enduml

🎨パレット2

パレット2のplantumlスニペット
@startuml Sample Diagram

skinparam BackgroundColor FFFFFF
skinparam shadowing false
skinparam RoundCorner 7
skinparam ArrowColor 454645
skinparam FontColor 454645
skinparam SequenceLifeLineBorderColor 696969
skinparam SequenceGroupHeaderFontColor 454645
skinparam SequenceGroupFontColor 696969
skinparam SequenceGroupBorderColor 696969
skinparam SequenceGroupBorderThickness 1
skinparam participant {
BackgroundColor FF6347
BorderColor FF6F61
FontColor FFFFFF
}

skinparam database {
BackgroundColor 00FFFF
BorderColor 696969
FontColor FFFFFF
}

skinparam note {
BackgroundColor 7FFFD4
BorderColor 7FFFD4
FontColor 454645
}

participant Client
participant Backend
participant Queue
database RDB
participant External

@enduml

あえてルール化しなかったもの

はじめにも記載されている通り、記事のゴールとして「必要最低限のルールだけに絞ってチーム設計の生産性と品質を上げる」があります。上記で記載されたルールはシーケンス図が期待される必要最低限の役割を果たすために含めてたものです。したがって分岐やループ等、処理の柱となるロジックやパフォーマンスを表すものは記載必須としています。一方で、シンプル化のため、下記のものはあえてルールとしていません。

  • ライフライン
    ライフラインの活性化と破壊はシンプル化のため、あえて使いません。
    こちらはactivatedeactivatedestroyで表現できるので、必要に応じて。

  • 線とアローヘッドの使い分け
    PlantUMLでは様々なアローヘッドや線の種類を指定することができます。「レスポンスは点線にする」等、世間ではアローヘッドと線の種類に関するいろんな使い分けが存在していますが、このルールではシンプル化のため、意識しません。こちらも必要に応じてやりましょう。

おわりに

勝手にルールを決めちゃいましたがルールの中身よりもルールを決めることが大事だと思います。
これからPlantUMLを利用してチームで設計を始めたいけどルールを決めるのが面倒くさい方々、この記事をスタートラインにしてみてはいかが。

参考&リンク