ベストプラクティス:クリーンで効率的なコードを書くためのヒント【JavaScript】

記事サムネイル

JavaScriptで開発を行う際、コードを読みやすく、バグが少なく、メンテナンスしやすくすることは非常に重要です。
これを実現するために、いくつかのベストプラクティスに従うことで、よりクリーンで効率的なコードを書くことができます。
この記事では、コード品質を向上させるためのヒントを具体例とともにご紹介します。

この記事のポイント

  • クリーンなコードを書くためのテクニックがわかる

一貫性のある命名規則を使う

変数、関数、クラスなどの名前は、コードの可読性を大きく左右します。
JavaScriptの命名規則として一般的なスタイルは以下です。

特徴

  • キャメルケース(ローワーキャメルケース):
    変数や関数には小文字から始まるキャメルケース(例: myVariable)を使用
  • パスカルケース(アッパーキャメルケース):
    クラス名には大文字から始まるパスカルケース(例: MyClass)を使用
  • アッパースネークケース:
    定数 (特に設定値、環境変数)などには、アッパースネークケースを使用(例:SETTING_VALUE)を使用

良い例

let userName = "John";   // 変数

function calculateTotal() {   // 関数
  // 処理
}

class UserProfile {   // クラス
  // プロパティとメソッド
}

悪い例

let username;         // 読みにくい

function calc_Total() {   // 不統一な表記
  // 処理
}

class userprofile {   // 一貫性のないケース
  // プロパティとメソッド
}

変数には constlet を使う

ES6以降、var の代わりに constlet を使うのがベストプラクティスです。
const は再代入できない変数、let は再代入可能な変数を宣言するために使います。
また、再代入することのない変数の定義にletを使うのも、予期せぬ再代入の可能性を生むため、お勧めしません。

良い例

const PI = 3.14159;  // 再代入しない定数
let total = 0;       // 再代入する変数

悪い例

var pi = 3.14159;    // `var` はスコープの制約が弱い
var total = 0;       // 不要な再代入を許してしまう

ver, let, constの詳しい使い分けについては別の記事で紹介しているので、参考にしてみてください。
https://join.codevillage.jp/blog/2327/

条件文を簡潔に書く

シンプルな条件文は、読みやすく理解しやすいコードにするための重要な要素です。
必要のないネストや冗長な条件式は避けましょう。
ただし、短ければ必ずいいというわけではなく、クリーンコードを書くには、
他の人が読んでわかりやすいか・意図が伝わるコードか(可読性)なども考慮する必要があります。

良い例

// 三項演算子を使ってシンプルに
function getUserName(user) {
  return user ? user.name : "Guest";
}

あまり好ましくない例

// ネストがあり、冗長なコード
function getUserName(user) {
  if (user !== null && user !== undefined) {
    return user.name;
  } else {
    return "Guest";
  }
}

三項演算子についても別の記事で紹介しているので、参考にしてみてください。
https://join.codevillage.jp/blog/2713/

コメントを入れる

関数やクラスに説明文を加えることで、コードの意図や使い方を明確にできます。
JavaScriptでは、JSDoc形式のコメントを使うと、コードエディタで補完機能や自動生成ドキュメントが活用できることが多いです。
通常の「//」をつけたコメントで補足を入れるのも良いです。

ただし、わかりやすくなるといえ、コメントを毎回書くと量が多くなり視認性が悪くなるので、必要なものだけにとどめましょう。
変数名・関数名などで意味を表現できることは、命名で表現しましょう。
良いコメントのポイントは、それを実装した背景の説明などコードで表現できないことを書くということです。

良い例

/**
 * 2つの数値を加算する
 * @param {number} a - 最初の数値
 * @param {number} b - 2つ目の数値
 * @returns {number} 合計
 */
function add(a, b) {
  return a + b;
}


// A社の足し算用に使用
function add2(a, b) {
  return a + b;
}

あまり好ましくない例

// ユーザー名を取得する関数  →コードからわかることを書いているため、無意味なコメントになっている
function getUserName(user) {
  return user.name;
}

不要なコードを削除する

使われていない変数や関数、不要なコメントアウトなどのコードは定期的に削除し、コードベースを整理しましょう。
これにより、コードが読みやすくなり、無駄なメモリ消費も防げます。

良い例

// クリーンなコード
function greetUser(name) {
  console.log(`Hello, ${name}`);
}

悪い例

// 不要なコードが多く含まれる
function greetUser(name) {
  // これは以前のバージョンで必要だったコメント
  let unusedVariable = "This is not used";
  console.log("Hello, " + name);
}

特に理由がなければ、==(等価演算子)よりも ===(厳密等価演算子)を使う

===(厳密等価演算子)は、型の変換を行わずに値と型の両方を比較するため、思わぬ型変換によるバグを避けることができます。
==(等価演算子)は異なる型同士でも比較が可能ですが、暗黙の型変換が行われるため、予期せぬ動作を引き起こしやすいです。

== の例(暗黙的な型変換が行われる)

console.log(0 == "0");   // true(文字列 "0" が数値 0 に変換される)
console.log(false == 0); // true(false が数値 0 に変換される)
console.log(null == undefined); // true(特別な例)

=== の例(厳密に型も比較される)

console.log(0 === "0");   // false(異なる型のため false)
console.log(false === 0); // false(異なる型のため false)
console.log(null === undefined); // false(型が異なるため false)

データ型の種類については別のJS基礎記事で紹介しているので、参考にしてみてください。
https://join.codevillage.jp/blog/2571/#content-6

if 文やアロー関数の記法を省略する

JavaScriptでは、if 文やアロー関数の場合、記法を省略することで短く書くことができます。
アロー関数の本体が1行であれば {}return を省略することが可能です。

if文の省略

{ } を省略して1行で書くことができます。

// 省略前
if (age > 18) {
  console.log("You are an adult.");
}
if (age < 18) {
  return;
}

// 省略後
if (age > 18) console.log("You are an adult.");
if (age < 18) return;

アロー関数の省略

省略の説明として、基本的に{ }とreturnが省略できます。
( )は引数が1つの場合のみ省略できます。ない場合や2つ以上の差異は省略できません。

//省略前
const square = (num) => { return num * num};

// 省略後
const square = num => num * num;

if 文の早期リターンを使う

if 文で特定の条件が満たされた場合に早めに関数を終了させる「早期リターン」を使うと、
コードの実行を早く終了させられるため、パフォーマンスの改善につながります。
また、不要なネストを減らし、コードが簡潔で読みやすくなります。(可読性が向上)

知らない方のために、returnの前提知識を簡潔に説明します。
retrunが実行されると、returnより下のコードは実行されず、値が返却されてその時点で処理が終了します。

処理を早く終わらせる

例:早期リターンを使わない場合

function processNumber(number) {
  if (number === 0) {
    // 数が正の数の場合のみ、処理を続ける
    console.log("Positive number:", number);
    // その他の処理
  }
}

例:早期リターンを使った場合

function processNumber(number) {
  if (number !=== 0) return; // 早期リターンで関数終了

  console.log("Positive number:", number);
  // その他の処理
}

この場合、number が0以下であれば早めに関数が終了するため、それ以降の処理を実行しません。
結果として、if 文のネストが浅くなり、読みやすいコードになります。

if 文のネストが深くになる際に、浅くなる

複雑な条件でネストが増えるとコードが読みづらくなるため、条件を整理してネストを浅くするのがベストプラクティスです。
たとえば、複数の条件が同時に成り立つ場合は && 演算子を使って1つの条件にまとめたり、条件ごとに早期リターンを使うと効果的です。

例:ネストが深い場合

function checkUser(user) {
  if (user) {
    if (user.isActive) {
      if (user.hasPermission) {
        console.log("User has access");
      }
    }
  }
}

例:早期リターンを使った場合

function checkUser(user) {
  if (!user) return;
  if (!user.isActive) return;
  if (!user.hasPermission) return;

  console.log("User has access");
}

この場合、number が0以下であれば早めに関数が終了するため、それ以降の処理を実行しません。
結果として、if 文のネストが浅くなり、読みやすいコードになります。

エラーハンドリングを丁寧に行う

エラーが発生する可能性があるコードには、エラーハンドリングを追加することで、予期せぬ動作やプログラムのクラッシュを防ぐことができます。

良い例

try {
  const data = JSON.parse('{"name": "John"}'); // 正しいJSON
  console.log(data.name);
} catch (error) {
  console.error("JSONの解析に失敗しました:", error);
}

コードの再利用性を高める

重複するコードが多いと、メンテナンスが難しくなります。
再利用できる処理は関数に分け、必要な場所で呼び出すようにしましょう。

良い例

function calculateTax(price, taxRate) {
  return price * (1 + taxRate);
}

const product1 = calculateTax(100, 0.08);
const product2 = calculateTax(200, 0.08);

関数のデフォルト値を活用する

関数で、引数が指定されなかった場合にデフォルト値を使用することで、エラーを防ぎ、コードを簡潔にできます。

良い例

function greet(name = "Guest") {
  console.log(`Hello, ${name}`);
}

greet();         // "Hello, Guest" と表示
greet("Alice");  // "Hello, Alice" と表示

小さく、シンプルな関数を作成する

1つの関数には1つの責任を持たせると、コードが理解しやすくなります。
複雑な処理は小さな関数に分割し、わかりやすく整理しましょう。

なんでもできる関数を作るとメンテナンス性の悪化や使い方が複雑になります。

良い例

function getUserData(userId) {
  const user = fetchUser(userId);
  return formatUserData(user);
}

function fetchUser(userId) {
  // ユーザーをAPIなどから取得
}

function formatUserData(user) {
  // ユーザーデータを整形して返す
}

配列操作には map, filter, reduce などのメソッドを活用する

ループを使う際、JavaScriptには forEach mapfilterreduce など便利なメソッドがあり、これらを活用することでコードを簡潔に保てます。

for文を使うと記述が多くなったり、自分でロジックなどを実装する必要があったりしますが、
これらの標準メソッドを使用することで、比較的少ない記述で簡単に機能が実装できます。
不要なロジックはメソッドに任せて隠蔽した方が、保守性や可読性が高まり、クリーンコードになります。

良い例

const numbers = [1, 2, 3, 4, 5];
const doubledNumbers = numbers.map(number => number * 2); // 各要素を2倍に
const evenNumbers = numbers.filter(number => number % 2 === 0); // 偶数のみ抽出

簡潔に書け、メソッドに任せているためバグを生む可能性が減る。可読性が良い。

filter関数の機能を自分で実装した あまり好ましくない例

const numbers = [1, 2, 3, 4, 5, 6];
const evenNumbers = []; // 条件に合った要素を格納するための新しい配列

for (let i = 0; i < numbers.length; i++) {
  if (numbers[i] % 2 === 0) {
    evenNumbers.push(numbers[i]);
  }
}

console.log(evenNumbers); // [2, 4, 6]

まとめ

これらのベストプラクティスを守ることで、クリーンで効率的なJavaScriptコードを書くことができます。
命名規則やループメソッド、エラーハンドリングなどに注意を払いながら、チームでの開発や長期的な保守を見据えたコードを心がけましょう。

ただし、これまで紹介したのはテクニックの一例にすぎません。
「簡潔だから」「この通りにしていれば」必ずいいとは限らず、チームの方針によっても変わるので、
状況に応じて判断し、ベストなコードを書くことが重要です。

全てをこの記事で紹介できていないので、他のテクニックも気になる方は調べてみてください。

CodeVilageでは無料カウンセリングを実施しております!

まずはお気軽に無料カウンセリングへご参加ください!
「興味はあるけど、自分にできるか不安...」
「どんなキャリアを描けばいいのか分からない...」
そんなあなたのために!!
何でも相談できる無料カウンセリングを実施しています。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です