Python JavaScript | プログラミングの繰り返し処理でマジックナンバーを避ける方法

JavaScript
スポンサーリンク

「なんとなく書いた数字」が、後からあなたや他の人を困らせる。それがマジックナンバー。まずは意味をつかんで、繰り返し処理(ループ)での具体的な回避テクを身につけましょう。


マジックナンバーの基礎

  • 定義: コードの中に直接書かれた、意味が読み取れない数値(や文字列)。例: for i in range(10): ... の「10」が何の上限なのか不明だと、マジックナンバーになります。
  • なぜ問題か: 可読性・保守性が落ち、変更時に影響箇所を見落としやすい。意図が伝わらないので、理解やバグ修正に余計な時間を使います。
  • 避け方の基本: 意味のある定数名・変数名を使う(例: MAX_USERS = 10)。命名により「何の10か」がコードから分かるようにします。

マジックナンバーは「コードの意図を曖昧にする代表例」。定数化・命名で意図を表現すると、可読性・保守性が大幅に向上します。


まず押さえるループの基本形

  • for: 回数が決まっているときに使う(例: 配列の長さ分まわす)。
  • while: 終了条件が状態で決まるときに使う(例: 入力が空でない間)。

ループの「回数・終了条件」にこそマジックナンバーが紛れ込みやすいので、そこに名前を与えるのが最優先です。


ループでマジックナンバーを避ける5つの鉄則

  1. 意味を名前にする(定数化)
    • 例: MAX_RETRY = 3 にして for _ in range(MAX_RETRY): ...
    • 「3回」は「何の3回?」を定数名で説明する。
  2. データから条件を導く(長さや境界は参照)
    • 配列や文字列の長さで回すなら、len(items) を使う。
    • 固定数の 10 より len(users) のほうが安全。
  3. ドメイン値は1箇所に集約(設定やコンフィグ)
    • 税率、タイムアウト、上限値などは設定ファイルや冒頭の定数へ。
    • 変更はその1箇所だけにすれば済む。
  4. 条件は“意味のある関数”に包む
    • 例: is_expired(now, deadline)within_limit(i, LIMIT) にして、式を直書きしない。
  5. 境界の意図をコメントで補足(最小限)
    • 命名で足りなければ、なぜその値かの理由を短く添える。

定数やデータ参照を使うのは、可読性・保守性を高めるための王道の対策です。


具体例で学ぶ(PythonとJavaScript)

Python

# 悪い例:何の10かわからない
for i in range(10):
    process(i)

# 良い例:意味を名前にする
MAX_BATCH_SIZE = 10  # 1バッチで処理する最大件数
for i in range(MAX_BATCH_SIZE):
    process(i)

# データに合わせる例:固定値をなくす
users = fetch_users()
for i in range(len(users)):  # または for user in users:
    process(users[i])

# 期限やリトライの例
MAX_RETRY = 3
TIMEOUT_SEC = 5  # 通信の待ち時間の上限秒数(要件から決定)
for attempt in range(MAX_RETRY):
    if call_api(timeout=TIMEOUT_SEC):
        break
Python

JavaScript

// 悪い例
for (let i = 0; i < 60; i++) {
  tick();
}

// 良い例
const TICKS_PER_MINUTE = 60; // 1分間のtick数
for (let i = 0; i < TICKS_PER_MINUTE; i++) {
  tick();
}

// 配列に合わせる例
const items = getItems();
for (let i = 0; i < items.length; i++) {
  process(items[i]);
}
// さらに良い:for...ofで意図が明確
for (const item of items) {
  process(item);
}
JavaScript

よくあるマジックナンバーと置き換えパターン

  • ループ回数の固定値
    • 置き換え: 定数化MAX_RETRYPAGE_SIZE
  • 配列のインデックス上限
    • 置き換え: 長さ参照items.lengthlen(items)
  • 時間やタイムアウト
    • 置き換え: 単位付き定数TIMEOUT_SECRETRY_DELAY_MS
  • ドメイン固有の数字(税率、閾値)
    • 置き換え: 設定値・定数TAX_RATEALERT_THRESHOLD
  • 境界のオフセット(+1、-1)
    • 置き換え: 意味付き関数is_last_index(i, items)

初心者向けチェックリスト

  • 数字に「意味のラベル」を付けたか?(定数・変数名)
  • 固定値の代わりに「データの長さ」を使えるか?
  • 同じ数字を複数箇所で繰り返していないか?(1箇所に集約)
  • 単位は明示したか?MSSECMB
  • なぜその値なのか、将来変わる可能性は?(コメントや設定に)

例外的に“直書きでもよい”ことがある

  • 普遍的な数学定数や慣例的な小さな値
    • 例: 0(初期値)、1(インクリメント)、-1(最後の要素)などは、文脈が自明なら許容されることが多い。
    • ただし「文脈が自明でない」なら、やはり名前を付けるほうが安全。

まとめ

  • マジックナンバーは「意味が分からない数字」。ループでは回数・境界・時間が特に危険地帯。定数化、データ参照、関数抽象で「意図をコードに刻む」のが最善です。

ソースコードに直接書いた謎の値は、可読性・保守性を下げます。意味のある定数・変数名を使うことで、意図が明確になり、将来の変更にも強いコードになります。

タイトルとURLをコピーしました