りまねどっとねっと

仕様駆動開発を手探りで最適化していく

AI

現在、多くの企業で Claude Code をはじめとした 自律型 AI エージェントによる開発が主流になってきていると思います。

ですが、さわっていればわかるんですけれど、「ログイン機能を作って」みたいな大雑把な指示だと、AI が良いように解釈して想像と異なるものが出来上がってしまうことがあります。

そうなると、結局手直しが多く必要となり、時間がかかることもめずらしくないです。

そこで考えられたのが「仕様駆動開発」というものです。

GitHub の Spec Kit や、 Amazon の Kiro などが有名だと思います。しかしそんな中で、「それらにインスピレーションを受けて、自らそのような環境を構築する」ということも僕の観測範囲内ではよく見られる気がします。

TL;DR

  • 大雑把な指示だと AI がよしなに解釈してしまうため、「要件定義 → 技術設計 → タスク分解 → タスク実行」の4フェーズをガードレールとして Agent Skill 化した
  • 要件定義フェーズでは、あえてビジネス視点の質問だけで AI にヒアリングさせ、EARS 要件定義書を生成することでとんちんかんな実装を防いでいる
  • 技術設計・タスク分割も要件定義書を踏まえて AI に生成させ、実装フェーズで読み込ませることでコード生成の手戻りを減らしている
  • 一方で仕様を固めすぎると手戻りしづらくなる課題もあり、小さな修正や hotfix には単発の簡易計画→実行スキルを使い分けている

ガードレールを作ろう

上記のとおり、大雑把な指示だと、AI がよしなに解釈して「それっぽいもの」を作ってしまいます。

そこで仕様駆動開発では、人間が先に仕様を決めて、それに則ってコードを生成してもらいます。

僕はこれを列車のレールや、車道のガードレールのようなものと認識しています。

仕様を段階的に具体化する

当初、個人的に「仕様をガッチリ決めてしまうのは時代に逆行している気がする」と思っていました。最近はウォーターフォール開発からアジャイル開発に時代が移り変わっているからです。

もちろん、アジャイル開発だからといって、要件定義や詳細設計がまったく不要というわけではありません。とはいえ、僕は「チーム内で打ち合わせ、メモ書き程度の要件定義」しかしていなかったです。

ですがその雰囲気のまま Claude Code を使用すると、以下のような問題がおきました。

  • まったく想定していないライブラリが使用される
  • プロジェクトで規定しているディレクトリ配置になっていない
  • すでに定義されている関数と類似したコードが生成されて車輪の再発明が生じる

たとえば、テストは Bun 標準のテストランナーで書いてほしいと伝えていたつもりが Vitest が使われていたり、UTC を JST に変換して「yyyy年mm月dd日」の形式に整形する関数が、複数のファイルにそれぞれ個別に生成されていたりしたことがありました。

そこで、僕は

  1. 要件定義
  2. 技術設計
  3. タスク分解
  4. タスク実行

のフェーズをまずは用意しました。

具体的な解決方法

AI と壁打ちして要件定義

AI と壁打ちして要件定義

AI が好き勝手動かないようにするためには、上流工程が大切だと思っています。

プロジェクトの柔軟性にもよると思うのですが、まずは要件定義がしっかりできる Agents Skill を作成しました。Agent Skill とは、Claude Code などにあらかじめ決めた指示を与えることができる、手順書のプリセットのようなものです。

大雑把に要約すると、

  1. 実装したい機能と、その機能が必要な理由と必要な場面を伝える(ユーザーストーリー)
  2. Claude Code がヒアリングをしてくれる
  3. 10問程度に答えると、EARS 要件定義書が生成される

のようなフローを構築しました。

まあまあ長いのでリンクとして貼っておきます。

要件定義生成スキル · rimanem18/hoxt-backlog

これを実行すると、 tasks/{requirements_ID}/spec というディレクトリが作成されます。

そしてその中に

  • requirements.md
  • technical-spec.md
  • interview.md

の3つのファイルが生成されます。

このスキルの特徴は、エンジニアではなく「プロダクトオーナー」「ステークホルダー」を質問の相手として想定した作りにしていることです。

AI エージェントが提示する質問内容から技術的観点を除外することで、ビジネス要件に関心の高い関係者に同席してもらって質問に答えていくことがスムーズにできるようになります。

コード生成時に AI がとんちんかんな内容を生成しないようにコントロールするには「どういう理由でこの機能が必要なのか」という背景を伝えることです。なので、そのような内容がふくまれた、EARS 要件定義書が出来上がる想定です。

たとえば「すでに Google ログインが実装されているアプリ」に対して Email / Password ログイン機能を実装したいと伝えたときには、ヒアリングでは、

  • 同じメールアドレスを Google とメールパスワードの両方で使うケースをどう扱いますか?
  • パスワードの要件(最低長や複雑さ)はビジネスとして指定がありますか?
  • パスワードリセットリンクの有効期限・使用回数に「業務上の期待」はありますか?

このような質問を AI がしてくれました。 網羅的に穴を埋めるように質問をしてくれるので、実装途中に「そういえばそこ決めてなかった」みたいなことも少なくなります。

生成されたメールパスワード認証 EARS 要件定義書 · rimanem18/hoxt-backlog

事前に詰めておけば「パスワードは複雑な方が良いですよね! 30文字以上で大文字小文字英数字と記号すべてふくめないと登録できないようにしておきました!」みたいなことを AI が勝手にしなくなり、「いや8文字以上で、記号は必須じゃなくていい」「わかりました! 修正します!」みたいな不毛なやりとりをしなくて済みます。

AI が生成した技術設計をベースに穴埋め

AI が生成した技術設計をベースに穴埋め

要件定義と同様、AI に縛りを設けるために、技術設計書も用意します。

技術設計では、要件定義のときに生成した以下のファイルを読むように伝えた上で、システムの設計や構成、データの処理と流れ、データモデルなど、より技術寄りの内容を生成してもらいます。

技術設計生成スキル · rimanem18/hoxt-backlog

これを実行すると、 tasks/{requirements_ID}/technical というディレクトリが作成されます。

そしてその中に

  • design.md

が生成され、詳細が必要と AI が判断した場合は、追加で

  • data-flow.md
  • api-design.md
  • data-model.md

というファイルが生成されます。基本的には1つで、最大4つということになります。

スキルを実行すると、まずは既存の認証基盤やライブラリ、既存実装を確認します。その後、要件定義書で求められる機能やセキュリティ要件を満たすため、どのような技術選定や実装が最適なのか文書にまとめてくれます。

生成されたメールパスワード認証 技術設計書 · rimanem18/hoxt-backlog

AI だけでは判断できなかった未決事項なども洗い出してくれるので、文書が生成されたあとに AI と対話して決めることが可能です。

AI が実行しやすい順序に整理したタスク分割

AI が実行しやすい順序に整理したタスク分割

次はタスク分割です。

Claude Code や Codex といった自律型 AI エージェントに限らず、多くの AI は、会話が積み重なったり抱えている情報が増えれば増えるほど、挙動が不安定になります。

そのため、実施する作業をいくつかのフェーズに分解しておきます。

タスク計画生成スキル · rimanem18/hoxt-backlog

これを実行すると、 tasks/{requirements_ID}/plan というディレクトリが作成されます。

そしてその中に

  • overview.md
  • phase1.md
  • phase2.md

… というように、phase ファイルがいくつか生成されます。

生成されたメールパスワード認証 タスク計画 · rimanem18/hoxt-backlog

このスキルでは、上記2ステップで生成した要件定義書と技術設計書を AI が読み込んだ上でタスク計画を生成してくれます。 なのである程度レールが敷かれた状態で、コードを生成してくれるようになります。

ただ、 Claude Code などの主要な AI エージェントには Plan モードというものがあったりして、そちらを使いこなしていれば恩恵はそんなに感じないかもしれません。

このやり方の場合、タスク計画時点で完全に見落としがない状態にする必要があります。タスク計画まできっちり決めた場合、途中で「あ、○○が考慮されてない」と気づくとやりづらいのが課題になっているのが正直なところです。

ある程度、柔軟に動いてもらえるようにするには、 overview.md だけ作って大筋を決め、段階的に Plan エージェントで計画を都度作成してコードを書いてもらうというのもいいかもしれません。

タスクの実行(実装)

次はいよいよタスクの実行による実装です。

タスク実行 / 実装スキル · rimanem18/hoxt-backlog

このスキルを実行するときは、要件ID、フェーズ番号を伝えます。すると、まずはその要件IDの以下のファイルを読み込みます。

  • requirements.md
  • design.md
  • overview.md
  • phase{number}.md

読み終わったあと、実際にフェーズファイルに記載された計画通りに実装を開始します。タスク分解では、「phase ファイルは4時間単位で終わるように分解しなければならない」と縛りを入れてありますが、だいたい10〜25分くらいで実装を終えます。 ただし、AI が書くコードは完全ではないので、適切に人間の目でレビューする必要があります。それも込みだと、1〜2時間くらいは必要かもしれません。

この開発方法も万能ではない

要件定義の時点で AI が細かな質問してくれる仕組みを構築したことは、僕にとって AI による開発をスムーズにできた大きな変化です。

とくに僕は要件定義が苦手なので「○○はどうしますか?」「△△は□□になっていますが、このままで問題ないですか?」のような質問を AI がしてくれるのは、非常に助かります。

でも完璧ではありません。これは AI に限った話ではありませんが、仕様を固めることにより柔軟性が失われるというデメリットもあります。一度タスク分解して細かい計画まで出してしまうと、途中で問題に気づいたとき「この実装を計画と違う書き方にするとこの次の計画に影響が…」みたいなことや「要件定義するほどではないけど修正したいところが…」みたいなことをいちいち考える必要が出てくるようになってしまい、停滞してしまうこともありました。

それらを解決するために、仕様書のアップデートに特化したスキルや、単発で簡易的な計画→実行をおこなうスキルなどを作成したりして、試行錯誤しています。

仕様書アップデート用のスキルは機能しなかったわけではないのですが、最近はあまり使う機会がなくなっています。一方、単発の簡易計画→実行スキルはかなり頻繁に使っています。プロダクトバックログに起こすほどでもない小さな機能開発や、hotfix のときによく使っています。

単発の簡易計画からの実行スキル · rimanem18/hoxt-backlog

このスキルでは、Haiku の Explore サブエージェントで調査、Opus の Plan サブエージェントで計画、メインエージェントで Red(テスト作成)、Sonnet Medium Effort または Haiku のサブエージェントで Green(実装)、そして再びメインエージェントで Refactor という役割分担にしています。

メインエージェントには要件定義書や技術設計書も読ませていないので、コンテキストが汚染される感覚が薄く、Auto Compact もほぼ走っていないような気がします。

関連記事

関連記事はありません。

新着記事

この記事より新しい記事はありません

Skeb と Skeb Coin ってどういう関係性のものなのか気になったので調べた