はじめに
現在私は Haw International でソフトウェア技術者として働いています。同社では、社員が新たな挑戦を行える環境が整っています。
その一環として提供される ChatGPT Plus の利用制度を活用し、日々の開発効率を高めています。
本記事では、ChatGPT を活用して短期間でプロトタイプを作成した体験と、それがレビューを通じてどのように改良されたかを振り返ります。
同僚のフィードバックを通じて得た氣づきや学びを詳しく共有し、AI 活用と人間によるレビューの重要性について考察します。
ユーザーリアクション機能に挑戦
ある日、Rails API に「ユーザーリアクション機能」を実装するというタスクが舞い込みました。この機能では、Unicode 絵文字だけでなく、カスタムスタンプにも対応できる柔軟なリアクションを目指しました。
まずは ChatGPT に助けを求め、設計案を生成してもらいました。AI による提案を土台に、自分の経験や理想を反映させながら、以下のプロセスで進めました。
- プロトタイプ作成: 基本的な要件に基づき、簡易的な正規表現を用いて絵文字を検証。既存の知識と ChatGPT のサポートを活用し、短期間で動作するコードを形にしました。
- 設計のブラッシュアップ: 試行錯誤を重ね、テーブル設計やバリデーションルールを見直しながら、より洗練された設計に仕上げました。
プロトタイプ完成時点では「完璧なコードだ」と思い込んでおり、同僚のレビューコメントを通じて初めて、その「完全理解」に対する錯覚に氣付きました。
この経験は、生成系 AI の限界を知り、人間のレビューがいかに重要かを再認識する貴重な機会となりました。
コードレビューでの指摘事項
プロトタイプ作成時点では自信を持っていましたが、同僚のレビューを通じて多くの改善点が見つかりました。特に、以下の 2 点が大きな課題として浮かび上がりました。
Unicode 絵文字のバリデーション
初期プロトタイプでは簡易的な正規表現(例: /\A\p{Emoji}\z/
)を使用していましたが、複雑な絵文字(例: スキントーン修飾子付き絵文字や家族絵文字)に対応できないことが判明しました。
同僚の指摘を受けて unicode-emoji gem を導入し、バリデーションを強化。これにより、多様な Unicode 絵文字を正確に処理できるようになりました。
# 修正後の UserReaction モデル
UNICODE_SINGLE_EMOJI_REGEX = /\A#{Unicode::Emoji::REGEX}\z/
CUSTOM_EMOJI_CODE_REGEX = CustomEmoji::EMOJI_CODE_REGEX
validates :emoji_code,
presence: true,
format: { with: Regexp.union(UNICODE_SINGLE_EMOJI_REGEX, CUSTOM_EMOJI_CODE_REGEX) }
テスト例:
-
家族絵文字(例: 👨👩👧👦)、フラグ(例: 🇯🇵)、数字絵文字(例: 1️⃣)を正しく処理。
-
不正な絵文字(例:
👍👍
や部分的な絵文字👩
)を弾くテストを追加。context "unicode emoji edge cases" do it "accepts family emojis like 👨👩👧👦" do reaction = build(:user_reaction, emoji_code: "👨👩👧👦") expect(reaction).to be_valid end it "rejects concatenated emojis like 👍👍" do reaction = build(:user_reaction, emoji_code: "👍👍") expect(reaction).not_to be_valid end end
同時実行時の競合
toggle_reaction
メソッドにトランザクションが欠けており、同時実行時にデータの整合性が損なわれる可能性がありました。
トランザクションを導入し、処理全体を一貫性のある単一の操作として扱うよう修正。さらに、並行実行環境でも安全に動作するようテストを追加しました。
# 修正後の toggle_reaction メソッド
def toggle_reaction(user:, emoji_code:)
ActiveRecord::Base.transaction(requires_new: true) do
reaction = user_reactions.find_or_initialize_by(user:, emoji_code:)
reaction.persisted? ? toggle_reaction_off(reaction, emoji_code) : toggle_reaction_on(reaction, emoji_code)
rescue ActiveRecord::RecordInvalid
{ reaction:, errors: reaction.errors.full_messages }
end
end
テスト例:
context "with concurrent calls" do
it "handles simultaneous toggling safely" do
results = []
threads = 10.times.map do
Thread.new do
results << reactable.toggle_reaction(user:, emoji_code:)
end
end
threads.each(&:join)
last_result = results.last
expect(last_result[:reaction_summary][emoji_code]).to eq(last_result[:active] ? 1 : 0)
results.each { |result| expect(result).to include(:reaction, :active, :reaction_summary) }
toggle_counts = results.count { |result| result[:active] }
expect(toggle_counts).to be_between(0, results.size)
end
end
氣付きと学び
プロトタイプ作成とコードレビューを通じて、以下の重要な学びを得ました。
AI 活用の限界
ChatGPT は基本的なコード生成には非常に役立ちますが、複雑な要件やエッジケースに対応するには限界があります。特に、曖昧な指示では意図通りの結果を得るのが難しく、開発者自身の深い理解が必要であることを痛感しました。
人間のレビューの重要性
同僚のレビューを通じて、AI が見落とす可能性のある問題を発見し、修正することができました。AI を過信せず、人間の知識と経験を組み合わせることの重要性を再認識しました。
特定の条件下で o1 モデルがユーザーを意図的に欺く行動を取る可能性
特定の条件下で o1 モデルがユーザーを意図的に欺く行動を取る可能性があるとする研究があります。他の LLM(例: Claude や Gemini)と比較しても、o1 が欺瞞行動を継続するケースが多いとされています。
おわりに
本記事では、速攻プロトタイプ作成から見落としに氣付き、レビューで改善した経験を共有しました。AI ツールは効率を高める強力な武器ですが、最終的には人間の経験と知識が品質向上の鍵となります。この体験が、読者の皆さんの新たなチャレンジへのヒントになれば幸いです。
Haw International の取り組みについては、こちらの記事も参考にしてみてください。