shoota works

GitHub Copilotはシニアエンジニアの夢を見るか

Photo by Alessio Ferretti

はじめに

この記事は ファインディ株式会社 Advent Calendar 2024の 12月5日の記事です。


GitHub Copilotの導入時の恩恵

Findyでは全エンジニアにGitHub Copilotを導入しています。私もVSCodeで連携し、主にコードサジェストやCopilot Chatを利用していました。
しかし導入したときはコードサジェストされるものが想定しているコードとかなり異なっており、VSCodeが推論するコードサジェストを打ち消してしまうなど、むしろ邪魔になっているような印象でした。

Findyのテックブログでもこれに似た状況の話が、GitHub Copilotの効果は本物?論文から読み解く開発生産性の真実 にかかれています。

一方、シニア開発者に対する影響は比較的小さいものでした。これには次のような要因が考えられます。
すでに確立された作業スタイルがある

ジュニア層にとっては構文の学習やコードサジェストが効率よくはたらく一方で、シニア層は確立された作業手順、いわゆる「手癖で書いている」という状態にインタラプトしてくることで全体効果が小さくなっているようでした。

ジュニア層だったころの作業方法と照らしてみる

シニアとなった今ではCopilotの恩恵が少ないという自分自身の感覚と一致する一方で、それはどういう作用順序で働くものだろうかと考察してみます。かつてジュニアだった自分はどうやってコードを書いていたのか、ということです。色々と自分なりにやってきたことを思い出すなかで、あっと気付くものがありました。コードに仕様書をコピペする ということをやっていたのを思い出したのです。


仕様書をコピペする、コメント駆動開発

かつて私がジュニア層だったころは、「詳細設計書」がプロジェクトの上流工程として良く書かれていました。実装対象の処理手順を記載する文書で、たとえば「商品の税込み価格を計算する」という実装の詳細設計書は以下のようなものです。

  1. 商品コードをキーに商品マスタと価格テーブルから商品価格と税区分を取得する
  2. 税区分で分岐
    2.1 税区分が「内税」の場合、商品価格を税込額とする
    2.2 税区分が「外税」の場合、商品価格を税額計算処理に渡し、税込額を取得する
  3. 税込み額を返却する

このような処理は以下のようなものになるでしょう。

public int getAmountWithTax( int productCode ) {
  int amount;
  Product product = retrieveProduct(productCode);
 
  if(product.taxType === INCLUDED_TAX) {
    amount = product.price;
  } else {
    amount = product.price + calculateTax(product.price)
  }
 
  return amount;
}

このようなコードを書くまでに、私は仕様書をコメントでコピペするということをよくやっていました。
ジュニアの私が最初に書くコードは以下のようなものです。

public int get税込み( int productCode ) {
  // 商品コードをキーに商品マスタと価格テーブルから商品価格と税区分を取得する
 
  // 税区分で分岐
  if( true ) {
    // 税区分が「内税」の場合、商品価格を税込額とする
  } else {
    // 税区分が「外税」の場合、商品価格を税額計算処理に渡し、税込額を取得する
  }
 
  // 税込み額返却する
  return 999;
}

もちろん、コードを書き終えた後はコメントはすべて消していました。
一見では面倒なように見えますが、考えることを小さく分割して何を書くかを整理するスケルトンコードとして使うことで劇的にコードを早くかけるようになったことを覚えています。私の脳内の原点はこのスケルトンコードにあるように思います。これを私は 「コメント駆動開発」 と勝手に名付けてやっていました。

キャリアを重ねるに連れてこれらのコメントは脳内で補間できるようになり、エディタに書かなくなっていきましたが、やはり考えるときの脳内はこのような手順を追っており、処理の分割と構造化から実装を進めています。


コメント駆動開発 現代版

ここでひとつの気づきがあります。
「実装したい内容を自然言語で書く」→「その内容をコードに落とし込む」という開発プロセスは、まさに生成AI活用の開発事例の代表格だということです。つまり私がジュニアのときにやっていたコメント駆動開発は、Copilot活用の手段とまったく一緒の手順を踏んでいたのです。ジュニア層の学習に有用であるというのは、おそらくこの「自然言語とコードの繋がり方をイメージするトレーニング」を効率的に行えるからではないかと思います。

同時に、シニアとなったいまではこの一度通過した手順を再度踏んでいるような、自分が考えている速度の後ろから提案をもらう感覚があり、邪魔なものという感覚が拭えなかったのだろうと思います。


どう活用していけばよいか

では生成AIを活用したコード生成はジュニアのためなのか、というとそれも違います。

先ほどの「邪魔な感覚」はGitHub Copilotがリリースされた初期の状態で、現在はさまざまなチューニングも可能となりました。
なかでも自然言語ベースでコーディングスタイルやコンテキストを伝えることができるカスタムインストラクション は、プロジェクトごとに期待する記法の型を理解させることができ、コードサジェストなどの精度を高めることができます。他にも、まだPreviewではありますが、複数のファイルに対して直接コードを変更させるCopilot Editsも利用可能になっています。

いずれも「こういう感じで書くのを平準化したい」といったような、シニアが書くコードのトレースに近いことをCopilotに学習・実行させることで、

  1. Copilotを通してシニアエンジニアの書き方をトレースして学習できる
  2. Linterや型などでは検査しきれない記法の揺れ、書き方をCopilotによって修正できる
  3. 結果的にシニアにとってもレビュー負荷が減り、リファクタリングが楽になる

といった効果を期待できると思います。

またCopilotのコードサジェストを色々と試行錯誤してみると、TypeScriptの型付けをかなり重視してコードサジェストをしているようでした。
通常の型推論でもある程度の精度がでますが、明示的に型を書くことで劇的にコードサジェストがうまくなっています。型をより詳細に書くことで特にテストの精度が高くなる傾向にあり、この辺はさらに追求してチーム全体の生産性を高めることも期待できそうです。


まとめ

  • コメントをコードに書いて脳内整理するのは結構おすすめ
  • そこにAIが乗っかればパワーアップ
  • 生成AIのチューニングがより高度に発達していくと本当の意味での「集合知」を形成できるかもしれない

ジュニアとシニアをつなぐ育成の話

今年の夏にフロントエンドリードとしてジュニア育成をしており、12/19にその振り返りイベントをやります。
イベントではCopilotの話はしませんが、育成に悩む方々の参考になれるようにがんばりますので是非、こちらもご参加ください!

挑戦するエンジニアを育てる!育成プロジェクトから振り返る、教える側・教わる側の心得
挑戦するエンジニアを育てる!育成プロジェクトから振り返る、教える側・教わる側の心得