ゆるっと備忘録

見たものを忘れないように記録する不定期ブログ

リーダブルコードを読んだ

背景

名著であるリーダブルコードを読んだ

備忘録として読んだものを軽くまとめる
自分にとって当たり前すぎることは記述していないので、読んでない方はぜひ読んでみてください
かなり読みやすいのでオススメです

1章 理解しやすいコード

コードは理解しやすくなければいけない
読みやすくコードを書くことは、他の人が最短時間で理解できるように書くことだと言える

第1部 表面上の改善

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

命名するときは以下のことを意識すると良い

  • 明確な単語を選ぶ
  • tmpなどの汎用的な名前は明確な理由が無い限り避ける
  • 具体的な名前を使う
  • 変数名に大切な情報を追加する
    例えばミリ秒を表すものには_msなど単位がわかるように
  • 名前の長さを決める
    短ければ短いほどいい。どれくらいの長さにするかはスコープで判断 名前にはstrのような省略形があるが、全員が理解できるなら省略系はあり
  • 名前にフォーマット規約をつける
    例えばプライベート関数は小文字から始めるなど フォーマットを決めることで情報量が多くなる。チームごとに決めると良い

3章 誤解されない名前

誤解されない名前にするために以下のことを気をつける

  • 他の意味に捉えられない名前にするべき 例: filter。これだと選択なのか除外なのかわからない。selectかexcludeにするべき
  • 数値周りの命名
    限界値を指定するときはmax, min
    範囲指定はfirst, last
    包含・排他的範囲はbegin, end
  • ブール値はis,has,can,shouldをつけることが多い
  • 名前を否定系にするのは避けた方がいい
  • get* というメソッドは軽量なものという暗黙な常識がある
    大量にデータを扱って計算する場合はcomputeとか別の名前にする
  • 名前を検討するときは複数出して、他人が見たらどうかを考えて決める

4章 美しさ

美しさとはコードの見た目の美しさのこと
余白、配置、順序に関することになる

3つの原則がある

  • 読み手が慣れているパターンと一貫性のあるレイアウトにする
  • 似ているコードは似ているように見せる
  • 関連するコードはまとめてブロックにする

重複する処理はメソッド化すると、簡潔になり、処理が何をしたいか明確になりやすいかも
ヘルパー関数を作成するつもりでいると良いかも

コードの並びが処理に影響を与えない場合は、意味のある順番にする

  • 他で並んでいた順番と同じにする
  • 最重要なものから重要度順
  • アルファベット順
    など

コードは意味のあるまとまりにして、段落分けを行う

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

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

コメントに書くべきではないこと

  • コードからすぐに理解できる
  • ひどいコードの補助(この場合はコードを変える方が良い。ひどい命名も同じ)

コメントすべきこと

  • 自分の大切な考えを記す
  • あとで改善したいTODO
  • 定数の場合はなぜ定義したか記録すべきことが多い
  • 他人に質問されそうな箇所
  • 間違った用途で使われそうな箇所
  • 全体像へのコメント
  • 関数内の、処理の塊の概要をコメント化(関数に分割できるならした方がいい)

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

コメントで意識すると良いこと

  • コメントは簡潔にする
  • 曖昧な代名詞は避ける
    「〇〇によって優先度を変える」ではなく「〇〇の優先度を高くする」というように直接的な表現にする
  • 時には実例をコメントに書くことでわかりやすさが上がる
    「listを逆順にソートする」という書き方より「値段が高い順にソートする」の方がわかりやすい。つまり高レベルの言い方を使う
  • 情報密度の高い言葉を使う
    キャッシュ、正規化、ヒューリスティックブルートフォース、ナイーブソリューションなど
    用語を覚えて使いこなす

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

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

if文について

if文内の式のオペランドでは

  • 左側を調査対象(値が変化する)
  • 右側を比較対象(値が変化しづらい)

という風にすると良い

if/else文の条件については下記を意識すると良い

  • 条件は否定形より肯定形を使う
  • 単純な条件を先に書く
  • 目立つ条件を先に書く

他に意識した方がいいこと

  • 三項演算子は簡潔で読みやすくなる時のみ使い、基本はif文を使用する方がいい
  • do/while文はわかりづらいので使用を避ける
    他にも条件が式よりも後ろに来る文は避けた方がいいかも(感想)
  • goto文は基本使わない
  • ネストはなるべく浅くする
    if文でネストを作らずにすぐにreturnを返すなどする

8章 巨大な式を分割する

コードの塊は小さくするべき。下記のことを意識すると良い

  • 式を変数に代入する
    式の説明として変数名を活用
    式の要約として変数名を活用
    何回も登場する式は要約変数にすると良い
  • 論理式はドモルガンの法則でわかりやすくできるかも
  • 複雑なロジックになる時は、そのロジックの反対を考えて簡潔にできないか試す

9章 変数と読みやすさ

コードを読みにくくする変数もあるため、それは削除するべき
下記のような変数はない方がいい

  • 複雑な式でもなく重複の削除にもなってない変数
  • 中間の結果を保持するための変数
    結果は保持するのではなくすぐに使う
  • 制御フロー変数

変数のスコープはできるだけ短くするべき
そのために下記を意識すると良い

変数の値が変更される箇所は少ない方がいい
変数は一度だけ書き込む状態が好ましい

第三部 コードの再構成

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

エンジニアリングは大きな問題を小さな問題に分割して解決するべき

  • 無関係な下位問題は別の関数にした方が良い
    例: 2地点の配列が与えられた時、最も距離が短い2地点を算出する関数をつくる。その時、2地点間の距離を求める部分は無関係な下位(だけど必要な処理)だと言える
  • どの場所でも使う関数があればユーティリティコードにする(例えば時間の変換など)
  • 汎用的な下位問題は抽出し、別の関数にする方が良い
    ただ、関数を別にしすぎると様々な関数を見にいく必要が出るため、やりすぎは注意

11章 1度に1つのことを

1度に複数のことを行うコードは分かりづらいので分割するべき
コードのタスクを列挙し、ジャンル分けをして、順番にタスクが行われるように整理する(必要であればタスクを別の関数にする)

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

理解した状態とは、相手に簡単な言葉で説明できる状態
コードも簡単な言葉で説明できるようにしておくべき

ロジックを簡単に説明してからコードを書き始めるといい
言葉にしたものをコードにすれば分かりやすくなるし、良い変数名を考えられる

13章 短いコードを書く

コードは書かないに越したことはない
コードを書くと、テスト・文書化・保守が必要になる

コードを書かないために

  • 不必要な機能はプロダクトから削除する(なぜあるのか、影響はあるのか調べる手間をなくす)
  • 最も簡単に解決できるようなアプローチを考える(例:経度緯度を計算して店舗検索するのではなく、現在位置の30m以内を店舗検索する方が実装しやすい)
  • 標準ライブラリに親しんでおいて、利用することで自前の実装を省略する

4部 選抜テーマ

14章 テストと読みやすさ

テストは読みやすさが重要。そうなればテストの追加や修正がしやすくなる

  • テストのトップレベルは極力簡潔にする。テストに必要な値の準備などは関数にまとめちゃっていい
  • テストでエラーが起こったときに、どんなエラーだったか詳細がわかると良い
  • テストケースは単純な値や組み合わせがいい。1つのテストケースを複雑にするなら、単純なテストケースを複数作る方がいい
  • テストケースは、エッジケースや極端な値を設定するケースもあるとなおよし
  • テスト関数名は長くてもいいので、何をテストするのかわかるようにする

実装本体のコードはテストがしやすいように書かれた方が、疎結合でわかりやすいコードになりやすい
ただし、テストコードを意識しすぎて本体コードに余分な処理を入れたり、時間がよりかかったりすると元も子もないので気をつける

15章 「分/時計カウンタ」を設計・実装する

実例だったが、C++だったのでよくわからなかった