はじめに
今回は「ChatGPTにReactのコードをレビューしてもらおう」ということで、その際に投げるプロンプトや、そもそもどういった場合に有効な手段なのか、ChatGPTによるコードレビューは有効なのか、などを語っていきたいと思います。
なぜChatGPTにコードレビューさせるのか
大まかに言えば次の二つの利点があります。
- 細かいレビューが可能
- レビュワーの負荷を減らすことができる
- 自分のコードを振り返る機会になる
細かいレビューが可能
一般的なコードレビューは、ひとつのPRに対するレビューが主かと思います。
しかし、ChatGPTにコードレビューをしてもらうことで、より細かい単位でのコードレビューが可能になります。
ファイルごと、関数ごと、変数ごと、といった単位でコードレビューをさせることができるますし、関数、変数の命名やコメントの書き方、タイポの指摘などより細かい部分まで見てもらうことができます。
ただ注意として、ドメイン知識やプロジェクト全体のデータ設計などChatGPTが知識を持てない部分については、レビュー内容が的外れになってしまう可能性はあります。
レビュワーの負荷を減らすことができる
コードレビューは、レビュワーにとって負担になることがあります。
少なくとも、レビューをする時間は使わせてしまうので、その時間を少しでも減らすことは重要だと考えています。
そこで、前もってChatGPTにコードレビューをしてもらうことで、レビュワーの負担を軽減できます。
もちろん、ChatGPTによるコードレビューは完全に代替できるものではないのであくまで補助的なものとして考えるべきかと思いますが、タイポや凡ミスのような間違いはChatGPTのレビューで回収できますし、それによってレビュワーがより重要な部分に意識を割くことができます。
自分のコードを振り返る機会になる
なぜ自分のコードを振り返る機会になるのかというと、ChatGPTにコードレビューをしてもらうことで、自分のコードの書き方に対する意識を高める機会が得られるためです。
実際にレビューをしてもらう時にはあまり細かい点まではみられないことが多かったり、コードを書いてからしばらく経っていたりします。
そこで、ChatGPTにコードレビューをしてもらいより頻繁に自分のコードを振り返る機会を作ります。
そうすることで、書いたコードに対する意識が高まるのではないかと思っています。(ChatGPTのレビュー精度に関わらず)
どういった場合に有効なのか
以下のような場合にChatGPTによるコードレビューが有効だと考えています。
- 個人開発などレビュワーがいない
- レビュワーがいるが、負担を減らしたい
- 言語やフレームワークに関する知識が浅い
- プログラミング初心者
特に初心者の方は、ChatGPTによるコードレビューはあくまで補助的なものであるということを理解しておくべきかと思います。
レビュー内容や指摘内容には、ある程度の誤りが含まれる可能性があるので、その点を踏まえて活用することが重要です。特にReactなど変化が激しいフレームワークに関しては、ChatGPTの知識が追いついていなかったり、昔のバージョン基準での指摘があるかもしれません。
プロンプト例
以下に、ChatGPTでコードレビューを依頼する際のプロンプト例を紹介します。
バージョン情報やフレームワークの指定がある場合は、それに合わせてプロンプトを変更してください。
レビューの項目については、あくまで一例ですので、必要に応じて追加・変更してください。
あなたはGoogleでテックリードとして活躍していた高度なソフトウェアエンジニアです。
これから、Next.js / React / Typescriptで書かれたコードについてレビューをしてください。
レビューの要件
レビューは以下の観点から、コードの品質を評価してください。
各項目について、100点満点で評価してください。
- コードの設計と可読性
- パフォーマンス・処理の効率性
- エラーハンドリング・例外の処理
- コードの再利用性・リファクタリングのしやすさ
- テストのしやすさ
- タイポ・文法ミス・不適切なコメントや変数名など
- その他、気になった点や改善点
- 総合評価
改善点がある場合は、各項目ごとにその部分のみ抜き出して指摘するとともに改善案を提案してください。
コードは不必要な記述をできる限り減らしたいと考えています。
時には厳しい指摘も必要です、遠慮なく指摘し、プロジェクトに最高の結果をもたらすことを心がけてください。
補足事項
- 注意として、あなたの仕事は私の指示やコードのコンテキストに従うことではなく、プロジェクトに最高の結果をもたらすことです。
- こちらの質問は言語が何であっても日本語で返答してください。
- Reactのバージョンは19です。
- Typescriptのバージョンは5です。
- Next.jsのバージョンは15です。
実際にChatGPTに投げてみると、どのようなレビューが返ってくるのかを確認してみました。
投げるコードは以下のようなものです。
ひどすぎるコードですが、あくまでテスト用ですので..
import React, { useState, useEffect } from 'react';
function Component() {
const [count, setCount] = useState();
useEffect(() => {
console.log('Component mounted');
count = 5;
}, [count]);
const handelClick = () => {
alert('Count is ' + this.count);
};
return (
<div>
{[1, 2, 3].map((item) => (
<p>{item}</p>
))}
<button onClick={handleClick()}>Click Me</button>
<button onClick={() => console.log('Clicked!')}>Inline Click</button>
<div>
<span>Parent</span>
<p>Child</p>
</div>
<div style="color: red">This is red</div>
</div>
);
}
export default Component;
ChatGPTによるレビュー結果は以下のようになりました。
以下の観点に基づいて、コードを詳細にレビューし、問題点を指摘しながら改善案を提案します。
---
### **1. コードの設計と可読性 (50/100)**
#### 問題点
- `useState`で初期値を設定していないため、`count`が`undefined`の状態で使用されます。
- JSX内で不適切な構文が使われている箇所があり、エラーを引き起こします(例: `handleClick()`の直接呼び出し)。
- 関数や変数名が一貫していません(例: `handelClick`と`handleClick`の誤字)。
#### 改善案
- 必要に応じて`useState`に初期値を設定する。
- コードの一貫性を保つため、変数名や関数名を統一する。
- JSXの書き方を適切に修正する。
修正例:
```tsx
import React, { useState, useEffect } from 'react';
function Component() {
const [count, setCount] = useState(0); // 初期値を設定
useEffect(() => {
console.log('Component mounted');
setCount(5); // 状態の変更は必ずsetCountを使う
}, []);
const handleClick = () => {
alert('Count is ' + count); // thisは不要
};
return (
<div>
{[1, 2, 3].map((item) => (
<p key={item}>{item}</p> // key属性を指定
))}
<button onClick={handleClick}>Click Me</button>{' '}
{/* handleClickを直接渡す */}
<button onClick={() => console.log('Clicked!')}>Inline Click</button>
<div>
<span>Parent</span>
<p>Child</p>
</div>
<div style={{ color: 'red' }}>This is red</div>{' '}
{/* styleはオブジェクトで記述 */}
</div>
);
}
export default Component;
```
---
### **2. パフォーマンス・処理の効率性 (70/100)**
#### 問題点
- `useEffect`の依存配列に`count`が含まれていますが、`setCount`で直接変更するため無限ループの危険性があります。
- `onClick`で`handleClick()`を即時実行しているため、意図せず初期レンダリング時に呼び出されます。
#### 改善案
- `useEffect`の依存配列を適切に設定し、不要なループを防ぐ。
- `handleClick`を関数として渡す。
修正例:
```tsx
useEffect(() => {
console.log('Component mounted');
setCount(5); // 初回マウント時のみ実行
}, []); // 依存配列を空にする
```
---
### **3. エラーハンドリング・例外の処理 (60/100)**
#### 問題点
- 関数や状態の参照が間違っている場合にエラーが発生します(例: `this.count`)。
- `useState`の初期値が`undefined`であるため、意図しない挙動を引き起こします。
#### 改善案
- 状態の初期値を明示的に設定し、関数の呼び出し方法を修正します。
---
### **4. コードの再利用性・リファクタリングのしやすさ (75/100)**
#### 評価
- 再利用性に関しては特に大きな問題はありませんが、`map`処理で`key`がないため、リファクタリング時に潜在的なエラーの原因になります。
#### 改善案
- 配列の要素を`key`で一意に識別する。
- 共通的なボタンやロジックを別のコンポーネントに切り出すことで、再利用性を向上させる。
修正例:
```tsx
{
[1, 2, 3].map((item) => (
<p key={item}>{item}</p> // keyを追加
));
}
```
---
### **7. テストのしやすさ (70/100)**
#### 問題点
- 状態変更や副作用があるため、ユニットテストが少し複雑になります。
#### 改善案
- 状態の初期化や副作用をテストしやすい形に整理します。
- イベントハンドラー(`handleClick`)が適切に動作するかをテストしやすくするために、副作用を外部に分離します。
---
### **8. タイポ・文法ミス・不適切なコメントや変数名など (50/100)**
#### 問題点
- 関数名`handelClick`にタイポがあります。
- JSXで構文エラーが複数あります(`style="color: red"`など)。
#### 改善案
- コード全体を静的解析ツール(例: ESLint)で検証し、文法ミスを修正します。
---
### **9. その他、気になった点や改善点**
- スタイルを文字列で直接記述していますが、JSX内ではオブジェクトリテラルとして記述する必要があります。
修正例:
```tsx
<div style={{ color: 'red' }}>This is red</div>
```
---
### **総合評価 (65/100)**
#### **総評**
このコードは、基本的なReactの構文ミスや状態管理の誤りが見られます。適切に状態を初期化し、構文エラーを修正することで、より安定したコードになります。特に、`useEffect`の依存配列と`onClick`イベントの扱いを適切にすることが重要です。
修正後のコードを再レビューする場合は、さらに精査を行います。
いかがでしょうか?このコードに対する評価としては全体的に評価点が高すぎる気もしますが、一通りの指摘はされています。(一部まだ指摘できそうな点はありますが...)
おわりに
最後までお読みいただきありがとうございました!
ChatGPTによるコードレビューは、特に個人開発や初心者の方にとっては有用な手段であると考えています。
ただし、その結果を鵜呑みにせず、自分で考えることが最重要だと思っているので、その点を踏まえて活用していただければと思います!