📛

Devinくんと一緒に成長したい話

に公開

はじめに

こんにちは、Medii の中島です。

弊社でも2ヶ月ほど前に AI エンジニア「Devin」を導入しました。
以来、主にお試しとして、またプロジェクト全体を見る能力があるか試す意味も含めて、これまであまり手が回っていなかった godoc コメントの整備(※)を Devin に任せてみることにしました。

その過程で見えてきた、うまくいったこと・いかなかったことについて共有させていただきます!

※ 正確には swag アノテーションの整備ですが、本記事では便宜上「godoc 整備」と記載します。
※ 「そもそもDevinとは…?」という状態の場合は他の方がまとめてくださっている記事を参考にしていただければと思います

↓参考までに紹介させていただきます!
Devinの使い方 - AIエンジニアがソフトウェア開発を自律的に行う
Devinを使ってみて1週間経ったので所感とTipsをまとめました

godoc 整備における Devin の活用を振り返る

さて、ここからは実際に Devin に godoc 整備を任せてみて、どんな風に進んだのか、うまくいったこと、そして「まだここは人間がやった方がいいかな…?」となった点について、具体的に共有させていただければと思います。

Devin への依頼内容と、その前提

今回 Devin にお願いしたのは、Go のコードコメント内に書かれている swag アノテーション を整えてもらう作業です。これは swag というツールで Swagger (OpenAPI) ドキュメントを生成するためのもので、一般的な godoc コメントとは少し毛色が違う点、ご留意いただけると幸いです…!

具体的には、主にこんな修正をお願いしました。

  • API のエンドポイント指定 (@Router など) が間違っている箇所の修正
  • セキュリティに関する定義 (@Security タグ) の追加
  • パラメータ定義 (@Param など) の修正や追記

どうやって確認したか

Devin が直してくれたコメントが、ちゃんと意図通りに API ドキュメントへ反映されているかは、swag コマンドで Swagger 仕様ファイルを生成し、それを swagger-ui で表示してチェックしました。

依頼するときのちょっとした工夫

Devin に作業をお願いする上で、少し工夫した点があります。それは、一度に「ここからここまで全部お願い!」と広範囲を指示するのではなく、「まずはこのディレクトリだけ」「このくらいの作業量(ACUを目安に)で」といった具合に、タスクを意図的に小さく分割してみたことです。こうすることで、指示がより正確に伝わって、手戻りが少なくなるかな、と考えました。

Devin が期待に応えてくれた!うまくいった事例

Devin にお願いした godoc 整備、実際に「お、これは助かる!」と感じた場面も多くありました。いくつかご紹介しますね。

1. 構造化されたアノテーションを一気に追記!

まず、既存のコードに対して、構造が決まっている swag アノテーションを効率的に追加してくれたのは、とても助かりました。特に、複数のAPIコントローラーに対して、同じようなパターンでアノテーションを追加していく作業では、人間がやるよりも一貫性を保ちながら、スピーディーに処理してくれました。

// --- 修正前(アノテーションなし)---
// GetUser godoc
// Handler for getting user information.
func (h *UserHandler) GetUser(c *gin.Context) {
    // ... implementation ...
}

// --- 修正後(Devinによる追加)---
// GetUser godoc
// @Summary ユーザー情報取得API
// @Description 指定されたIDのユーザー情報を取得します。
// @Tags users
// @Accept json
// @Produce json
// @Param user_id path string true "ユーザーID" example("usr_12345")
// @Success 200 {object} dto.UserResponse "成功時レスポンス"
// @Failure 400 {object} dto.ErrorResponse "リクエストエラー"
// @Failure 404 {object} dto.ErrorResponse "ユーザーが見つからない"
// @Failure 500 {object} dto.ErrorResponse "サーバーエラー"
// @Security BearerAuth
// @Router /api/v1/users/{user_id} [get]
func (h *UserHandler) GetUser(c *gin.Context) {
    // ... implementation ...
}

(※ dto.UserResponse, dto.ErrorResponse は架空のレスポンス型です)

こうした追加作業を、数十のAPIエンドポイントに対して短時間で完了させてくれたおかげで、開発者(私)の工数をかなり削減できたと感じています。

2. 既存コメントから「こういうことかな?」と意図を汲み取り

Devin は、元々書かれていた簡単な godoc コメントから、API の目的や動きを結構正確に推測して、適切な @Summary@Description を生成してくれました。コードの中身と既存コメントを組み合わせて文脈を理解する能力が高いようで、まるで人間が書いたかのような、自然な説明文を作ってくれることもありました。

// --- 修正前 ---
// ListItems - 商品一覧を取得する
func (h *ItemHandler) ListItems(c *gin.Context) {
    // ... implementation ...
}

// --- 修正後 ---
// ListItems - 商品一覧を取得する
// @Summary 商品一覧取得API
// @Description 条件に合致する商品の一覧を取得します。ページネーションとフィルタリングに対応しています。
// @Tags items
// @Accept json
// @Produce json
// @Param page query int false "ページ番号" minimum(1) default(1) example(1)
// @Param limit query int false "1ページあたりの件数" minimum(1) maximum(100) default(20) example(20)
// @Param category query string false "カテゴリー名(カンマ区切りで複数指定可)" example("electronics,books")
// @Param status query string false "商品ステータス (e.g., 'active', 'sold_out')" example("active")
// @Success 200 {object} dto.ItemListResponse "成功時レスポンス"
// @Failure 400 {object} dto.ErrorResponse "リクエストエラー"
// @Failure 500 {object} dto.ErrorResponse "サーバーエラー"
// @Security BearerAuth
// @Router /api/v1/items [get]
func (h *ItemHandler) ListItems(c *gin.Context) {
    // ... implementation ...
}

(※ dto.ItemListResponse, dto.ErrorResponse は架空のレスポンス型です)

実装コードからパラメータの最小値・最大値、デフォルト値なんかもちゃんと推測して追記してくれたので、API を利用する側にとっても分かりやすい情報が増えたのは良かったです。

3. バラバラだったエラーレスポンス定義を統一

プロジェクト全体で、エラーレスポンスの書き方が統一されていなかった箇所があったのですが、Devin はそういった部分を見つけて、一貫した形式に修正してくれました。特に @Failure アノテーションで、適切なステータスコードとレスポンスの型をきれいに揃えてくれたのは助かりました。

// --- 修正前(不統一なエラー定義)---
// @Failure 400 {string} string "Bad Request - Invalid parameter"
// @Failure 404 {object} map[string]interface{} "Resource not found"
// @Failure 500

// --- 修正後(統一されたエラー定義)---
// @Failure 400 {object} dto.ErrorResponse "リクエストエラー(パラメータ不正など)"
// @Failure 404 {object} dto.ErrorResponse "リソースが見つからない"
// @Failure 500 {object} dto.ErrorResponse "サーバー内部エラー"

(※ dto.ErrorResponse は架空のレスポンス型です)

おかげで、生成される Swagger ドキュメントが見やすくなり、API を使う側の理解も助けられたと思います。

4. 長いコメントも読みやすく整形

コメントが長文になったり、パラメータの説明が複雑になったりする場合でも、Devin は適切に改行やインデントを調整して、読みやすい形に整えてくれました。特に複数行にわたる説明を書く際に、人間がやるような気配りを見せてくれたのは印象的でした。

// --- 修正前(一行に詰め込まれた説明)---
// @Description ユーザーの注文を作成します。在庫状況を確認し、利用可能な場合は決済処理に進みます。注文確定後はユーザーと管理者へ通知メールが送信されます。

// --- 修正後(読みやすく整形された説明)---
// @Description ユーザーの注文を作成します。
// @Description 在庫状況を確認し、利用可能な場合は決済処理に進みます。
// @Description 注文確定後はユーザーと管理者へ通知メールが送信されます。

こうした整形のおかげで、コード自体の可読性やメンテナンス性も向上したと感じています。

これらの成功事例を見ると、Devin のおかげで API ドキュメントの質が上がり、特に API を利用する開発者とのコミュニケーションがスムーズになった面は大きいです。人間だとつい見落としがちな細部まで、網羅性と一貫性を持って丁寧に対応してくれた点は、大きな成果だったと言えそうです。

一方で、「もう一歩!」と感じた、うまくいかなかった事例

もちろん、良いことばかりではありませんでした。Devin が godoc 整備で少し苦戦していた点、つまり「うまくいかなかった」と感じた部分についても、正直にお話しします。

1. コード全体の繋がりを掴むのは、まだ難しい?

Devin は多くの場合、コード全体の関連性まで完全に把握するのは難しいようでした。特に、大規模なプロジェクトになってくると、@Router で指定するパスが、他の部分と整合性が取れているか、という点に苦戦している様子が見られました。例えば、同じリソースに対する操作なのに、微妙に違うパス構造(単数形と複数形など)を提案してくることがあり、結局、手作業で修正する必要がありました。

// Devinが提案した記述例(単数形)
// @Router /api/v1/order/{order_id} [get]

// プロジェクト全体で見ると、こちらが正しい(複数形)
// @Router /api/v1/orders/{order_id} [get]

2. セキュリティ設定、ちょっと多かったり足りなかったり…

API ごとのセキュリティ要件を完全に理解するのも、まだ少し難しいようです。@Security タグを追加する際に、本来は認証が不要な公開APIに付けてしまったり、逆に認証必須なAPIに追加し忘れたり、といったことがありました。特に、API によって要求される権限レベル(例:一般ユーザー向け、管理者向け)が違う場合など、一貫性を保つのが難しかったようです。

// 本来不要な公開APIにセキュリティ定義を追加してしまう例
// @Security BearerAuth

// あるいは、認証が必要な箇所に追加し忘れる例
// (Securityタグがない状態)

これは、プロジェクト固有の認証・認可ルールなど、コードを見ただけでは判断できない情報が必要だったためかもしれません。

3. パラメータの「型」、特にカスタム型は苦手?

パラメータやレスポンスの型を定義する @Param@Success タグで、正しい型を指定するのが難しい場面もありました。特に、プロジェクト独自のカスタム型を使っている場合、Go の型と Swagger の型定義をうまく対応付けられないことがあったようです。基本的な型(string, int など)は問題ないことが多いのですが…

// Devinが提案した記述例(基本的な型になってしまう)
// @Param item_id path string true "商品ID"

// 正しくは、プロジェクト固有のカスタム型を指定する必要がある
// @Param item_id path mytypes.ItemID true "商品ID"

(※ mytypes.ItemID は架空のカスタム型です)

こうした不正確な記述は、生成される Swagger ドキュメントの仕様にも影響してしまうため、API を利用する開発者を混乱させてしまう可能性がありました。

これらの課題に対しては、より具体的に「こういうルールでお願いね」とガイドラインを示したり、一度に任せる作業範囲を小さくしたりすることで、少しずつ改善は見られました。

godoc 整備で Devin を使ってみて感じたメリット・デメリット

ここまで godoc 整備での具体的な事例を見てきましたが、改めて Devin を活用するメリットと、考慮すべきデメリットを整理してみたいと思います。

メリット:Devin がもたらしてくれた良いこと

  1. 効率化と生産性アップは確か!
    数十のAPIに対して、決まった形式のアノテーションを短時間で追加してくれたのは、やはり大きなメリットでした。人間が手作業でやっていたら、もっと時間がかかっていたはずです。特に、単調で繰り返しの多い作業における Devin のスピードと集中力は、人間以上かもしれません。

  2. チームの知識共有にも一役買う
    Devin が生成してくれた詳細なコメントは、結果的にチーム内での知識共有ツールとしても機能しました。新しくプロジェクトに参加したメンバーにとって、整った API ドキュメントはコードを理解する上で良い学習リソースになったのでは?と思います。

  3. 文脈を読み取る能力もなかなか
    既存のコメントやコードから、API の目的や動きを推測し、自然な説明文を生成してくれたのは驚きでした。特に、パラメータの制約(最小値、最大値、デフォルト値など)を実装から読み取ってくれたあたりは、人間のエンジニアに近いレベルの理解力を持っていると感じました。

デメリット:まだ課題と感じる点、注意点

  1. 100% 正確とは限らない、レビューは必須
    とはいえやはり、プロジェクト全体の文脈を完全に理解するのはまだ難しいようで、API のパス指定 (@Router) やセキュリティ要件の解釈で間違いが見られました。そのため、Devin が生成したコードは、必ず人間がレビューしてチェックする必要がありました。

  2. プロジェクト固有のルールへの対応はこれから?
    そのプロジェクト特有の命名規則や、カスタム型の扱いなど、細かなローカルルールへの適応は、まだ完璧ではありませんでした。Devin にプロジェクト固有の慣習を覚えてもらうには、より丁寧な指示や継続的なフィードバックが必要になりそうです。(※ 今回の例ではカスタム型 (mytypes) の扱いが課題として挙がりました)

  3. コストと、使い方(リソース管理)の工夫
    Devin の利用には ACU という作業単位でコストがかかります。大規模なプロジェクトで広範囲に活用しようとすると、コスト管理も意識する必要があります。また、一度に大きなタスクを任せると精度が落ちる傾向があるため、タスクを小さく分割する工夫が求められますが、これは管理の手間が増えることにも繋がります。

  4. 結局は「使う人」次第? スキルも必要
    Devin を効果的に使うには、月並みになってしまいますがやはり「何をどう指示するか」を考えられる人間が必要です。Devin は完全に自律して何でもやってくれるエンジニアというよりは、熟練したエンジニアの作業を強力にサポートしてくれるアシスタント、という位置づけが現状では近いかもしれません。新人のジュニアエンジニア(優秀)という表現はとてもピッタリだと思います。
    どういう指示を出せば期待通りに動いてくれるか、そのノウハウ自体がある種のスキルになると感じました。

今後の展望

PdM 職への展開、スクラムチームへの参加

最近の話になりますが、弊社では PdM (プロダクトマネージャー) 職のメンバーも Devin が利用可能になりました。

スクラムチームの一員としてDevinくんが作業できるように
バックログにあった「やらないといけなくて、やればすぐ直せそうな気がするけど、優先順位が下の方にされてしまっていてできていなかった修正」というようなチケットについて
Deivnができそうかどうかを判断したのち、個別に積んでいくDevinバックログができました。
ちなみに現在早速10個以上のタスクが積まれています。がんばれDevinくん
もちろん実装後最終的なチェックはエンジニアが行う想定ですが、修正着手(チケット作成)から完了までのリードタイムが大幅に短縮できるのでは、と期待しています。

↓我が子のように(?)可愛がられています

うまく付き合っていくためのバランス

これらのメリット・デメリットを踏まえると、Devin と最も効果的に協業する方法は、「人間と AI の得意なことを組み合わせる」ことにあると思います。具体的には、

  1. 作業範囲を絞り、明確なタスクを Devin に:曖昧さを減らし、精度を高めます。
  2. 生成物は人間がレビュー&修正:品質を担保し、間違いを修正します。
  3. フィードバックで Devin を育てる:間違いを教え、次回以降の精度向上につなげます。

このサイクルを回していくことで、Devin にプロジェクト固有の知識を少しずつ学習させながら、人間の負担を徐々に減らしていく、という進め方が現状では現実的かもしれません。
でもすごい勢いで賢くなっているので、
同じようなものを頼むにしても消費するACUsもどんどん減らせていて(=作業スピードが上がっているはず)
日々成長を感じます。本当にこれからが楽しみです。

ちなみにDevinくんはリファラルもできます
こちらのリンクから Devin に登録いただくと、紹介者・被紹介者それぞれに 100ACUs が付与されますので、導入を検討されている方はこちら是非お試しください…!


Discussion