本書は「コードは理解しやすくなければいけない」という考えを元に、
「読みやすいコード」を書くことを目的としている。
「読みやすいコード」を指標として紹介している為、
開発に携わっている人は立場問わず、一読する価値があると思う。
複数のプログラミング言語が記載されているが、
簡単な例文しか扱っていない為、プログラミング初心者でも読み易い。
以下概要を記す。
#第 I 部 表面上の改善
##1章 理解しやすいコード
鍵となる考え
・コードは理解しやすくなければいけない。
・コードは他の人が最短時間で理解できるように書かなければいけない。
- 「理解する」とはコードに変更を加えたりバグを見つけたりできるという意味。
- 「他の人」とは自分のコードに見覚えのない未来の自分も含む。
- コードは短くしたほうがいいが、「理解するまでにかかる時間」を短くするほうが大切。
- 「理解するまでにかかる時間」は、その他の目標(設計やテスト等のし易さ)とは競合しないし、寧ろそれらの達成に繋がることが多い。
##2章 名前に情報を詰め込む
鍵となる考え
・名前に情報を詰め込む。
・気取った言い回しよりも明確で正確なほうがいい。
-
明確な単語を選ぶ
⇒Get
ではなく、状況に応じてFetch
やDownload
などを使う。 -
汎用的な名前を避ける
⇒tmp
やretval
などの汎用的な名前を使うときは、それ相応の理由を用意する。 -
抽象的な名前よりも具体的な名前を使う
⇒ServerCanStart()
よりもCanListenOnPort()
のほうが明確だ。 -
接尾辞や接頭辞を使って情報を追加する
⇒ ミリ秒を表す変数名の後ろに_ms
をつける。
⇒ エスケープが必要な変数名の前にraw_
をつける。 -
名前の長さを決める
⇒ スコープの大きな変数には長い名前をつける。
⇒ 短い名前はスコープが数行の変数につけるべき。 -
名前のフォーマットで情報を伝える
⇒ クラスのメンバ変数にアンダースコアをつけて、ローカル変数と区別する。
##3章 誤解されない名前
鍵となる考え
・名前が「他の意味と間違えられることはないだろうか?」と何度も自問自答する。
-
filter
length
limit
等、プログラミングに使うには意味があいまいな単語は使用しない。
⇒ 限界値を明確にするには、名前の前にmax_
やmin_
をつける。
⇒ 範囲を指定するときはfirst
とlast
を使う。
⇒ 包含/排他的範囲にはbegin
とend
を使う。
⇒ ブール値にはis
やhas
などを使い、disable
のような否定形は避ける。 -
単語に対するユーザの期待にも注意する。
⇒get()
やsize()
には軽量なメソッドが期待されている。
##4章 美しさ
鍵となる考え
・一貫性のあるスタイルは「正しい」スタイルよりも大切だ。
3つの原則
・読み手が慣れているパターンと一貫性のあるレイアウトを使う。
・似ているコードは似ているように見せる。
・関連するコードをまとめてブロックにする。
##5章 コメントすべきことを知る
鍵となる考え
・コメントの目的は、書き手の意図を読み手に知らせることである。
・コードからすぐにわかることをコメントに書かない。
-
コメントするべきでは「ない」ことを知る。
⇒ コードからすぐに抽出できることはコメントしない。
⇒ コードを補うコメントは、コメントを書くのではなくコードを修正する。 -
コードを書いているときの自分の考えを記録する。
⇒ なぜ他のやり方と同じではないのかや、定数の値にまつわる「背景」をコメントする。
⇒ コードの欠陥をTODO:
やXXX:
などの記法を使って示す。 -
読み手の立場になって何が必要になるかを考える。
⇒ コードを読んだ人がハマりそうなところを予想してコメントをつける。
⇒ ファイルやクラスには「全体像」のコメントを書く。
⇒ 読み手が細部に捕らわれないように、コードブロックにコメントをつけて概要をまとめる。
##6章 コメントは正確で簡潔に
鍵となる考え
・コメントは領域に対する情報の比率が高くなければいけない。
- 複数のものを指す可能性がある「それ」や「これ」などの代名詞を避ける。
- コメントに含める入出力の実例を慎重に選ぶ。
- 多くの意味が詰め込まれた言葉や表現を使って、コメントを簡潔に保つ。
#第 Ⅱ 部 ループとロジックの単純化
##7章 制御フローを読みやすくする
鍵となる考え
・条件やループなどの制御フローはできるだけ「自然」にする。コードの読み手が立ち止まったり読み返したりしないように書く。
・行数を短くするよりも、他の人が理解するのにかかる時間を短くする。
・変更するときにはコードを新鮮な目で見る。一歩下がって全体を見る。
- 比較を書くときには、変化する値を左に、より安定した値を右に配置する。
-
if/else
文のブロックは、一般的には肯定形
・単純
・目立つもの
を先に処理する。 -
三項演算子
・do/while
・goto
を使うとコードが読みにくくなることが多いので、代替えとなるコードの記載と比較し、読みやすい方を採用する。 - ネストしているとコードを追うのに集中力が必要になる為、
ガード節
等を用いてネストを浅くする。
##8章 巨大な式を分割する
鍵となる考え
・巨大な式は飲み込みやすい大きさに分割する。
・「頭がいい」コードに気を付ける。あとで他の人がコードを読むときにわかりにくくなる
- 説明変数を用いて巨大な式を分割する。
if line.split(':')[0].strip() == "root":
↓
username = line.split(':')[0].strip()
if username == "root":
- 要約変数を用いて巨大な式を分割する。
if (request.user.id == document.owner_id) {
// ユーザはこの文書を編集できる
}
...
if (request.user.id != document.owner_id) {
// 文書は読み取り専用
}
↓
final boolean user_owns_document = (request.user.id == document.owner_id);
if (user_owns_document) {
// ユーザはこの文書を編集できる
}
...
if (!user_owns_document) {
// 文書は読み取り専用
}
- ド・モルガンの法則を用いて巨大な式を分割する。
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章 変数と読みやすさ
鍵となる考え
・変数のことが見えるコード行数をできるだけ減らす。
・変数を操作する場所が増えると、現在値の判断が難しくなる。
-
邪魔な変数を削除する。
⇒ 一時変数、中間結果を保持する変数、制御フロー変数は削除する。 -
変数のスコープをできるだけ小さくする。
-
一度だけ書き込む変数を使う。
#第 III 部 コードの再構成
##10章 無関係の下位問題を抽出する
-
目標に直接的に効果があるコードか、無関係の下位問題を解決しているコードかを切り分ける。
⇒ 無関係の下位問題を解決しているコードが相当量あれば、それらを抽出して別の関数にする。 -
汎用コードをたくさん作る
⇒ プロジェクト固有のコードから汎用コードを分離する。
##11章 一度に一つのことを
鍵となる考え
・コードは1つずつタスクを行うようにしなければいけない。
- 分割できるタスクは分割する
##12章 コードに思いを込める
-
プログラムのことを簡単な言葉で説明する。
⇒ 自分よりも知識が少ない人が理解できるような「簡単な言葉」で説明する能力が大切。 -
コードをより明確にする簡単な手順
1.コードの動作を簡単な言葉で同僚にもわかるように説明する。
2.その説明のなかで使っているキーワードやフレーズに注目する。
3.その説明に合わせてコードを書く。
##13章 短いコードを書く
鍵となる考え
・最も読みやすいコードは、何も書かれていないコードだ。
- 不必要な機能をプロダクトから削除する。過剰な機能は持たせない。
- 最も簡単に問題を解決できるような要求を考える。
- 定期的にすべての
API
を読んで、標準ライブラリに慣れ親しんでおく。
第 IV 部 選抜テーマ
##14章 テストと読みやすさ
鍵となる考え
・他のプログラマが安心してテストの追加や変更ができるように、テストコードを読みやすくする。
・コードを完全にテストする最も単純な入力値の組み合わせを選択しなければいけない。
・テストには最もキレイで単純な値を選ぶ。
- テストのトップレベルはできるだけ簡潔にする。入出力のテストはコード1行で記述できるといい。
- テストが失敗したらバグの発見や修正がしやすいようなエラーメッセージを表示する。
- テストに有効な最も単純な入力値を使う。
- テスト関数に説明的な名前をつけて、何をテストしているのかを明らかにする。
##15章 「分・時間カウンタ」を設計・実装する
- これまでの技術を用いてコードを読みやすくする実践編。
#付録
- 高品質のコードを書くための書籍
- 『Code Complete 第2版〈上〉〈下〉 完全なプログラミングを目指して』 スティーブ・マコネル 著
- 『リファクタリングプログラムの体質改善テクニック』 マーチン・ファウラー 著
- 『プログラミング作法』 ブライアン・カーニハン、ロブ・パイク 著
- 『達人プログラマー システム開発の職人から名匠への道』 アンドリュー・ハント、 デビッド・トーマス 著
- Clean Code̶̶アジャイルソフトウェア達人の技』 ロバート・C・マーティン 著
- プログラミングに関する書籍
- 『JavaScript: The Good Parts -「良いパーツ」によるベストプラクティス』 ダグラス・クロックフォード 著
- 『Effective Java 第2版』 ジョシュア・ブロック 著
- 『オブジェクト指向における再利用のためのデザインパターン』 エリック・ガンマ、 リチャード・ヘルム、ラルフ・ジョンソン、ジョン・ブリシディース 著
- 『珠玉のプログラミング 本質を見抜いたアルゴリズムとデータ構造』 ジョン・ベ ントリー 著
- 『ハイパフォーマンスWebサイト 高速サイトを実現する14のルール』 スティーブ・サウダーズ 著
- 『Joel on Software』 ジョエル・スポルスキー 著
- 歴史的記録
- 『ライティングソリッドコード バグのないプログラミングを目指して』 スティーブ・マグワイア 著
- 『ケント・ベックのSmalltalkベストプラクティス・パターン シンプル・デザインへの宝石集』 ケント・ベック 著
- 『プログラム書法』 ブライアン・カーニハン、P.J.プローガー 著
- 『文芸的プログラミング』 ドナルド・E.クヌース 著
#解説
自然に読みやすいコードを書けるようになるための3つのステップ
1.実際にやる
⇒ 他の人に読んでもらう。
2.当たり前にする
⇒ 続けることが大事。
3.コードで伝える
⇒ 添削コミットを行う。
「自分が書いたコードってどのくらい覚えているんですか?」
「ほとんど覚えていないですよ。」
「直すときどうするんですか?わからなくなってるじゃないですか。」
「忘れても見たら簡単にわかるように書いておくんですよ。」