ソフトウェアアーキテクチャにおけるユーザーフローの文書化
バグレポートはシンプルに見えました:「チェックアウトが断続的に失敗する。」
美しいアーキテクチャ図がありました。C4図にはすべてのサービス、データベース、統合が示されていました。しかし「カートに追加」から「注文確認」までのユーザーの旅路を追跡しようとしたとき、正確な順序について誰も合意できませんでした。どのサービスが関与しているか?どの順序で?在庫チェックは決済の前か後か?
3人のエンジニアが3つの異なるメンタルモデルを持っていました。静的なアーキテクチャ図は構造を示しましたが、振る舞いは示していませんでした。
そのとき、ユーザーフローが必要だと気づきました。
ユーザーフローとは何か
ユーザーフローは、ユーザーが目標を達成するためにシステムを通って取る旅路を文書化します。静的な構造ではなく(それはC4図の仕事)、動的なシーケンスです。
構造と振る舞いのギャップ
C4コンテナ図はコンポーネントの存在と接続方法を示します。しかし、ユーザーがチェックアウトするとき最初に何が起きるか?APIは決済を呼び出す前に在庫を検証するか?これらの質問にはフローの理解が必要です。
有用なユーザーフローの構造
1. 目標の記述
ユーザーが達成しようとしていることから始めます。
2. 前提条件
このフローが始まる前に真でなければならないこと。
3. ハッピーパス
期待される成功パスをまず文書化:
1. ユーザーが「チェックアウト」ボタンをクリック
→ Web Appが配送先住所フォームを表示
2. ユーザーが配送先住所を入力し「続行」をクリック
→ APIが住所フォーマットを検証
→ APIが配送オプションを計算
3. ユーザーが配送方法を選択し「続行」をクリック
4. ユーザーが支払い情報を入力し「注文する」をクリック
→ APIがデータベースに保留注文を作成
→ APIがPayment Serviceを呼び出す
→ Payment ServiceがStripeに課金
→ 注文確認
4. エラーパスとエッジケース
ハッピーパスは始まりにすぎません。本当の価値は、問題が発生したときの文書化から来ます。
決済拒否: Payment Serviceがエラーを返し、APIは注文を確認せず、保留注文を削除。
在庫変更: APIが在庫を再確認し、アイテムが利用不可なら在庫エラーを返す。
これらのエラーパスはバグが潜む場所です。
フローとアーキテクチャの接続
Archylでは、フローの各ステップに関与するコンポーネントを注釈できます。双方向のトレーサビリティが生まれます:
- フローを見て、どのコンポーネントが関与しているか確認
- コンポーネントを見て、どのフローがそこを通るか確認
異なるタイプのフロー
ユーザーフロー
UIから開始されるシーケンス:チェックアウト、登録、パスワードリセット。
システムフロー
マシンが開始するシーケンス:夜間調整ジョブ、Webhook処理、イベント駆動カスケード。
統合フロー
クロスシステムシーケンス:サードパーティの注文インポート、決済精算バッチ。
よくある間違い
間違い1:詳細すぎる
フロードキュメントはコードのように読むべきではありません。個別のデータベースクエリを文書化しているなら、間違った粒度です。
間違い2:ハッピーパスだけ文書化する
ハッピーパスは簡単です。エラーパスこそバグが潜むところです。「このステップが失敗したらどうなる?」と自問してください。
間違い3:変更後に更新しない
現実と一致しない文書化されたフローは、ドキュメントがないより悪いです。
間違い4:フローを静的なものとして扱う
ユーザーフローは進化します。生きたドキュメントとして扱ってください。
まとめ
静的なアーキテクチャ図はシステムの構成を教えてくれます。ユーザーフローはシステムの振る舞いを教えてくれます。両方が必要です。
最も重要なフローから始めましょう。ハッピーパスを文書化し、少なくとも3つのエラーケースを文書化してください。
深夜2時にデバッグしている未来の自分が感謝するでしょう。
アーキテクチャドキュメントについてさらに学ぶ:C4モデル入門 | アーキテクチャ決定記録 | なぜドキュメントが重要か