動機
だいぶ昔の投稿で、「強くお勧め!PAD図ならブレない!!フローチャート、アクティビティ図だと制御構造表現がブレる」というのを書きました。
プログラムの論理構造を図示しようとしたら、「PAD図(Problem Analysis Diagram)」は非常に強力なツールで、処理の流れを木構造で表現するため、「スパゲッティコード」を物理的に防ぎ、構造化されたきれいなロジックになるので、大変おすすめです。
で、PAD図をMarkdownで書きたいなぁと思いまして、 「Mermaid」 の シーケンス図 を応用して、PAD図を描く方法を紹介します。
なぜシーケンス図でPAD図が描けるのか?
シーケンス図は「時間経過に伴うオブジェクト間のやり取り」を表現しています。で、視点をちょっと変えてみると・・・
通常の使い方: 縦軸=「時間」、横軸(ライフライン)=「登場人物」
視点を変える: 縦軸=「処理順序」、横軸(ライフライン)= 「ネストの深さ(インデント階層)」
この発想の転換で、シーケンス図の持つ「厳密な枠組み」が、そのまま構造化プログラミングの「スコープ」の表現に利用できると思ったのです。
実例:FizzBuzzをPAD風に描いてみる
ということで、書いてみました。まずは完成図をご覧ください。プログラミングの定番問題「FizzBuzz」のロジックです。
FizzBuzzのPAD図
コードスニペット
```mermaid
sequenceDiagram
autonumber
participant L0 as Main (Lv0)
participant L1 as Loop Scope (Lv1)
participant L2 as Decision Scope (Lv2)
Note over L0: プログラム開始
loop i = 1 to 100
L0->>+L1: 反復開始(i)
alt i % 15 == 0 (FizzBuzz)
L1->>+L2: 条件成立
Note right of L2: 出力: "FizzBuzz"
L2-->>-L1: break
else i % 3 == 0 (Fizz)
L1->>+L2: 条件成立
Note right of L2: 出力: "Fizz"
L2-->>-L1: break
else i % 5 == 0 (Buzz)
L1->>+L2: 条件成立
Note right of L2: 出力: "Buzz"
L2-->>-L1: break
else その他 (数字そのまま)
L1->>L2: そのまま出力
Note right of L2: 出力: i
end
L1-->>-L0: 次の反復へ
end
Note over L0: プログラム終了
「上から下へ流れる処理」と、「右へ展開するネスト構造」が視覚的に整理されて、PAD図風な仕上がりになったと思います。
書き方の3つのルール
この図を描くためのルールは非常にシンプルです。
Rule 1: 登場人物(Participant)を「階層レベル」と定義する
シーケンス図では、登場人物は「人」や「システム」ですが、PAD図風にするため、ロジックの「深さ」を表すものとします。
sequenceDiagram
participant L0 as Main (Lv0)
participant L1 as Loop Scope (Lv1)
participant L2 as Decision Scope (Lv2)
%% 必要に応じてL3, L4...と定義
Rule 2: PAD図の記号を「制御ブロック(囲み枠)」で表現する
Mermaidのシーケンス図には、処理をグループ化して 「四角い枠」 で囲む機能があります。これをPAD図の記号(ループや分岐)に見立てて使います。
| PAD図の構造 | Mermaidのキーワード | 役割(プログラミング的意味) |
|---|---|---|
| 反復 | loop ... end |
While/Forブロック。 繰り返し処理全体を枠で囲みます。 |
| 選択 | alt ... else ... end |
If-Elseブロック。 条件分岐による処理の分かれ道を枠で囲みます。 |
| 任意 | opt ... end |
If (単一) ブロック。 特定の条件の時だけ実行する処理を囲みます。 |
これらを使うことで、ロジックが物理的な「箱(ブロック)」で囲まれ、構造化が強制されます。
Rule 3: 処理スコープを「Activate/Deactivate」で可視化する
処理がその階層(ブロック)の中にいる間は、縦に伸びる棒(アクティベーションバー)を表示させると、「今どの深さの処理をしているか」が明確になります。
-
->>+: 深い階層へ移動し、処理バーを開始(Activate) -
-->>-: 浅い階層へ戻り、処理バーを終了(Deactivate)
sequenceDiagram
%% L1階層の処理開始(ブロックに入る)
L0->>+L1: ループ開始
%% L1の中で何らかの処理...
%% L1階層の処理終了(ブロックから出る)
L1-->>-L0: ループ終了
まとめ:構造化を強制する図法
この「PAD風シーケンス図」の最大のメリットは、 「インデント(ネスト)を深くしないと、右側のレーンに処理が書けない」 というMermaidの制約そのものです。
これが、PAD図が持つ「矢印をあちこちに飛ばせない(GOTO文禁止)」という特性と合致し、結果として誰が書いても構造化された、読みやすいロジック図ができあがります。
おまけ
FizzBuzz以外にそれっぽいロジックをPAD図風に書いてみたもの。
```mermaid
sequenceDiagram
autonumber
%% 階層を定義(アクター表示を消して線だけにするため "actor" ではなく "participant" 推奨)
participant L0 as Lv0
participant L1 as Lv1
participant L2 as Lv2
participant L3 as Lv3
Note over L0: 処理開始
%% 【反復】PADのループ記号に相当
loop 商品リストの末尾まで
L0->>+L1: データ取得
%% 【選択】PADの分岐記号に相当
alt 価格 >= 10,000円
L1->>+L2: 高級品ロジック
%% 【背景色】特定の処理ブロックを強調
rect rgb(240, 248, 255)
L2->>L3: 割引率 = 10%
L2->>L3: ポイント = 2倍
end
L2-->>-L1: 完了
else 価格 < 1,000円
L1->>+L2: 安価品ロジック
L2->>L3: 割引率 = 0%
L2-->>-L1: 完了
else その他
L1->>L2: 通常処理 (割引率 5%)
end
%% 【オプション】単発の条件分岐
opt 在庫僅少フラグ == True
L1->>L2: 発注リストに追加
end
end
Note over L0: 処理終了