🧠

ChatGPT・GitHubCopilotを使用したAI時代のアプリケーション開発

2023/05/21に公開

初めに

ChatGPTの登場によって、ここ数カ月、生成系AIが非常に盛り上がっていますね。
連日新しいサービスやプラグインが生まれているイメージです。

さて、エンジニア界隈では、このChatGPTにプログラムを自動生成してもらい、ノーコードツールのように使用するようなユースケースが度々見受けられます。(日本語で書いた文章から自動でアプリケーションを構築するサービスなんかも出来てましたね)

今回は、そんなChatGPTとGitHubCopilot(以降Copilotと表記します)を使用してアプリケーション開発をしてみたので、その感想や上記ツールを使用するコツを書いていこうと思います。

アプリケーションアーキテクチャ

今回開発したアプリケーションのアーキテクチャは以下の構成になっています。(本記事に直接は関係ないので、読み飛ばしてもらって問題ないです)

バックエンド

  • AWS Chalice
    • AWSが開発したAWS Lambda専用のフレームワークです。
    • CDK構築もサポートされており、AWS Lambdaだけに限らず、APIGatewayやDynamoDBもChalice上で定義したものがデプロイされています。
    • https://aws.github.io/chalice/

フロントエンド

その他

  • WebSocket通信
    • 今回はクライアント間でのリアルタイム通信が必要なアプリケーションを開発したため、単純なHTTP通信ではなく、サーバープッシュ技術のWebSocket通信を使用しています。
    • 細かいインフラ構築はChalice側で自動構成してくれるので、あまり意識してないです。

ChatGPTの使いどころ

正直なところ、今回ChatGPTはほとんど使っていません。。。後述するCopilotで大抵のことが出来てしまうので、逆説的にCopilotでは出来ない事をChatGPTにカバーしてもらいます。数は少ないながらも、効果は絶大なので、その例を紹介したいと思います。

コードのリファクタリング

一番役に立ったポイントはこれですね。
Copilot(+ちょっと自分)が実装をしていく中で、どうしても無駄な分岐やパフォーマンス的に懐疑的な処理があった時に、ChatGPTに聞くと効果的です(デグレってないことの確認はちゃんとしましょう!)。Copilotには機能を指定してその実装をしてもらうことは可能ですが、対話的に要求を通すことは出来ないので、そこはChatGPTの方が便利です。
以下は実際にChatGPTにリファクタリングを依頼した一例です。

設計レベルでの質問

実装自体の補助ツールとしてではなく、設計の補助ツールとして使用する場合も、ChatGPTは効果的です。
今回は、WebSocket通信を使用していて、そのライフサイクル管理に困っていたのですが、ChatGPTに解決してもらいました。(解答が長いので省略していますが、イベントリスナの登録はuseEffectでやろうねってことらしいです)

GitHubCopilot凄すぎる

さて、ここからはCopilotの紹介をしていきます。
Copilot自体の登場は2021年ですので、ChatGPTと比較すると古いサービス(一般利用可能になったのは2022年6月です)ですが、こちらも非常に強力です。今回はVSCodeとCopilotを連携して使用しましたが、実装の8割程度はCopilotに書いてもらっています。

ChatGPTとの大きな違いは、自分が実装したコードを「ほぼ全て」インプットにして次のコードをレコメンドしてくれるので、私が設計した構造を理解してコード補完してくれます。一方でChatGPTの場合、前提情報を自分で入力しなければならないため、入力する内容の整理や文字数制限が厄介です。

Copilotを活用するコツ

Copilotのユースケース・・・と言っても当然「コード補完」なので、私が今回感じたCopilotを活用する上で意識したほうが良いコツを紹介していきたいと思います

有名なデザインパターンを利用する

CopilotはGitHub上のソースコードを元に学習をしていますので、多くのエンジニアが書いているコードに寄せれば寄せるほど、Copilot側も得意です。
今回はバックエンドをオニオンアーキテクチャに従って実装をしていた(オニオンアーキテクチャについてはこちらの記事などをご参照)のですが、あるApplicationServiceを実装しようとした時のCopilot側の提案が以下です。

大体想定通りの構成をしています。これこそApplicationService層の責務をCopilotが知っている(+私の他のコードから学習)から出来る事です。
ちなみにfinish_game関数はまだ実装されていない関数ですが、こちらもこのドメインオブジェクトを実装しているファイルを開くとすぐに作成を提案してくれます。
ただし、ドメインオブジェクトの内部実装は(定義から言って)ドメイン知識(=アプリケーション特有の知識)を表現する場となるので、想定通りの実装になっているかは注意が必要です。

高凝集性を意識した設計をする

上記デザインパターンの話とも関連していますが、凝集度は非常に重要です。
凝集度が高ければ、「そのクラスがどんな責務を担っているか」×「明白な意図を持った関数名」によって実装内容が大体決定できるはずです。

ちなみにPythonで実装する場合、TypeHintは非常に重要です。引数や戻り値の型情報は関数の意図を示す非常に重要な情報になりますので。

以下はCopilotに辞書データのキーをcamelケースに変換するコードを作ってもらった例です。(独立した機能を持つ関数なので凝集度とはあまり関係ないですが。。。)

「recursive_convert_dict_key_to_camel」という関数名と引数、戻り値が辞書であるという情報だけでここまで作れるのは凄いですね!

テストコードもガンガン書いてもらう

テストコードの生成にはそれ専用のツールもたくさん生まれてきていますが、Copilotでかなり強力な補助をしてもらえます。
テストコードも、テスト関数名でその関数で確認するべき観点を明白に定義すれば、Copilot側でかなり察してくれます。
また、テストコード作成時に頭を悩ませる(というより面倒な)パラメータの設定なんかも、Copilot側でまず最初に作ってくれますので、開発者は多少のチューニングのみで済みます。

Copilotを使用すればテストコードの開発も大幅に生産コストを削減することが出来ますので、更に開発が捗ります!

まとめ

今回はChatGPT、GitHubCopilotを使用した開発体験について紹介していきました。
現代では、IDEを使用しない開発は不便すぎて現実的にあり得ないと思いますが、今後はこれらのAIツールもそんなポジションになっていくのかなぁと思います(プロダクトコードの実装にはセキュリティ問題が付きまといますが。。。)

Discussion