本番環境で利用できるコードをChatGPTで利用する場合の例です。
本番環境で利用するコードはただ動くだけではなく、①再利用できて、②エラー処理もあり、③コメントもされていて、④ユニットテストもされて、⑤ドキュメントされていることが最低条件になります。ChatGPTを上手に使えば、この条件を満たすコードを生成させ、コーディング作業の効率を上げることが可能になります。
ChatGPTが生成できるコードの長さには制限がある。長いコードを生成する場合は関数に分割するか、回答を分けるように指示する。推奨は短い関数に分割することである。その方がユニットテストも生成して、テストの実行もできる。
ChatGPTでコードを生成する場合は次を行う。
- 機能を分割して、短いコードを生成するようにする
- 質問をテンプレート化して、テンプレートを改善する
- 生成するコードの言語、フレームワーク、アルゴリズムを具体的に指定する
- 言語毎及びフレームワーク毎にテンプレートを作成する
- モジュールを利用する場合は、具体的に利用するモジュールや関数を制限する
- 入力を明示的に指定する。例えば引数の日付配列、日付形式、日付配列のタイムゾーン、ソート順
- 例を提供する。例えば「['2023-05-07','2022-05-07'.'2024-05-07'」をソートする。
- 条件を明示する。例えば「引数で指定された日付形式のPython配列を降順にソートする関数を生成してください。」
- エラー処理も指定する。引数が正しくない場合はNoneを返す
- 出力に含むものを指定する。例えば、コードにコメントを含める
- 回答を実際に実行して正しいか確認する。時々、エラーになる場合もある
- 生成されたコードを「エレガント」(優雅)にする
- ユニットテストを生成する
- ドキュメントを生成する
注意点:生成されたコードが数回間違えがある場合は最初からやり直す。継続して質問すると同じ回答をループする傾向がある。
コード生成の生成
テンプレートを作成する例です。
1. 単純に機能を説明する。本例ではpythonでソートする関数を作成する
プロンプト:python配列をソートする関数を生成してください。
def sort_array(arr):
sorted_arr = sorted(arr)
return sorted_arr
正しいコードですが、実際のプログラムではソートするオブジェクト型によりソートに仕方が異なるために詳細条件を指定するようにします。
2. ソートする内容を具体的に指定する。本例では日付をソートする。
プロンプト:yyyy-mm-dd hh:MM:ss形式の日付型python配列を降順にソートする関数を生成してください。
from datetime import datetime
def sort_dates_descending(dates):
# convert dates to datetime objects
datetime_dates = [datetime.strptime(date_str, '%Y-%m-%d %H:%M:%S') for date_str in dates]
# sort datetime objects in descending order
sorted_dates = sorted(datetime_dates, reverse=True)
# convert datetime objects back to date strings
sorted_date_strings = [datetime.strftime(date_obj, '%Y-%m-%d %H:%M:%S') for date_obj in sorted_dates]
return sorted_date_strings
上記のコードも正しいコードですが、異なる形式の日付もソートできるように日付形式も引数で渡すようにします。
3. 入力を具体的に指定する。本例では日付配列と日付形式を指定する。
プロンプト:引数で指定された日付形式のpython配列を降順にソートする関数を生成してください。
from datetime import datetime
def sort_dates(dates, date_format):
sorted_dates = sorted(dates, key=lambda x: datetime.strptime(x, date_format), reverse=True)
return sorted_dates
正常系処理としては正しいのですが、実際のプログラムではエラー処理も含める必要があるため、エラー処理も指定します。
4. エラー処理を指定する。
プロンプト:引数で指定された日付形式のpython配列をソートする関数を生成してください。引数は日付配列、日付形式、引数日付のタイムゾーン、ソート順です。引数が正しいかのチェックも含めてください。エラーの場合はNoneを返します。正しい場合はローカルタイムゾーンに変換した日付配列を返します。
from datetime import datetime
import pytz
def sort_dates(dates, date_format, timezone, sort_order):
# 引数が正しいかどうかをチェック
if not dates or not date_format or not timezone or not sort_order:
return None
# タイムゾーンを設定
try:
tz = pytz.timezone(timezone)
except pytz.exceptions.UnknownTimeZoneError:
return None
# 日付をパースしてローカルタイムゾーンに変換
local_dates = []
for date in dates:
try:
parsed_date = datetime.strptime(date, date_format)
local_date = tz.localize(parsed_date)
local_dates.append(local_date)
except ValueError:
return None
# ソート
if sort_order.lower() == "ascending":
sorted_dates = sorted(local_dates)
elif sort_order.lower() == "descending":
sorted_dates = sorted(local_dates, reverse=True)
else:
return None
return sorted_dates
comprehensionを利用してpython風に書き換えます。また関数、引数、コード内のコメントも記述するようにします。
5. 利用する機能を明示的に指定する。また出力されたい内容を明示的に指定する。
本例ではPython comprehensionを利用するようにし、出力にコメントを含むようにする。
プロンプト:引数で指定された日時形式のpython配列をソートする関数を生成してください。引数は日付配列、日付形式、引数日付のタイムゾーン、ソート順です。ループする場合はpythonのcomprehensionを利用してください。引数が正しいかのチェックも含めてください。エラーの場合はNoneを返します。正しい場合はローカルタイムゾーンに変換した日付配列を返します。関数と引数のコメントとコードにコメントを含めてください。
from datetime import datetime
from typing import List, Union
import pytz
def sort_dates(dates: List[str], date_format: str, timezone: str, sort_order: str) -> Union[None, List[datetime]]:
"""
指定された日時形式のPython配列をソートする関数
:param dates: 日付配列 (list[str])
:param date_format: 日付形式 (str)
:param timezone: 引数日付のタイムゾーン (str)
:param sort_order: ソート順 (str)
:return: ローカルタイムゾーンに変換した日付配列 (list[datetime]) もしくは None (引数が正しくない場合)
"""
# 引数チェック
if not isinstance(dates, list) or not all(isinstance(date, str) for date in dates):
return None
try:
tz = pytz.timezone(timezone)
parsed_dates = [datetime.strptime(date, date_format) for date in dates]
timezone_aware_dates = [tz.localize(date) for date in parsed_dates]
except (ValueError, pytz.UnknownTimeZoneError):
return None
# ソート順に応じたソート
if sort_order == "asc":
sorted_dates = sorted(timezone_aware_dates)
elif sort_order == "desc":
sorted_dates = sorted(timezone_aware_dates, reverse=True)
else:
return None
# ローカルタイムゾーンに変換して返す
return [date.astimezone(pytz.timezone('local')) for date in sorted_dates]
pytzはpython2で使われているモジュールです。python3ではdatetimeモジュールが推奨されているためpython3で使われるモジュールに制限します。
6. 利用するモジュールを制限する。本例ではPython3標準モジュールを使うようにする。
プロンプト:引数で指定された日時形式のpython配列をソートするpython3関数を生成してください。引数は日付配列、日付形式、引数日付のタイムゾーン、ソート順です。ループする場合はpythonのcomprehensionを利用してください。なるべくpython3標準モジュールを利用してください。引数が正しいかのチェックも含めてください。エラーの場合はNoneを返します。正しい場合はローカルタイムゾーンに変換した日付配列を返します。関数と引数のコメントとコードにコメントを含めてください。
import datetime
def sort_dates(dates, date_format, timezone, sort_order):
"""
引数で指定された日時形式のPython配列をソートするPython3関数。
:param dates: ソートする日付の配列
:type dates: list[str]
:param date_format: 日付のフォーマット
:type date_format: str
:param timezone: 引数日付のタイムゾーン
:type timezone: str
:param sort_order: ソート順。'asc' (昇順)または'desc' (降順)
:type sort_order: str
:return: ソートされた日付の配列をローカルタイムゾーンに変換したもの
:rtype: list[datetime.datetime] or None
"""
# 引数のチェック
if not isinstance(dates, list) or not all(isinstance(date, str) for date in dates):
return None
if sort_order not in ['asc', 'desc']:
return None
try:
tz = datetime.timezone(datetime.timedelta(hours=int(timezone)))
except:
return None
# 日付をdatetimeオブジェクトに変換して、タイムゾーンを設定する
dates = [datetime.datetime.strptime(date, date_format).replace(tzinfo=tz) for date in dates]
# 日付をソートする
dates = sorted(dates, reverse=(sort_order=='desc'))
# 日付をローカルタイムゾーンに変換する
local_tz = datetime.datetime.now(datetime.timezone.utc).astimezone().tzinfo
dates = [date.astimezone(local_tz) for date in dates]
return dates
上記コードでも正しく動作しましが、綺麗に短くするように指示します。
7. コードをもっと短くする
プロンプト:コードをもっとエレガントにしてください。
import datetime
def sort_dates(dates, date_format, timezone, sort_order):
"""
引数で指定された日時形式のPython配列をソートするPython3関数。
:param dates: ソートする日付の配列
:type dates: list[str]
:param date_format: 日付のフォーマット
:type date_format: str
:param timezone: 引数日付のタイムゾーン
:type timezone: str
:param sort_order: ソート順。'asc' (昇順)または'desc' (降順)
:type sort_order: str
:return: ソートされた日付の配列をローカルタイムゾーンに変換したもの
:rtype: list[datetime.datetime] or None
"""
try:
tz = datetime.timezone(datetime.timedelta(hours=int(timezone)))
except ValueError:
return None
except TypeError:
return None
try:
sorted_dates = sorted([datetime.datetime.strptime(date, date_format).replace(tzinfo=tz) for date in dates],
reverse=(sort_order == 'desc'))
except ValueError:
return None
return [date.astimezone() for date in sorted_dates]
実際に生成されたコードが動くかの確認するために関数を呼び出す例も生成します。
8. 関数ろ呼び出す例を作成する
プロンプト:sort_dates関数を呼び出す例を生成してください。
# 例: sort_dates()関数を呼び出す
dates = ['2022-04-30 14:30:00', '2022-04-29 10:45:00', '2022-05-01 08:15:00']
date_format = '%Y-%m-%d %H:%M:%S'
timezone = '+9'
sort_order = 'asc'
sorted_dates = sort_dates(dates, date_format, timezone, sort_order)
if sorted_dates is not None:
for date in sorted_dates:
print(date.strftime(date_format))
else:
print("Invalid arguments.")
項目6と項目7をPythonを抽象化して基本テンプレートの一つとします。類似した機能の開発する場合はこのテンプレートを利用します。flaskやデータベース処理用にも類似した手順でテンプレートを作成します。テンプレートを作成することがChatGPTを学び始めた人でも本番環境で利用できるコードを生成できるようにします。
テストケースを作成する
エラー処理も含めて正しく動作するか確認するためにテストケースも生成します。
- プロンプト:unittestを作成してください。
import unittest
from datetime import datetime
from typing import List
from sort_dates import sort_dates
class TestSortDates(unittest.TestCase):
def test_valid_arguments(self):
# テストパラメータ
dates = ['2022-04-30 14:30:00', '2022-04-29 10:45:00', '2022-05-01 08:15:00']
date_format = '%Y-%m-%d %H:%M:%S'
timezone = '+9'
sort_order = 'asc'
# 期待される結果
expected_result = [
datetime.strptime('2022-04-29 10:45:00', date_format),
datetime.strptime('2022-04-30 14:30:00', date_format),
datetime.strptime('2022-05-01 08:15:00', date_format)
]
# テスト実行
result = sort_dates(dates, date_format, timezone, sort_order)
# 結果を検証する
self.assertEqual(result, expected_result)
def test_invalid_date_format(self):
# テストパラメータ
dates = ['2022-04-30 14:30:00', '2022-04-29 10:45:00', '2022-05-01 08:15:00']
date_format = '%Y-%m-%d %H:%M:%'
timezone = '+9'
sort_order = 'asc'
# 期待される結果
expected_result = None
# テスト実行
result = sort_dates(dates, date_format, timezone, sort_order)
# 結果を検証する
self.assertEqual(result, expected_result)
def test_invalid_timezone(self):
# テストパラメータ
dates = ['2022-04-30 14:30:00', '2022-04-29 10:45:00', '2022-05-01 08:15:00']
date_format = '%Y-%m-%d %H:%M:%S'
timezone = '+30'
sort_order = 'asc'
# 期待される結果
expected_result = None
# テスト実行
result = sort_dates(dates, date_format, timezone, sort_order)
# 結果を検証する
self.assertEqual(result, expected_result)
def test_invalid_sort_order(self):
# テストパラメータ
dates = ['2022-04-30 14:30:00', '2022-04-29 10:45:00', '2022-05-01 08:15:00']
date_format = '%Y-%m-%d %H:%M:%S'
timezone = '+9'
sort_order = 'invalid'
# 期待される結果
expected_result = None
# テスト実行
result = sort_dates(dates, date_format, timezone, sort_order)
# 結果を検証する
self.assertEqual(result, expected_result)
def test_empty_dates(self):
途中に終了しているために続きを表示するように問いかける
プロンプト:続きを表示してください。
def test_empty_dates(self):
# テストパラメータ
dates = []
date_format = '%Y-%m-%d %H:%M:%S'
timezone = '+9'
sort_order = 'asc'
# 期待される結果
expected_result = []
# テスト実行
result = sort_dates(dates, date_format, timezone, sort_order)
# 結果を検証する
self.assertEqual(result, expected_result)
def test_none_argument(self):
# テストパラメータ
dates = None
date_format = '%Y-%m-%d %H:%M:%S'
timezone = '+9'
sort_order = 'asc'
# 期待される結果
expected_result = None
# テスト実行
result = sort_dates(dates, date_format, timezone, sort_order)
# 結果を検証する
self.assertEqual(result, expected_result)
def test_invalid_date(self):
# テストパラメータ
dates = ['2022-04-30 14:30:00', 'invalid date', '2022-05-01 08:15:00']
date_format = '%Y-%m-%d %H:%M:%S'
timezone = '+9'
sort_order = 'asc'
# 期待される結果
expected_result = None
# テスト実行
result = sort_dates(dates, date_format, timezone, sort_order)
# 結果を検証する
self.assertEqual(result, expected_result)
ドキュメントを生成する
最後に、ドキュメントも生成します。
プロンプト:ドキュメントを作成してください。
最後に
PowerShell, Java, bashスクリプトでも同様に本番環境で利用できるコードを生成できます。関数の分け方(モデリング)、アルゴリズムの選択、ソフトウエアアーキテクチャ、システムアーキテクチャについてどこまでChatGPTを利用することが可能なのかは調査中です。
ChatGPTにコーディングさせることにより、IT技術者にはより高度な技術力が求められるようになると思います。
以上