連載「業務SEのための仕様駆動開発」第6回
この記事では、機能を分割した単位を「部品」と呼びます(いわゆるモジュールです)。
大きな機能をまとめてAIに頼むと、途中から噛み合わなくなる
Claude CodeなどのAIに、大きめの機能をまとめて頼むと、最初のうちは順調に進んでいるように見えます。ところが途中から、話が噛み合わなくなります。直してほしいところと違う場所を触る。以前決めた入出力の仕様が、いつの間にか変わっている。新しい要望を追加しようとすると、仕組み全体の見直しが必要になる。
問題は、AIの能力不足だけではありません。一度に任せる機能の範囲が広すぎることにもあります。人が設計するときには自然に分ける機能の境界も、AIにまとめて任せると曖昧になりがちです。
結論:1つの部品は1つの役割に絞る。つなぎ目は入出力の仕様を決める
私は、AIに任せる前に部品を分けます。
1つの部品は、1つの役割に絞る
部品どうしのつなぎ目は、入出力の仕様を決める
部品の内部実装は、入出力の仕様を守る限り変更できる
ここでいう入出力には、受け渡すデータの内容だけでなく、必要な形式や受け渡しのルールも含みます。通信の方式や使う道具を決める話ではありません。先に決めるのは、部品の境界と、部品間で何をどう受け渡すかです。
この考え方は、業務SEが普段行っている機能設計にも通じます。新しい技法ではありません。相手がAIになると、一気に作らせたくなるので、切り分けを先に言葉にしておく必要があります。
仕様駆動開発(SDD)では、目的確定→設計→テスト作成→実装→テストと、文書を先に固めてから作ります。工程の進め方は、エンジニアになじみのあるウォーターフォールに近いものです。部品の境界を設計の段階で決めておくのも、その延長です。
型:モジュール分割の判断基準
コピーして使ってください。AIに実装を頼む前、または設計書の部品一覧を見るときに、各項目を確認します。
モジュール分割の判断基準
対象の部品名:____________
- 1. 一言:この部品の役割を、一文で説明できるか
- 2. 入出力:受け取るものと出すもの(形式・受け渡しのルールを含む)を具体的に書けるか
- 3. 切り分け:壊れたとき、「この部品が原因か」を切り分けられるか
- 4. 入れ替え:内部実装を変えても、前後の入出力の仕様を変えずに済むか
- 5. 依頼範囲:AIへの依頼を、この部品の話だけに絞れるか
どれか1つでも「いいえ」なら、部品の範囲がまだ広すぎる可能性があります。役割や入出力を見直し、必要に応じて分けます。細かくしすぎると、部品間の連携が増えて別の難しさが出るので、「全部はいになるまで機械的に割る」ことが目的ではありません。
使い方:一言で表してから、入出力を定義する
まず、いまAIに任せようとしている機能を、一言で表してみます。その説明に複数の動作が含まれている場合は、異なる役割が混ざっていないか確認します。
たとえば「届いた内容を読んで、振り分けて、関係する処理を動かす」という機能には、受信・振り分け・実行という役割が含まれています。それぞれを別の部品に分け、個々の部品に判断基準を当てはめます。
次に、各部品の入出力を定義します。何を受け取り、何を返すのかを具体的に書けない場合は、部品の境界がまだ曖昧です。部品どうしを連携させるには、一方の出力をもう一方の入力として受け取れるように、データの形式や受け渡しのルールを決めます。内部の実装方法まで共有する必要はありません。部品間の約束を守れば、それぞれの内部を独立して変更しやすくなります。
Claude Codeに頼むときも、同じ単位で分けます。一度に「全体を作って」と頼むのではなく、「この部品だけ。受け取るものはこれ、出すものはこれ」と渡します。依頼の範囲が狭いほど、途中で話がずれにくくなります。判断基準の5つ目は、そのための確認です。依頼対象と関係のない部品の仕様まで指示に含めると、直してほしくない場所まで変わりやすくなります。
たとえば、連載で使っている「受注CSVを取り込む」の話なら、まとめて頼むと「読み取り・検証・結果出力」が一つの塊になりやすいです。これを「ファイルを読み取る」「行を検証する」「取り込み結果を出す」に分けると、検証のルールだけ後から変えても、読み取りと結果の出し方の仕様が同じなら、検証の部品だけ差し替えられます。
分けたあとは、設計書に部品名と入出力の仕様を記載します。第5回のダメ出し観点で言う「入出力」と「分担」を、部品単位で見られるようにするためです。テスト仕様書も、入力に対する期待出力を部品ごとに定義しやすくなります。
実体験:まとめて実装して起きた問題と、分割による改善
以前、受信したメールの内容に応じてフォルダに振り分けたり、別のシステムを動かしたり、処理結果をシステムに通知したりする仕組みを作ろうとしました。
当初は、これらの機能をまとめて実装しました。ある程度は動くものができたものの、各機能の汎用性が低く、細かな制御も難しい状態でした。さらに、機能を追加しようとすると、データの持ち方から見直さなければならないこともありました。一つの変更が仕組み全体に影響してしまうのです。
そこで、メールを読む部分、処理を振り分ける部分、実際に処理を実行する部分を分け、それぞれが決められた形式で情報を受け渡す構成に変更しました。その結果、個々の機能を独立して調整しやすくなりました。
振り返ると、分割後の各部品は、先ほどの判断基準を満たしていました。役割を一言で説明でき、入出力を定義でき、問題が起きたときに原因を切り分けやすい。AIに実装を依頼するときも、対象の部品に範囲を絞れるようになりました。
別の例で考える、モジュール分割の考え方
別の例として、SNSに投稿する動画やブログ記事を作る仕組みを考えてみます。
こうした仕組みでは、まず投稿の方針を決め、素材を用意し、それらを組み合わせて最終的なコンテンツを作ります。この一連の処理をひとまとめに実装すると、素材の作り方や最終的な出力形式を変えたいときに、ほかの処理まで修正が必要になるかもしれません。
そこで、役割ごとに部品を分け、部品間の入出力を定義します。1つひとつの部品をシンプルにし、決めた仕様に沿って連携させる。これは業務SEにとってなじみのある設計の考え方です。AIに実装をまとめて任せる場合も、同じように部品の境界を明確にしておくことが重要です。そのために、実装を依頼する前に判断基準で分割位置を確認します。
まとめ
大きな機能をまとめてAIに頼むと、途中から噛み合わなくなりやすい
1つの部品は1つの役割に絞り、つなぎ目では入出力の仕様を決める
一言・入出力・切り分け・入れ替え・依頼範囲の5項目で、分ける単位を確認する
次回は、いわゆるバイブコーディングを、私が案件で使わない理由と、使う場面の見分け方を扱います。
連載「業務SEのための仕様駆動開発」
一覧はこちら → https://qiita.com/sha44444/stocks/3c9167054a4a82837bb3
この連載では、仕様駆動開発の「型」を1回に1つずつ紹介しています。
5つの工程を実案件でどう回しているか(各工程でAIに渡す依頼文、変更が入ったときの回し方、通しの実例)は、1冊の本にまとめました。第1章は無料で読めます。
→ https://zenn.dev/shin4/books/31499dd20de8ac