Day 79:コードレビュー
Day 79では、自分が書いたコードを読み返し、わかりやすさや安全性、修正のしやすさを確認する「コードレビュー」を学びます。今回のチェック項目は、変数名、関数の長さ、重複コード、コメント、エラー処理です。
コードレビューは、間違い探しだけではありません。コードをほかの人が読んでも理解できるか、あとから自分が修正しやすいかを確かめる作業です。自分のコードを少し時間を置いて読み直すことも、立派なレビューになります。
コードレビューをする順番
いきなり細かい書き方を直すのではなく、まずコードの目的と動作を確認します。次の順番で見ていくと、レビューしやすくなります。
- このコードが何をするのか、短く説明します。
- 実際に動かし、正常時と失敗時の動作を確かめます。
- 変数名や関数名から、役割が想像できるか確認します。
- 長すぎる関数や重複している処理がないか確認します。
- コメントやエラー処理が必要な場所を確認します。
- 変更したら、もう一度同じ動作を確認します。
例題:ユーザー検索コードをレビューする
まず、レビュー対象として、ユーザー情報を取得して検索結果を表示するコードを考えます。次のコードには、意図的に改善できる点をいくつか含めています。
// 学習用の例:ひとつの処理に複数の役割が集まっている
async function run() {
const r = await fetch("https://jsonplaceholder.typicode.com/users");
const d = await r.json();
const q = document.getElementById("keyword").value;
const x = d.filter(function (u) {
return u.name.includes(q);
});
const list = document.getElementById("results");
list.innerHTML = "";
x.forEach(function (u) {
const li = document.createElement("li");
li.textContent = u.name;
list.appendChild(li);
});
document.getElementById("message").textContent =
`${x.length}件見つかりました。`;
}JavaScriptこのコードは、基本的な検索はできます。しかし、レビューすると、次の点を確認できます。
- `r`、`d`、`q`、`x`、`u`は、値の意味が読み取りにくい名前です。
- `run()`が通信、検索、画面表示をまとめて担当しています。
- 通信に失敗したときの処理がありません。
- `response.ok`を確認していないため、HTTPエラーを適切に扱えません。
- 入力値が空の場合や、検索結果が0件の場合の扱いを明確にしたいです。
- 検索処理と表示処理を分けると、確認や修正がしやすくなります。
チェック1:変数名は分かりやすいか
変数名を見ただけで、どんな値が入っているか想像できるかを確認します。
- `d`より`users`のほうが、ユーザー一覧だとわかります。
- `q`より`keyword`のほうが、検索語だとわかります。
- `x`より`matchedUsers`のほうが、検索に一致したユーザーだとわかります。
変数名は、何文字以上ならよいという決まりはありません。短すぎて意味がわからない名前を避け、役割が伝わる長さにします。
チェック2:関数が長すぎないか
関数を読んだときに、複数の異なる役割が混ざっていないか確認します。例題のrun()は、API通信、検索、画面更新、メッセージ表示をすべて行っています。これを役割ごとに分けると、問題が起きたときに確認する場所が絞りやすくなります。
ただし、すべての処理を細かく関数にすればよいわけではありません。関数名で目的が伝わり、まとまったひとつの仕事を担当しているかを目安にします。
チェック3:重複コードがないか
同じ処理が複数箇所にあると、あとで表示方法やルールを変えるときに、修正漏れが起きやすくなります。たとえば、メッセージ要素の更新方法が何度も出てくる場合は、共通関数にできます。
// メッセージの表示を共通化する
function setMessage(messageElement, text) {
messageElement.textContent = text;
}JavaScriptただし、見た目が似ているだけで目的が違う処理を、無理にひとつにまとめる必要はありません。共通化する前に、処理の目的やルールが本当に同じかを確認します。
チェック4:コメントは必要か
コメントは、コードを読めばすぐわかることを繰り返すより、「なぜこの処理が必要なのか」「どんな前提があるのか」を説明するために使います。
// よい例:この確認をする理由がわかる
if (!response.ok) {
throw new Error("ユーザー情報を取得できませんでした。");
}JavaScript一方、次のようなコメントは、コードと同じ内容を繰り返しているだけなので、あまり役に立ちません。
// よくない例:コードをそのまま説明している
// messageに文字列を設定する
message.textContent = "検索が完了しました。";JavaScriptコメントが古くなると、コードと説明が食い違うことがあります。処理を変更したときは、関連するコメントも一緒に見直しましょう。
チェック5:エラー処理があるか
API通信では、ネットワークの問題やサーバー側のエラーが起きる可能性があります。fetch()は通信に失敗した場合に例外を投げますが、HTTPのエラー応答ではresponse.okを確認する必要があります。
利用者には状況がわかる案内を表示し、開発者が調査できる詳細はコンソールに出すなど、用途を分けるとよいです。
レビュー後の改善例
次の例では、API取得、検索、表示、全体の進行を関数ごとに分けています。HTMLには、keyword、searchForm、results、messageというIDの要素がある想定です。
// HTML要素を取得する
const searchForm = document.getElementById("searchForm");
const keywordInput = document.getElementById("keyword");
const resultList = document.getElementById("results");
const message = document.getElementById("message");
// APIからユーザー一覧を取得する
async function fetchUsers() {
const response = await fetch(
"https://jsonplaceholder.typicode.com/users"
);
// fetchはHTTPエラー時に自動で例外を投げないため確認する
if (!response.ok) {
throw new Error(`通信に失敗しました(${response.status})`);
}
const users = await response.json();
// 受け取ったデータが配列か確認する
if (!Array.isArray(users)) {
throw new Error("ユーザー情報の形式が正しくありません。");
}
return users;
}
// 名前またはメールアドレスでユーザーを絞り込む
function filterUsers(users, keyword) {
const normalizedKeyword = keyword.trim().toLowerCase();
return users.filter(function (user) {
// 欠けている値があっても検索処理が止まらないようにする
const name = String(user.name ?? "").toLowerCase();
const email = String(user.email ?? "").toLowerCase();
return (
name.includes(normalizedKeyword) ||
email.includes(normalizedKeyword)
);
});
}
// 検索結果を画面に表示する
function renderUsers(users) {
// 前回の結果を削除する
resultList.replaceChildren();
users.forEach(function (user) {
const item = document.createElement("li");
// 外部データはHTMLとして解釈させず、文字として表示する
item.textContent = `${user.name ?? "名前不明"} / ${user.email ?? "メールアドレス不明"}`;
resultList.appendChild(item);
});
}
// フォームが送信されたときに検索する
searchForm.addEventListener("submit", async function (event) {
// フォーム送信によるページ再読み込みを防ぐ
event.preventDefault();
const keyword = keywordInput.value.trim();
// 空欄の場合は検索せず、案内を表示する
if (keyword === "") {
resultList.replaceChildren();
setMessage(message, "キーワードを入力してください。");
return;
}
try {
setMessage(message, "検索中です...");
// APIからデータを取得し、キーワードで絞り込む
const users = await fetchUsers();
const matchedUsers = filterUsers(users, keyword);
// 結果と件数に応じた案内を表示する
renderUsers(matchedUsers);
if (matchedUsers.length === 0) {
setMessage(message, "該当するユーザーが見つかりませんでした。");
return;
}
setMessage(message, `${matchedUsers.length}件見つかりました。`);
} catch (error) {
// 利用者向けの案内と開発者向けの詳細を分ける
setMessage(message, "検索できませんでした。時間をおいて再度お試しください。");
console.error("ユーザー検索のエラー:", error);
}
});
// メッセージを画面に表示する共通関数
function setMessage(element, text) {
element.textContent = text;
}JavaScriptこの改善例では、fetchUsers()が通信、filterUsers()がデータ処理、renderUsers()が画面表示を担当しています。イベント処理は、それらを必要な順番で呼び出します。
改善後に動作を確認する
レビューでコードを変更したら、変更前に確認した動作をもう一度試します。
- 名前で検索したとき、該当するユーザーが表示されるか確認します。
- メールアドレスの一部でも検索できるか確認します。
- 空欄で送信したとき、案内が表示されるか確認します。
- 該当データがないとき、専用メッセージが表示されるか確認します。
- 通信に失敗したとき、エラー案内が表示されるか確認します。
レビューは、見た目を整えて終わりではありません。コードの変更後も、期待した動作が保たれていることを確かめて完了です。
そのまま使えるレビュー用チェックリスト
自分のコードを見直すときは、次の項目を使えます。
- 変数名や関数名から、役割が想像できますか。
- 関数が複数の役割を抱え込んでいませんか。
- 同じ処理を何度も書いていませんか。
- コメントは、理由や注意点を説明していますか。
- 通信や入力で問題が起きた場合の処理がありますか。
- 空欄や0件など、通常と異なる入力も確認しましたか。
- 外部データを画面へ安全に表示していますか。
- 変更後に、主要な動作を再確認しましたか。
すべてを一度に完璧に直す必要はありません。気づいた改善点を記録し、動作を確認しながら小さく直していくことが大切です。
Day 79のゴール
Day 79では、次のことができるようになっていれば十分です。
- 自分のコードを、利用者や次の開発者の視点で読み直せます。
- わかりにくい名前や長すぎる関数を見つけられます。
- 重複コードや不足しているエラー処理に気づけます。
- コメントが本当に理解の助けになっているか判断できます。
- 変更後に動作を確認し、レビュー内容を反映できます。
まとめ
Day 79では、自分のコードをレビューする方法を学びました。変数名がわかりやすいか、関数が長すぎないか、重複コードがないか、コメントが役立っているか、エラー処理があるかを確認します。
コードレビューは、コードを批判することではなく、より読みやすく、修正しやすく、安心して使える状態へ近づける作業です。最初に動作を確認し、改善点を一つずつ直し、最後に同じ操作で再確認する習慣を身につけましょう。
