GitHub Copilotを使いこなしてプログラミングの生産性を上げる大切なコツ
皆さんはGitHub Copilotを使っていますか?VSCodeやIDEに拡張を入れると、生成AIとペアプロのようなことができるという、アレです。
最近はこれがないと仕事ができない。なかった時代を思い出せないという人が増えています。プログラミングの生産性に明確に差が生まれます。僕もその口です。
ただ、GitHub Copilotを使いこなせていないという話も度々聞きます。Copilotが提案してくれるコードが微妙で役に立たないというような感じです。
その差はどこにあるのか?を知りたくて6/24に試しにCopilotを使った動画を撮ってみました。実践的なCopilot実演動画というのはすごく珍しいらしく、GitHub dockyardというコミュニティの竣工イベントに登壇してみないか?というお声がけをいただいたので、8/5にGitHub Copilotを使いこなせるとどうなるのかというライブデモを実演しました。
僕のライブデモ以外にも、GitHub ProjectsやGitHub Actionsなど、GitHub愛があふれんばかりの素敵なイベントでした。
アーカイブ配信が始まったので、この記事ではライブデモについて解説をします。基本的にはGitHub Copilotを使いこなすためには適切に誘導する必要があります。スライドも公開しているのでご覧ください。
少しでも皆さんのCopilot活用の一助になればと思っています。
対象読者はGitHub Copilotを使って効率的にプログラミングをしたい人です。
僕とGitHub Copilot
じつはGitHub Copilotを使い始めたのは今年3月くらいです。GitHub Copilot for Businessが登場したタイミングですね。
最近LLM転職をしたんですが、4/10からシゴラクAI(開発当時はビジネスGAI)というビジネス版ChatGPTのようなモノを開発するためにGitHub Copilotを本格的に使うようになりました。
最初の2ヶ月はひとりで、メインのチャット画面と管理画面を20画面くらい作ってたんですが、この開発を支えたのがGitHub Copilotです。
ライブデモの解説
Copilotのデモという性質上、動画で見た方が良いので、アーカイブ動画を見ながらこの記事を読んでみてください。この記事ではスクショを貼り付けていますが、キャプションに時間を記述しています。(本当はnoteにアニメーション画像とかで動画を貼り付けられるとちょうど良いのですが、サイズ制限がかなり厳しそうでした。なんかいいやり方あったら教えてください!)
アーカイブ配信の9:40くらいからが僕の発表ですが、デモは、20:10くらいからです。いま考えると序盤もうちょっと短くしておけばよかったという反省点…。登壇慣れしてないのです…。
アーカイブ動画
https://github.com/erukiti/t3-demo-github-dockyard-0805 が今回のデモ用に作成したリポジトリです。create-t3-app で作ったもので、一部設定などをいじっています。
ここで使っている T3 Stack (TypeScript, Next.js, Tailwind CSS, Prisma, tRPCなどの技術を組み合わせたもの)はフロントエンド・バックエンドの融合した環境なので、双方にまたがったデモになります。
git clone git@github.com:erukiti/t3-demo-github-dockyard-0805.git
cd t3-demo-github-dockyard-0805
cp .env.example .env
pnpm i
pnpm prisma db push
# dev環境で実行する
pnpm dev
この手順とGitHub Copilotで、皆さんの手元でも試せると思います。ここでは Node.js の npm マネージャとして pnpm を使ってますが、もちろん npm や yarn でも可能です。
1. スキーマをいじる(21:00〜)
元々 create-t3-app が生成するスキーマ定義には Example というモデル(RDBのテーブルに該当するもの)が存在しますが、不要なので消して、ブログに必要なモデルである Post を作成します。
prisma/schema.prisma を開いて model Post { まで入力して少し待つと Post というモデルにふさわしい定義を提案してくれます。
ブログを作るという題材は全世界で散々擦られ続けているネタなので生成しやすいというのはありますが、もともと名前からの提案力は高めです。英語として的を射た名前をつけていれば、その名前から想像しやすい、よくあるモデルを提案してくれます。
今回は、デモ用で published や author などは使わないので、それら三行を削ります。
また、ID を auto increment の数値にされるのは気に食わないので Int 以後を消して String を書くと、デフォルト値は uuid() だよね、という提案をしてくれます。
ここまででモデルの作成が終わりました。
なおスキーマ定義をしたあとは、DBやPrismaライブラリへの反映が必要です。
pnpm prisma migrate dev
スキーマ変更のあとは、VSCodeの場合 TypeScript: Restart TS Server を実行しないとVSCodeの支援に反映されない点にご注意ください。
2. APIを作る(22:45〜)
さて、スキーマ定義が完了して、DBができあがったのでAPIを作ります。
src/server/api/root.ts と src/server/api/routers ディレクトリ以下のファイルが、tRPC APIの定義ファイルです。元々は src/server/routers/example.tsにexampleRouterが定義されていますが、それらをpost向けに書き直してからAPIを作成します。
postRouter にならlistがあるはずだ、という予測のもと、勝手にコードを生成してくれます。1行ごとに生成するので Tab Enter を連打するだけです。
今度は read を定義します。list の定義のあとに空行を入れるとgetというメソッドはどうかと提案してくるんですが、個人的な好みとしてAPIにgetという名前をつけたくないのとCRUD的にするため read: と入力すると、一通り提案をしてくれます。
ただ、初期の提案では id の型が間違っているので z.number() という引数のバリデーションを z.string() に修正する必要があります。(tRPCではzodというバリデーションスキーマ定義のライブラリを使って引数の型やバリデーション情報を定義しています)
引数のバリデーションを変更してからは、ひたすら Tab Enter を押すだけで read が完成します。
postRouter にある read というAPIで id が引数ならば、prisma の findUnique を使って読み込んだデータを返すものだろう、という生成AIによる予測がなされているわけです。生成AIマジすごい。
さて、ここから次の入力を促すためにEnterを押すと、readがあるならcreateもあるはずだという提案をしてくれます。全世界のOSSには散々CRUDが定義されているからでしょうか。
あとはTab Enterをひたすら押す機械になることでcreateの中身についても予測して、生成してくれます。
tRPCでは更新系はqueryではなくmutationなので、書き換えます。
おそらくGitHub Copilotが使っている言語モデルの学習タイミングである2021年9月時点ではtRPCのAPIが今と違ってたのではないかと思います。当時tRPC触ってなかったので詳しいことは知らんけど!
Copilotは、自分が直接学習したものじゃなくても、似たようなモノを散々学習しまくってるので、ここまでやったように、様々なヒントを与えてあげるだけでうまく生成できるようになります。
ここまでの間 postRouter のソースコードには、初期のexampleのコードを残していますが、これはexampleにある構造を真似をしてもらうためでした。これもヒントですね。
GitHub Copilotはコードを真似する力がめちゃくちゃ高いので、ある程度パターンがあるものは、そのパターンの1・2つくらいを例示してあげると、いい感じにコード生成できるようになります。
さて、このあと CRUDの残り update や delete もいい感じに提案してくれて、僕はひたすら Tab Enter を押すだけでコードが生成されました。
3. ホーム画面を作る(26:25〜)
APIができたので、今度はホーム画面を作ります。
初期状態では、何を作ろうとしているかを、GitHub Copilotも絞り込めないため、ただのサンプルコードですよという顔で、最低限の表示だけを生成してくれます。
フロントエンドのコードを生成するときのGitHub Copilotではよくあることなので、ある程度何をしようとしているのか?という方向性を与えてあげる必要があります。
export default function Home() {
const { data } = api.post.list.useQuery()
これくらい書くと、api.post.listなんてのを読み込んでるんだから、どうせそのリストを表示するんやろ?と推測をしてくれて、リストを表示するコードを生成してくれます。dataには配列で入っていることも理解しています。
もちろんこのままでは、何の装飾もなくタイトルだけを一覧表示してくれるだけなのですが、プログラムのたたき台としては十分です。
さて、ここまでで一覧を表示できるようにしましたが、投稿するためのボタンを追加します。このときボタンを Next の Link を使って書こうとすると、生成されたコードではエラーが生じます。
これは最近のNext.jsではLinkの書き方が変わったためです。これもやはりさっきのtRPCの件と同じく学習タイミング以後に変わったことは、そのままでは正しく生成できません。
エラー修正ついでに、TailwindCSSで装飾を与えてみます。
これは今後のコードの伏線です。APIの時もそうでしたが、コードを真似する力がとても高いので、GitHub Copilotは「なるほど…… コレがイイのね 覚えちゃったぞ〜〜」って感じで学習してくれるのです。
4. 投稿ページを作る(30:50〜)
ホーム画面から投稿ページの遷移を作ったので、投稿ページを作ります。
投稿ページを作り始める時点では、ホームを書き始めたとき同様に、コード生成能力はあまり高くありません。
仕方ないので必要になるパーツを書き始めるとアシストが始まります。
パーツとして、投稿するAPIと、画面上で編集するtitle, contentが必要となるので、それを書くと、投稿するためのコードを書き始めてくれます。
ただ、僕もライブデモのときは忘れてたんですが api をインポートしてないために、予測精度があまり高くない状態が続いていました。
JavaScript/TypeScriptでは必要なパーツをimportしているかどうかで、予測精度が圧倒的に変わります。(事前に散々練習してたんだけど、ちゃんとそこらへんをデモに反映できなかった)
まぁ、このhandleSubmitで十分動くので、あとは投稿したあとに、ホーム画面に戻るという処理を追加しておけば、画面は勝手に書いてくれます。
先ほどのCSSの伏線を回収してます。Homeの時とは違い、classNameが最初から定義されています。「どうせ画面のレイアウト同じなんでしょ?装飾してあげたよ」と言わんばかりに。
あとはひたすらTab Enterを押すだけのお仕事です。
画面上で確認すると、タイトルやコンテンツの入力欄がわかりづらいので装飾を与えようとして class と書くだけで勝手に、それっぽい装飾をあててくれます。(補足: TailwindCSSを採用しており className="…." で装飾が当てられます)
ここまでの傾向(か、過去に学習したTailwindCSSのコード)から、薄いグレイの枠線を、少し角丸で当てておけばいいんだろう?って推測してくれています。
CSSを当ててデザインの調整なんかも、誘導すればそこそこやってくれるので、プロトタイピングがめちゃくちゃ捗ります。
時間配分をちょっと間違えて、ここまでで結構時間を食ってしまったので、ここでライブデモは終了です。
感想
改めて記事としてまとめることで、GitHub Copilotの特性について解像度が上がった気がします。
これは確かに、コツが必要だなという感じです。僕は半ば無自覚にやってたんですが、GitHub Copilotをかなり誘導してあげてますね。
GitHub Copilotが使っている言語モデルCodexは学習タイミングが2021年9月なので、それより後に登場したものは直接は学習できていないため、結構ヒントを与えてあげる必要がありますし、そもそも方向性を与えてあげないと何を作ったらいいのかわからないという状態に陥りやすいようです(それはそう)。
そういった問題はありつつも、言語モデルが強力なため
既存のコードの真似をする力がめちゃくちゃ高い
コードのたたき台を都度生成できるので、新規に書くコードのアシスト力も高い
この2点がやはり強みです。
真似する力もスゴいですが、意外と馬鹿にできないのが、たたき台を都度生成できるという側面です。
プロトタイピングをする上で、最小限の動くものを作って、そこにデザインなり機能なりを追加していく、というリーンな進め方の第一歩を力強く踏み出してくれるというのは、とても力強い武器なのです。
是非とも動画やこの記事を見ながら、皆さんもコツを掴んでGitHub Copilotを最大限活用してみてください。強力なアシストが働いた時、とても気持ちよくプログラミングができます。