NTTドコモR&Dの技術ブログです。

「実装は一瞬、レビューは地獄」からの脱却:生成AI時代の開発プロセスを最適化するIssue管理術

はじめに

NTTドコモ データプラットフォーム部(以下DP部)外山です。 DP部では「『あらゆる業務・現場のニーズに応じられる』柔軟なデータ活用環境」を目指し、社内データ活用プラットフォームPochi*1の開発を進めています。

私たちのチームでは、各メンバーがアジャイル開発に則り、約40個のアプリを開発・運用しています。2023年の初期開発時は、エンジニアが自らの手で開発を行っていましたが、生成AIの急速な普及により、直近ではVibe Codingが主流となりつつあります。 この開発方法の変化は価値提供までのリードタイムを大幅に短縮できる反面、これまで人間が行ってきたからこそ暗黙的に調整されていたレビュープロセスに大きく影響を与えています。

そこで、Vibe Codingに何をどこまで実行させるかのカギとなるIssue管理も、生成AIでコントロールすることで、ただ実装が早いだけではなく、それを行う人間に優しい開発プロセスに変えようとしています。本取り組みは、DP部の廣重貴行さんに進めていただいており、以下は、廣重さんに執筆いただいています。

社内データ活用プラットフォームPochiとは
私たちDP部は社内のデータ民主化を目指し、StreamlitとGoogle Cloudで圧倒的に使いやすいデータ活用プラットフォームを開発・推進しています。このプラットフォームは、24年度は30万時間もの業務効率化を実現し、直近では5,000人以上の社員に利用が拡大しています。
ASCII.jp:NTTドコモ、Streamlit利用の“ポチポチ分析アプリ”開発で社内データ活用を促進 (1/3)

はじめまして。DP部の廣重です。Pochiのアプリ開発のチームリーダーの一人として、主に要件整理、設計、開発補助を担当しています。私のチームは生成AIを積極的に活用しVibe Codingを導入していますが、生成AIの提案を受け入れた結果、膨大な差分プルリクエスト(PR)が発生してしまい、コードレビューでは変更点を素早く把握し指摘するということが難しく、指摘の反映が開発フェーズの後半に集中して手戻りが大きくなる課題と直面しました。

Vibe Codingでコードは速く書けるのに、PRは重くなりレビューは遅くなる

この矛盾に立ち向かうべく、Cline*2の力を借りることでIssueを分割し、GitHub Projectsで小さく管理することに取り組んでいます。本記事では、データソースをCSVからデータベースへ移行するという実例を通じて、Issue生成からレビューまでのユースケースをご紹介します。

Vibe Coding導入後、直面した3つの課題

Vibe Codingを導入し、開発スタイルが変化することで私が抱えることになった課題は、大きく分けて下記の3つとなります。

1. 開発速度の向上と品質管理のジレンマ
ClineやGitHub Copilotの活用で、コーディング速度は従来の倍以上に向上しました。しかしその一方で、この「速さ」が新たな問題を引き起こしています。

Vibe Codingを実践すると、実装前の設計フェーズがおざなりになりがちです。あいまいな要件のままコード生成を指示すると、AIが過剰な例外処理や、必要以上に汎用的なコードによってコードベースを肥大化させてしまいます。その結果、1つのプルリクエストが極端に大きくなり、レビュアーは変更点の把握に膨大な時間を費やすことになります。つまり、高速に実装してもレビューが追いつかず、指摘遅れによる手戻りや、レビュー漏れが発生するようになり、最終的な品質が悪くなることがありました。

2. Issue管理の粒度問題
従来の人間ベースの開発では、Issueの粒度が粗くても人間が別途資料を参照するなどして、コンテキストを暗黙的に補うことで問題は生じませんでした。しかし、生成AIは粗い粒度のIssueであっても一気に実装を完了させてしまいます。

そのため、開発途中の細かな進捗や中間成果物を追うことが困難になりました。その結果、問題が発覚した時点ではすでに大量のコードが書かれており、手戻りのコストが従来よりも格段に大きくなってしまうことがありました。

3. Vibe Codingによる開発プロセスの後退
これまで私は開発プロセスの見える化に努めてきました。しかし、皮肉なことに、Vibe Codingの導入がプロセスを逆行させる事態を招いています。

生成AIを使えば高速で動くものが作れるため、「とりあえず実装させてみる」という場当たり的なアプローチが増えてしまいました。その結果、本来不可欠であるはずの事前設計や要件整理が軽視される傾向が強まっています。

特に現在着手しているプロジェクトではユーザーヒアリングを基にアプリのモックを作成しています。 この場合、事前設計・要件整理を見逃してしまうと、長期的なメンテナンス性を全く考慮していないコードが生成されてしまい、結果大規模な改修が必要となっています。

解決策:生成AIによるIssueの生成、管理

これらの課題の根源は、Vibe Codingによる実装の爆発的な高速化に、人間中心の管理プロセスが追いついていない点にあります。特に、実装の最小単位であるIssueの粒度が粗いままでは、生成AIの強力なコード生成能力を適切にコントロールできず、巨大なPRとそれに伴うレビュー地獄、そして大きな手戻りを生み出すだけです。

そこで私は、このアンバランスを解消するため、実装だけでなく、その前段階であるIssueの生成・管理自体にも生成AIを導入することで、開発プロセス全体を生成AI時代に最適化するアプローチを試しています。具体的には、以下の3つのステップで進めています。

  1. 生成AI(Cline)による自動細分化されたIssueの生成
  2. GitHub Projectsによる一元管理
  3. 人間-AI協働レビュープロセス

実際のワークフローは以下の通りで、要件から実装まで一貫した品質管理を行っています。

以降では実際のアプリ開発で発生したケースを例にし、それぞれの工程について、何に注意しているかを説明します。 分析したデータを画面上に表示するようなアプリで、データソースをCSVファイルからデータベースに変更する改修作業をイメージしてください。

①:要件定義・基本設計

Vibe Codingを取り入れた影響で設計フェーズがおざなりになることがあったため、改めて設計フェーズに生成AIを取り入れて、品質の向上を目指しています。 この要件定義・基本設計フェーズでは特にAIフレンドリーな資料を生成することに気を付けています。

最近の生成AIはコンセプトキャンバスなどを画像ファイルから読み取ることも可能ですが、どうしても精度が低くなることがあります。 そのため、一度読み取らせて内容をmarkdownファイル化させ、その後人間の手で加筆修正するなど、最終成果物をmarkdownにする必要があります。

また、生成AIが正しくIssueを作成するために、技術調査資料、テーブル設計、サンプルファイルなどをドキュメントとしてリポジトリに追加しておき、コンテキストとして活用しています。

今回の例は簡単なものなのでテーブル定義書をリポジトリに格納するのみとなっています。

②:生成AIを活用した自動Issue生成

従来は、この改修を「データソースをCSVからデータベースに移行」という1つの巨大なIssueで管理していました。これでは担当者が異なると進捗が見えず、最終的に生まれるPRも数千行に及ぶ巨大なものになっていました。また、内容についても別資料へのリンクなどで済ませることも多くありました。

そこで、要件定義・基本設計が完了したら、この大きな要件をプロンプトに入力し、ClineにIssue分割を依頼します。 生成AIには、リポジトリをコンテキストとして参照させ、機能単位に分割することで、人間よりも簡単に細かくIssueを分割することが可能です。

Issue発行プロンプト例

次の要件を機能単位で細かくIssueに分割してください。

**要件**
CSVファイルからの取得をデータベースからの取得に変更する。
データ構造は互換性を保ち、既存のフィルタ機能も維持する。

**出力形式**
issues.mdファイルとして以下の形式で出力:

# [Issue]
**概要**
[何をするIssueか]

**実装内容**
[具体的な実装項目]

**技術要件**
[使用する技術・ライブラリ・パターン]

**完了条件**
[どのような状態になれば完了か]

**注意点**
[実装時の注意事項]

上記プロンプトに基づき、Clineに出力させたIssue一覧は以下イメージになります。 Clineは単に要件を分解するだけでなく、#の見出しを用いて、Issueごとに概要・実装内容・完了条件などを構造化して出力してくれます。特筆すべきは、人間が見落としがちな「設定・環境対応」や「テスト・動作確認」といった、本質的だが後回しにされがちな非機能要件に関するIssueも網羅的に提案してくれる点です。これにより、開発初期段階で考慮すべき点の抜け漏れを大幅に削減できます。

生成結果イメージ

# イベント実績データ取得クエリの作成
**概要**
CSVファイルの代わりにデータベースからイベント実績データを取得するためのクエリファイルを作成する。

**実装内容**
1. イベント実績データ取得のメインクエリ関数の作成
   - 関数名: `get_event_data()`
   - 戻り値: `pd.DataFrame`(CSVと同じ構造)

2. フィルタ条件対応のクエリ関数の作成
   - 関数名: `get_event_data_filtered()`
   - パラメータ: 開始日、終了日、ステータス、イベント区分、実施日数範囲
   - バインド変数によるSQLインジェクション対策

3. 対象テーブル

**技術要件**
- 既存の`get_event_companies_query.py`と同様の構造に従う
- `query_executor.py`の`get_query_result_bind()`を使用
- エラーハンドリングとログ出力の実装
- パフォーマンス最適化(必要な列のみ取得)

**注意点**
- 大量データの取得時のメモリ使用量に注意
- 開発環境・本番環境のテーブル名切り替え対応

# データローダーのデータベース対応
...
# データ変換・正規化処理の統一
...
# event_performance.pyの修正
...
# 設定・環境対応
...
# テスト・動作確認
...

③:GitHub Projectsへの追加

上記で作成したIssueを人間がレビューし、問題なければGitHub Projectsに追加します。 GitHub Projectsへの追加については効率化のため、GitHub CLI(ghコマンド)を用いています。

今回はIssueに調査も含まれるため、現在は全てのIssueを一旦draftとし、フィールドを設定後、必要に応じてリポジトリのIssueへと変換しています。

ghスクリプト例

# GitHub Host 認証 
gh auth refresh -s project

# アイテム追加
gh project item-create 999 --owner owner --title "イベント実績データ取得クエリの作成" --body "**概要**\nCSVファイルの代わりにデータベースからイベント実績データを取得するためのクエリファイルを作成する。\n...."

# アイテム一覧から上記で追加したアイテムのidを取得する
gh project item-list 999 --owner owner --limit 2000 --format json | jq > items/item-list.json

# プロジェクト一覧からproject-idを取得する
gh project list --owner owner

# フィールド一覧からfield-idを取得する
gh project field-list 999 --owner nttdocomo-com --format json | jq . > data/field-list.json

# フィールド設定、ここでは値XXXXを追加する場合
gh project item-edit --id id --field-id field-id --project-id project-id --single-select-option-id XXXX

ghコマンドにより、作業効率化は図れたものの、困った点としては、以下の3点です。

  1. アイテム追加時にはtitleとbodyしか追加できず、各種フィールド設定には何度もコマンドを叩く必要があること
  2. アイテム一覧取得時にはタイトルによるフィルタ機能などはないため、limit 2000などとして全件取得する必要があること
  3. フィールド設定に必要なidが多く、その特定にもコマンドを何度も叩く必要がある

これらの点については、今回解消できなかったものの、ghからGraphQL APIを叩くとより効率的に行えるようなので、今後試していきたいです。

④:レビュー

生成したIssueについて開発者と共に再度レビューを行います。 レビュー時には下記について特に注意します。

設計・実装方針が現実的か?

生成AIがある程度の実装方針を立てていますが、必要以上に複雑な方針となっている場合があるため、 現状はアプリの内部をよく知っている開発者とともに、方針をレビューする場合もあります。

UI/UXが考えられているか?

生成AIが出した実装方針はUI/UX、特にUXが不十分となることがあります。これはどうアプリをユーザーに使ってもらうかを落としこむ要件整理段階での検討不足による部分が大きいです。 具体的には、ワイヤーフレームを使った画面設計がユーザーとは認識があっていても、開発観点で考慮すべきことが不足している場合に発生しがちです。 ワイヤーフレームはユーザーとの認識合わせを加速させるよい手段ではあるものの、それを画面設計として生成AIに取り込む上でどうあるべきかは今後検討していきたいと考えています。

導入による効果

GitHub ProjectsとClineを連携したIssue管理の効率化により、以下の具体的な成果を得ることができました。

1. 要件定義・基本設計の品質向上

これまでよりIssueの粒度が細かくなり、記述もリポジトリの内容を踏まえながら、詳細化されたことで、開発者が要件定義や基本設計をレビューし、コメント・質問をすることが容易になりました。これにより、仕様不備を実装前に発見できるようになりました。

例えば、今回の事例では、AIが生成したIssue「データローダーのデータベース対応」をチームでレビューした際、@st.cache_dataデコレータの適切な設定という考慮漏れを開発者が発見しました。このデコレータは初期開発時に生成AIが設定したもので、チーム内ではその存在が意識されていませんでした。従来の巨大なIssue管理では、実装終盤まで見落とされた可能性が高い観点であり、これを早期に発見しタスクを追加できたことで、手戻りを未然に防ぐことができました。

2. プルリクエストのレビュー品質向上

Issue作成時点でレビュアーが修正予定箇所のコードを一度確認済みであること、 従来の大きなPR→レビューから、1つのIssue単位の小さなものにPRが細分化されていることから、1つのPRに対するレビュー時間も半分ほどに短縮され、レビュアーが変更内容を常に把握できるようになりました。

3. 開発者の負担軽減

Issueが詳しくなったことにより、実装の方向性に迷うことが減少し、開発者の負担軽減に繋がりました。

今後の課題

今回の⽣成AIによるIssue管理の補助を取り入れることで、開発者の負担を減らしながら、開発品質の向上とその後のプルリクエストへのレビュー工数が短縮されました。一方で、以下2つの課題が残っている現状です。

1. Issue間の優先度、依存関係管理

生成されたIssueは実装方針についての記載に終始してしまっている場合があり、その状況でIssueが細分化されると、優先度や依存関係に混乱する場面もありました。 当初、プロンプトで依存関係の定義も試みましたが、作業時間が増えるばかりで開発効率への寄与が少なかったため、現状はIssueの洗い出しはAIに任せ、依存関係の整理と優先順位付けはスプリントプランニングで人間が議論するというハイブリッドな形に落ち着いています。Issue生成の元となった背景情報を人間が補足することは依然として必要な状況になっています。

2. IssueドリブンなAIコーディングに向けた資料整備

GitHub Copilot、Coding AgentなどIssueから開発・レビュー・Pushまでを生成AIが自律的に行える機能が各社から出てきていますが、現状、業務上安心して利用できる品質に至れていないこともあり、活用できていません。これは設計や必要な業務知識などのコンテキスト情報がAIフレンドリーな形式でリポジトリに含まれていないことが原因と考えています。これらの情報を含めることが出来れば、開発プロセスの起点となるIssueの生成についても、より精度高く行えるため、今後検討していきたいと考えています。

現在は、開発者向けのIssueであるため大きな問題となりませんが、将来的には説明の対象がAI自身にシフトすることを見据えると、これらの課題解決がアプリ開発プロセス全体をAIに委ねていく鍵となるため、継続検討していきたいと思います。

最後までお読みいただき、ありがとうございました。

*1:Pochiは社内の開発コードネームです

*2:Visual Studio Code向けの開発支援エージェント拡張で、LLMを用いたIssue分割・計画・コード編集で利用しています