リーダブルコード(readable code)とは、他人がそのコードを理解するまでにかかる時間が最短になるように書かれたコードのことです。この基準を「読みやすさの基本定理」として打ち出したのが、Dustin Boswell・Trevor Foucherの書籍『リーダブルコード』(オライリー・ジャパン、2012年)です。この記事では、言葉の意味と書籍の4部15章の要約を押さえたうえで、書籍の内容を命名・コメント・制御フロー・関数分割の4原則に整理し直してPythonの例で示し、2012年刊の内容のうちLinterで自動化できる部分と人が判断すべき部分を実測で切り分けます。
まとめ:リーダブルコードの要点
- 意味:読み手が理解するまでの時間を最短にするコード。ここでの「理解」は、変更できる・バグに気づける・他のコードとの関係がわかる水準を指す。
- 短さとは別物:行数が少なくても読むのに時間がかかるなら読みにくいコード。迷ったら「理解までの時間」が書籍の他のどのルールよりも優先する。
- 書籍の構成:第I部 表面上の改善(2〜6章)、第II部 ループとロジックの単純化(7〜9章)、第III部 コードの再構成(10〜13章)、第IV部 選抜テーマ(14〜15章)。260ページ。
- 4原則:名前に情報を詰め込む/コメントには「なぜ」と罠を書く/早期リターンと説明変数で制御フローを単純にする/無関係の下位問題を関数に切り出す。
- 古いか:ネストの深さ・複雑度・return 後の不要な else などは Ruff や ESLint で機械的に検出できるようになった。名前の意味・コメントの中身・関数の切り方は今も人が判断する部分で、ここに書籍の価値が残る。
リーダブルコードの意味と「読みやすさの基本定理」
「理解するまでにかかる時間」を最短にする基準
書籍の第1章は、読みやすさの指標のなかで他のどれよりも重要なものが1つあるとして、それを「読みやすさの基本定理」と呼びます。原書 The Art of Readable Code の該当箇所は「Code should be written to minimize the time it would take for someone else to understand it.」です。同僚がコードを読んで理解するまでの時間(time-till-understanding)を測ったと仮定し、それを最小にすることを目標に置きます。
「理解」の水準は高く設定されています。原書は、コードを変更できる、バグを見つけられる、他のコードとの関わりがわかる、の3つを満たして初めて理解したとみなします。一人で書くコードでも同じで、「他人」には半年後の自分も含まれると書かれています。リーダブルコードという言葉が、単に「見た目が整ったコード」ではなく保守のしやすさの基準として使われるのはこのためです。読みやすさを含めた良いコードの原則全体は良いコードの書き方|可読性・保守性を高める12の原則とJavaの実例で整理しています。
行数の短さと理解しやすさの違い
第1章の「小さなことは絶対にいいこと?」の節では、1行に詰め込んだ assert 文より、変数に代入してから if で判定する2行のほうが早く理解できる例が示されます。コメントも行数を増やしますが、理解を早めるなら書く価値があります。行数を減らすのは良い目標でも、理解までの時間を減らすほうがより良い目標、というのが書籍の立場です。
性能や設計のしやすさとぶつからないか、という問いにも第1章が答えています。著者らは、これらの目標はほとんど衝突せず、高度に最適化したコードでも読みやすく書く方法はあると述べ、迷ったときは基本定理が書籍の他のどのルールよりも優先するとしています。逆に、すでに理解しやすいコードなら、完璧に整理されていなくても次へ進んでよい、とも書かれています。既存コードを読みやすさのためだけに書き換え続けるのは、この基準から外れます。
書籍『リーダブルコード』の基本情報と4部15章の要約
書誌と目次はオライリー・ジャパンの書籍ページで確認できます。
| 項目 | 内容 |
|---|---|
| 書名 | リーダブルコード ―より良いコードを書くためのシンプルで実践的なテクニック |
| 原書 | The Art of Readable Code(2011年) |
| 著者・訳者 | Dustin Boswell、Trevor Foucher 著/角征典 訳 |
| 日本語版の解説 | 須藤功平 |
| 発行年月日 | 2012年6月23日 |
| ページ数・ISBN | 260ページ・978-4-87311-565-8 |
| 価格・形式 | 紙・電子とも2,640円(電子はPDF・EPUB) |
本文は1章の基本的な考え方のあと、4部に分かれます。章ごとの要点は次のとおりです。
| 部 | 章 | 要点 |
|---|---|---|
| - | 1 理解しやすいコード | 読みやすさの基本定理 |
| I 表面上の改善 | 2 名前に情報を詰め込む | 汎用名を避け、単位や属性を名前に入れる |
| I | 3 誤解されない名前 | min/max・first/last・begin/end・ブール値 |
| I | 4 美しさ | 改行位置・整列・段落分けの一貫性 |
| I | 5 コメントすべきことを知る | 自明なことは書かず、考えと罠を書く |
| I | 6 コメントは正確で簡潔に | 代名詞を避け、入出力の実例を示す |
| II ループとロジックの単純化 | 7 制御フローを読みやすくする | 条件の並び順・早期リターン・ネスト削減 |
| II | 8 巨大な式を分割する | 説明変数・要約変数・ド・モルガンの法則 |
| II | 9 変数と読みやすさ | 変数を減らし、スコープを縮め、一度だけ書く |
| III コードの再構成 | 10 無関係の下位問題を抽出する | 汎用処理を関数やユーティリティへ |
| III | 11 一度に1つのことを | タスクを列挙して分ける |
| III | 12 コードに思いを込める | 処理を言葉で説明してから書く |
| III | 13 短いコードを書く | 不要な機能を作らず、ライブラリを知る |
| IV 選抜テーマ | 14 テストと読みやすさ | テストとエラーメッセージを読みやすく |
| IV | 15 分/時間カウンタを設計・実装する | 3つの設計案を比べる総合演習 |
第I部は名前やコメントなど1行単位で直せる改善、第II部は条件分岐と式、第III部は関数やモジュールの分け方と、後ろの部ほど扱う単位が大きくなります。初めて読むなら第I部と第II部(2〜9章)を先に読み、第III部はある程度の規模のコードを書いた経験があってから読むと、例の意味が取りやすくなります。
原則1:情報を詰め込み誤解を防ぐ命名
汎用名の回避と単位・属性の明示
第2章が最初に挙げるのは tmp・retval のような汎用名を避けることです。retval は「戻り値である」以外の情報を持たないので、sum_squares のように中身がわかる名前にします。値の単位も名前に含めます。時間なら delay_secs、容量なら size_mb とすると、呼び出し側でミリ秒と秒を取り違える事故を名前で防げます。
名前の長さはスコープで決めます。数行で使い終わるループ変数なら i でも困りませんが、関数をまたいで使う変数は長くても情報を持つ名前にします。ケースの書き分けや言語ごとの慣習はプログラミングの命名規則まとめ|キャメルケース・スネークケースの違いとPythonのファイル名など6言語の書き方、動詞や対義語の選び方は命名規則を英語で書く方法|ケース・品詞・対義語と公式ガイドの規定で扱っています。
範囲と真偽値の名前:max・first/last・begin/end
第3章は「別の意味に読めないか」を名前の判定基準にします。limit だけでは上限を含むのか含まないのかが読めないため、限界値を含むなら max_・min_ を付けます。範囲は、両端を含むなら first/last、終端を含まないなら begin/end と書き分けます。真偽値は is_・has_ などで始め、disable_ssl のような否定形を避けて use_ssl とします。
# 上限を含むことを max で示す(10個までは入る)
MAX_ITEMS_IN_CART = 10
def can_add_item(item_count):
return item_count < MAX_ITEMS_IN_CART
# begin は含み end は含まない(Python の range と同じ)
def hours_between(begin_hour, end_hour):
return list(range(begin_hour, end_hour))
print(can_add_item(9), can_add_item(10)) # True False
print(hours_between(9, 12)) # [9, 10, 11]
原則2:実装の理由と罠を残すコメント
第5章は、コードを読めばすぐわかることはコメントに書かない、と明言します。i += 1 # iを1増やす のようなコメントは、読む行を増やすだけです。ひどい名前をコメントで補うのも勧めず、その場合は名前を変えます。
書くべきなのは、コードから復元できない情報です。書籍はこれを「監督のコメンタリー」と呼び、なぜこの実装を選んだのか、どんな欠陥が残っているのか、定数がなぜその値なのか、読み手がはまりそうな罠は何かを挙げています。さらに、新しく加わった人がつまずきやすいクラス間の関係やデータの流れといった「全体像」のコメントや、関数内の処理のまとまりを1行で示す要約コメントも勧めています。
# 外部APIが同じIDのレコードを重複して返すことがあるため、先に重複を除く。
# 並び順は保証されないので、後段でソートし直している。
records = dedupe_by_id(raw_records)
(上は関数と入力の定義を省いた抜粋です。)
第6章はコメントの書き方そのものを扱います。「それ」「これ」のような代名詞は指す対象がずれやすいので名詞で書き、関数の動作は入出力の実例(例:"1,234円" を渡すと 1234 を返す)で示します。
原則3:早期リターンと説明変数による制御フローの単純化
早期リターンによるネストの削減
第7章はネストを浅くすることと、関数から早く返すことを勧めます。条件分岐が入れ子になるほど、読み手は「いまどの条件の中にいるか」を覚えながら読むことになるためです。例外的な条件を関数の先頭で処理して返せば、入れ子は消えます。次の2つの関数は同じ結果を返しますが、下の版は条件を上から順に読むだけで済みます。
# ネストした版:else がどの if に対応するかを追う必要がある
def shipping_fee_nested(order):
if order is not None:
if not order.is_digital:
if order.subtotal < FREE_SHIPPING_THRESHOLD:
return STANDARD_FEE
else:
return 0
else:
return 0
else:
raise ValueError("order is required")
# 早期リターン版:例外的な条件を先に返す
def shipping_fee(order):
if order is None:
raise ValueError("order is required")
if order.is_digital:
return 0
if order.subtotal >= FREE_SHIPPING_THRESHOLD:
return 0
return STANDARD_FEE
FREE_SHIPPING_THRESHOLD = 5000、STANDARD_FEE = 500 として、小計1,000円・5,000円・9,000円とダウンロード商品の4通りで両者の戻り値が一致することをPython 3.14.6で確かめています。ガード節の書き方や、早期リターンを使わないほうがよい場面はアーリーリターン(early return)とは?ガード節の書き方と言語別の実装・使わない場面で詳しく扱っています。
説明変数・要約変数による巨大な式の分割
第8章は、長い式に名前を付けた変数を挟むことを勧めます。式の意味を説明する変数を説明変数、意味は読み取れても大きな式を短い名前に置き換えて扱いやすくする変数を要約変数と呼びます。原書の要約変数の例は、ユーザーIDと文書の所有者IDの比較を user_owns_document という名前に置き換えるものです。
line = "root:x:0:0:root:/root:/bin/bash"
# 説明変数なし:何を比べているのかを式から読み解く必要がある
if line.split(":")[0].strip() == "root":
...
# 説明変数あり:比べているのがユーザー名だとわかる
username = line.split(":")[0].strip()
is_admin = username == "root"
if is_admin:
...
第9章は反対に、役に立たない一時変数は削り、変数のスコープはできるだけ狭くし、値は一度だけ書き込むことを勧めます。変数を増やすか減らすかの判断基準は、どちらも「理解までの時間が短くなるか」です。
原則4:無関係の下位問題の関数への切り出し
第10章は、関数の中で「この関数の目的と直接関係しない処理」を見つけたら、別の関数に切り出すよう勧めます。次の例では、合計金額を出す関数から、価格の文字列を数値に変える処理を切り出しています。切り出した parse_yen は合計の計算を知らないので、単体でテストでき、別の画面でも使えます。
def parse_yen(text):
"""'1,234円' や '¥1,234' を整数 1234 にする"""
digits = text.replace(",", "").replace("円", "").replace("¥", "").strip()
return int(digits)
def total_price(price_texts):
return sum(parse_yen(t) for t in price_texts)
print(total_price(["1,234円", "¥2,000", " 300円 "])) # 3534
第11章の「一度に1つのことを」は、関数がしているタスクを書き出し、別々に分けられるものは分けるという手順です。ただし、10章には「やりすぎ」の節もあります。数行のために小さな関数を量産すると、読み手は関数の間を行き来することになり、かえって理解に時間がかかります。責務の分け方の判断はSRP(単一責任の原則)とは?意味と具体例、SRP違反・やりすぎ(過剰分割)の見極め方が参考になります。
『リーダブルコード』は古い?Linterで自動化できる原則とできない原則
2012年刊のため「古いのでは」と検索されることがありますが、原則そのものは古くなっていません。変わったのは、書籍が人の注意力に頼っていた部分の一部、たとえばネストの深さや return 後の不要な else を、静的解析ツールが検出できるようになった点です。どこまで機械に任せられるかを確かめるため、ネストが深い関数と else の不要な関数を用意し、Ruff 0.17.3 と ESLint 10.13.0 にかけました。実行したコマンドは次のとおりです(ESLintは設定ファイルで "max-depth": ["error"] と "complexity": ["error", 5] を有効にしています)。
uvx ruff check --isolated --select E741,C901,RET505,PLR2004 \
--config 'lint.mccabe.max-complexity=5' sample.py
uvx ruff check --isolated --preview --select PLR1702 sample.py
npx eslint a.js
Python版とJavaScript版では検査したコードが異なるため、表の複雑度7と6はツール間の数え方の差を比べたものではありません。
| 書籍の章 | ツールとルール | 実測の出力 |
|---|---|---|
| 3 誤解されない名前 | Ruff E741 | Ambiguous variable name: `l` |
| 2 名前に情報を詰め込む | Ruff PLR2004 | 比較の 100・1000・5000 を指摘 |
| 7 早期リターン | Ruff RET505 | Unnecessary `else` after `return` |
| 7 ネストを浅く | Ruff PLR1702(preview) | Too many nested blocks (6 > 5) |
| 7 ネストを浅く | ESLint max-depth | nested too deeply (5)・既定の上限4 |
| 7〜8 分岐と式 | Ruff C901/ESLint complexity | 上限5でRuff 7・ESLint 6を警告 |
ルールの定義はRuffのRET505・PLR1702、ESLintのmax-depthの各ページにあります。PLR1702 は Ruff 0.17.3 ではプレビュー扱いで、--preview を付けないと「preview is not enabled」の警告が出て検査されませんでした。複雑度の数え方と上限の決め方はサイクロマティック複雑度とは?計算方法・目安10の根拠とツールで値が違う理由、指標をCIの合否に組み込む手順はコード品質とは?測る指標と品質ゲートでCIに組み込む手順で解説しています。
一方、ツールが指摘できるのは「名前が1文字で紛らわしい」「数値がそのまま書かれている」といった形の問題までです。l を items に変えるべきか pending_orders にすべきか、PLR2004 が指摘した 5000 にどんな定数名を付けるか、コメントに何の理由を書くか、どの処理を下位問題として切り出すかは、コードの目的を知る人にしか決められません。書籍の2〜3章・5〜6章・10〜12章の大半はこの判断の訓練で、ここが今も読む価値のある部分です。
運用では、整形とルールで機械的に直せるものは Formatter と Linter に任せ、レビューでは名前の意味とコメントの中身、関数の分け方に時間を使うのが効率的です。ただし、Linter を導入した直後にリポジトリ全体の違反を一括で直し、それを機能追加と同じプルリクエストに混ぜるのは避けてください。差分が膨らみ、肝心の変更が読めなくなります。整形だけのコミットを分けるか、変更したファイルから順に直します。AIによるコードレビューを併用する場合の製品例はGreptileとは?seat廃止後の料金・使い方・CodeRabbitとの違い【2026年10月】で取り上げています。
よくある質問
リーダブルコードとは簡単に言うと何ですか?
他人が理解するまでにかかる時間が最短になるように書かれたコードです。同時に、その考え方をまとめたオライリー・ジャパンの書籍名でもあります。動くかどうかではなく、他人が変更やバグ修正をできるまでの速さを品質の基準に置きます。
書籍『リーダブルコード』は古くて今読む価値はありませんか?
原則は今も有効です。ネストの深さや不要な else のような形の問題はLinterで検出できるようになりましたが、名前の付け方・コメントに書く理由・関数の切り方はツールが決められないため、書籍の大半を占めるこの部分の価値は残っています。
リーダブルコードのPDFはありますか?
正規の電子版は、オライリー・ジャパンが販売しているPDF・EPUB形式のEbook(2,640円)です。紙の書籍も同じ2,640円です。購入前に内容を確認したい場合は、書籍ページで全章・全節の目次を見られます。
リーダブルコードとリファクタリングは何が違いますか?
リーダブルコードは目指す状態と基準を指し、リファクタリングは外部の振る舞いを変えずに内部構造を改善する作業を指します。読みにくいコードをリーダブルな状態に近づける手段の1つがリファクタリングです。作業の進め方はリファクタリングとは?24の観点とタイミング・進め方で解説しています。
プログラミング初心者でも読めますか?
読めます。例はC++・Python・JavaScriptなどで書かれていますが、主張は言語に依存しません。最初は第I部(名前・美しさ・コメント)と第II部(制御フロー・式・変数)から読み、自分のコードの変数名を1つずつ見直すところから始めると、効果を確かめやすくなります。