開発プロジェクトでは、「varを使わない」「関数名は動詞から始める」「1ファイルは○行以内」「例外を握りつぶさない」など、さまざまなコーディングルールが設けられます。そのとき議論になりやすいのが、ルールに従うメンバー全員が、そのルールの技術的な理由まで説明できる必要があるのかという問題です。
結論から整理すると、メンバー全員がすべてのルールについて背景や言語仕様まで詳しく説明できる必要はありません。一方で、プロジェクトとしてルールを採用している以上、そのルールの目的や根拠を誰も説明できない状態は好ましくありません。
重要なのは、「全員が専門家レベルで説明できること」と「チームとして説明可能なルールになっていること」を分けて考えることです。この記事では、JavaScriptのvar禁止を例に、コーディングルールの理由をどこまで理解すべきか、ルールをどう管理するとよいのかを解説します。
- コーディングルールには大きく2種類ある
- メンバー全員がルールの詳細を説明できる必要はない
- ただし「誰も理由を説明できないルール」は問題になりやすい
- 説明責任があるのは「個々のメンバー」より「ルールを管理するチーム」
- JavaScriptで「var禁止」が採用される理由
- varはブロックスコープではない
- varでは同じ名前を再宣言できる
- varはホイスティングの挙動が直感とずれることがある
- constを優先すると「変更しない変数」が明確になる
- ではvarを使うと必ずバグになるのか
- 「var禁止の理由を説明できない人」がいても、それ自体は問題ではない
- ルールを「守れること」と「説明できること」は別の能力
- ルールの理由を知らないことで困るのは「例外」が出たとき
- 理由のないルールは「カーゴ・カルト」になりやすい
- 良いコーディングルールには目的が書かれている
- すべてのルールに長文の技術解説は必要ない
- 自動化できるルールは人間に暗記させない
- レビューでは「ルールだから直して」だけにしないほうがよい
- コーディングルールは「法律」ではなく開発を助ける道具
- 「なぜ?」と聞ける文化はチームにとって有益
- ただし毎回すべてのルールを議論し直す必要もない
- ルールを変更する手順を決めておくと揉めにくい
- 例外を許さないルールほど理由の明確化が重要
- ルールの価値は「守らなかったとき何が起きるか」で考える
- ルールの根拠は「絶対的な正解」である必要はない
- 実務では「理由を知らない」より「理由を確認できない」ほうが問題
- おすすめのコーディングルール管理方法
- まとめ:全員が説明できる必要はないが、チームとして説明可能であるべき
コーディングルールには大きく2種類ある
コーディングルールを考えるときは、まず「技術的な事故を防ぐためのルール」と「書き方を統一するためのルール」を分けると整理しやすくなります。
例えば「SQL文字列を直接連結しない」「秘密情報をソースコードへ書かない」といったルールは、セキュリティや不具合を防ぐ明確な理由があります。一方、「文字列はシングルクォートに統一する」「末尾セミコロンを付ける」といったルールは、複数の正解がある中でスタイルを統一する目的が中心です。
この2種類を同じ強さで説明しようとすると、「なぜこの書き方でなければならないのか」という無用な議論が増えます。スタイル上のルールなら「チーム内で統一し、レビューのノイズを減らすため」という理由だけで十分な場合もあります。
メンバー全員がルールの詳細を説明できる必要はない
実務では数十、数百のルールをESLint、Prettier、Stylelintなどで適用することがあります。そのすべてについて、全メンバーが言語仕様や過去の不具合事例まで説明できる状態を求めるのは現実的ではありません。
例えば新人メンバーが「このプロジェクトではvarではなくconstかletを使う」と理解し、それに従ってコードを書けるのであれば、最初からvarのスコープ規則やホイスティングの細部まで説明できなくても実務上は問題にならないでしょう。
運転に例えるなら、「赤信号では止まる」というルールへ従うために、全員が信号制御システムの設計思想まで説明できる必要はありません。必要な行動を理解し、ルールを守れることにはそれ自体の価値があります。
ただし「誰も理由を説明できないルール」は問題になりやすい
一方で、チームの誰に聞いても「昔からそうだから」「前任者が決めたから」しか答えられないルールには注意が必要です。
技術環境は変化します。以前は妥当だった制約が、言語やツールの進化によって不要になっていることがあります。それでも理由を検証せず残していると、ルールそのものが開発効率を下げる可能性があります。
例えば、昔のブラウザ互換性を理由に特定構文を禁止していたプロジェクトで、現在は対象ブラウザが変わっているにもかかわらず禁止だけ残っている、という状況が典型例です。
説明責任があるのは「個々のメンバー」より「ルールを管理するチーム」
コーディングルールの理由を説明する責任は、全メンバーへ均等に求めるより、ルールを制定・管理する側が持つと考えるのが自然です。
例えばテックリード、アーキテクト、開発チーム全体などが、「なぜこのルールがあるのか」「どの問題を防ぐのか」「例外は認めるのか」をドキュメントとして残しておけば十分です。
一般メンバーは必要になったときにその資料を参照できればよく、すべてを暗記する必要はありません。知識を個人の記憶へ依存させず、チームの共有知識として残すことのほうが重要です。
JavaScriptで「var禁止」が採用される理由
JavaScriptのvar禁止は、比較的理由を説明しやすいコーディングルールです。現在のJavaScriptでは、変数宣言には主にconst、let、varがあります。
このうちvarは関数スコープを持ちます。一方、letとconstはブロックスコープです。そのためif文やfor文の波括弧内だけで使いたい変数について、letやconstのほうが有効範囲を限定しやすくなります。
例えば条件分岐の内部で宣言した変数が、意図せずその外側からも参照できると、コードが大きくなった際に変数の影響範囲を把握しにくくなることがあります。
varはブロックスコープではない
例えば次のようなコードを考えます。
if (true) {
var message = 'hello';
}
console.log(message);
varで宣言されたmessageはifブロックの外側からも参照できます。varはifの波括弧ではスコープを作らないためです。
一方、letなら次のコードのmessageはブロック外から参照できません。
if (true) {
let message = 'hello';
}
console.log(message); // ReferenceError
変数の有効範囲が狭いほど、どこで変更・参照されるかを追跡しやすいため、letやconstを優先する設計には合理的な理由があります。
varでは同じ名前を再宣言できる
varには、同じスコープ内で同じ名前を再宣言してもエラーにならないという特徴もあります。
var count = 1;
var count = 2;
このコードは実行可能です。一方、letやconstを同じスコープ内で再宣言すると構文エラーになります。
大きなコードでは、意図せず同名変数を宣言した場合に早い段階でエラーになったほうが、不具合を発見しやすいことがあります。そのため再宣言を許すvarを避けるという方針には保守性上の意味があります。
varはホイスティングの挙動が直感とずれることがある
varで宣言した変数は、その宣言がスコープの先頭へ移動したような挙動を示します。実際には宣言処理が先に行われ、代入は元の位置で実行されます。
console.log(value);
var value = 10;
このコードでは宣言前のvalueへアクセスしても、即座にReferenceErrorになるのではなくundefinedが得られます。
letやconstにも言語仕様上のホイスティングに関する挙動はありますが、宣言前にアクセスするとTemporal Dead ZoneによってReferenceErrorになります。そのため、誤った順序で変数を使った場合に問題を発見しやすくなります。
constを優先すると「変更しない変数」が明確になる
現在のJavaScriptでは、「再代入しない変数はconst、再代入が必要ならlet」というルールを採用するプロジェクトが多くあります。
例えば次のようなコードです。
const userName = 'Alice';
let retryCount = 0;
userNameは再代入しないことが宣言時点で分かり、retryCountは後で値が変わる可能性があることが読み手へ伝わります。
varではこの意図を宣言だけから区別できません。そのためconstとletを使い分けることには、単に新しい文法だからという以上にコードの意図を明確にするメリットがあります。
ではvarを使うと必ずバグになるのか
もちろん、varを使ったから必ず不具合が発生するわけではありません。長年JavaScriptを書いてきた開発者なら、varの仕様を理解したうえで安全に使うこともできます。
実際、ES2015より前のJavaScriptではvarが通常の変数宣言方法でした。世界中の大規模なアプリケーションがvarを使って開発されてきました。
したがって「varは危険だから絶対に使ってはいけない」というより、現在はletとconstという、より意図を表現しやすく事故を防ぎやすい選択肢があるため、通常はvarを選ぶメリットが少ないと理解するほうが正確です。
「var禁止の理由を説明できない人」がいても、それ自体は問題ではない
チーム内の一人に「なぜvar禁止なの?」と聞いて、その人が答えられなかったとしても、それだけでチームのルール運用が失敗しているとはいえません。
例えばその人がデザイナー寄りのフロントエンド担当だったり、入社したばかりだったりすれば、「ルールとしてconstとletを使う」と覚えていれば十分な時期もあります。
問題なのは、テックリードやルール文書まで確認しても理由が分からず、さらにそのルールを見直す方法も存在しない状態です。
ルールを「守れること」と「説明できること」は別の能力
コーディングルールには、まず実際のコードを統一する役割があります。そのため日々の開発では、ルールを正しく適用できることが最優先になります。
一方、ルールを改善したり例外を判断したりする人には、背景まで理解することが求められます。この二つは役割が違います。
| 立場 | 求められる理解 |
|---|---|
| 新規参加メンバー | 基本ルールを守れる |
| 通常メンバー | 主要ルールの目的を概ね理解する |
| レビュー担当 | ルールを適切に適用・説明できる |
| ルール制定者・テックリード | 根拠、例外、トレードオフを説明できる |
全員へ同じレベルの説明能力を要求する必要はありません。
ルールの理由を知らないことで困るのは「例外」が出たとき
普段は「var禁止」というルールを機械的に守っていても問題ありません。しかし特殊なケースで例外を認めるべきか判断するときには、ルールの目的を理解している必要があります。
例えば古いJavaScript環境との互換性を維持する必要があり、letやconstがそのまま使えない状況があったとします。そのとき「varは悪だから絶対禁止」という理解だけでは適切な判断ができません。
ルールの目的が「ブロックスコープを明確にして保守性を上げること」だと理解していれば、トランスパイル環境なども含めてより合理的に判断できます。
理由のないルールは「カーゴ・カルト」になりやすい
ソフトウェア開発では、背景を理解せず「有名企業がやっているから」「前の案件でもそうだったから」という理由だけで手法をコピーすることがあります。
こうした状態は、しばしばカーゴ・カルト的な開発と表現されます。本来の目的を失い、形式だけが残ってしまうからです。
例えば「関数は20行以内」というルールがあるとして、本来は複雑な巨大関数を防ぐことが目的だったのに、20行を超えた瞬間に意味のない関数分割を始めれば、むしろ読みづらくなる可能性があります。
良いコーディングルールには目的が書かれている
ルール文書では「○○は禁止」とだけ書くより、その理由を1~2行添えると運用しやすくなります。
例えば「varは禁止。変数のスコープを明確にし、意図しない再宣言を防ぐため、原則constを使用し、再代入が必要な場合のみletを使用する」と書けば十分です。
これなら新しく参加したメンバーも短時間で目的を理解できますし、将来ルールを見直すときにも判断材料になります。
すべてのルールに長文の技術解説は必要ない
一方で、コーディング規約を言語仕様の教科書にする必要はありません。
例えばインデントをスペース2個に統一する理由について、「タブとスペースの歴史」「各エディターでの表示差」まで何ページも説明する必要はないでしょう。「チーム内で表示を統一するため」で十分です。
詳しい技術的理由が必要なものだけ、公式ドキュメントやIssue、ADRなどへのリンクを付ければ運用しやすくなります。
自動化できるルールは人間に暗記させない
コーディングスタイルについては、可能な限りLintやFormatterへ任せたほうが効率的です。
JavaScriptならESLintでvarを禁止する「no-var」ルールなどを利用できます。そうすればコードレビューで毎回「varは禁止です」と人間が指摘する必要がありません。
さらにPrettierでフォーマットを自動化すれば、スペース数や改行位置のような議論も減らせます。
レビューでは「ルールだから直して」だけにしないほうがよい
コードレビューで「ルール違反です。直してください」とだけコメントすると、メンバーは理由を理解しないまま修正することになります。
頻繁に質問されるルールなら、「このプロジェクトではスコープを限定するためvarを禁止しています。ESLintのno-varも有効です」のように簡単な理由を添えると教育効果があります。
一度説明した内容を規約ドキュメントへ追記すれば、次からはリンクだけで済みます。
コーディングルールは「法律」ではなく開発を助ける道具
ルールを厳格に運用していると、いつの間にか「ルールを守ること」自体が目的になることがあります。
本来の目的は、バグを減らす、読みやすくする、レビューを効率化する、複数人で安全に開発する、といった成果を得ることです。
ルールを守った結果、コードが著しく複雑になるのであれば、そのルールや例外条件を見直す余地があります。
「なぜ?」と聞ける文化はチームにとって有益
既存ルールに対して「なぜこの決まりがあるのですか?」と質問すること自体は、否定的に捉える必要はありません。
その質問によって、ルールが現在も必要なのか確認できます。説明できるなら新メンバーの理解が深まり、説明できないなら調査・整理するきっかけになります。
「決まりだから黙って従う」より、「目的を確認しつつ最終的にはチームで合意したルールへ従う」という文化のほうが改善を続けやすくなります。
ただし毎回すべてのルールを議論し直す必要もない
理由を質問できることと、各メンバーが気に入らないルールを毎回ゼロから議論することは別です。
例えばインデント幅について、プルリクエストのたびに「4スペースのほうが良い」「2スペースが良い」と議論していたら開発が進みません。
一度チームで決めたスタイル上のルールは、見直しのタイミングまでは従うという運用も必要です。
ルールを変更する手順を決めておくと揉めにくい
良いプロジェクトでは、ルールそのものを変更する方法も決めておくと便利です。
例えば「規約変更はIssueで提案し、メリット・デメリットを書き、チームレビュー後に採用する」といった仕組みです。
これならコードレビューの最中にルールの是非を延々と議論する必要がなく、通常の開発と規約改善を分離できます。
例外を許さないルールほど理由の明確化が重要
強制力の高いルールには、それだけ明確な根拠が求められます。
例えば「本番DBへの直接アクセス禁止」のようなルールなら、セキュリティや誤操作防止という強い理由があります。そのため例外を認めない運用にも合理性があります。
逆に「変数名は必ず8文字以内」のようなルールを例外なく強制するなら、それによって得られるメリットを説明できなければ疑問が生じやすいでしょう。
ルールの価値は「守らなかったとき何が起きるか」で考える
コーディングルールの必要性を判断するときは、「このルールをなくしたら具体的に何が困るか」を考える方法があります。
var禁止をなくした場合、let、const、varが混在し、スコープや再代入の意図を読み分ける必要が増える可能性があります。それを避けたいならルールには価値があります。
一方、あるスタイルルールをなくしてもFormatterによって完全に統一されるなら、人間向け規約として細かく説明する価値は低いかもしれません。
ルールの根拠は「絶対的な正解」である必要はない
コーディング規約には、唯一の正解が存在しないものも多数あります。
例えば命名規則をcamelCaseにするかsnake_caseにするかは、言語やエコシステムの慣習こそありますが、数学的にどちらか一方だけが正しいわけではありません。
その場合の理由は「利用している言語の一般的な慣習に合わせる」「既存コードとの一貫性を維持する」だけでも十分です。
実務では「理由を知らない」より「理由を確認できない」ほうが問題
メンバーがその場で即答できないこと自体は大きな問題ではありません。「分からないので規約を確認します」と言えればよいからです。
一方で、規約文書にも理由がなく、決めた人も退職済みで、変更してよいのかも誰にも分からない状態になると、技術的負債として残りやすくなります。
そのため、組織として重要なのは「全員が覚えていること」ではなく、必要になったときに根拠へたどり着けることです。
おすすめのコーディングルール管理方法
ルールを運用するなら、次のような形にすると分かりやすくなります。
| 項目 | 記載例 |
|---|---|
| ルール | varを使用しない |
| 推奨 | 原則const、再代入時のみlet |
| 目的 | スコープを限定し、再宣言などによる混乱を防ぐ |
| 自動化 | ESLint no-var |
| 例外 | 原則なし。必要時はレビューで相談 |
これだけでも、単に「禁止」と書くよりはるかに運用しやすくなります。
まとめ:全員が説明できる必要はないが、チームとして説明可能であるべき
プロジェクトのコーディングルールについて、メンバー全員がすべての技術的背景を説明できる必要はありません。新人や普段その領域を担当しない人まで、言語仕様の詳細を暗記することを求めるのは現実的ではありません。
一方で、チームとして採用しているルールについて、誰も目的や根拠を確認できない状態は避けたほうがよいでしょう。理由が分からなければ、そのルールが現在も必要なのか、例外を認めるべきなのか判断できないからです。
JavaScriptのvar禁止には、ブロックスコープではないこと、同一スコープで再宣言できること、宣言前アクセスがundefinedになり得ることなど、let・constと比べたときの明確な違いがあります。そのため現在のプロジェクトで「原則const、必要な場合のみlet、varは禁止」とするのは合理的な方針の一つです。
ただし、一般メンバーがそれらをその場で説明できなくても問題とは限りません。重要なのは、規約やLint設定などから理由を確認でき、ルールを制定・変更する立場の人が根拠とトレードオフを説明できることです。
コーディングルールは守ること自体が目的ではなく、バグを減らし、コードを読みやすくし、複数人で効率よく開発するための道具です。「全員が暗記する」より「チームとして理由を残し、自動化できるものはツールへ任せ、必要なときに見直せる」という状態を作ることが、実務ではより重要です。


コメント