🧬

【ChatGPT】対話型AIを用いて安全にリファクタしてみる

2022/12/10に公開

これはどんな記事?

ChatGPTのAPIを利用して安全なリファクタを実践してみます。
具体的には以下二つをChatGPTに任せることで、エンジニア負担を減らしつつ安全にリファクタを行うことができます。

  • テストケースの生成
  • function単位のリファクタ

今回はPHPが対象言語になっていますが、JSでもPythonでも可能なため、適宜読み替えて試してみてください。

また注意点としてChatGPTは現在プレビュー期間のため、仕様が頻繁に変更される可能性があります。これを読んだタイミングではできなくなっている可能性があることをご了承ください。また、プロンプトに入力した内容はOpenAI側で利用される可能性があるため、個人が著作権を保持しているもののみがスコープになります。
https://openai.com/terms/

手っ取り早く何やればいいか箇条書きで教えて

  1. pyenvとvenvでpython環境を構築
  2. ChatGPTのGUIクライアントをインストールし起動
  3. コードを質問文に含ませてリファクタしてもらう
  4. 該当コードのテストコードを作成してもらう
  5. テストコードが回ることを確認し次第リファクタしてもらったコードを入れてみる

ChatGPTとは

ChatGPTとは、OpenAIという非営利団体が開発した対話型AIです。質問や要求を入力すると回答が出力されます。サービスのAPIも公開されており、有志がAPIを利用したクライアントソフトを公開しています。12/1の公開から一週間で利用者が100万人を超える活発なサービスです。

環境構築

アカウントの作成

https://chat.openai.com/auth/login
上記URLからアカウントを作成してください。アカウントが作成できない場合は1日待ってください(不安定)

python3.10の導入

このアプリはpython3.10を利用します。pyenvから3.10をインストールしておいてください。

クライアントソフトの環境構築

この記事では以下のツールを使用します。
下記をcloneしてください。
https://github.com/Cubicpath/ChatGPT-GUI

リポジトリに移動し、pyenvの指定とvenv(仮想環境)の作成を行ってください。
python3 -m venv .venv
pyenv local 3.10.9
仮想環境は下記コマンドでアクティベートできます。アクティベートは利用の際毎回行います。
. .venv/bin/activate
仮想環境でライブラリをインストールしてください
pip install chatgpt-gui
実行するとGUIアプリが起動します。
chatgpt
右上の人物マークから、先ほど作ったアカウントでログインしてください。ログインできない場合は大体あっちが悪いので1日くらい待ってください。

以上で環境構築は完了です。

実践

とりあえずリファクタコードをみてみる

まず対象を決めます。テストクラスが書きやすいclass化しているものを対象にすると良いです。今回は誕生年月日を渡すと何歳か返してくれるコードを対象としてみます。(下記コードもChatGPTで生成したものです)

<?php

function calculateAge($birthDate) {
  // 現在の日時を取得する
  $now = strtotime("now");

  // 誕生日をタイムスタンプに変換する
  $birthDate = strtotime($birthDate);

  // 誕生日から現在の日時を引く
  $age = date("Y", $now) - date("Y", $birthDate);

  // 現在の月日が誕生日より前なら、1歳引く
  if (date("md", $now) < date("md", $birthDate)) {
    $age--;
  }

  // 結果を文字列として返す
  return "{$age}歳";
}

echo calculateAge("1998-11-05");

テストコードを作る

これをリファクタしてほしいですが、とはいえテストがないと怖いです。テストコードが作れるか聞いてみます。

下記のPHPの関数のテストを作成したいです。PHPUnitで動くコードを作成してください。

(以下コードなので後略)

そうするとChatGPTがコメント付きでテストコードを生成してくれました。

<?php

// calculateAge関数を読み込む
require_once 'calculateAge.php';

// calculateAge関数のテストを行う
class CalculateAgeTest extends PHPUnit_Framework_TestCase
{
  // calculateAge関数をテストする
  public function testCalculateAge()
  {
    // 年齢が計算されることを確認する
    $this->assertEquals(calculateAge('2000-01-01'), '22歳');
    $this->assertEquals(calculateAge('2000-12-31'), '21歳');
    $this->assertEquals(calculateAge('2001-01-01'), '21歳');
  }
}

これでテストコードの生成ができました。PHPUnitを実行してpassすることを確かめてください。その後は異常系を追加したり、dataproviderを用いるように指示してみたりすると、ケースの追加やテストコードのリファクタを行ってくれます。

リファクタ

リファクタも同様に行います。柔軟にコードを変える傾向にあるので引数や返り値は変えないことや型指定等、大事にしたい要件は明示して指示します。

下記のPHPの関数のリファクタリングを引数と返り値は変えずに行いたいです。PHP8以降で動くため、型指定もしたいです。コードを生成してください。
(以下省略)

できあがった最終的なコードが下記になります。これを先程作成した単体テストでグリーンになれば一旦終了です。不安な場合は自分でレビューを行ったり、あらかじめ作ってあればE2Eテストを実行しても良いと思います。

function calculateAge(string $birthDate): string
{
  // 現在の日時を取得する
  $now = strtotime("now");

  // 誕生日をタイムスタンプに変換する
  $birthDate = strtotime($birthDate);

  // 誕生日から現在の日時を引く
  $age = date("Y", $now) - date("Y", $birthDate);

  // 現在の月日が誕生日より前なら、1歳引く
  if (date("md", $now) < date("md", $birthDate)) {
    $age--;
  }

  // 結果を文字列として返す
  return "{$age}歳";
}

まとめ

ChatGPTのAPIを用いたクライアントソフトを利用し、無事安全にリファクタリングを行うことができました。APIを使った理由はソースコードを提出する上で複数行入力が必要になったためです。APIは公開されているため、自分でよしなにツールを自作しても良いと思います。

ChatGPTを使う上でのTips

  • コードが長いと途中で止まります。その際は続きをお願いすると続きが出力されます。
  • セッションが続く限りは会話の内容を覚えています。セッションが切れたら再度最初から行ってください。

この記事で何か質問等あればコメントか下記のツイッターにてお願いします。
https://twitter.com/sald_ra

Discussion