【リーダブルコード】まとめ

 

目次

はじめに

この記事は「リーダブルコード」を読んで自分なりにまとめた学習メモです。 

リーダブルコード ―より良いコードを書くためのシンプルで実践的なテクニック (Theory in practice)

リーダブルコード ―より良いコードを書くためのシンプルで実践的なテクニック (Theory in practice)

 

 

1章 理解しやすいコード

 コードを書く上でいちばん大切な原則

  • コードは理解しやすくなければいけない

 読みやすさの基本定理

  • コードは他の人が最短時間で理解できるように書かなければいけない 

 

第 I 部 表面上の改善

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

 名前を見ただけで情報を読み取れるようにすること。

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

 

3章 誤解されない名前

 最善の名前とは、誤解されない名前である。つまり、自分のコードを読んでいる人が、自分の意図を正しく理解できるということ。英語の単語は、filter・length・limit のように、プログラミングに使うには意味があいまいなものが多い。

 名前を決める前に反対意見を考えるなどして、誤解されない名前かどうかを想像してみる。最善な名前というのは、誤解されない名前である。

  • 上下の限界値を決めるときには、max_ や min_ を前につける
  • 包含的範囲は、first や last を使う
  • 包含/排他的範囲は、begin と end がイディオムなのでそれを使う
  • ブール値は、ブール値だとわかるように is や has などの単語を使う

 

4章 美しさ

 一貫性と意味のあるやり方でコードを「整形」すれば、すばやく簡単に読むことができる。

  • 複数のコードブロックで同じようなことをしていたら、シルエットも同じようなものにする
  • コードの「列」を整形すれば、概要が把握しやすくなる
  • ある場所で A・B・C のように並んでいたものを、他の場所で B・C・A のように並べてはいけない。意味のある順番を選んで、常にその順番を守る
  • 空行を使って大きなブロックを論理的な「段落」に分ける

 

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

 コメントの目的とは、コードの意図を読み手に理解してもらうこと。

 

コメントすべきでは「ない」こと

  • コードからすぐに抽出できること
  • ひどいコード(例えば、ひどい名前の関数)を補う「補助的なコメント」。コメントを書くのではなくコードを修正する

記録すべき自分の考え

  • なぜコードが他のやり方ではなくこうなっているのか(「監督コメンタリー」)
  • コードの欠陥を TODO: や XXX: などの記法を使って示す
  • 定数の値にまつわる「背景」

読み手に立場になって考える

  • コードを読んだ人が「えっ?」と思うところを予想してコメントをつける
  • 平均的な読み手が驚くような動作は文書化しておく
  • ファイルやクラスには「全体像」のコメントを書く
  • 読み手が細部に捕らわれないように、コードブロックにコメントをつけて概要をまとめる

 

6章 コメントは性格で簡潔に

 小さな領域にできるだけ多くの情報を詰め込んだコメントを書くこと。

  • 複数のものを指す可能性がある「それ」や「これ」などの代名詞を避ける
  • 関数の動作はできるだけ正確に説明する
  • コメントに含める入出力の実例を慎重に選ぶ
  • コードの意図は、詳細レベルではなく、高レベルで記述する
  • よくわからない引数にはインラインコメントを使う(例:Function(/* arg = */))
  • 多くの意味が詰め込まれた言葉や表現を使って、コメントを簡潔に保つ 

 

第 Ⅱ 部 ループとロジックの単純化

7章 制御フローを読みやすくする

比較

  • 変化する値を左に、より安定した値を右に配置する
  • 例:while(bytes_expected > bytes_received) while(bytes_received < bytes_expected)

if/else 文

  • ブロックを適切に並び替える
  • 肯定形・単純・目立つものを先に処理する

三項演算子(? :)・do/while ループ・goto など:

  • コードが読みにくくなることが多い
  • 代替となるものが必ずあるので、これらは使わないほうがいい

ネストしているコード

  • コードを追うのに集中力が必要になる
  • ネストが増えるたびに「スタックにプッシュ」することが増える
  • 深いネストを避けるには「直線的」なコードを選択する
  • 早めに返してあげると、ネストを削除したりコードをクリーンにしたりできる
  • 特に「ガード節」(関数の上部で単純な条件を先に処理する)が便利

 

8章 巨大な式を分割する

 巨大な式を一度に理解しようと思うと難しい。巨大な式を分割して、読み手が1つずつ飲み込めるようにする。

 

説明関数

  • 巨大な式を分割できる
  • 簡潔な名前で式を説明することで、コードを文書化できる
  • コードの主要な「概念」を読み手が認識しやすくなる

ド・モルガンの法則

  • 論理式をキレイに書き直すことにも使える
  • 例:if(!(a && !b)) → if(!a || b)
  • 問題を「否定」したり、反対のことを考えてみたりすることが必要になる

 

9章 変数と読みやすさ

 変数を減らして、できるだけ「軽量」にすれば、コードを読みやすくなる。

  • 邪魔な変数を削除する
    • 結果をすぐに使って、「中間結果」の変数を削除する
  • 変数のスコープをできるだけ小さくする
    • 変数を数行のコードからしか見えない位置に移動する
  • 一度だけ書き込む変数を使う
    • 変数に一度だけ値を設定すれば(あるいは、const や final などのイミュータブルにする方法を使えば)、コードが理解しやすくなる

 

第 Ⅲ 部 コードの再構成

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

 プロジェクト固有のコードから汎用コードを分離するということ。

  • ほとんどのコードは汎用化できる
  • 一般的な問題を解決するライブラリやヘルパー関数を作っていけば、プログラムに固有の小さな核だけが残る

 

11章 一度に一つのことを

  • 読みにくいコードがあれば、そこで行われているタスクを列挙する
  • タスクをどのように分割するかよりも、分割するということが大切
  • いちばん難しいのは、プログラムが行っていることを正確に説明すること

 

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

 プログラムのことを簡単な言葉で説明することでコードがより自然になっていく。

  • 問題や設計をうまく言葉で説明できないのであれば、何か見落としているか、詳細が明確になっていないということ
  • プログラム(あるいは自分の考え)を言葉にすることで明確な形になる

 

13章 短いコードを書く

 できるだけコードを書かないこと。新しいコードには、テストや文書や保守が必要になる。また、コードが増えると「重く」なるし、開発が難しくなる。

 

新しいコードを書かないようにするには

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

 

第 Ⅳ 部 選抜テーマ

14章 テストと読みやすさ

 テストコードでも読みやすさが大切。

  • テストのトップレベルはできるだけ簡潔にする。入出力のテストはコード1行で記述できるといい
  • テストが失敗したらバグの発見や修正がしやすいようなエラーメッセージを表示する
  • テストに有効な最も単純な入力値を使う
  • テスト関数に説明的な名前をつけて、何をテストしているかを明らかにする。Test1() ではなく、Test_<関数名>_<状況> のような名前にする

 特に、新しいテストの追加や修正を簡単にすることが大切。