プログラムの命名規則

1. なぜ命名規則が重要なのか

変数・関数・クラス・パッケージなどの名前は、コードを読む人(未来の自分を含む)が最初に触れる情報です。命名が適切であれば、実装の中身を読まなくても役割や意図が伝わり、次のような効果が得られます。

  • 可読性の向上:名前だけで役割や目的が推測できる
  • 保守性の向上:バグの特定や機能追加がしやすくなる
  • チーム開発の効率化:レビューや引き継ぎがスムーズになる
  • 事故の防止:後述するように、命名の曖昧さや紛らわしさは実際のバグやセキュリティ事故に直結することがある

命名規則は「好み」の問題ではなく、品質・セキュリティに関わるエンジニアリングの基本事項として扱う。


2. 基本原則

2.1 意図を正確に表す

抽象的すぎる語(get, data, temp, flag, check など)は避け、具体的な動詞・対象を選ぶ。

悪い例 良い例 理由
getUserData() fetchUserFromDB() / loadUserFromFile() getだけでは取得元が分からない
data orderList, userProfile 何のデータか不明
flag isPublished, hasError 真偽値の意味が不明瞭
temp tempFilePathBeforeUpload スコープが広がると意味を見失う

2.2 名前と実体を一致させる

名前は実装の現状を正しく反映していなければならない。仕様変更で実体が変わったら、名前も追従してリネームする。

例:文字色を赤にするために RED というクラス名を付けた場合、後で色を青に変更すると class="RED" なのに青文字、という矛盾が発生する。

2.3 単位・型・変換の方向を名前に含める

数値に単位がある場合や、形式変換を行う関数では、単位や変換元・変換先を名前に含めることで、実装を見ずに意味が分かるようにする。

timeoutMs        // ミリ秒であることが明確
convertMinutesToSeconds(min)  // 変換の方向が明確
priceInJPY

2.4 真偽値・状態を表す語彙を統一する

チーム内でプレフィックスのルールを決め、必ず統一する。

プレフィックス 意味
is 状態 isActive, isEnabled
has 所有 hasPermission, hasError
can 可能性 canEdit, canDelete
should 必要性・義務 shouldRefresh, shouldRetry

二重否定は避けるisNotDisabled, notFound = false など)。条件式を組み立てる際に論理が反転しやすく、実務でも頻出のバグ原因になる。

2.5 言語・フレームワークの慣習に従う

  • Python:snake_case(変数・関数)、PascalCase(クラス)、UPPER_SNAKE_CASE(定数)
  • Java / JavaScript:camelCase(変数・関数)、PascalCase(クラス)
  • 定数:全言語共通で大文字+アンダースコア区切りが一般的

プロジェクト固有のルールがある場合は、それを言語標準より優先する。

2.6 ハンガリアン記法は基本的に非推奨

変数名の先頭に型を表す接頭辞を付けるハンガリアン記法(iCount, strName など)は、近年ではほとんどの言語・プロジェクトで非推奨とされている。型推論やIDEの型表示機能が発達した現在では、可読性を下げる要因になりやすい。

2.7 ルールの運用

  • スタイルガイドを文書化し、チームで共有する
  • ESLint / Pylint などの静的解析ツールで機械的にチェックする
  • コードレビューで命名の妥当性も確認項目に含める
  • リネーム(命名変更)を行う際は、影響範囲(外部API、設定ファイル、ログ解析ツールなど文字列として名前を参照している箇所)を事前に洗い出す

3. 失敗事例

事例1:パッケージ名の類似によるサプライチェーン攻撃(npm crossenv, 2017年)

人気パッケージ cross-env と紛らわしい crossenv(ハイフンなし)という名前の悪意あるパッケージが公開された。中身は正規パッケージと同じ機能を持ちながら、環境変数(npmの認証トークンなど)を密かに収集し、外部サーバーへ送信する不正コードが仕込まれていた。摘発までに数百のホストがダウンロードしたと報告されている。

教訓:パッケージ名・ライブラリ名の「紛らわしさ」は、単なる可読性の問題を超えてセキュリティインシデントに直結する。外部パッケージを導入する際は、公式リポジトリのURLやダウンロード数、スペルを必ず確認する。同様の手口(文字の入れ替え、ハイフン/アンダースコアの混同、スコープの偽装など)は他のパッケージレジストリ(PyPI, RubyGems)でも繰り返し発生している。

事例2:曖昧な名前によるクラス名と実体の矛盾

CSSのクラス名を色そのもの(REDなど)で命名した結果、デザイン変更で色を変えた際に名前と見た目が矛盾する状態になった。

教訓:見た目や実装の詳細をそのまま名前にすると、変更に弱くなる。「役割」(例:highlightText)で命名する方が変更に強い。

事例3:二重否定による条件分岐バグ

isNotDisabled のような二重否定の真偽値名を使ったコードで、if (!isNotDisabled) のような条件式が生まれ、レビュー・実装の両方で論理を誤読しやすくなり、意図と逆の分岐が実行されるバグが発生した。

教訓:真偽値は肯定形で統一する(isDisabled を使い、否定が必要な箇所は !isDisabled とする)。

事例4:単位を含まない変数名による不整合

距離や時間などの数値変数に単位を含めなかったため、モジュール間でkmとmile、msと秒など単位の解釈が食い違い、計算結果が大きくずれる不具合につながった。1999年のNASA火星探査機喪失事故(単位系の不一致が一因)は、命名そのものの問題ではないが、「名前だけでは単位が分からない」ことの危険性を象徴する事例としてよく引用される。

教訓:単位を持つ値は変数名に単位を含める(timeoutMs, distanceKm など)。

事例5:予約語・大文字小文字の違いによる衝突

  • Windowsでは CON, PRN, AUX, NUL, COM1COM9, LPT1LPT9 という名前のファイル・フォルダを作成できない。これを知らずに命名規則(例:ログファイル名にCOM1.logなど)を設計すると、特定の名前だけ処理が失敗する。
  • 大文字小文字だけで区別した命名(userUser)は、大文字小文字を区別しないファイルシステム(Windows/macOSの標準設定)でファイル名が衝突する原因になる。

教訓:命名規則はOS・ファイルシステム・実行環境の制約も考慮して設計する。


4. チェックリスト(運用時に確認する項目)

  • [ ] 名前だけで役割・目的が推測できるか
  • [ ] 実装の現状と名前が一致しているか(リネーム漏れがないか)
  • [ ] 単位・型・変換の方向を含める必要がないか
  • [ ] 真偽値は肯定形で統一されているか(二重否定を避けているか)
  • [ ] プロジェクトの言語・フレームワークの慣習に沿っているか
  • [ ] 外部パッケージ導入時に、名前の紛らわしさ(タイポスクワッティング等)を確認したか
  • [ ] OS・ファイルシステムの予約語・大文字小文字の扱いを考慮しているか
  • [ ] リネーム時に外部連携・設定ファイル・ログ解析への影響を確認したか