リーダブルコード定石


ということで、リーダブルコードの定石として使えそうなものを章ごとに抽出。
対象者はリーダブルコードの読者です。
弊記事を通して、何度も定石を思い出しリーダブルコードを読みなおし、自分の肉としてください。

(ただし、これらに囚われすぎず、プロダクトが動くのが第一!!というのが本音なのは内緒)

なお、チェックリストは既出でした
「リーダブルコード適用 チェックリスト」を作ってみました

が、弊記事は、より本書の内容に踏み込んでいます。
では行きましょう。(自己満自己理解のための、あうとぷ記事です...

1章 理解しやすいコード

  • コードは理解しやすく
  • コードは他人が最短時間で理解できるように書く

2章 名前に情報を詰め込む

  • 明確な単語を選ぶ
    • Getではなく、状況に応じてFetchやDownload
  • tmpやretvalなどの汎用的な名前を避ける
    • retvalという名前には情報がない。変数の値を表すような名前を使う
    • tmpという名前は、生存期間が短くて、一時的な補完が最も大切な変数にだけ使う
    • tmp・it・retvalのような汎用的な名前を使うときは、それ相応の理由を用意
  • 具体的な名前を使って、物事を詳細に説明する
    • ServerCanStart() より CanListenOnPort() のほうが明確
  • 変数名に大切な情報を追加する
    • ミリ秒を表す変数名には、後ろに_msをつける。これからエスケープが必要な変数名には、前にraw_をつける
  • スコープの大きな変数には長い名前を付ける
    • スコープが数画面に及ぶ変数に1~2文字の短い暗号めいた名前を付けない。短い名前はスコープが数行の変数につける
  • 大文字やアンダースコアなどに意味を含める
    • クラスのメンバ変数にアンダースコアを付けて、ローカル変数と区別する

3章 誤解されない名前

  • 名前が「ほかの意味と間違えられることはないだろうか」と何度も自問自答する
  • 上下の限界値を決めるときは名前の前にmax_やmin_
  • 包含的範囲ではfirstやlast
  • 包含/排他的範囲ではbeginとend
  • ブール値への名前付けではisやhasを使い、否定形を避ける
  • ユーザーの期待に注意する
    • get()やsize()には軽量なメソッドが期待される
  • 複数の名前を検討する

4章 美しさ

  • 読み手が慣れているパターンと一貫性のあるレイアウトを使う
    • コードの列を整理して概要を把握しやすく
    • 一貫性のあるスタイルは「正しい」スタイルよりも大切
  • 似ているコードは似ているように見せる
    • 意味のある順番を選んで、常にその順番を守る
  • 関連するコードをまとめてブロックにする
    • 複数コードブロックで同じようなこと→シルエットも同じにそろえる
    • 空行を使って大きなブロックを論理的な「段落」に分ける

5章 コメントすべきことを知る

  • コメントすべきで「ない」こと
    • コードからすぐに抽出できること
    • ひどいコードを補う →コメントを書くのではなくコードを修正
  • 記録すべき自分の考え
    • なぜ他のやり方でなく、そうするのか
    • コードの欠陥をTODO:やXXX:などの記法で示す
    • 定数の値にまつわる「背景」
  • 読み手の立場で考えて生み出すコメント
    • 質問されそうなこと
    • ハマりそうな罠の告知
    • ファイルやクラスの全体像
    • コードブロックの概要

6章 コメントは正確で簡潔に

  • コメントは領域に対する情報の比率を高くする
  • 曖昧代名詞を避ける
    • 複数可能性があるものに、指示代名詞を避ける
  • ブラッシュアップ歯切れ悪い文章
  • 関数動作を正確に
  • 入出力のコーナーケースに実例の選定
  • コードの意図は、詳細レベルではなく高レベル
  • 「名前付き引数」コメの使用
  • 情報密度の高い言葉

7章 ループとロジックの単純化

  • 条件やループなどの制御フローはできるだけ「自然」にする。コードの読み手が立ち止まったり読み返したりしないように書く
  • 条件は肯定形
    • if(!debug)よりif(debug)
  • 単純な条件を先に書く
  • 関心を引く条件や目立つ条件を先に書く
  • 行数を短くするよりも、他人が理解するのにかかる時間を短くさせる
  • 基本的にはif/elseを使う。三項演算子はそれによって簡潔になるときにだけ使う
  • do/whileループを避ける
  • 関数から早く返す
  • 基本的にgotoは使わない
  • ネストを浅く
  • 変更するときはコードを新鮮な目で見る。一歩座がって全体を見る
  • ループ内部のネストを削除

8章 巨大な式を分割する

  • 巨大な式は飲み込みやすい大きさに分割
    • 説明変数の導入
    • 要約変数の導入
  • ド・モルガンを使う
  • 「頭がいい」コードに注意。後で他人が読む際分かりにくくなる

9章 変数を削除する

  • 邪魔な変数を削除
    • 中間結果の変数を削除
  • 変数のスコープをできるだけ小さく
  • 変数を操作する場所を増やさない
  • 一度だけ書き込む変数を使う

10章 無関係の下位問題を抽出する

  • 関数やコードブロックを見て「このコードの高レベルの目標」を自問
  • コードの各行に対して「高レベルの目標に直接的に効果があるか、無関係の下位問題を解決しているのか」を自問
  • 無関係の下位問題を解決しているコードが相当量あれば、抽出して別関数にする

11章 一度に一つのことを

  • コードは1つずつタスクを行うようにする
    • コードが行っている「タスク」をすべて列挙
    • タスクをできるだけ異なる関数に分割

12章 コードに思いを込める

  • ロジックを明確に説明する
  • ライブラリを知る
  • 解決策を言葉で説明する
  • 手法を再帰的に適用する
  • 問題を声に出して説明してみる

13章 短いコードを書く

  • 最も読みやすいコードは何も書かれていないコード
  • 不必要な機能をプロダクトから削除する。過剰な機能は持たせない
  • 最も簡単に問題を解決できるような要求を考える
  • 定期的にすべてのAPIを読んで、標準ライブラリに慣れ親しむ

14章 テストと読みやすさ

  • テストのトップレベルはできるだけ簡潔に。入出力のテストはコード1行で記述が理想
  • テストが失敗したらバグの発見や修正がしやすいエラーメッセージを表示
  • 安心してテストの追加や変更ができるように、テストコードを読みやすく
  • テスト関数に説明的な名前をつけ、何をしているか明確に
  • コードを完全にテストする最も単純な入力値の組み合わせを選択
  • テストには最もキレイで単純な値を選ぶ

一つでも改善すると、未来のコード読者、自分が喜ぶはず!