Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
リーダブルコード_読書メモ

1. 理解しやすいコード

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

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

  • 明確な単語を選ぶ
    • 気取った言い回しよりも明確で正確なほうがいい
    • 例えば Get ではなく、状況に応じて Fetch や Download などを使う
  • temp や retval などの汎用的な名前を避ける
    • retval という名前には情報がない。変数の値を表すような名前を使う
    • tmp という名前は、生存期間が短くて、一時的な保管がもっとも大切な変数にだけ使う
    • temp・it・retval のような汎用的な名前を使うときは、それ相応の理由を用意する
  • 抽象的な名前よりも具体的な名前を使う
    • 具体的な名前を使って、物事を詳細に説明する
    • 例えば、ServerCanStart() よりも CanListenOnPort() の方が明確
  • 名前に情報を追加する
    • ミリ秒を表す変数には、後ろに ms をつける
    • これからエスケープが必要な変数名には、前に raw をつける
  • 名前の長さを決める
    • スコープが数画面に及ぶ変数に 1 〜 2 文字の短い暗号めいた名前をつけてはいけない
    • 短い名前はスコープが数行の変数につけるべき
  • 名前のフォーマットで情報を伝える
    • 大文字やアンダースコアなどに意味を含める
    • 例えば、クラスのメンバ変数にアンダースコアをつけて、ローカル変数と区別する

3. 誤解されない名前

名前が「他の意味と間違えられることはないだろうか?」と何度も自問自答する

  • 最善の名前とは、誤解されない名前である
    • 上下の限界値を決めるときには、max や min を前につけるといい
    • 包含的範囲であれば、 first や last を使うといい
    • 包含/排他的範囲であれば、begin と end がイディオムなのでそれを使う
    • ブール値に名前をつけるときには、それがブール値だとわかるように is や has などの単語を使う
    • disable_ssl のような否定的な名前は避ける
  • 単語に対するユーザの期待にも注意する
    • 例えば、 get() や size() には軽量なメソッドが期待されている

4. 美しさ

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

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

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

コメントの目的は、書き手の意図を読み手に知らせることである

  • コメントすべきではないこと
    • コードからすぐに抽出できること
    • 酷いコードを補う「補助的なコメント」。コメントを頑張るのではなくコードを修正すべき
  • コメントすべきこと
    • 記録すべき自分の考え
      • なぜコードが他のやり方ではなくこうなっているのか(オーディオコメンタリ)
      • コードの欠陥を TODO: や XXX: などの記法を使って示す
      • 定数の値にまつわる「背景」
    • 読み手の立場になって考える
      • コードを読んだ人が「えっ?」と思うところを予想してコメントをつける
      • 平均的な読み手が驚くような動作は文書化しておく
      • ファイルやクラスには「全体像」のコメントを書く
      • 読み手が細部に捕らわれないように、コードブロックにコメントをつけて概要をまとめる

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

コメントは領域に対する情報の比率が高くなければならない

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

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

条件やループなどの制御フローはできるだけ「自然」にする
コードの読み手が立ち止まったり読み返したりしないように書く

  • 比較を書くときには、変化する値を左に、より安定した値を右に配置する
  • if/else 文のブロックは適切に並び替える
    • 一般的には、肯定系、単純、目立つものを先に処理する
  • 三項演算子、do/while ループ、goto などのプログラミング構成要素を使うと、コードが読みにくくなることが多い
    • 代替となるものが必ずあるので、これらは使わない方がいい
  • ネストしているとコードを追うのに集中力が必要になる
    • 深いネストを避けるには、「直線的」なコードを選択する
    • 早めに返してあげると、ネストを削除したりコードをクリーンにしたりできる
    • 特に「ガード節」(関数の上部で単純な条件を先に処理するもの)が便利

8. 巨大な式を分割する

巨大な式は飲み込みやすい大きさに分割する

  • もっとも簡単な方法は「説明変数」を導入すること。利点は以下の3つ
    • 巨大な式を分割できる
    • 簡潔な名前で式を説明することで、コードを文書化できる
    • コードの主要な「概念」を読み手が認識しやすくなる
  • ド・モルガンの法則を使ってロジックを操作する
    • 論理式を反転させることで、キレイにできることがある
  • 上記の方法が取れない場合は、問題を否定したり、反対のことを考えてみたりすると良い
    • if 文の中身が2行以上含まれていないのが理想的な状況

9. 変数と読みやすさ

  • 邪魔な変数を削除する
    • 役に立たない一時変数を削除する
    • 中間結果をしまう変数を削除する
  • 変数のスコープをできるだけ小さくする
  • 一度だけ書き込む変数を使う
    • 変数に一度だけ値を設定すれば(あるいは final を指定すれば)、コードが理解しやすくなる

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

著者がやっていることは以下の3つ

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

簡潔にまとめると、プロジェクト固有のコードから汎用コードを分離する、ということ
一般的な問題を解決するライブラリやヘルパ関数を作っていけば、プログラムに固有の小さな核だけが残る

この技法が役に立つのは、プロジェクトの他の部分から分離された、境界線の明確な小さな問題に集中できるから
こうした下位問題に対する解決策は、より緻密で正確なものになる
あとでコードを再利用できる可能性もある

11. 一度に1つのことを

コードは1つずつタスクを行うようにしなければいけない

  • 読みにくいコードがあれば、そこで行われているタスクを全て列挙する
    • そこには別の関数(やクラス)に分割できるタスクがあるはず
    • それ以外は、関数の論理的な「段落」になる
  • タスクをどのように分割するかよりも、分割するということが大切
  • 一番難しいのは、プログラムが行なっていることを正確に説明すること

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

コードをより明確にする手順は以下の通り

  • コードの動作を簡単な言葉で同僚にもわかるように説明する
  • その説明のなかで使っているキーワードやフレーズに注目する
  • その説明に合わせてコードを書く

説明することでコードがより自然になっていく
説明で使っている単語やフレーズをよく見れば、分割する下位問題がどこにあるかがわかる

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

13. 短いコードを書く

もっとも読みやすいコードは、何も書かれていないコードである 新しいコードを書かないようにするには、

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

14. テストと読みやすさ

他のプログラマが安心してテストの追加や変更ができるように、テストコードを読みやすくする

  • テストのトップレベルはできるだけ簡潔にする 入出力のテストはコード1行で記述できるといい
  • テストが失敗したらバグの発見や修正がしやすいようなエラーメッセージを表示する
  • テストに有効なもっとも単純な入力値を使う
  • テスト関数に説明的な名前をつけて、何をテストしているのかを明らかにする
    • Test1() ではなく、 Test_関数名_状況 のような名前にする
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment