1章 理解しやすいコード
読みやすいコードとは?
他の人が最短時間で理解できるコード
※コードが短くした方がいいが、理解するまでにかかる時間を短くする方が大事
2章 名前に情報を詰め込む
- 明確な単語を選ぶ
例えば、Getではなく、状況に応じてFetchやdownloadなどを使う
- 汎用的な名前を避ける
tmpやretvalなどの汎用的な名前を避ける。ただし、明確な理由があればOK
- 抽象的な名前よりも具体的な名前を使う
具体的な名前を使って、物事を詳細に説明する。例えば、ServerCanStart()よりもCanListenOnPort()の方が明確
- 接尾辞や接頭辞を使って情報を追加する
ミリ秒を表す変数名には、後ろに_msをつける。これからエスケープが必要な変数には、前にraw_をつける
- 名前の長さを決める
スコープが数画面に及ぶ変数に1-2文字の短い暗号めいた名前をつけてはいけない。短い名前はスコープが数行の変数につけるべきだ
- 名前のフォーマットで情報を伝える
大文字やアンダースコアなどに意味を含める。例えば、クラスのメンバ変数にアンダースコアをつけて、ローカル変数と区別する
3章 誤解されない名前
前提
名前が「他の意味と間違えられることはないだろうか?」と何度も自問自答する
-
filter()
→select()/exclude() -
clip(text, length)
→truncate(text, max_chars) -
CART_TOO_BIG_LIMIT
→MAX_ITEMTS_IN_CART -
包括的な範囲を表す(=終端を範囲に含める)
→first,last/min,max -
包含/排他的範囲を表す(=終端を範囲に含めない)
→begin,end -
boolの変数名はis, has, can, shouldを頭につける、否定形を避ける
→bool HasSpeceLeft() -
get()
→getで始まるメソッドはメンバの値を返すだけの「軽量アクセサ」
4章 美しさ
三原則
1.読み手が慣れているパターンと一貫性のあるレイアウトを使う
2.似ているコードは似ているように見せる
3.関連するコードをまとめてブロックにする
- 一貫性のある簡潔な改行位置
- メソッドを使った整列
- 縦の線をまっすぐにする
- 一貫性と意味のある並び
- 宣言をブロックにまとめる
- コードを「段落」に分割する
- 個人的な好みと一貫性
5章 コメントすべきことを知る
コメントの目的は、書き手の意図を読み手に知らせること
-
コメントするべきでは「ない」ことを知る
- コードからすぐにわかることをコメントに書かない
- ひどい名前はコメントを付けずに名前を変える
- 優れたコード > ひどいコード + 優れたコメント
-
コードを書いてる時の自分の考えを記録する
- 「監督のコメンタリー」を入れる
- コメントにはコードに対する大切な考えを記録する
- なぜコードが他のやり方ではなくこうなっているのか
- コードの欠陥にコメントをつける
- TODO:あとで手を付ける(TODO=大きな問題、todo,maybe-later=小さな問題)
- FIXME:既知の不具合があるコード
- HACK:あまり綺麗じゃない解決策
- XXX:危険!大きな問題がある
- 定数にコメントをつける
- 定数の値にまつわる「背景」
- 「監督のコメンタリー」を入れる
-
読み手の立場になって何が必要になるかを考える
- 質問されそうなことを想像する
- コードを読んで人が「えっ?」と思うところを予想してコメントをつける
- ハマりそうな罠を告知する
- 「このコードを見てびっくりすることは何だろう?どんなふうに間違えて違う可能性があるだろう?」と自分に問いかける
- 平均的な読み手が驚くような動作は文書化しておく
- 「全体像」のコメント
- ファイルやクラスには「全体像」のコメントを書く
- 要約コメント
- コードをうまく要約したコメントをかく
- 読み手が細部に囚われないようにコードブロックにコメントをつけて概要をまとめる
- 質問されそうなことを想像する
-
ライターズブロックを乗り越える
ライターズブロック=行き詰まってしまって文章が書けないこと- 頭の中にあるコメントをとにかく書き出す
- コメントを読んで改善が必要なものを見つける
- 改善する
6章 コメントは正確で簡潔に
前提
コメントは領域に対する情報の比率が高くなければいけない
-
コメントを簡潔にしておく
-
曖昧な代名詞を避ける
- 複数のものを指す可能性がある「それ」や「これ」などの代名詞を避ける
-
歯切れの悪い文章を磨く
-
関数の動作を正確に記述する
-
入出力のコーナーケースに実例を使う
-
コードの意図を書く
-
「名前付き引数」コメント
-
情報密度の高い言葉を使う
7章 制御フローを読みやすくする
前提
条件やループなどの制御フローはできるだけ自然にする。コードの読み手が立ち止まったり読み返したりしないように書く
-
条件式の引数の並び順
左側:「調査対象」の式。変化する
右側:「比較対象」の式。あまり変化しない -
if/elseブロックの並び順
- 条件は否定系よちも肯定系を使う。例えば、if(!debug)ではなく、if(debug)を使う
- 単純な条件を先に書く。ifとelseが同じ画面に表示されるので見やすい
- 関心を惹く条件や目立つ条件を先に書く
-
三項演算子
※行数を短くするよりも、他の人が理解するのにかかる時間を短くする
※基本的にはif/elseを使う。三項演算子はそれによって簡潔になるときだけに使う -
do/whileループを避ける
-
関数から早く返す
-
悪名高きgoto
-
ネストを浅くする
8章 巨大な式を分割する
前提
巨大な式は飲み込みやすい大きさに分割する
-
説明変数
- 指揮を簡単に分割するには、式を表す変数を使えばいい
- メリット
- 巨大な式を分割できる
- 簡潔な名前で式を説明することで、コードを文書化できる
- コードの主要な「概念」を読み手が認識しやすくなる
-
要約変数
- 大きなコードの塊を小さな名前に置き換えて、管理や把握を簡単にする変数のことを要約変数と呼ぶ。
-
ド・モルガンの法則
- not(a or b or c) ⇄ (not a) and (not b) and (not c)
- not(a and b and c) ⇄ (not a) or (not b) or (not c)
-
短絡評価の悪用
- 「頭がいい」コードに気を付ける。あとで他の人がコードを読むときにわかりにくくなる
-
式を簡潔にするもう一つの創造的な方法
9章 変数と読みやすさ
変数を適当に使うことで起きる問題
-
変数が多いと変数を追跡するのが難しくなる
-
変数のスコープが大きいとスコープを把握する時間が長くなる
-
変数が頻繁に変更されると現在の値を把握するのが難しくなる
-
変数を削除する
- 役に立たない一時変数
✖️ now = datetime.datetime.now()
root_message.last_view_time = now○ root_message.last_view_time = datetime.datetime.now()
- 中間結果を削除する
- 制御フロー変数を削除する
-
変数のスコープを縮める
10章 無関係の下位問題を抽出する
無関係の下位問題を積極的に見つけて抽出する
- 関数やコードブロックを見て「このコードの高レベルの目標は何か?」と自問する
- コードの各行に対して「高レベルの目標に直接的な効果があるのか?あるいは、無関係の下位問題を解決しているのか?」と自問する
- 無関係の下位問題を解決しているコードが相当量あれば、それらを抽出して別の関数にする
ユーティリティコード
→複数のプロジェクトで使えるあらかじめ用意しているようなコード。既存の関数がない場合、その関数を自分で書き、ユーティリティコードにする
- やりすぎに注意する
- 小さな関数を作りすぎると逆に読みにくくなってしまう。あちこちに飛び回る実行パスを追いかけることになるから
11章 一度に1つのことを
前提
コードは一つずつタスクを行うようにしなければならない
読みにくいコードがあれば、そこで行われているタスクを全て列挙する。そこには別の関数(やクラス)に分割できるタスクがある。それ以外は、関数の論理的な「段落」になる。タスクをどのように分割するよりも、分割するということが大切。
-
コードが行なっている「タスク」を全て列挙する。この「タスク」という言葉はゆるく使っている。「オブジェクトが妥当かどうかを確認する」のように小さいなこともあれば、「ツリーの全てのノードをイテレートする」のように曖昧なこともある。
-
タスクをできるだけ異なる関数に分割する。少なくとも異なる領域に分割する。
12章 コードに思いを込める
おばあちゃんがわかるように説明できなければ、本当に理解したとは言えない By Albert Einstein
ラバーダッキング=問題や設計をうまく言葉で説明できないのであれば、何かを見落としているか、詳細が明確になっていない。プログラム(あるいは自分の考え)を言葉にすることで明確な形になる。
コードをより明確にする簡単な手順
- コードの動作を簡単な言葉で同僚にもわかるように説明する
- その説明の中で使っているキーワードやフレーズに注目する
- その説明に合わせてコードを書く
13章 短いコードを書く
前提
最も読みやすいコードは、何も書かれていないコード
- コードをできるだけ小さく軽量に維持するためには、
- 汎用的な「ユーティリティ」コードを作って、重複コードを削除する
- 未使用のコードや無用の機能を削除する
- プロジェクトをサブプロジェクトに分割する
- コードの「重量」を意識する。軽量で機敏にしておく
できるだけコードを書かないようにする。新しいコードには、テストや文書や保守が必要になる。また、コードが増えると「重く」なるし、開発も難しくなる。
新しいコードを書かないようにするには、
- 不必要な機能をプロダクトから削除する。過剰な機能は持たせない。
- 最も簡単に問題を解決できるような要求を考える。
- 定期的に全てのAPIを読んで、標準ライブラリに慣れ親しんでおく。
14章 テストと読みやすさ
前提
他のプログラマが安心してテストの追加や変更ができるように、テストコードを読みやすくする
起こり得る問題
-
本物のコードを修正するのを恐れる
-
新しいコードを書いたときにテストを追加しなくなる
-
テストのトップレベルはできるだけ簡潔にする。入出力のテストはコード1行で記述
-
テストが失敗したらバグの発見や修正がしやすいようなエラ〜メッセージを表示する
-
テストに有効な最も単純な入力値を使う
-
テスト関数に説明的な名前をつけて、何をテストしているのかを明らかにする。Test1()ではなく、Test_<関数名>_<状況>のような名前にする
15章 「分/時間カウンタ」を設計・実装する
※難しいのであとで読み直し
外部の視点を得る
外部の視点を得るというのは、コードが「ユーザーフレンドリー」かどうかを確認する優れた手段である。
解説
自然に読みやすいコードを書けるようになるための3つのステップ
-
実際にやる
- 読む側ではなく書く側の視点でコードを見ているため、はじめはどこをよくすれば良いかを見つけることが難しい。リーダブルコードを読み直したり、仲間にコードを読んでもらったりしながら自分で「気づける」ようになることが大事。
-
当たり前にする
- 一時的にコードを読みやすくしようというスタイルではなく、継続してコードを読みやすくしようというスタイルでコードを書く
- 読みやすいコードを書くということはたまに思い出してやることではなく、習慣にして常に実践すること
-
コードで伝える
- コミットメール=バージョン管理システム(Gitなど)に変更を追加(コミット)したときに送られる通知メール
- diff入りのコミットメールを仲間に届くようにする
- 改善案を読みやすいコードで伝える