現場では、ちょっとしたコード生成や質問を GitHub Copilot Chat に投げてやってもらっています。
当記事では私がWebアプリのバックエンド(Java, SpringBoot, MyBatis)をやっていたときにサクッと投げたプロンプトをいくつか紹介します。
※当記事ではGitHub Copilot Chatを単純にCopilotと呼ぶことにします。
DtoへのLombok適用その1
Lombokが使われておらず全フィールドがpublicになっていたDtoがあったため、修正をお願いしました。
クラスに「@Data」を付与し、各フィールドをprivateに変えてください!
まぁこれくらいなら自分で修正したほうが速かったかも?
DtoへのLombok適用その2
Lombok修正と同時に @Serial 付与もお願いしました。
- クラスに「@Data」を付与
- 各フィールドをprivateに変更
- シリアルバージョンUIDには「@Serial」を付与
上記3点をお願いできますか?
上記のプロンプトは、送信したらマークダウンと見なされて箇条書きの表示に変わりました。(プロンプト入力中は単なる半角のスペースとハイフンでした)
コンパイルエラーの自動修正
コンパイルエラーを直す作業をお願いします。
createMessage() メソッドまでは私のほうで直したので、参考になると思います。
privateな変数への代入は、setterを使うとよいです。
resources.getMessage は、埋め込むパラメータは配列にして、第3引数は Locale.getDefault() を使うとよいです。
似たようなメソッドが20個くらいあるクラスで、全てのメソッドがほぼ同じエラーを起こしている状況でした。
直し方が同じということで、はじめの5個だけ私が直し、残りはCopilotに丸投げしました。
方針を示したのが良かったようで、問題なくエラーは解消されました。
MyBatisのidの正確な穴埋め
hogeMapper.xml を見てください。xxxxxが20個あると思います。
hogeMapper.java のメソッド名に沿って、xxxxxの部分を修正していただけますか?
触っていいのはxxxxxのところだけです。ほかは一切変更しないでくださいね。
これはMyBatisの話ですね。
xmlとjavaをうまく紐付ける必要があるわけですが、紐付けるためのidをいちいち記述するのが面倒だったため、私は id="xxxxx" とだけ書いておき、記述はCopilotに任せました。空欄の穴埋めを任せたイメージです。
MyBatisのSQLの文字置換
例えば58行目を見ると、SQL文中に不等号が使われています。
このような不等号は、xmlファイルにおいて「書きかけのタグ」と見なされて、エラーの温床となります。
「<」のようなエンティティ参照に置換していただけますか?
ありがとうございます。同様に「>」への置換もお願いします。
こういう地味に面倒な置換もCopilotにお任せ。
メソッドの仕様チェック
これはコード修正の依頼ではなく、質問を投げたときのプロンプトです。
calcDiffDays() というメソッドがありますが、
fromが 2000年12月1日22時30分00秒
toが 2000年12月1日22時29分00秒
のとき、どうなりますか?
メソッド名から「日付の差を返すこと」が想像できます。
では日付が同じだったらどうなるのか、質問してみたときのプロンプトです。
整数除算をしているため、0を返します。 といった回答が返ってきました。(実際そうやっているので正解でした)
安全性チェックその1
このコントローラークラスの処理で、DBの値を参照する場面がきっとあると思います。
DB更新時のロック処理のタイミングや、エラー時の正しいロールバック処理が実行されるかどうかは、大丈夫そうでしょうか?
このコントローラーの処理範囲では、DB更新はしておらず、明示的なロック取得もしていないので、ここ自身が「更新ロックの取り方」や「更新失敗時のロールバック漏れ」を起こす作りにはなっていません。 といった回答が返ってきました。
安全性チェックその2
このコントローラークラスの処理において、SQLインジェクションやクロスサイトスクリプティングは大丈夫そうでしょうか?
このコントローラー単体を見る限り、SQLインジェクションは概ね問題なさそうです。一方でXSSは「このクラス内で即アウト」ではないものの、返したデータの使われ方次第でstored XSSになり得ます。 といった回答が返ってきました。
人間が調査する前のヒントになりますね。
参照箇所チェック
必要なタイミングで権限チェックをするために、インターセプターによる割り込み処理を挟む設計は、ウェブアプリでは定番だと思います。
DBにある権限情報をインターセプターが毎回参照していたらレスポンス的に無駄なわけですが、そのようなことをしていないかどうか、Copilotに質問してみました。
このインターセプターで操作権限チェックをする際に、DBの USER_ROLE というテーブルを見に行くことはありますか?
あります(ただし間接的です)。
このインターセプター自体はDBを直接参照せず、roleService.getRole() でキャッシュを見ています。
そのキャッシュ元は RoleMapper#selectRole() で、RoleMapper.xml のSQLは USER_ROLE を SELECT しています。
つまり、権限チェック時の通常リクエストはキャッシュ参照のみですが、キャッシュ初期化時には USER_ROLE を読みに行きます。
…といった回答が返ってきました。権限はちゃんとキャッシュで保持されていました。
Copilotは処理の流れを追いたいときにも役立ちますね。
以上です。
当記事で紹介した程度のちょっとしたコード生成依頼や質問なら、Copilotはそつなくこなしてくれました。
いずれも作業時間の短縮になり、手作業よりも効率化できたと感じています。
もっと活用していきたいですね。