リーダブルコードとは何か:可読性をリスクと投資で説明する
1. リーダブルコードとは何か
リーダブルコードはよく
「読みやすいコードを書く技術」
として説明されるが、リーダブルコードは 目的ではなく手段 であることを強調したい。
つまり、リーダブルなコードを書く本当の目的は別にあり、それは、
- コードのリスクを下げること
- 将来に投資すること
の2つにあると考える。
そのため逆に言えば、
- リスクがほぼ問題にならない
- 将来への投資がほぼ必要ない
のであれば、必ずしも リーダブルなコードを書く必要はない と考える。
2. リスクの少ないコードを書くために
2.1 リスクとは何か
防災やセキュリティ、PMBOK、環境問題など様々な分野でリスクアセスメントの議論が行われている。
リスクについてはある程度定式化されており、分野や文脈によって多様だが防災の分野では以下のようになる。
$Risk = Hazard \times Damage$
$(リスク) = (災害そのものの強さ・起こりやすさ) \times (起きたときの被害)$
そして被害は
$Damage = Exposure \times Vulnerability$
$(起きたときの被害) = (そこに何がどれだけ晒されているか)\times(晒された対象がどれだけ傷つきやすいか)$
で表される。
さらに 傷つきやすさ は
$Vulnerability \propto \dfrac{Fragility}{Detection \times Recovery}$
$(晒された対象がどれだけ傷つきやすいか) \propto \dfrac{(壊れやすさ、傷つきやすさ)}{(弱点や異常を発見できる能力) \times (被害が出た後に立て直せる能力)}$
と考えることができる。
これを比例定数を1として単純化しつつまとめると、
$Risk = \dfrac{Hazard \times Exposure \times Fragility}{Detection \times Recovery}$
$(リスク) = \dfrac{(災害そのものの強さ・起こりやすさ) \times (そこに何がどれだけ晒されているか) \times (壊れやすさ、傷つきやすさ)}{(弱点や異常を発見できる能力) \times (被害が出た後に立て直せる能力)}$
ここからわかるのは、リスクは
- 災害そのものの強さ・起こりやすさ
- そこに何がどれだけ晒されているか
- 壊れやすさ、傷つきやすさ
に比例し、
- 弱点や異常を発見できる能力
- 被害が出た後に立て直せる能力
に反比例するのであり、これらのパラメータを変化させることでリスクを低減/上昇させることになり、ここれらの要素を指標としてリスク評価が行われている。
2.2 リーダブルコードとリスク
ここまでをまとめると、リスクを下げるには次の状態が望ましい。
- 危険なものが少ない
- 危険な場所に晒されない
- 弱点が少ない
- 異常を検出できる
- 回復しやすい
しかし実際のソフトウェア開発では、 どこに弱点があるのかを理解すること自体が難しい。
コードが理解しにくいと、
- 弱点を見つけられない
- バグを検出できない
- 修正が怖くなる
という状態になる。
つまり コードが読めないこと自体が Detection(検出能力) と Recovery(回復能力) を下げる。
ここでリーダブルコードが意味を持つ。
コードが理解しやすければ
- 問題を見つけやすくなる
- 変更の影響を把握できる
- 修正が安全になる
つまり 可読性はソフトウェアのレジリエンスを上げる。
リーダブルコードとは、単に見た目を整えることではない。
それは
- 問題を検出しやすくし
- 問題発生時の回復を容易にし
- 将来の変更を安全にする
ための技術である。
3. 価値あるコードを書く
3.1 ソフトウェアの価値
ソフトウェアの価値は「完成した機能」だけではない。
もう一つ重要なのが 将来どんな機能でも作れる余地 である。
ビジネスの現場では、
- iOSアプリを作る
- Androidアプリを作る
- Webアプリを作る
と最初から決まっていることは少ない。
むしろ「とにかく使いやすいものを作りたい」のように、要件が曖昧なことが多い。
このとき重要なのは、後から選択できる状態を残しておくこと である。
たとえば
- データ構造を柔軟にする
- プラットフォーム依存を減らす
- 変更しやすい設計にする
といった準備である。
これは言わば 後出しジャンケンをできる状態を作る ようなものだ。
未来が不確実であるほど、この価値は高くなる。
つまりビジネスでは 将来の選択肢を増やすこと自体が価値 になる。
3.2 リーダブルコードという投資
将来の選択肢を残す設計は、多くの場合上流工程で決まる。
しかし実際にコードを読むのはエンジニアである。
将来の変更コストを下げるには、変更しやすいコードを書いておく必要がある。
そのため リーダブルなコードを書くことは投資 になる。
可読性を上げることは
- 将来の理解コストを下げる
- 変更の安全性を上げる
- 将来の選択肢を残す
ことにつながる。
つまりリーダブルコードは単なる作法ではない。未来への投資なのである。
4. 可読性の淘汰
上記のように良いことばかりであれば、
多くの現場で可読性の高いコードに溢れていてもよさそうである。
しかし実際にはそうなっていない。
一見、リーダブルなコードを書くことは面倒であり、リーダブルでないコードを書くことは容易であるから、エンジニアの怠慢のようにも見える。
しかし、実際は 構造の問題 であり、意識していないとリーダブルなコードは淘汰されてしまう。
4.1 囚人のジレンマとは
囚人B 黙秘 囚人B 自白 囚人A 黙秘 (2年,2年) (10年,0年) 囚人A 自白 (0年,10年) (5年,5年) 2人の囚人A・Bにとって、「互いに自白」して互いに5年の刑を受けるよりは「互いに黙秘」して互いに2年、合計で4年の刑を受ける方が得である。
しかし、2人の囚人が「互いに黙秘」が全体の利益で得であると認識した上で2人の囚人A・Bがそれぞれ自分の利益のみを追求している限り、「互いに黙秘」という結果ではなく「互いに自白」という結果となってしまう。これがジレンマと言われる所以である。
4.2 リーダブルなコードにおける囚人のジレンマ
まず、整理をすると
- Readableなコード
- 時間をかけて書く
- 読む人にやさしい
であり、対立概念を
- Hackyなコード
- その場しのぎ
- LLMの出力をそのまま使えば短時間で書ける
とする。
このとき開発現場には、ReadableなコードとHackyなコードによる「囚人のジレンマ」 が生まれる。
個人最適で考えると、Hackyなコードは合理的な選択になりやすい。
しかしチーム全体ではHackyなコードが積み重なり、
- コードを読む時間が増える
- 変更コストが上がる
- さらにHackyなコードを書きやすくなる
という悪循環が生まれる。
つまり、これは個人の意識や技術力の問題ではなく、 構造的な問題である。
5. 可読性の復活
このように、可読性が低いコードはエンジニアの怠惰でも礼儀がないわけでもなく、構造的な問題であるため、リーダブルでないコードになることは自然である 。
しかし、前述のように可読性にはリスクを下げ、投資の意味合いがあるため、可読性を復活させる必要に迫られる。
ただし、パレートの法則(80:20の法則)に従えば、「結果の80%は、全体の20%の要素が生み出している」はずなので、全体の可読性を上げる必要はないはずだ。
いつ、どこで、何を、どのように、すればいいのかについてはさまざまな議論があるが、ここで一例を取り上げる。
5.1 タイミング(When)
エクストリーム・プログラミング(XP)3を提唱したKent Beck氏によれば、以下になる。
先に整頓するときというのは確実に存在する。このようなときだ。
$cost(整頓) + cost(整頓のあとに振る舞いを変更) < cost(整頓せずに振る舞いを変更)$
こうなら、間違いなく先に整頓しよう。調子に乗って整頓しすぎてしまいがちだが、どこまで整頓するかの境界を決めて守ればきっと大丈夫だ。
また、同氏は以下の開発手法も提唱している。
"Make it work, make it right, make it fast."
テスト駆動開発(TDD; Test Driven Development) とも呼ばれる上記を合わせれば、 動くようにしてから、正しくして、速くする という順序になるため、リーダブルなコードは初期段階では不要であり、動作確認以後、高速化する以前、が必要になるタイミングといえるだろう。
5.2 対象(What)
先に引用したようにリスクは
- Hazard: 災害そのものの強さ・起こりやすさ
- Exposure: そこに何がどれだけ晒されているか(被害を受ける対象の量)
- Vulnerability: 脆弱性
に比例する。
害を受ける対象の量(Exposure)は、利用が大きいものほど大きくなる。
そして、上記に時間軸を導入すると、大抵の場合、起こりやすさ(Hazard)は時間とともに増加する。
つまり、長期間使われたり、使用頻度の高いコードほどリスクが大きくなる。
そのため、重要なコードであればあるほどリーダブルにしていくことでリスクを低減することが求められる。
具体的には、(MICEではないものの)以下のようにコーディングを分類すれば、下のものほどリーダブルに書くことの投資対効果が高くなる。
- PoC(Proof of Concept、概念実証)
- アドホック分析
- バッチスクリプト
- サービスロジック
- 共通ライブラリ
つまり、可読性の目的を忘れずにいれば、重要なコードほど可読性を復活させる価値があると言えそうだと考える。
5.3 手法(How)
紙幅が足りないので、他実用書に譲る。
5.4 可読性の粒度と境界
インフォメーション
「Vibe Coding の時代にリーダブルコードって笑」という声が聞こえるので、弁明を添える。
なお、この項は個人の見解を多く含む。
CPUが直接実行する機械語は 0 と 1 の列で構成されており、人間にとっては扱いにくい。
そのため、機械語の命令に対応するニモニック(例: MOV, ADD)を導入したアセンブリ言語が生まれた。
しかしアセンブリ言語も依然として低水準であり、大規模なプログラムを書くには負担が大きかった。
そこで C のような高級言語が生まれ、その後も Python や Scratch など、より人間にとって読みやすい言語が発展してきた。
もちろん、どのような高級言語で書かれたコードも、最終的にはコンパイルや解釈を通じて機械語に変換される。
しかし人間は、そのすべてを機械語として理解する必要はない。
for や if のような抽象化された構文のレベルで意味を把握できれば十分である。
つまりプログラミングとは、抽象化の階層を作り、人間が扱える単位でシステムを理解できるようにする営みである。
この階層構造は、コードの構造にも現れる。
コードには粒度がある。
行がロジックブロックを作り、ロジックブロックが関数を作り、関数がモジュールを作り、モジュールがシステムを構成する。
$行 < 変数 < 関数 < モジュール < アーキテクチャ$
したがって、可読性にも粒度が存在する。
すべてのレベルで同じ可読性を求めることが常に合理的とは限らない。
人間には認知の限界があり、LLMにもコンテキスト長という制約があるからである。
そのため、粒度に応じて可読性の要求水準を変えるという考え方が成立する。
例えば
- LLMに任せてよい粒度では、機能性や簡潔さを優先する
- 人間が責任を持って理解する粒度では、明確な可読性を保つ
- 機械的に処理される粒度では、人間の可読性を必ずしも重視しない
これは本質的には新しい話ではない。
カプセル化(encapsulation)や情報隠蔽(information hiding)といった、従来の設計原則の延長線上にある。
LLMがコーディングの現場にいる現在、「リーダブルなコードはLLMに任せればよい」という主張も理解できる。
しかしLLMも万能ではなく、コンテキスト長という制約を持つ。
そのため可読性は、「人間がすべて読むため」のものだけではない。
人間とLLMが協調して扱える単位にコードを整理するためのものでもある。
実務では特に、関数やモジュール単位の可読性が重要になることが多い。
これはソフトウェア設計におけるカプセル化や情報隠蔽と深く関係している。
言い換えれば、エンジニアが担うべき可読性とは、単に行単位の読みやすさではなく、 構造を理解しやすい形に保つこと なのではないだろうか。
6. まとめ
LLMの発展によって「書く」のコストはほぼゼロになったが、「選ぶ・直す・捨てる」のコストが人間側に集中した。
実装能力 < 判断能力 になる今後のエンジニアにとって今一度リーダブルコードを検討する必要があると感じる。
参考文献
- Boswell, D., Foucher, T. (2012). リーダブルコード: より良いコードを書くためのシンプルで実践的なテクニック. 日本: オライリー・ジャパン.
- Beck, K., 永瀬 美穂. (2024). Tidy First? 個人で実践する経験主義的ソフトウェア設計. 日本: オライリー・ジャパン.
- 石川 宗寿. (2022). 読みやすいコードのガイドライン: 持続可能なソフトウェア開発のために. 日本: 技術評論社.