Amazon Web Services ブログ

イベントストーミングから要件・設計・タスクへ。Kiro を活用した仕様駆動開発

こんにちは!AWS Japan でアプリ開発コンサルタントをしているしょぼちむです。

本ブログは Kiroweeeeeeek ( X: #kiroweeeeeeek ) の第 7 日目です。昨日のブログは小西 (konippi) さんの「Amazon Q Developer CLI から Kiro CLI へ : 知っておくべき変更点」という内容でした。ブログリレー、お楽しみいただけているでしょうか!

イベントストーミングは、ビジネスの流れを可視化し、業務のエキスパートや開発メンバーが同じ理解を持てるようにするためのプラクティスです。Big Picture を使ってサブドメイン間の関係性を整理したり、業務内容をコードに落とし込むための設計に活用したりと、業務分析から設計まで幅広く役立ちます。しかし、イベントストーミングで得られた成果物を「どこから実装に落とし込むのか」「どうテストするのか」といった部分は、開発者がつまずきやすいポイントではないでしょうか。

本ブログでは、Kiro の Spec 機能を活用して、イベントストーミングの成果物を要件定義・設計・実装タスクへと変換していくプロセスを紹介します。

イベントストーミングの実施

題材として、イメージしやすいけれど複雑な「EC サイトの注文プロセス」を選びました。このドメインには、以下の特徴があります。

  • 状態遷移がわかりやすい(カート → 注文確定 → 在庫確保 → 支払い)
  • ビジネスルールが多い(在庫確認・支払い処理など)

まず、イベントストーミングを実施し、注文プロセスのフローを可視化します。イベントストーミングでは、色分けされた付箋と付箋間の遷移のルールに従って、業務フローを可視化します。それぞれの付箋の意味と、今回の成果物の例を以下に記載します。

  • 緑色の付箋:ユーザーに表示するためのビュー
    • 商品詳細、カート状況
  • 薄い黄色の付箋:操作を実行するユーザー
    • 顧客
  • 青色の付箋(コマンド):ユーザーやシステムが実行する行動
    • 商品をカートに追加する、注文を確定する、在庫を確保する、在庫を更新する、支払いを処理する
  • 濃い黄色の付箋(集約):イベントやコマンドもとに、関連する概念をまとめたもの
    • カート集約、注文集約、在庫集約
  • オレンジ色の付箋(イベント):システム内で発生した事実
    • カートを追加した、注文を確定した、在庫を予約した、在庫を更新した、支払いを完了した
  • 紫色の付箋(ポリシー):イベントをトリガーに、自動的に実行されるビジネスルール
    • 在庫確保ポリシー、支払い処理ポリシー
  • ピンク色の付箋(外部システム):システムの境界外にある連携先
    • 決済システム

Kiro の Spec 機能を使う

Kiro の Spec 機能は、複雑な機能開発を構造化して進めるための仕組みです。Spec 機能を利用すると、以下の 3 つのドキュメントを順に生成しながら作業を進めていきます。生成 AI へのプロンプトから一気にコードを書くのではなく、プロセスが 3 つの段階に分かれることで、要件や設計がレビューしやすくなり、認識が大きくズレた成果物が出力されてしまうことを防げます。

  • requirements.md:要件定義(EARS (Easy Approach to Requirements Syntax) 形式で記述)
  • design.md:設計ドキュメント(アーキテクチャ、データモデル、プロパティなど)
  • tasks.md:実装のタスクリスト

Kiro への最初のプロンプト

イベントストーミングの画像を Kiro に添付し、以下のシンプルなプロンプトを送りました。Kiro は画像も理解してくれます。

このイベントストーミングの結果を要件に出力してください。
不明な点があれば質問してください。

「不明な点があれば質問してください。」とプロンプトに加えたことで、Kiro が要件の曖昧さを解消するための質問をいくつか返してくれました。イベントストーミングでは表現できてなかった情報を洗い出すのに役立ちます。

Kiro からの質問:

イベントストーミングの図を確認しました。注文管理システムのフローのようですね。
いくつか確認させてください:
1. システムの範囲: このシステムは注文の受付から支払い完了までを管理するものですか?
   それとも、より広い範囲(配送、在庫管理など)も含みますか?
2. 顧客の種類: 顧客は一般消費者ですか?それとも企業顧客も含みますか?
3. 商品とカート:
   - 商品カタログは既存のシステムから取得しますか?
   - カートに追加できる商品数に制限はありますか?
   - カートの有効期限はありますか?
4. 注文処理:
   - 「注文を確定する」と「注文を確定した」の間で、在庫確認や価格計算などの処理が必要ですか?
   - 注文のキャンセルや変更は可能ですか?
5. 在庫管理:
   - 「在庫を確保する」「在庫を予約した」のプロセスで、在庫が不足している場合の処理は?
   - 在庫の更新や返却のシナリオはありますか?
6. 支払い:
   - 支払い方法は何がありますか?(クレジットカード、銀行振込、代引きなど)
   - 支払い処理は外部システムと連携しますか?
   - 支払い失敗時の処理は?
7. 在庫確認ポリシーと在庫更新ポリシー:
   - これらのポリシーの具体的なルールを教えてください
   - 例:在庫確認のタイミング、在庫更新の条件など
8. 決済システム:
   - 決済完了後の処理(領収書発行、配送手配など)は含みますか?
これらの情報をもとに、EARS形式の要件を作成します。

要件ドキュメントのレビュー

Kiro へ質問を返すと、以下のような構成の要件のドキュメント(requirements.md)が生成されました。Kiro はドキュメントの生成後、この要件で問題がないかを確認し、返答を待機します。(Move to design phase ボタンが表示されます。)この段階でレビューを入れられることで、Kiro の認識にズレがないかを早期にチェックできます。

  • 用語集:システムで使用される重要な用語が明確に定義されている
  • 8つの要件:(EARS 形式:WHEN / IF / THEN の形式で記述され、読みやすく理解しやすい)
    • 商品閲覧とカート管理
    • 注文確定と価格計算
    • 在庫確保
    • 支払い処理
    • 配送連携
    • 注文キャンセルと返金
    • 在庫管理ポリシー
    • データ整合性
  • 受入基準:各要件に対して具体的な受入基準が定義されている

生成された要件の 1 つ目はこちらです。イベントストーミングでは「カートへのアイテムの追加」のフローしかありませんでしたが、ここでは削除のフローも考慮して要件を整理してくれました。今回はこのまま進めますが、もちろん Kiro との対話やファイルの編集によって、この requirements.md を修正することもできます。

### 要件 1: 商品閲覧とカート管理
**ユーザーストーリー:** 顧客として、商品を閲覧してカートに追加したいので、購入する商品を選択できるようにしたい
#### 受入基準
1. WHEN 顧客が商品カタログを閲覧する THEN 注文システムは商品カタログシステムから商品情報を取得する
2. WHEN 顧客が商品をカートに追加する THEN 注文システムはその商品をカートに保存する
3. WHEN 顧客がカート内の商品を確認する THEN 注文システムはカート内のすべての商品を表示する
4. WHEN 顧客がカートから商品を削除する THEN 注文システムはその商品をカートから除去する

設計フェーズへ

要件が確定したら、次は設計フェーズに進みます。設計フェーズでは、requirements.md をベースとした設計ドキュメント(design.md)が生成されます。ここからは、要件がどのように実際の構造へと落とし込まれていくかを見ていきます。今回の設計ドキュメントには、以下の情報が含まれていました。先ほどと同じように、ここでも Kiro はドキュメントの生成後、レビューのために待機します。

  • アーキテクチャ設計
  • コンポーネント設計
  • ドメインモデル(エンティティや値オブジェクト)
  • エラーハンドリング方針
  • プロパティベーステスト
  • セキュリティやパフォーマンス面の考慮

イベントストーミングの付箋では「XXX集約」と集約名しか書いていませんでした。しかし、design.md のデータモデルの章を見てみると、そこからさらに踏み込んで、以下のようにエンティティのプロパティまで定義されていました。Order のステータス(PENDINGCONFIRMEDINVENTORY_RESERVEDPAYMENT_COMPLETEDSHIPPING_ARRANGED)は、イベントストーミングで可視化したイベントの流れ(「注文を確定した」→「在庫を予約した」→「支払いが完了した」)を反映しています。また、要件の質問への回答にて配送もシステムの設計対象だと伝えたことで、イベントストーミングにはなかった配送の集約も追加されていました。

  • Cart(カート):顧客ID、商品リスト、作成日時などを持つ
  • Order(注文):注文ID、顧客ID、商品リスト、合計金額、ステータス
  • Payment(支払い):決済情報と決済ステータス
  • Shipping(配送):配送先情報と配送ステータス
  • Inventory(在庫):商品ID、利用可能数量、予約済み数量、最終更新日時
  • InventoryReservation(在庫予約):予約ID、注文ID、商品ID、予約数量、予約日時

さらに、イベントストーミングでコマンドの付箋として書いていたものが、サービスのメソッドとして設計されていました。このように、設計段階でも実装方針のレビューのステップがあることで、Kiro との認識のズレがあった場合でも修正できます。

  • 「商品をカートに追加する」→ CartService.addItem()
  • 「注文を確定する」→ OrderService.confirmOrder()
  • 「在庫を確保する」→ InventoryService.reserveInventory()
  • 「支払いを実行する」→ PaymentService.processPayment()

さらに、Kiro は設計段階で正確性プロパティを自動生成しました。それぞれのプロパティには、以下の情報が含まれます。

  • プロパティの説明(任意の〜に対して、〜すべきである)
  • 検証対象となる要件番号

イベントストーミングでは「〜したら、〜になる」という業務の流れと因果関係を可視化します。これは、正確性プロパティの「任意の〜に対して、〜すべきである」という考え方と似ているため、この 2 つはとても相性が良いです。ここで定義されたプロパティは、後続の実装フェーズでプロパティベーステストとして実装されます。プロパティテストについては詳細を「Kiro : コードは仕様と一致していますか? 〜プロパティベーステストで「正しさ」を測定する〜」にてご紹介しているので、ぜひご参照ください。実際の design.md から一部抜粋したものがこちらです。

### プロパティ1: カートへの商品追加の一貫性
*任意の*顧客IDと商品IDに対して、商品をカートに追加した後、そのカートを取得すると、追加した商品が含まれているべきである
**検証対象: 要件 1.2**

### プロパティ2: カート内容の完全性
*任意の*カートに対して、カート内容を取得すると、カートに追加されたすべての商品が返されるべきである
**検証対象: 要件 1.3**

実装タスクの生成

設計が完了すると次は実装タスク(tasks.md)を生成します。例えば、次の画像の「2.2 データモデルのプロパティテスト」は、最初はオプションタスク扱いになっており、タスクリスト上でも文字色がグレーアウトされています。しかし、チャットに表示されている「全てのタスクを必須にする(最初から包括的)」のボタンを押すことで、プロパティテストも含んだタスクのリストが出来上がります。あとは、タスクリストもレビューをして、Kiro のエディタ上に表示されている Start task ボタンから実装を開始するだけです!実装後もレビューは忘れないようにしましょうね!

まとめ

イベントストーミングと Kiro Spec を組み合わせて利用したことで、付箋で議論した内容がそのまま要件・設計・タスクに繋がり、実装までの道のりが整理されました。イベントストーミングがあることで、業務全体の規模感や、現在どの業務プロセスに取り組んでいるか、このあとどんな業務フローにつながるのかといった、地図が手に入ります。そして、Kiro が自然言語で要件や設計を整理することで、チームの共通言語として理解が進み、設計の抜け漏れやタスクの取りこぼしを防げます。(無いのが理想ですが、イベントストーミングをやっていても、チーム間で実は認識が違った!ってこともありますよね…。)プロパティベーステストを始めとした、ドメイン駆動設計と相性が良いプラクティスも多く組み込まれているため、仕様の漏れを軽減しながら設計と実装を進められます。ぜひ、チームでドメインを理解しながら、実装に進める流れを体感してみてください!

使ってみた感想や疑問などあれば、ぜひ #kiroweeeeeeek に共有していただけると嬉しいです!

著者

しょぼちむ (Mizuki syobochim Ugajin)

『いちばんやさしいGit&GitHubの教本』の著者。AWS Japan のアプリ開発コンサルタントとして、主にドメイン駆動設計の導入のご支援をしています。最近は書籍の内容やイベントセッションのグラレコをポストしてご紹介などもしています。インドア派でしたが、子どもができてから毎週お出かけして日の光を浴びてます。