0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

PythonユーザーのためのPlantUML入門:シーケンス図と状態遷移図

Last updated at Posted at 2025-06-16

はじめに

PlantUML は、シンプルなテキスト記述から各種UMLダイアグラムを生成できるオープンソースツールです。テキストベースで記述できるため設計内容をコード同様にバージョン管理しやすく、Gitでの管理とも相性が良い点が魅力です。特にPythonエンジニアにとっては、PlantUMLをPythonスクリプトから呼び出して図を自動生成することも可能で、シーケンス図やクラス図などを手軽に作成できます。本記事では、シーケンス図状態遷移図(ステートマシン図)に焦点を当て、Pythonの考え方に対応づけながらPlantUMLの基本的な使い方を解説します。物理実験装置や衛星開発、観測機器のオペレーションといった場面で現れるシーケンスや状態遷移に使えるよう分かりやすく説明してみます

初めての方向け : まずはオンラインでやってみよう

初めての方は、下記のコードをコピーして、

@startuml

start
:User Submits Order;
if (Check Warehouse Stock?) then (In Stock)
    if (Process Payment) then (Payment Success)
        if (Dispatch Order) then (Dispatch Success)
            :Show Success;
        else (Dispatch Failed)
            :Show Error;
        endif
    else (Payment Failed)
        :Show Error;
    endif
else (No Stock)
    :Show Error;
endif

stop

@enduml

を、

にある、plantuml のオンラインのインターフェースにコピペしてみてください。

次のような図を生成されるはずです。(qiita は plantuml というコード指定で可視化します。)

PlantUML以外の選択肢

PlantUML以外にも似たようなツールがあるので、長所と短所を整理しておきます。

ツール名 URL 長所 短所
PlantUML https://plantuml.com/ 多彩な図に対応、カスタマイズ性高い Java依存、構文がやや複雑
Mermaid https://mermaid-js.github.io Markdown埋め込み可、軽量、ブラウザ対応 表現力に制限あり、詳細制御が難しい
draw.io https://www.diagrams.net/ GUIで直感的、チーム共有に便利 ソースコード管理に不向き
Graphviz https://graphviz.org/ グラフ構造やDAG(有向非巡回グラフ)可視化に強い シーケンスや状態遷移図には不向き
D2 https://d2lang.com/ 軽量、次世代的、Mermaidより表現力が高め 開発中でツールや環境が限定的

ここでは、汎用性の高いPlantUMLについて紹介します。

シーケンス図とは?

シーケンス図は、システム内のオブジェクトやコンポーネントなどの参加者(パーティシパント、エンティティ)が時間軸に沿ってどのように相互作用するか、一連の処理の流れをメッセージのやり取りとして表現する図です。オブジェクト間のメソッド呼び出しやデータの受け渡しなど、「誰が」「誰に」「何を」 実行するかを時系列で示すことで、処理手順やオブジェクト間の責務分担を視覚化できます。

開発時には「どのクラスがどの処理を担うか」「複数のモジュールがどの順番でやりとりするか」を整理するのに有用で、既存実装のトレースやユースケースの確認にも利用されます。Pythonの関数呼び出しやオブジェクトメソッドの呼び出しに馴染みのある読者であれば、シーケンス図はプログラム内の関数コールフローを図式化したものと捉えると理解しやすいでしょう。

PlantUMLでシーケンス図を描く

PlantUMLでは、シーケンス図をテキストで記述する際に以下のような基本構文を用います。

  • 参加者(Participants)の定義:
    シーケンス図に登場する主体をparticipantキーワードで定義します。人(アクター)を表す場合はactorキーワードを使うとシルエットが人型になり、それ以外のシステムや外部サービスはparticipant(デフォルトのボックス表示)で定義します。オブジェクト名に別名をつけたい場合はasを使ってエイリアスを指定できます。例えば、actor ユーザ as User のように書くと「ユーザ」という表示名のアクターを定義し、内部ではUserという別名で参照できます。

  • メッセージ(矢印)の記述:
    矢印演算子->メッセージ送信(メソッド呼び出しやデータ送信など)を表現します。左辺に送信元、右辺に宛先を書き、コロン:に続けてメッセージ名や説明を記述します。例えば、A -> B : 実行要求 と書けば「AがBに対して『実行要求』というメッセージを送る」ことを表します。戻りメッセージや応答は実線の矢印の代わりに点線の矢印(-->)で描くこともできます(この場合、PlantUMLでは同期/非同期の表現として用いられますが、基本的な図では深く気にしなくても構いません)。メッセージ行はコメント('から行末)を付けて補足説明することも可能です。

  • アクティブ期間(ライフライン)の明示:
    activate オブジェクト名deactivate オブジェクト名 を使うと、あるオブジェクトが処理を実行している期間(ライフライン上の細長い長方形)を強調表示できます。例えば、activate Serverdeactivate Serverでサーバーオブジェクトの処理区間を図中にハイライトできます。これは「あるオブジェクトが処理中であること/応答待ちであること」を明示し、処理の開始・終了タイミングを表現するのに役立ちます。ただし、簡単な図では必須ではありませんので、必要に応じて使用すると良いでしょう。

以上の基本構文を踏まえて、実際にPlantUMLでシーケンス図を描いてみます。以下は「ユーザがPCに対して入力を行い、その結果がディスプレイに表示される」というシンプルな対話のシーケンス図の例です。

@startuml
actor ユーザ
participant PC
participant ディスプレイ

ユーザ -> PC : キー入力
PC -> ディスプレイ : 文字を表示
ディスプレイ -> ユーザ : 表示結果
@enduml

上のPlantUMLコードを、下記に貼り付けると、このようなシーケンス図が得られます(qiitaでは```plantuml で記述すると画像で表示します)。

図では左に人型アイコンの「ユーザ」、中央に「PC」、右に「ディスプレイ」が配置され、それぞれ実線矢印でメッセージの流れが描画されています。例えば「ユーザ -> PC : キー入力」はユーザからPCへの入力操作を表現し、続く「PC -> ディスプレイ : 文字を表示」でPCがディスプレイに文字出力を行い、その結果を「ディスプレイ -> ユーザ : 表示結果」でユーザが目にする、といった一連の流れを示しています。

このように、シーケンス図を読むことで処理の流れ担当箇所が一目で把握できます。特に、Pythonコードで書かれた関数呼び出しの連鎖やオブジェクト間メッセージのやり取りを視覚化するのに便利です。

Python視点で見るシーケンス図

上記のシーケンス図の内容は、Pythonのオブジェクトや関数で擬似的に表現すると以下のようになります。

class Display:
    def output(self, text):
        print(f"[ディスプレイ] {text}")

class PC:
    def __init__(self, display):
        self.display = display
    def receive_input(self, text):
        print(f"[PC] ユーザ入力を受信: {text}")
        # 入力を処理しディスプレイに出力
        self.display.output(text)

class User:
    def __init__(self, pc):
        self.pc = pc
    def type_input(self, text):
        print(f"[ユーザ] PCに入力: {text}")
        self.pc.receive_input(text)

# オブジェクトの準備
display = Display()
pc = PC(display)
user = User(pc)

# シーケンス実行のシミュレーション
user.type_input("Hello")  
# 出力例:
# [ユーザ] PCに入力: Hello
# [PC] ユーザ入力を受信: Hello
# [ディスプレイ] Hello

上のコードでは、User.type_inputメソッドがPCに入力を送り(ユーザからPCへの矢印)、PC側でreceive_inputメソッドがその入力を受け取りディスプレイのoutputメソッドを呼び出しています(PCからディスプレイへの矢印)。ディスプレイのoutputでは単純にテキストを表示するだけですが、これがシーケンス図中のディスプレイからユーザへの点線矢印(「表示結果」)に対応すると考えてください。実際のコードではディスプレイからユーザへ直接通知することはないものの、ユーザがディスプレイを見て結果を知るという受動的な関係を図ではメッセージとして表現しています。

このように、シーケンス図の各矢印はメソッド呼び出し関数の実行に相当し、コード上の処理フローと対応しています。Pythonでクラス間のメソッド呼び出しを追っていくイメージでシーケンス図を描くと、プログラムの動的な振る舞いを整理しやすくなるでしょう。

状態遷移図とは?

次に状態遷移図(ステートマシン図)を見ていきます。状態遷移図は、システムやオブジェクトが取り得るさまざまな状態と、それらの間で起こり得る遷移(状態の変化)を視覚的に表現した図です。形式的には「有限状態マシン(Finite State Machine, FSM)」の考え方に基づいており、「ある状態で特定のイベントが起こったら、別の状態(または同じ状態)に遷移する」という振る舞いを記述します。各遷移にはしばしばトリガーとなるイベントや条件が付加され、システムが時間経過とイベント発生によってどのように状態を推移していくかを表します。

例えば、物理実験装置を考えてみましょう。装置には「待機中」「計測中」「エラー発生中」「停止」などの状態があり、ユーザが「計測開始ボタン」を押す、計測が完了する、異常が検出される、といったイベントによって状態が変化します。状態遷移図ではこれらを丸や角丸四角の「状態」ノードと**矢印の「遷移」**で表し、矢印には遷移を引き起こすイベント名をラベルとして記載します。こうした図を描くことで、システムのライフサイクル全体や異常系も含めた振る舞いを俯瞰できます。

PlantUMLで状態遷移図を描く

PlantUMLで状態遷移図(ステート図)を記述する基本構文は以下の通りです。

  • 状態の定義:
    状態はstateコマンドで定義します。例えば、単純に state Idle と書けば「Idle」という名前の状態が定義されます。状態名に空白や記号が含まれる場合や、図中に表示する名前と内部識別子を分けたい場合は、state "表示名" as 別名 の形式で 表示名別名(エイリアス) を設定できます。別名をつけておけば、遷移の記述を簡潔にしたり、名前変更にも柔軟に対応できます。長い名前と別名が同じで良い場合はas以降を省略可能です(つまり前述の簡易な state Idle でOK)。

  • 遷移(矢印)の記述:
    状態間の遷移は、状態A --> 状態B のように矢印-->で二つの状態名(もしくは別名)を結んで表現します。矢印の上には必要に応じてイベント名や条件を : の後ろに記述できます。例えば Locked --> Unlocked : コイン投入 と書けば、「Locked状態でコイン投入イベントが発生するとUnlocked状態に遷移する」ことを意味します。イベント名を省略すれば単なる状態遷移(常時または内部処理による遷移)を表せます。なお、同じ状態への自己遷移も State --> State : Event と記述できます。

  • 開始状態・終了状態:
    UML状態図には、特別な 開始状態(開始ノード)と 終了状態(終了ノード)が存在します。PlantUMLではどちらも [*] という記号で表現します。開始状態は図のエントリポイントで、通常はそこから最初の状態への矢印を描きます。同様に、終了状態は最終的な停止/完了を示すもので、ある状態から終了状態 [*] へ矢印を描くことで「システムが停止する」などの終端を表現できます(複数描いても構いません)。開始状態から最初の状態への遷移、および各状態から終了状態への遷移を適切に記述することで、状態図が完結します。

以上の構文を踏まえ、具体例としてストップウォッチの状態遷移図をPlantUMLで描いてみましょう。ストップウォッチは「計測中」「一時停止(ポーズ)」「リセット/終了」といった状態を持ち、ユーザが押すボタンによって状態が変わる典型的な状態機械です。

@startuml ストップウォッチ状態遷移
[*] --> 計測中 : Sボタン   ' 開始状態から計測中へ(スタートボタン)
計測中 --> 一時停止 : Sボタン   ' 計測中に再度スタートボタン(ポーズ)
一時停止 --> 計測中 : Sボタン   ' ポーズ中にスタートボタン(再開)
一時停止 --> [*] : Rボタン    ' ポーズ中にリセットボタン(終了)
@enduml

上図はストップウォッチの状態遷移を表したものです。最初、開始ノード[*]から「計測中」状態に遷移しています。これはストップウォッチが初期状態(待機状態)から、ユーザの**Sボタン(スタートボタン)**操作によって計測を開始することを意味します。その後、計測中に再度Sボタンを押すと「一時停止」状態へ遷移し、さらにもう一度Sボタンを押すと「計測中」状態に戻っています。これは計測の一時停止と再開を表現しています。そして「一時停止」状態で Rボタン(リセットボタン) を押すと終了状態[*](停止)へ遷移し、計測が完全に終了する流れになっています。

この状態遷移図により、ストップウォッチの挙動を網羅的に理解できます。どのボタン操作でどの状態に移るのか、一目瞭然です。また、例えば「計測中」にRボタンを押すケース(この図では描かれていない)など、図にない遷移が発生した場合は何も起こらない(入力無視)か、あるいは操作自体を無効化する、といった扱いになることも読み取れます(状態遷移図では表現しない部分ですが、コード設計時に検討が必要なポイントです)。

Python視点で見る状態管理

続いて、このストップウォッチ状態遷移のロジックをPythonコード風に表現してみます。状態は文字列やEnumなどで管理し、ボタン押下イベントごとに状態を更新する実装です。

class Stopwatch:
    def __init__(self):
        # 初期状態を「停止中(Reset)」とする
        self.state = "Reset"

    def press_s(self):
        # Sボタン押下時の状態遷移
        if self.state == "Reset":
            self.state = "Measuring"      # 停止→計測開始
        elif self.state == "Measuring":
            self.state = "Paused"         # 計測中→一時停止
        elif self.state == "Paused":
            self.state = "Measuring"      # 一時停止→再開(計測中)
        print(f"[Sボタン] 現在の状態: {self.state}")

    def press_r(self):
        # Rボタン押下時の状態遷移
        if self.state == "Paused":
            self.state = "Reset"          # 一時停止→リセット(停止)
        print(f"[Rボタン] 現在の状態: {self.state}")

# ストップウォッチ状態遷移のテスト
sw = Stopwatch()
sw.press_s()  # 初期停止状態 -> 計測中
sw.press_s()  # 計測中 -> 一時停止
sw.press_s()  # 一時停止 -> 計測中(再開)
sw.press_r()  # 計測中状態ではRボタン効かず(状態変化なし)
sw.press_s()  # 計測中 -> 一時停止
sw.press_r()  # 一時停止 -> 停止リセット

上記コードでは、Stopwatchクラスが内部にself.stateを持ち、press_s()メソッドとpress_r()メソッドがそれぞれSボタン・Rボタン押下時の状態遷移を実装しています。初期状態は「Reset」(停止中)で、press_s()が呼ばれるとReset -> Measuringに状態が変わります(計測開始)。続けてもう一度press_s()を呼ぶとMeasuring -> Paused(一時停止)になり、さらにpress_s()Paused -> Measuring(再開)となります。press_r()は一時停止中(Paused)のときのみReset状態に遷移させ、それ以外(計測中など)では状態を変えないようにしています。この挙動は前述の状態遷移図と一致しています。

実行結果のログ(コメントで示した状態変化)からも、PlantUMLで描いた図の通りに状態が遷移していることが確認できます。なお、実際の実装では計測中にRボタンが押された場合の扱い(このコードでは無視しています)や、エラー状態の追加など、状態遷移図に描かれていないケースも検討する必要があります。しかし、状態遷移図があることで 「実装すべき基本遷移」と「無視すべきイベント」 が明確になり、抜け漏れの少ない堅牢な設計につながります。

※補足:Pythonにはこのような状態遷移を扱うための便利なライブラリ(例えばtransitions)も存在します。これを使うと、状態と遷移を定義するだけで上記と同等のステートマシン動作を実現でき、さらにPlantUML形式の状態図を自動生成する機能も提供されています。興味がある方は下記の記事などを参照してください。

PlantUML文法の具体例と図別の書き方のまとめ

アクティビティ図(処理フローを描く)

主な文法ルール

記法 意味 表示される図形
start / stop 開始/終了 ● → ●
:処理; アクション 長方形
if (...) then (...) / else (...) / endif 条件分岐 ひし形
repeat / repeat while (...) 繰り返し ループ構造

🔸 具体例:ログイン処理のフロー

login.pu
@startuml
start

:ログイン画面を表示;
:ユーザーがIDとパスワードを入力;

if (認証成功?) then (yes)
  :ホーム画面を表示;
else (no)
  :エラーメッセージを表示;
endif

stop
@enduml

シーケンス図(時系列のやり取り)

主な文法ルール

記法 意味
participant, actor 登場人物またはシステム
A -> B: メッセージ 通常の呼び出し
A --> B: 応答 戻り(非同期)
activate, deactivate ライフラインの強調

具体例:WebアプリのAPI呼び出し

webapp.pu
@startuml
actor User
participant "Web App" as Web
participant "DB Server" as DB

User -> Web: GET /user/123
activate Web
Web -> DB: SELECT * FROM users
activate DB
DB --> Web: ユーザーデータ
deactivate DB
Web --> User: JSONレスポンス
deactivate Web
@enduml

クラス図(オブジェクトの構造)

主な文法ルール

記法 意味
class クラス名 クラス定義
+, -, # アクセス修飾子(public/private/protected)
extends / `< --` 継承関係

具体例:動物と犬の継承

dog.pu
@startuml
class Animal {
  +name: String
  +speak(): void
}

class Dog extends Animal {
  +breed: String
  +speak(): void
}

Animal <|-- Dog
@enduml

ユースケース図(ユーザーと機能の関係)

主な文法ルール

記法 意味
actor ユーザーや外部システム
usecase 機能
actor --> usecase 利用関係

具体例:ショッピングサイト

shop.pu
@startuml
actor 顧客
actor 管理者

usecase "商品を検索" as UC1
usecase "商品を購入" as UC2
usecase "商品を登録" as UC3

顧客 --> UC1
顧客 --> UC2
管理者 --> UC3
@enduml

状態遷移図(状態の変化)

state.pu
@startuml
[*] --> 待機中
待機中 --> 通知受信 : 新しいメール
通知受信 --> 閲覧中 : ユーザーがタップ
閲覧中 --> 待機中 : 閉じる
@enduml

🎨 カスタマイズ:色やレイアウトも指定可能

color.pu
@startuml
class Animal {
  +name: String
  +speak(): void
}

class Dog extends Animal {
  +breed: String
  +speak(): void
}

Animal <|-- Dog

skinparam backgroundColor #F5F5DC
skinparam classAttributeIconSize 0
skinparam ArrowColor Blue
skinparam DefaultFontName "Helvetica"
@enduml

よく使うオプションまとめ

設定 内容
skinparam 見た目全体のカスタマイズ
note right/left of 各要素にコメントをつける
grouprectangle 図中でグループ化・枠を付ける

補足:PlantUMLの思想

  • テキストで描く → Git管理しやすい
  • 自動生成もできる(CIやドキュメント自動化)
  • シンプルな構文で複雑な図も表現できる

機能のまとめ

  • PlantUMLの構文はシンプルで直感的
  • UMLの主要な図(アクティビティ・シーケンス・クラス・ユースケース)をすべてカバー
  • GUIではなく「テキストで図を書く」ことで再利用性・履歴管理がしやすい

おわりに

本記事では、Pythonに馴染みのあるエンジニア向けに PlantUMLによるシーケンス図と状態遷移図の描き方 を解説しました。シーケンス図ではオブジェクト間のメッセージの流れを時間順に追い、状態遷移図ではシステムの状態変化を網羅的に整理できます。どちらも設計内容の理解を深め、ドキュメントとして残すのに非常に有用な手法です。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?