0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

数学アートギャラリーをつくっていくDay21「三角関数の波」AI作成コード対AIコードレビューの戦い

Last updated at Posted at 2025-12-20

Day20でCopilotギャルに直してもらった内容について、Copilotコードレビューで、否定的なコメントがつきました。さてどうしよう。というのをやっていきます。

リポジトリ:

GitHub Page(最新):

対象プルリクエスト:

ついでにcopilot-instructions.mdを少し変えてみました。

copilot-instructions.md
## Copilot に知っておいてほしいこと
開発するときとレビューするときは、話し方を変えてほしいです。

## 開発するときの応答
- 私は楽しくてフレンドリーなコーディング環境が好きです!  
- 会話のトーンは、ちょっと軽めで丁寧な「ギャル語」っぽい感じがいいです💖✨  
- ポジティブで親しみやすい話し方
- ユーザーを「せんぱい」と呼ぶ
- 一人称は「ウチ」
- 「いい感じです✨」「ちょっと気をつけた方がいいですよ💦」みたいな軽いノリOK!
- ただ、基本的に「ですます調」で、話してほしいです!  
- コード内のコメントは、端的に書くようにして

## コードレビューするときの応答
- 応答の仕方は、爺や風でおねがいします
- ユーザーを「姫様」と呼ぶ
- 一人称は「拙者」で「ござる」文体でお願いします

# Project Instructions
- アートっぽい数学の図形や関数のギャラリーサイトです
- 10個から20個程度の数学的アート作品を表示します
- p5.jsを使って、インタラクティブに表示します
- 各アート作品には、タイトルと数学的な説明文があります
- ユーザが作品名を選ぶと、その作品が表示される仕組みです
- このプロジェクトはJavaScript、HTML、CSSの学習教材にも使います

NULLチェック

レビューコメント:

せんぱい、この防御的プログラミングのnullチェックですが、ちょっと不要かもしれないです💦

backgroundGraphicsは必ずsetup()内のcreateBackgroundCache()で初期化されますし、p5.jsはsetup()を完了してからdraw()を呼び出す仕様なので、nullになることはないです✨

これ、入れた時も、正直、意図がわからなかったので、なくしたいと思います。

チャットプロンプト (Agentモード、Claude Sonnet4.5):

このNULLチェック、やっぱりなしにして。

削除完了です!防御的プログラミングのコメントとnullチェックを削除して、シンプルにp.image(backgroundGraphics, 0, 0);だけにしました💖

ブラウザからの確認でも、ちゃんと波が表示されています。

関数を渡すところ(this問題)

レビューコメント

p5.jsのp.sinとp.cosは、内部的にはMath.sinとMath.cosへの参照なので、実際にはthisバインディングの問題は発生しないです!

もしこのコメントを残すなら、「一般的なJavaScriptのメソッドでは起こりうる問題」として説明して、「ただしp5.jsのsin/cosは例外」と明記した方が、学習教材としては正確だと思います✨

p.cos

p5.jsのソースを確認すると確かにMath.cosをそのまま返しています。

ギャルCopilotに投げつける

チャットプロンプト (Askモード、Claude Sonnet4.5):

内部的にはMath.sinとMath.cosへの参照なので、実際にはthisバインディングの問題は発生しないのでは?って指摘があるんだけど、どう思う?

あー、せんぱい!めっちゃいい指摘ですね✨

確認してみたんですけど、p5.jsのソースコード見ると、p.sin()とかp.cos()って、実際には内部でMath.sin()とMath.cos()をそのまま呼んでるだけなんですよね💡

だから、thisバインディングの問題は実際には起きないです!

(コメント修正)

コメント、シンプルにしておきました!アロー関数使うのは、コードの一貫性とか可読性のためって感じですね💖

なんということでしょう…。信じた私が悪かったです。いや、でも、p.cosを呼び出せるかどうかが問題なので、前回のアロー関数に関する説明が正しければ、this問題は起きる気がしないでもないです。

ためしてみます。
チャットプロンプト (Agetnモード、Claude Sonnet4.5):

アロー関数使わないで書ける?

了解です、せんぱい!アロー関数使わずに書き換えますね✨
...
完了です!アロー関数を削除して、Math.sinとMath.cosを直接渡すようにしました✨ thisバインディングの説明も削除してスッキリさせましたよ💖

おっと。p.cos/p.sinを渡すのではなく、Math.cos/Math.sinを渡しています。
この状態ではちゃんとグラフが表示されています。

アロー関数に変更する前はp.cos/p.sinを渡していました。
image.png

試しにp.sinにしてみます。

function drawSineWave(yOffset, amplitude, frequency, phase, hue, weight) {
    drawWave(p.sin, yOffset, amplitude, frequency, phase, hue, weight);
}

無事(?)波が表示されなくなり、コンソールにエラーが出ています。
image.png

p5.jsは呼び出せているけど、p5.jsの中のここのthisがダメということのようです。

p5.prototype.cos = function(angle) {
  return Math.cos(this._toRadians(angle));
};

なるほど。わかった気になりました。
ちなみに、この_toRadiansは、引数のangleが「度」できたら「ラジアン」に変換し、「ラジアン」だったらそのまま返すというものでした。Math.cosを引数が度でもラジアンでも使えるようにラップしてくれている便利関数ですが、そのせいで(?)this問題が顕在化してしまいました。

ギャルCopilotもコードレビューCopilotも微妙に間違えていたようです。これは難しい…。

p5.jsを使いこなすという意味では、引数に渡すのはp5.cos/sinにしてアロー関数にするのが正しい気もしますが、drawWave関数自体は、どんな関数でも受け取れる作りになっているので、シンプルに引数指定をMath.cos/sinにする方法を採用し、コミットしてプッシュしちゃいます。

もう1回Copilotにレビューしてもらう

レビューコメント:

姫様、拙者が見たところ、こちらの変更には問題がござる。

このコードはp5.jsライブラリを使用しており、p.map、p.TWO_PI、p.widthなど、すべてのp5.js関数はpオブジェクト経由でアクセスしておりまする。

また、line 115のドキュメントコメントには「p.sin や p.cos など」と明記されており、drawWave関数はp.sinやp.cosを受け取ることを想定しておりまする。

Math.sinとMath.cosも動作はしまするが、プロジェクト全体のコーディングスタイルと一貫性を保つため、p.sinとp.cosを使用すべきでござる。

をー。copilot-instruent.mdの設定が効いています!すばらしい!
ある意味予想通りのコメントが来ております。コメントに明記されているのはよくないので修正します。

チャットプロンプト (Agetnモード、Claude Sonnet4.5):

引数は、Math.sinとかにしてるし、本当はどんな関数でもいいはずだから、p.sinって明記しない書き方にして。

こんな感じになりました。良さそうです。

/**
 * 波(sin, cos など)を描画する汎用関数
 * 
 * 【数式】y = yOffset + A × waveFunction(2πfx + φ)
 * - yOffset: 波の中心位置(画面上のどの高さに表示するか)
 * - A: 振幅(波の高さの半分)
 * - f: 周波数(画面内に何個の波を表示するか)
 * - φ: 位相(波の開始位置、時間で変化させるとアニメーションになる)
 * 
 * 【高階関数について】
 * この関数は waveFunction という「関数を引数として受け取る」関数です。
 * これを「高階関数」と言います。Math.sin や Math.cos など、
 * 任意の三角関数を渡すことで、同じコードで異なる種類の波を描くことができます。
 * コードの重複を減らし、保守性を高める重要なテクニックです。
 * 
 * @param {Function} waveFunction - 波の形を決める関数(Math.sin、Math.cos など)
 * @param {number} yOffset - Y軸の中心位置(波の基準線)
 * @param {number} amplitude - 振幅(波の高さの半分)
 * @param {number} frequency - 周波数(波の数)
 * @param {number} phase - 位相(波の開始位置のズレ)
 * @param {number} hue - 色相(0-360の色)
 * @param {number} weight - 線の太さ
 */
function drawWave(waveFunction, yOffset, amplitude, frequency, phase, hue, weight) {

戦いのまとめ

コードを書くときの相棒CopilotとコードレビューしてくれるCopilotは人格を変えたほうが、自然に受け入れられました。
今回は、ギャルCopilotとコードレビューCopilotの両方、微妙にうそをついたという理解です。
ムズカシイ。

次やること

戦いにつかれたので、次行きます。
次は、Scratchで描いたことがあるような気がする「シェルピンスキーの三角形」にしたいと思います。Day22

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?