リーダブルコード
読み始めた動機
- コードを書く人にとってのバイブル的存在の一つ?ぐらい有名な本の為、読んでおきたかった
- 半年後、一年後の自分が見てもわかるようなコードをきっと書けるようになりコードを「見たら思い出せる」状態にしたらきっと保守性も高くなりそうだから
- 俗に言う「読みやすい」コードがどんなものか知りたかった
読んだ感想
- コードに触れる機会が少ない時に読んでも実用的な例がたくさんあり役に立ったと実感
- 読みやすいコードが書けたら人にも説明でき、自分の理解も深まる
- 周りの人のことを考えるから周りの人に対して優しくなれる(気がする)
- デザインパターン、アーキテクチャなどのハウツー本とかではなく、純粋にコードのまとまりに対する考え方が紹介されてる為イメージが沸きやすい
- 「〜しなければいけない」ではなく、「〜した方が良い」という考え
- プロジェクトの一貫性の方が大切な(理解しやすい)ため、それを崩すのはあまり良くないという考え
- Java, JavaScript, Python, C++などのサンプルコードの説明もあるため比較的読みやすい(特にJSが少し多い)
- コードを書く全ての人に是非一読してもらいたい
- プログラミング勉強中に読んだ時と、実際に働き始めてから読むのでは耳の痛さが違う
↑音楽のコード(和音、ハーモニー)を連想させる表紙↑
(プログラミングに無縁の人から見たら音楽関連の本にも見える)
今回の技術書紹介の目的
- 有名な本だけど読んだことない人にすぐに意識できる内容をいくつか紹介
- 「当たり前やん」って思うような内容もある為、そう感じる時は復習気分でOK
- たくさんある為、どれか一つをお持ち帰りできたら幸いです
- 詳細は最後の参考記事に大変素敵な形でまとめられています
紹介の進め方
- 本の中身、内容をさらっと紹介
- 詳細が気になったら是非本書を読んでみてください(僕の私物で良ければ喜んで貸します)
- 本に書かれておらず、私(この記事を書いてる人)の考えを含めたところは(所感)と書いてます。
1章:理解しやすいコードとは?
鍵となる考え
- コードは理解しやすくなければいけない
- コードは他の人が最短時間で理解できるように書かなければいけない
- 「他の人」には数ヶ月後、数年後の自分も含まれている(所感)
第1部:表面上の改善
2章:名前に情報を詰め込む
鍵となる考え
- 名前に情報を詰め込む
- 明確な単語を選ぶ
- ex.
GetPage(url) → DownloadPage(url)
- ex.
- 汎用的な名前を避ける(それなりの理由があるならOK)
- ex.
tmp → tmp_file
- ex.
- 抽象的な名前より具体的な名前を使う
- ex.
Stop() → Kill()
- ex.
- 接頭辞や接尾辞などで名前に情報を追加する
- ex.
start → start_ms(単位を追加)
- ex.
- スコープの大きな変数には長い名前をつける
- スコープが短い時は短い名前をつける
- 大文字や_に意味を含める
- 明確な単語を選ぶ
3章:誤解されない名前
鍵となる考え
- 名前が「他の意味と間違えられることはないだろうか?」と何度も自問自答する
- 最善の名前は「誤解されない名前」である
- ex.
filter~
は「選択する」、「除外する」の2つの意味があるため避ける-
select~
やexclude~
などにする
-
- ex.
Clip(text, length)
は単位が複数考えられるし最初がいつで最後の値を含むかわからない- 限界値を明確にする
- 名前の前に
max_
やmin_
を
- 名前の前に
- 範囲を指定する
- 関数内の変数に
first
やlast
を使用する
- 関数内の変数に
- 包含/排他的範囲の場合
- 関数内の変数に
begin
やend
を使用する
- 関数内の変数に
- 限界値を明確にする
- ex.
bool disable_ssl = false
は否定的な名前のためわかりにくい- 頭にis/has/can/shouldをつける
- 否定系よりも肯定系でかく
bool use_ssl = true
- ex.
- 単語に対するユーザーの期待に合わせる
- どんな知識・経験を持った人が読み手なのか、を意識する(所感)
- get()やsize()は軽量なメソッドが期待されている(重い処理は期待されていない)
4章:美しさ
3つの原則
- 読み手が慣れているパターンと一貫性のあるレイアウトを使う
- 同じようなパターンのコードがあれば同じレイアウトにする
- 具体的には関数やif文などの改行位置(所感)
- 同じようなパターンのコードがあれば同じレイアウトにする
- 似ているコードは似ているように見せる
- 余白・配置・順序を保つ
- オブジェクトの中身など(所感)
- 余白・配置・順序を保つ
commands[]={
・・・
// 余白を設け、コードを揃えて美しくすることで楽に流し読みができる。
{ "timeout", NULL, cmd_spec_timeout },
{ "timestamping", &opt.timestmping, cmd_boolean },
{ "tries", &opt.ntry, cmd_number_inf },
・・・
};
- 関連するコードをまとめてブロックにする
- 読み込むクラスなど、関連する読み込みなどはまとめて段落ごとにまとめる
- ハンドラ、ヘルパーなど
- 読み込むクラスなど、関連する読み込みなどはまとめて段落ごとにまとめる
5章:コメントすべきことを知る
- コメントすべきではないこと
- コードを一眼見てわかること
- ひどいコードを補う「補助的なコメント」
- →コメントを書くのではなくコードを修正しよう
- コメントすべきこと
- なぜコードが他のやり方ではなくこうなっているのか
- 他の方法がたくさんある中で記述したコードの方法を選んだ理由(実行速度が速いなど)(所感)
- コードの欠陥を
TODO:
などの記法で示す- 欠陥があることを認める(所感)
- 定数にはコメントする
- 定数を設定した背景をコメントに残す
- なぜコードが他のやり方ではなくこうなっているのか
- 読み手の立場になって考える
- 読んだ人が「ぇ?」と思うところを予想してコメントをつける
- これ、コードだけじゃなく何かを説明するときや普段の言動にも気を配りたい(所感)
- 平均的な読み手が驚くような動作は文書化しておく
- ファイルやクラスには「全体像」のコメントを書く
- 読み手が細部に捕らわれないようにコードブロックにコメントをつけて概要をまとめる
- 読んだ人が「ぇ?」と思うところを予想してコメントをつける
6章:コメントは正確で簡潔に
鍵となる考え方
コメントは領域に対する情報の比率が高くなければならない
→ 質が高いコメントを書く(所感)
- 代名詞を避ける
- 複数のものを指す可能性がある「それ」「これ」は避ける
- 関数の動作はできるだけ正確に説明する。
- コメントに含める入出力の実例を慎重に選ぶ
- 実例も含めたコメントは長くなりそうなので注意(所感)
- コードの意図は詳細レベルではなく、高レベルで記述する
- コードの動作しか書かれていないものはコメントで意図を記述する(所感)
- よくわからない引数にはインラインコメントを使う
- 関数の引数で変数の型を指定しない時など(所感)
- 多くの意味が込められた言葉や表現を使ってコメントを簡潔に保つ
- 専門用語や曖昧な表現が増えて読みにくくなりそう。コードを読む人が誰か、を深く想定する必要あり。(所感)
第2部:ループとロジックの単純化
7章:制御フローを読みやすくする
鍵となる考え
- 1.条件やループなどの制御フローはできるだけ「自然」にする。コードの読み手が立ち止まったり読み返したりしないように書く。
- →コードの読み手を想定することは大前提。どんな知識・経験を持った人が読むのかなどを考えることが前提。(所感)
- 2.変更するときはコードを新鮮な目で見る。一歩下がって全体を見る。
まとめ
-
if/else文の引数の順番(※賛否両論あり)
- 比較を書くときは、変化する値を左に、より安定した値を右に記述する。
-
if( userWeight > averageWeight )
- 個人的に値が小さくなる方を左に書いた方が(数直線的に見て)読みやすい。つまり上記の例より
if( averageWeight < userWeight )
の方が読みやすく感じる(所感)
- 個人的に値が小さくなる方を左に書いた方が(数直線的に見て)読みやすい。つまり上記の例より
-
- 比較を書くときは、変化する値を左に、より安定した値を右に記述する。
-
if/elseブロックの並び順
- 肯定・単純・目立つものを先に処理する
- 衝突がない場合は基準を守ろう
- 肯定・単純・目立つものを先に処理する
-
三項演算子・do/while・gotoなどのプログラミング構成要素を使うと読みにくくなることが多い。
- 三項演算子は使うことによって簡潔になるときにだけ使おう
- 1行でかけるし便利だから使いがちだけど、長い変数名など記述が長くなるときはなるべくif/elseを使うようにしよう(所感)
- 三項演算子は使うことによって簡潔になるときにだけ使おう
-
ネストを浅くする
- 関数をなるべく早く返してあげる
- 関数の上部で単純な条件を先に処理するものを上部に記述する
- 関数をなるべく早く返してあげる
8章:巨大な式を分割する
鍵となる考え
巨大な式は飲み込みやすい大きさに分割する。
「頭がいい」コードに気を付ける。あとで他の人がコードを読むときにわかりにくくなる。
→ 1行で書くことに一種の喜びを感じるかもしれないが、他の人がコードを読む速度のことも考えると読みにくくなることが多い
- 説明変数、要約変数を使う
- 巨大な指揮を分割できる
- 簡潔な名前で指揮を説明することでコードを文書化できる
- コードの主要な「概念」を読み手が認識しやすくなる
- ド・モルガンの法則を使う
- 条件の言い換え(所感)
9章:変数と読みやすさ
鍵となる考え
1.変数のことが見えるこーど行すうをできるだけ減らす。
2.変数を操作する場所が増えると、現在値の判断が難しくなる。
- 邪魔な変数を削除する
- 中間結果を保持する変数を削除する
- for文を回す時などに使いがちなので注意(所感)
- 中間結果を保持する変数を削除する
- 変数のスコープをできるだけ小さくする
- 変数は使う直前に記述する
- 一度だけ書き込む変数を使う
- 変数に一度だけ値を設定(constなどを使用)すればコードが理解しやすくなる
第3部:コードの再構成
第3部の目的
- プログラムの主目的と関係のない「無関係の下位問題」を抽出する
- コードを再構成して、一度に1つのことをやるようにする
- 最初にコードを言葉で説明する。その説明を元にして綺麗な解決策を作る
10章:無関係の下位問題を抽出する
- プロジェクト固有のコードから汎用コードを分離する
- 関数などがあれば使用するのもあり
- 言語に用意された関数がなくても自分で関数を作って汎用化する
- よく使う表示変換(数値から円に、など)を汎用コードに分離する(所感)
- コード汎用化のやりすぎは読みにくくなる為注意する
- 関数などがあれば使用するのもあり
11章:一度に1つのことを
鍵となる考え
コードは一つずつタスクを行うようにしなければならない。
「一度に1つのタスクをする」ために意識している手順
- コードが行なっている「タスク」を全て列挙する。
- タスクをできるだけ異なる関数に分割する。少なくとも異なる領域に分割する。
→ 領域(デフォルト値の設定、値の取得、各変数の更新など)ごとに分けて記述する(所感)
プログラムが行なっていることを正確に説明することが一番難しい
→ タスクを全て列挙し、分割する際にまずは言葉で説明する必要があるため。この作業が難しい、確かに。(所感)
12章:コードに想いを込める
コードをより明確にする手順
- コードの動作を簡単な言葉で同僚にもわかるように説明する
- 説明の中で使っているキーワードやフレーズに注目する
- 説明に合わせてコードを書く
実装に悩んでいる時、実装内容を誰かに説明しようとすると解決策が見つかる。
逆に、説明できないときは何かを見落としているか、詳細が明確になっていないということ。
13章:短いコードを書く
鍵となる考え
もっとも読みやすいコードは、何も書かれていないこーどだ。
- 不必要な機能をプロダクトから削除する。過剰な機能は持たせない。
- 仕様変更などで廃止になった機能などは積極的に消す。(所感)
- 最も簡単に問題を解決できるような要求を考える
- ライブラリの使用もOK
- 知っているのと知らないとでは天地の差。(所感)
- ライブラリの使用もOK
- 定期的に全てのAPIを読んで、標準ライブラリに慣れ親しんでおく。
- 標準ライブラリのリファレンスは使う時ぐらいしか読まないけど、日々のこういう行動が短いコードを書くことにつながる。(所感)
選抜テーマ
14章:テストと読みやすさ
割愛(実際の本を参考ください)
基本的にこれまでの章と同じことをテストコードに応用してる。(所感)
15章:「分/時間カウンタ」を設計・実装する
割愛(実際の本を参考ください)
実際の機能を設計・実装していく過程でこれまでのテクニックを応用している。(所感)
まとめ(所感)
最後の14、15章は(これまでのまとめみたいなもののため)割愛しました。
記事を書いてる人の所感も入れた要約はなかなかなかった為(いらないとか言わないで泣)、備忘録としてのメモ。
本書は各章の最後に「まとめ」が書いてあり、本当に読みやすいから読み手にとても優しい。
是非、技術書紹介やまとめ記事を読むだけではなく本書を手に取って一読してほしい一冊。
そして忘れた頃に読みたい一冊。(いつ?!)
参考記事
まとめる際に、各要約記事も参考にさせていただきました。
ありがとうございました。