はじめに
エンジニア2年目の私が、AI駆動開発の現場に入ってみて、体験したこと、感じたことを書いてみました。
「AI駆動開発」と聞くと、どんな開発方法を想像しますか?
AI駆動開発は、作るのはAI、何を作るかを決めて確かめるのは人間、という役割分担で進める開発スタイルを指すことが多いです。
この開発方法を実際に経験し、私が一番の落とし穴だと感じたことがあります。
それは、「自分が何も理解していなくても、仕様通りに動くものができてしまう」ということです。
なぜそう思ったのかを、私のAI駆動開発での体験をふまえて紹介します。
私たちとAIの役割分担
「AIが作り、人間が判断する」。
実際に開発してみて、一番強く感じたのはこれです。
開発には、何を作るかを決めて設計し、実装してテストするといった工程があります。
このうち最初の「何を作るか」さえ決まっていれば、その先の工程の多くは、AIがそれらしくこなしてくれます。
そこで問題になるのが、何を作るのか、AIが作ったものが求めていたものなのかを誰が判断するのかです。
最終的にそれを使うのも、何かあったときに責任を持つのも人間です。
だからこそ、判断は人間がする必要があります。
じゃあAIは作るだけ?
いいえ、AIはレビューもします。
たとえるなら、AIのレビューは一次面接です。
明らかなミスをここで弾いて、人間が見やすい状態にしておく。
AIのレビューはかなり正確で、この段階で完成度はかなり上がります。
それでも、本当に求めていたものかを判断し、合否を出すのは面接官である人間です。
人間とAIの役割分担を整理すると、このようになります。
| 担当 | 役割 |
| 人間 | 何を作るかを決める・最終判断をする |
| AI | コードを書く・レビューをする・調べる |
そして、判断するためには、まず自分が理解していなければなりません。
1つのタスクを追ってみる
ここからは、私が実際に担当したタスクを例に、開発の流れを追っていきます。
題材は「お知らせ機能」です。
アプリを使っていると、「あなたへのお知らせ」や「スケジュールのお知らせ」が表示されることがありますよね。
あれを作る機能です。
この機能は、設計をチームの別のメンバーが担当し、私が実装を担当しました。
途中で、設計を少し手直しすることもありました。
タスクは、次の4つのステップで進んでいきます。
- タスクを受け取り、仕様を理解する:AIに渡す前に、人間が機能の目的を理解する
- AIが実装する:実装はAIが担当し、まっさらな状態のAIがレビューする
- 自分でAIの成果物を確認する:AIが作ったものを、自分の目で確かめる
- チームにレビュー依頼を出す:チームのレビューでOKが出たら、完了
タスクを受け取り、仕様を理解する
私たちのチームでは、タスクをGitHubで管理しています。
チャットや声をかけられて、自分が担当者に設定される場合が多いです。
そんな感じでタスクが始まります。
では、ここでAIになったつもりで次のことを考えてみてください。
AIになってみよう
あなたはAIです。次の指示を受け取りました。
「お知らせ機能を作ってください」
さて、どう作りますか?
考えてみると、決めなければならないことがたくさんあります。
- 誰がお知らせを作れるのか
- 全員に届けるのか、一部の人だけに届けるのか
- いつからいつまで表示するのか
- 読んだかどうかを管理するのか
人間なら「これ、どうしますか?」と聞き返すところです。
でもAIは、何も言われなければ、わからない部分を「それらしく」埋めて、そのまま作り上げてしまいます。
こうした疑問をなくしていくために必要になるのが、設計です。
今回受け取ったお知らせ機能は、チームのメンバーがすでに詳細設計まで済ませていました。
APIが返すデータの形まで書かれた、かなりしっかりした設計です。
ここまで決まっているなら、あとはAIに渡すだけだと思いますよね。
でも、設計があればそれで安心、というわけでもありません。
大事なのは、この機能が何のためにあるのかを、人間がしっかり理解することです。
私がまずやったのは、自分自身が設計を読み込むことでした。
わからないところは設計した人に確認し、変更が必要になりそうな部分が見つかれば、チームで共有します。
実際、設計書を読み込んでいくと、手直しが必要なところがいくつか出てきました。
たとえば、10日に配信する予定だったお知らせが、配信の処理が止まってしまい、12日に届いたとします。
このとき、受け取る人の画面に表示する「配信日」は、10日と12日のどちらでしょうか。
設計を読み込む中でこの点が曖昧だと気づき、受け取る側には「実際に届いた日」を表示することにしました。
ほかにも、すでに届いたお知らせの宛先を後から変えられないようにするなど、いくつか手直しを入れました。
これらはどれも、「このお知らせは、誰に、いつ、何のために届くのか」を考えて、初めて気づけることです。
特に「配信日」は、同じ言葉でも人によって思い浮かべる意味が違います。
曖昧さを残したままAIに渡すと、AIはどちらかの意味を「それらしく」選んで作ってしまいます。
仕様のサンプル
- 誰が作る? → 管理者
- 誰に届ける? → 全員、または選んだ人だけ
- いつ届ける? → 選んだ日に届く
- 「配信日」とは? → 実際に届いた日
- 届いた後に変えられる? → タイトルや本文はOK。宛先と配信日は変えられない
仕様が固まったら、いよいよAIに渡します。
まずは仕様を読み込んでもらい、疑問点があれば質問してもらいます。
下記プロンプトのサンプルですが、このような簡単なプロンプトでも、確認をとってくれるようになるので認識の齟齬がかなり減ります。
docs/notice.mdにお知らせ機能の仕様があります。
読み込んでください。まだ実装はしないでください。
質問がきて答えると、また新しい質問をしてくる。
これを何回か繰り返します。
人間と同じようなやりとりですね。
さっき「AIは何も言われなければ、それらしく埋めてしまう」と書きましたが、裏を返せば、「わからなければ聞いて」と頼めば、ちゃんと聞いてくれるんです。
ここまで準備ができて、ようやく実装に入ります。
AIが実装する
実装するのはAIです。
私は、AIに指示を出して進めていきます。
参画したばかりの頃は、AIがどう作ってくるのかがわからなかったので、まず実装の計画を出してもらい、その計画を確認してから進めていました。
AIを使っていく中で、傾向が徐々にわかってきました。
たとえばこのような傾向です。
- 仕様に書かれていない部分を一般的な作り方で埋めてしまう
- 出してくる文章が細かすぎる
傾向がわかると、どこを重点的に見ればいいかもわかります。
今は細かい計画までは見ていません。
実装の流れを短くまとめてもらい、仕様にない部分が紛れていないかを中心に確認しています。
そのうえで、一度全部実装してもらいます。
実装が終わったら、AIのレビューを入れます。
このときレビューを担当するのは、実装の経緯を知らない、まっさらな状態のAIです。
弊社でのAIのレビューは、全部をAIだけで判断するわけではなく、人間の判断が必要なところは質問してくるように仕組み化されています。
では、AIが作業している間、私は何をしているのか。
ただ待っているわけではありません。
ほかのタスクを進めたり、AIに不具合の調査をさせたり、今あるコードでわからない部分を調べてもらったりしています。
ここで、レビューするAIになったつもりで、AIが作ったコードを見てみましょう。
AIになってみよう
AIが作った「お知らせを更新する処理」です。
仕様を確認しながら、このままOKを出していいか考えてみてください。
仕様のサンプル
- 誰が作る? → 管理者
- 誰に届ける? → 全員、または選んだ人だけ
- いつ届ける? → 選んだ日に届く
- 「配信日」とは? → 実際に届いた日
- 届いた後に変えられる? → タイトルや本文はOK。宛先と配信日は変えられない
※実際のプロジェクト内のコードではなく、状況をイメージしてもらうためのGOのサンプルコードです。
// お知らせを更新する処理
func UpdateNotice(id int, input UpdateNoticeInput) (*Notice, error) {
// 更新したいお知らせを探す。見つからなければエラーにする
notice, err := findNotice(id)
if err != nil {
return nil, err
}
// タイトルと本文を、新しい内容に書き換える
notice.Title = input.Title
notice.Body = input.Body
// 新しい宛先が指定されていたら
if len(input.Recipients) > 0 {
// 新しく追加された宛先を調べる
added := diffRecipients(notice.Recipients, input.Recipients)
// 宛先を書き換える
notice.Recipients = input.Recipients
// すでに配信済みなら、追加された宛先にも届ける
if notice.Status == "delivered" && len(added) > 0 {
if err := sendNoticeTo(notice, added); err != nil {
return nil, err
}
}
}
// 変更を保存して、更新したお知らせを返す
if err := saveNotice(notice); err != nil {
return nil, err
}
return notice, nil
}
答えを見る
仕様と見比べたとき、問題は2つあります。
1つ目は、配信が終わったお知らせでも、届ける相手を変えられてしまうこと。
仕様のサンプルには「届いた後は、宛先と配信日は変えられない」とありました。
2つ目は、追加された宛先にお知らせを送る処理が入っていること。
AIは「宛先が増えたなら、新しい人にも届けたほうが親切だ」と判断したのかもしれません。
これは仕様のどこにも書かれていない、AIが自分で埋めた機能です。
このくらいの実装ミスであれば、今はAIのレビューで見つかります。
裏を返せば、自分がこの問題に気づけなくても、実装は先に進んでしまうということです。
自分でAIの成果物を確認する
AIのレビューを通ったら、いよいよ自分の目でのレビューです。
「AIが実装する」で体験してもらったくらいの問題なら、今のAIは自分で見つけて直してしまいます。
人間に質問してくるのは、判断が必要なところだけです。
つまり、細かい判断をしなくても、実装までは終わってしまうのです。
だからこそ、仕様だけでなく、実装方法についても自分から動かないと、何も学べないまま次に進んでしまいます。
さらに、AIが実装する速さと、人間がレビューする速さには大きな差があり、すべてを細かく読むのはとても間に合いません。
そこで意識しているのが、いきなり細かいところを読まないことです。
まずAIに、「この変更はどんな前提で作ったのか」「もともとどんな動きだったものが、どう変わったのか」を聞きます。
全体の大枠をつかんでから、細かい部分を見るようにしています。
こうすることで、どこを重点的に見ればいいかが見えてきます。
チームにレビュー依頼を出す
自分での確認が終わったら、チームにレビューを依頼します。
実装がどんどん進むので、レビュー依頼も出そうと思えばすぐに出せてしまいます。
PRの説明文もAIがまとめてくれますが、細かすぎることが多いので、読みやすく整えてから出しています。
ただ、ここでも問題があります。
実装の量が膨大だと、自分でも把握しきれていない部分が出てくることです。
そこをレビューで質問されると、その場で答えられないこともあります。
最終的には、レビューでOKが出ないとマージできない仕組みなので、判断するのは必ず人間です。
OKが出たらマージされて、このタスクは完了です。
※PR(プルリクエスト):自分の変更内容をまとめて、チームに「確認してください」と依頼する仕組み。
実際にやってみて感じたこと
実際にAI駆動開発をやってみていいことばかりではないというのが素直な感想でした。
「自分でAIの成果物を確認する」や「チームにレビュー依頼を出す」で触れた、学ぶ機会を逃しやすいことや、AIの実装内容を把握しきれないことなどの問題がありました。
これらの原因は次のことによるものではないかと考えました。
冒頭で書いた「自分が何も理解していなくても、仕様どおりに動くものができてしまう」ということです。
これまでは、仕様どおりに動かすまでに、少なくとも1つは自分で方法を考えて実装する必要がありました。
実装に必要な知識を、半ば強制的に学ぶ環境だったのです。
今は、自分なりの実装方法を1つも持たないまま、実装ができてしまいます。
学ぶかどうかが自分次第の、自主学習のような環境になっていると感じます。
もちろん、良い面もあります。
最初から完成品に近いものを見られるので、最適解に近い形を知ることができます。
自分で一から作るよりも、穴の少ないものができているとも感じます。
ただし、それが本当に最適解なのかは、知識がなければ判断できません。
だからこそ、AIが作ったものを「なぜこうなっているのか」と自分から読み解く姿勢が必要だと思います。
まとめ
AI駆動開発を体験して、AIにすべてを任せる開発ではないことを実感しました。
AIは、何を作るかが決まっていれば、自分で考え、人間よりも速く、仕様通りに動くものを作り上げてくれます。
自分が何も理解していなくても、開発は進んでしまいます。
AIが作ったものを判断するには、まず自分が理解していなければなりません。
コードを書く機会が減った今だからこそ、「なぜこうなっているのか」を自分から学ぶ姿勢が、これまで以上に大切になっていると感じます。
AIには何を任せるのか、自分自身は何をしなければならないのかを理解していくことが重要になると考えます。
これからAI駆動開発に触れる方にとって、少しでも参考になればうれしいです。
最後まで読んでいただき、ありがとうございました。
