誤解を防ぐ変数・関数名の付け方 - 明確で一貫性のある命名でバグを減らす方法

# 誤解を防ぐ変数・関数名の付け方 - 明確で一貫性のある命名でバグを減らす方法
理解しやすいコードを書くためには、誤解されない関数名や変数名をつけることが大切である。

## あいまいな名前を避ける

曖昧な言葉を使うと、誤解されるコードになる。

```javascript
// 曖昧な例
const result = database.allRecords.filter(record => record.year <= 2025);
```

この場合の`filter`で考えられる動作として以下の2つが考えられる:
- 「 year <= 2025 」の**条件に一致する**オブジェクト
- 「 year <= 2025 」の**条件に一致しない**オブジェクト

名前が曖昧だと、開発者によって解釈が異なる可能性がある。このような場合は、より明確な名前を使うべきである。例えば:

```javascript
// より明確な例
const result = database.allRecords.where(record => record.year <= 2025);
// または
const matchingRecords = database.allRecords.filter(record => record.year <= 2025);
```

## 限界値を含むかどうかを明確にする

例えば、範囲を表す時に「limit」という言葉は曖昧である。

```javascript
// これは10個以上でエラーなのか、11個以上でエラーなのか？
const CART_TOO_BIG_LIMIT = 10;
if (shoppingCart.getItemCount() >= CART_TOO_BIG_LIMIT) {
  throw new Error("カート内のアイテムが多すぎます。");
}
```

より明確にするには「min」や「max」などの言葉を使う:

```javascript
const MAX_ITEMS_IN_CART = 10;
if (shoppingCart.getItemCount() > MAX_ITEMS_IN_CART) {
  throw new Error("カート内のアイテム数が上限を超えています。最大: " + MAX_ITEMS_IN_CART);
}
```

## 範囲の表現には適切な名前を

範囲を表す変数名も慎重に選ぶべきである。

### 閉区間（両端を含む）には「first」と「last」を使う

| 変数名 | 意味 |
| --- | --- |
| first | 範囲の開始位置（含む） |
| last | 範囲の終了位置（含む） |

例えば、配列のインデックス[1, 3]は以下のように表現できる:

|  | | first | | last | |
| --- | --- | --- | --- | --- | --- |
| インデックス | 0 | **1** | **2** | **3** | 4 |
| 要素 | ~~A~~ | **B** | **C** | **D** | ~~E~~ |

この場合:
- first = 1 (Bを含む)
- last = 3 (Dを含む)

```javascript
// [first, last]の範囲（両方含む）
function getElementsInRange(array, { first = 1, last = 3 }) {
  // firstからlastまでの要素を取得（両端を含む）
  return array.slice(first, last + 1); // last + 1 とすることで last も含める
}

// 使用例
const letters = ['A', 'B', 'C', 'D', 'E'];
const result = getElementsInRange(letters, { first: 1, last: 3 });
console.log(result); // ['B', 'C', 'D']
```

### 半開区間（始点を含み、終点を含まない）には「begin」と「end」を使う

| 変数名 | 意味 |
| --- | --- |
| begin | 範囲の開始位置（含む） |
| end | 範囲の終了位置（含まない） |

例えば、配列のインデックス[1, 4)は以下のように表現できる:

| | | begin | |  | end |
| --- | --- | --- | --- | --- | --- |
| インデックス | 0 | **1** | **2** | **3** | 4 |
| 要素 | ~~A~~ | **B** | **C** | **D** | ~~E~~ |

この場合:
- begin = 1 (Bを含む)
- end = 4 (Eを含まない)

```javascript
// [begin, end)の範囲（beginは含み、endは含まない）
function getElementsInOpenRange(array, { begin = 1, end = 4 }) {
  // beginからend-1までの要素を取得
  return array.slice(begin, end); // JavaScriptのsliceはendを含まないので調整不要
}

// 使用例
const letters = ['A', 'B', 'C', 'D', 'E'];
const result = getElementsInOpenRange(letters, { begin: 1, end: 4 });
console.log(result); // ['B', 'C', 'D']
```

## ブール値の変数名

ブール値の変数名は特に注意が必要である。

```javascript
// 曖昧な例 - これは「パスワードを読み込む必要がある」のか「パスワードが読み込まれた」のか不明
let readPassword = true;
```

ブール値には「is」「has」「can」「should」などのプレフィックスを付けるとよい:

```javascript
// 明確な例
const isAuthenticated = true;
const hasPermission = false;
const canEdit = true;
const shouldRetry = false;
```

「xxxFlg」という命名パターンも注意が必要である:

```javascript
// 曖昧な例
let deleteFlg = true; // これは「削除済み」なのか「削除対象」なのか不明確
let activeFlg = false; // 否定の状態が何を意味するのか分かりにくい
```

より明確な命名方法:

```javascript
// 明確な例
const isDeleted = true; // 「削除済み」という状態が明確
const isActive = false; // 「アクティブではない」ことが明確
const shouldDelete = true; // 「削除すべき」という意図が明確
```

また、否定形よりも肯定形を使うほうが理解しやすくなる:

```javascript
// 悪い例
const disableSsl = false;
const notCompleted = true;
const deleteFlg = false; // 「削除フラグがオフ」という二重否定的な意味になる

// 良い例
const useSsl = true;
const isInProgress = true;
const isActive = true; // 「アクティブである」という肯定的な意味
```

## 期待に沿った名前をつける

関数名が実際の動作と一致していることも重要である。

```javascript
// getMeanという名前だが、実際には計算処理が必要
class Statistics {
  getMean() {
    // すべてのサンプルを反復処理して計算するので重い処理
    return this.samples.reduce((sum, value) => sum + value, 0) / this.samples.length;
  }
}
```

この場合、「get」は通常、軽量な操作を意味する。しかし実際には計算処理が必要なので、「compute」を使うほうが適切である:

```javascript
class Statistics {
  computeMean() {
    // 計算処理が必要なことが名前から明確
    return this.samples.reduce((sum, value) => sum + value, 0) / this.samples.length;
  }
}
```

## 単位や状態を名前に含める

変数名に単位や状態を含めると、誤解を防ぐことができる:

```javascript
// 悪い例
function startProcess(delay) { /* ... */ }
function createCache(size) { /* ... */ }
function throttleDownload(limit) { /* ... */ }

// 良い例
function startProcess(delayMs) { /* ... */ }
function createCache(sizeMb) { /* ... */ }
function throttleDownload(maxKbps) { /* ... */ }
```

データの状態を示す場合:

```javascript
// 悪い例
const password = "abc123";
const comment = "<p>ユーザーコメント</p>";
const html = "<div>コンテンツ</div>";

// 良い例
const plaintextPassword = "abc123";
const unescapedComment = "<p>ユーザーコメント</p>";
const htmlUtf8 = "<div>コンテンツ</div>";
```

## まとめ

良い名前を選ぶことは、コードの品質に大きく影響する。誤解されない名前をつけることで:

- チームメンバーがコードを理解しやすくなる
- バグの発生リスクが下がる
- 将来のメンテナンスがしやすくなる

名前を選ぶときは、「他の開発者がこの名前を見たとき、誤解なく理解できるか？」と自問するとよい。

## 参考文献
- 『リーダブルコード』（Dustin Boswell, Trevor Foucher 著、角征典 訳、オライリー・ジャパン、2012年）