EurekaMoments

This is my studying logs about Autonomous driving, Machine learning technologies and etc.

PlantUMLを通じてシーケンス図の描き方を学ぶ

はじめに

ソフトウェアの仕様書、設計書の作成や管理を効率化するために、Markdown + PlantUMLによる作成方法を日々模索しています。 しかしながら、そもそもUML図の正式な書き方というものをちゃんと分かっていないというのが正直なところなので、PlantUMLを通じてUMLの各種図の書き方を勉強していきます。

  • 本稿のテーマは、「UMLによるシーケンス図の書き方」です。
  • 本稿におけるUML図の作成は、Markdown + PlantUMLがベースであることを前提とします。

シーケンス図とは

  • シーケンス図とは、クラスやオブジェクト間のやり取りを時間軸に沿って表現するものである。
  • 詳細設計の成果物の中で最も重要な図。描く際はいきなりゼロから描くのではなく、ロバストネス図を参考にしながら描く。

設計プロセスにおけるシーケンス図の立ち位置

  • 設計プロセスは、予備設計(あるいは事前設計)と詳細設計の2段階に分けて行われる。
  • 下記の図のように、要求定義→予備設計→詳細設計→実装・テストまでを必要最低限のステップで実践的に行うプロセスをICONIXプロセスという。
  • 8割程度完成させたら次のフェーズに進み、前のフェーズの成果物を更に進化させるという段階的な設計。

f:id:sy4310:20190118232506p:plain

f:id:sy4310:20190118232734p:plain

  • 予備設計では、実際のクラスを気にせずに「システム全体としてどう振る舞うべきか」を先に決める。
  • 次の詳細設計で、適用したアーキテクチャの都合を考慮しながらクラスに責務を割り当てていく。
  • 事前にロバストネス図さえ描いていれば、要件定義にきちんと結びついたシーケンス図が描ける。

シーケンス図の描き方についてのヒント

ヒント1

  • ロバストネス図上の「コントロール」はいずれかのクラスのメソッドとなる。
  • いずれも1対1である必要はない。1つのコントロールが複数のメソッドに対応していても構わない。
  • コントロールは1本の線になり、それがシーケンス図におけるやり取りとなる。

f:id:sy4310:20190118234652p:plain

ヒント2

  • ロバストネス図上の「エンティティ」は全て、シーケンス上に登場する。
  • シーケンス図を描く最大のメリットは、図上で「プリファクタリング」が行えることである。
  • プリファクタリングとは、実装前にシーケンス図を用いて設計を再考・改善する事です。

シーケンス図を構成する要素

メッセージ

PlantUMLでは下記のように記述する。

Alice -> Bob : メッセージ

f:id:sy4310:20190118235202p:plain

メッセージ種別と矢印の形状

f:id:sy4310:20190118235256p:plain

記述例

Alice -> Bob : 同期メッセージ
Alice <-- Bob : 戻りメッセージ

Alice ->> Chuck : 非同期メッセージ

f:id:sy4310:20190118235355p:plain

自己メッセージ

対象を同じにすると自己メッセージとなる。

Alice -> Alice : 自己メッセージ

f:id:sy4310:20190118235821p:plain

外部とのメッセージのやり取り

送り手や受け手がダイアグラム上にない場合は [ または ] を使用する。

[-> Alice : DoWork

Alice ->] : Request
Alice <--]

[<- Alice : Done

f:id:sy4310:20190118235933p:plain

ライフライン

  • ライフラインの要素はメッセージの出現順に左から表示される。
  • 要素名に記号などの英数字以外を使う場合には"で囲む。
  • asキーワードで別名を付けることもできる。
Alice -> "Bob : Human"
Alice -> 太郎
Alice -> "I have a really\nlong name" as Long
Alice <-- Long

f:id:sy4310:20190119000107p:plain

実行仕様(イベント)の表現

  • ライフラインでイベントが実行中であることを表現する。
  • ライフラインの線の上に白い箱で表現する。
activate Alice
Alice -> Bob : Message
Alice <-- Bob
deactivate Bob

f:id:sy4310:20190119003339p:plain

シーケンス図の例: ログイン

ユーザがシステムにログインするというシーケンス図

activate User
    User -> LogIn : ログインする
    activate LogIn
        LogIn -> UserInfo : ユーザが存在するか
        activate UserInfo
            UserInfo --> LogIn
        deactivate UserInfo
        UserInfo -> AuthorityInfo : 権限があるか?
        activate AuthorityInfo
            AuthorityInfo --> LogIn
        deactivate AuthorityInfo
        LogIn --> User
    deactivate LogIn

f:id:sy4310:20190119003632p:plain

複合フラグメント

f:id:sy4310:20190119004034p:plain

alt 分岐処理の表現例

ログイン処理の成功と失敗

activate User
    User -> LogIn : ログインする
    activate LogIn
        LogIn -> UserInfo : ユーザが存在するか
        activate UserInfo
            UserInfo --> LogIn
        deactivate UserInfo
        UserInfo -> AuthorityInfo : 権限があるか?
        activate AuthorityInfo
            AuthorityInfo --> LogIn
        deactivate AuthorityInfo
        alt 認証[成功]
            LogIn --> User : dashboardにリダイレクト
            deactivate LogIn
        else 認証[失敗]
            LogIn --> User: 認証失敗のメッセージを表示
        end

f:id:sy4310:20190119004331p:plain

ref 相互作用使用 別参照

  • シーケンス図を簡略化するため、他のシーケンス図を参照して欲しい時に使う。
  • 下記は、ログイン処理の権限確認を別参照とした例
activate User
    User -> LogIn : ログインする
    activate LogIn
        LogIn -> UserInfo : ログイン処理
        ref over UserInfo, AuthorityInfo : 権限をチェック
        UserInfo --> LogIn
        alt 認証[成功]
            LogIn --> User : dashboardにリダイレクト
            deactivate LogIn
        else 認証[失敗]
            LogIn --> User: 認証失敗のメッセージを表示
        end
    deactivate LogIn

f:id:sy4310:20190119004544p:plain

opt 条件による実行の表現

  • 特定の条件を満たした場合に実行されるシーケンスを表現する。
  • 下記は、ログイン処理の例に会員未登録の場合のシーケンスを追加した例

f:id:sy4310:20190119005446p:plain

delay 非同期の遅延処理

  • 非同期の処理において、遅延してから処理されるものを表現する。
  • 下記は、会員登録時のメール配信処理から送信までに1分の遅延が起きるとする例
activate User
    User -> Registration : 新規登録
    Registration ->] : メール配信処理
    User <-- Registration

    ...1分後...

    User <--] : メール送信
    User -> Registration : 有効化

f:id:sy4310:20190119005617p:plain

par 並列処理

actor Bob

Bob -> 目覚まし : 止める
Bob <-- 目覚まし

par
    Bob -> 歯ブラシ : 磨く
    Bob <-- 歯ブラシ
else
    Bob -> 新聞 : 読む
    Bob <-- 新聞
end

f:id:sy4310:20190119005757p:plain

loop 繰り返し処理

  • loopの後は任意の文字列が使える。
  • UMLでは、[開始, 終了]の形式で書く。
actor 客

loop 1, 商品数
    客 -> 店員 : 商品
    店員 -> レジ : バーコード入力
end

店員 <-- レジ : 合計金額
客 <-- 店員 : 合計金額
客 -> 店員 : お金
店員 -> レジ : お金

f:id:sy4310:20190119010049p:plain

break 中断処理

actor "客(未成年)" as guest

loop 1, 商品数
    guest -> 店員 : 商品
    break 商品 = 酒
        guest <- 店員 : 販売拒否
    end
    店員 -> レジ : バーコード入力
end
店員 <-- レジ : 合計金額
guest <-- 店員 : 合計金額
guest -> 店員: お金
店員 -> レジ : お金

f:id:sy4310:20190119010234p:plain

critical 排他制御処理

actor ユーザー as user
participant 画面 as view
participant データ as data

create view
user -> view : 表示
view -> data : データの読み取り
view <-- data : データ
user <-- view

user -> view : データの変更
user <-- view

user -> view : 保存
critical
    view -> data : データの書き込み
    view <-- data
end
user <-- view
destroy view

f:id:sy4310:20190119010345p:plain

グループ化

  • PlantUMLがサポートしていない複合フラグメントを使いたい場合
  • 単に処理をグループ化したい場合
actor Bob

Bob -> めざまし : 止める
Bob <-- めざまし

group 朝の準備
    par
        Bob -> 歯ブラシ : 磨く
        Bob <-- 歯ブラシ
    else
        Bob -> 新聞 : 読む
        Bob <-- 新聞
    end
    Bob -> 服 : 着替える
    Bob <-- 服
end

f:id:sy4310:20190119010724p:plain

作成と消滅

  • オブジェクトの作成と消滅を表現する。
  • create, destroyキーワードを使用する。
participant "Main Window" as main

create Loader
main -> Loader : <<作成>>
main <-- Loader
destroy Loader

f:id:sy4310:20190119010833p:plain

上下でメッセージ間でスペースを空ける

  • 上下のメッセージの間に|||を入れる。
  • ||スペースのピクセル値||でスペースの大きさを調整できる。
Alice -> Bob : message 1
Bob --> Alice : OK
|||
Alice -> Bob : message 2
Bob --> Alice : OK
||60||
Alice -> Bob : message 3
Bob --> Alice : OK

f:id:sy4310:20190119010940p:plain

分離線

== 初期化 ==
Alice -> Bob : 認証要求
Bob --> Alice : 認証応答
== 後処理 ==
Alice -> Bob : タスク関数
Alice <-- Bob

f:id:sy4310:20190119011050p:plain

ボックス

f:id:sy4310:20190119011611p:plain

ノート

メッセージのノート

  • メッセージのノートはメッセージの直下に記述する。
  • 位置はrightまたはleftで指定する。
  • 背景色を変えたい場合は、#色名、#RGB値で指定する。
Alice -> Bob : Hello
note left : 最初のメッセージに対するノート

Bob -> Alice : OK
note right #aqua : 次のメッセージに対するノート

Bob -> Bob : I am thinking
note left #FFAAAA : 複数行の\nノート

f:id:sy4310:20190119011359p:plain

GitHub

今回の記事で記載している各種PlantUML図のコードは下記のGitHubリポジトリで公開しています。

github.com

参考資料