シーケンス図(詳細版)の位置づけ
基本設計フェーズで「システム間」のやり取りを示した概要シーケンス図を受けて、詳細設計フェーズでは「クラス・メソッドレベル」の詳細シーケンス図を作成する。
💡 詳細シーケンス図に含めるべき内容
メソッド名と引数・戻り値の型、条件分岐(alt/opt)、ループ処理(loop)、非同期処理、例外発生と伝播、外部システム呼び出し。
定義すべき内容
| 要素 | 説明 | 必須度 |
|---|---|---|
| 参加者 | User / Controller / Service / Repository / 外部システム | ◎ |
| メッセージ | メソッド名・引数・戻り値 | ◎ |
| 条件分岐 | alt(if/else)・opt(if のみ) | ◎ |
| ループ | loop [n回 or 条件] | ○ |
| 非同期 | 非同期メッセージ(-->> 矢印) | ○ |
| 例外 | 例外スロー・catch の表現 | ◎ |
| 外部IF | 外部システムとの通信を参加者として表現 | ◎ |
同期処理のシーケンス
@startuml
title 注文確定シーケンス(同期)
actor User
participant "OrderController" as Ctrl
participant "OrderService" as Svc
participant "StockService" as Stock
participant "OrderRepository" as Repo
database "Database" as DB
User -> Ctrl: POST /api/v1/orders
activate Ctrl
Ctrl -> Svc: confirmOrder(OrderRequest)
activate Svc
loop items ごとに
Svc -> Stock: checkStock(productId, quantity)
activate Stock
Stock -> DB: SELECT stock_quantity FROM products
DB --> Stock: stock_quantity
alt 在庫不足
Stock --> Svc: throw BizException(BIZ_001)
Ctrl --> User: 400 {"errorCode":"BIZ_001"}
end
Stock --> Svc: available_quantity
deactivate Stock
end
Svc -> Repo: save(Order)
activate Repo
Repo -> DB: INSERT INTO orders
DB --> Repo: order_id=12345
Repo --> Svc: Order{id=12345}
deactivate Repo
Svc --> Ctrl: OrderResponse{orderId=12345}
deactivate Svc
Ctrl --> User: 201 {"orderId":12345}
deactivate Ctrl
@enduml
非同期処理のシーケンス
@startuml
participant "OrderService" as Svc
participant "MessageQueue" as MQ
participant "EmailWorker" as Worker
participant "MailService" as Mail
Svc ->> MQ: publish(OrderConfirmedEvent)
note right: 非同期(fire and forget)
== 非同期処理(別プロセス) ==
Worker -> MQ: consume(OrderConfirmedEvent)
activate Worker
Worker -> Mail: sendOrderConfirmation(email, orderId)
alt 送信成功
Mail --> Worker: success
Worker -> MQ: ack
else 送信失敗
Mail --> Worker: error
Worker -> MQ: nack(3回リトライ)
end
deactivate Worker
@enduml
例外処理フロー
【例外処理の記述ルール】
1. 業務例外(BizException)
- try/catch ではなく alt で条件分岐として表現
- 発生条件を明記する
2. システム例外(RuntimeException)
- 上位層(Controller)で一括 catch
- ログ出力(ERROR) -> SYS_001 エラーレスポンス返却
3. 外部IFエラー
- タイムアウト・接続エラーを alt で表現
- リトライ回数を loop で表現
【シーケンス図に含めるべき例外パターン】
□ 認証エラー(JWT 期限切れ・権限不足)
□ バリデーションエラー(必須項目欠如)
□ ビジネスエラー(在庫不足・残高不足)
□ 外部IFエラー(タイムアウト・5xx)
□ DB エラー(接続エラー・デッドロック)
PlantUML での記述
| 表現したいこと | PlantUML 記法 |
|---|---|
| 同期メッセージ | A -> B: methodName(args) |
| 戻り値 | B --> A: returnValue |
| 非同期メッセージ | A ->> B: asyncMethod() |
| 条件分岐 | alt 条件A ... else 条件B ... end |
| ループ | loop N回 ... end |
| 並行処理 | par 処理A ... and 処理B ... end |
Python Tips — 呼び出しシーケンスの自動抽出
import ast
def extract_call_sequence(source, target_class, target_method):
tree = ast.parse(source)
calls = []
for node in ast.walk(tree):
if isinstance(node, ast.ClassDef) and node.name == target_class:
for item in node.body:
if isinstance(item, ast.FunctionDef) and item.name == target_method:
for stmt in ast.walk(item):
if isinstance(stmt, ast.Call):
if isinstance(stmt.func, ast.Attribute):
caller = stmt.func.attr
if hasattr(stmt.func.value, 'attr'):
obj = stmt.func.value.attr
calls.append(f"{target_class} -> {obj}: {caller}()")
return calls
# 使用例
sample = open("order_service.py").read()
calls = extract_call_sequence(sample, "OrderService", "confirm_order")
print("@startuml")
for c in calls:
print(c)
print("@enduml")
レビューチェックリスト
| # | チェック項目 |
|---|---|
| 1 | メッセージにメソッド名・引数が記載されているか |
| 2 | 主要な例外パターンが alt で表現されているか |
| 3 | 非同期処理が同期処理と明確に区別されているか |
| 4 | DB・外部IFが参加者として表現されているか |
| 5 | トランザクション境界が明示されているか |