📑

リーダブルコード 要点メモ

2023/08/05に公開

概要

リーダブルコードを読んで個人的に重要と感じた点を、備忘録としてまとめている。

https://www.oreilly.co.jp/books/9784873115658/

※ 原書(英文)を翻訳しながら読み、かつ自分なりに解釈し記載しているため、ニュアンスや内容が異なる可能性がある。

内容

コードは理解しやすくあるべき (1 章)

テストと可読性 (14 章)

  • テストは読みやすく、メンテしやすいようにすべき。
    他の開発者がテストを見て、その挙動・仕様を把握しやすくするため。
    また、プロダクトコードを書き換えることやテストを追加することへの心理的障壁を少なくするため。
  • 何をテストしているテストなのかがわかりやすいテスト名にすること。

<表層レベルの改善>

リファクタリングやコードの変更を行うことなく、小さな労力で実施できる内容。

名前に情報を詰める (2 章)

  • 具体的な単語を選ぶこと。汎用的すぎたり、伝える内容が薄い単語は避ける。
  • カラフルな単語を選ぶこと。
  • tmp という単語は、本当に一時的かつ局所的なら OK。
  • ループのイテレーターとしてijを使うのは OK
    場合によっては、複数の配列をネストループするときなどは、users 配列のイテレーターのui 、members 配列のイテレーターのmiなどと命名したほうが良い。
  • 変数名に単位をつけたほうが伝わりやすい。(sなのかmsなのか、MBなのかGBなのか)
  • スコープが小さいなら、変数名も短いもので OK。その変数がどういうものか定義した行が、それを使う行のすぐ近くにあるため。2,3 行上のコードを見ればすぐわかる。
    逆に言うと、スコープが大きいと、それが何かを理解するのに必要な情報を詰め込んだ名前 にしないといけない。
  • 略語を使っていいかどうかは、「新しくジョインしたチームメイトが理解できる名前かどうか」で判断すると良い。

誤解されない名前 (3 章)

  • 誤解されない名前をつけること。
  • 「~以上、~以下」を表す場合
    その境界値を含むことを明確に表すために max*, min*という prefix を付けると良い。
    範囲の場合は、first, last
  • 「~未満(~より小さい)」を表す場合
    end を使うのが良い。(英語として 未満 のような言葉が無いが、end が一番良いらしい。)
  • bool 値
    • is(かどうか)
    • has(持っているかどうか)
    • can(可能かどうか)
    • use(使っているかどうか) など

コードを美しく整える (4 章)

何をコメントすべきかを知る (5 章)

<何をコメントすべきでないか>

  • コメントがあることによって、コメントを読む時間というのが発生し、コメントの分画面が埋まる。
    なので、コメントにはそれに見合う価値が無いといけない。

  • コードからすぐに(簡単に)読み取れる事実はコメントしないこと。
    逆に、複雑な処理をしているコードに対して、それが何をしているのかをコメントすることは、読み手の助けになるので OK。

<考えていることをコードに記録する>

  • 定数にはコメントを。
  • なぜそう実装したのか(なぜ他の方法を選択しなかったのか)をコメントする。

読み手になりきって、そのコードを読むのにどんな情報が必要か想像する

  • 読み手が疑問に思いそうなことを想像して(先回りして)コメントする。
  • 読み手を驚かせるようなコードになっていないか、誤用されないか を確認すること。
  • What(何を)、Why(なぜ)、How(どのようにしたか)をコメントすべき。

コメントは正確かつコンパクトに (6 章)

  • 関数の入出力の具体例をコメントすると、文字で説明するよりも効果的な場合がある。
    (この場合どうなるのか?と思うような境界値や重複、並び順、返り値などを具体例に取り上げる。)
  • 複雑じゃないコードの場合、そのコードの挙動をコメントするのでなく、そのコードをもって何を実現したいのか(1 つ高い抽象度で)説明するコメントを書く。
    (例:「降順に並び替える」 でなく、「値段が高いもの順に表示する」 など)
  • 情報が多い単語を選び、コメントをコンパクトにする。

<複雑なロジックを理解しやすく>

複雑なロジックであっても、心理的負担をかけず脳内メモリを専有せずに、読み手が簡単に理解できるようにする。

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

  • 比較演算子の 左側には比較したいもの(変化するもの)、右側には比較の基準となるもの(より一定であるもの=定数や定数に近いもの)を置く。

    if recieved_value > expected_value
    
  • 条件分岐では、否定形でなく肯定形を使い、関心が高い or 目立つ条件を先に書く

  • コードの行数を減らすのでなく、コードを読む時間が減るように書く。
    (感想: コードの行数を減らすことも大事。ただ、そのせいで読みにくくなってはいけない。)

  • 三項演算子を使うのは、簡単な条件分岐の場合のみ。

  • 早期リターンすること。

巨大な表現を噛み砕く (8 章)

  • 説明変数を使う。

  • ド・モルガンの法則を使う

    !(A || B) は (!A && !B) に等しい ... 'AかB でない' = 'Aでない かつ bでない'
    !(A && B) は (!A || !B) に等しい ... 'AかつB でない' = 'Aでない か Bでない'
    

    https://basics.k-labo.work/2017/08/31/論理演算/

  • DRY(Don’t Repeat Yourself)

変数と可読性 (9 章)

  • JavaScript では変数にはいつもconstを付けること。(付けないとグローバル変数になる。)
  • 変数のスコープは狭く。
    JavaScript と Python は、ループ内で定義した変数もループ外で使えるため、注意が必要。(スコープが広い)

<1 度に 1 つのことしかしない>

無関係な問題を抽出する (10 章)

  • 関数内で、やりたいことと関係のないことを行っているコードは、別の関数に分ける。
  • 細かすぎる単位で関数に分けると、かえって読みにくくなる。コードをジャンプして読まないといけなくなるため。
  • プロジェクト(ドメイン)特有のコードは、一般的なコードから隔離する。

考えをコードに変換する (12 章)

  • 否定(not)をできるだけ使わない。複雑なロジックの中で否定を使うと理解が難しくなる。
  • ライブラリが提供しているものを知ることで、コードを簡潔に書ける。

コードを書かない (13 章)

  • コードを書くと、それをテストしたりメンテナンスする必要が生じる
    ライブラリを使ったり機能を排除したりすることで、コードを書かずに済み、時間を節約できる。
  • プログラマーは、すべての機能を実装したがる傾向がある。ほとんどの機能は、未完成に終わる or 使われない or アプリケーションを複雑にするだけ。(オーバーエンジニアリング)
    また、機能の実装にかかる労力を過小評価する傾向がプログラマーにはある。実装自体の時間に加え、将来のメンテナンス、ドキュメンテーション、アプリケーションに追加されたコードの「重量」どれだけ複雑にしたか)を考えていない。
  • 要求に対し、本当に必要かどうか疑問を持つ要求を分解する。
  • プロジェクト内のコードを小さくする。
    • 重複したコードをまとめる。
    • 使われていないコードを削除する。
  • 標準ライブラリや、使用しているライブラリの機能を把握する
    • たまに 15 分間読み込む時間を設けるのはどうか、と本書は提案している。
      目的は暗記することではなく、「見たことがあるかも...」という勘を得るため。
    • ライブラリのコードは、デバッグ、最適化、テストのプロセスを経過して生き延びたコード。
  • (プログラム言語で書くのでなく)OS コマンドで実現するほうが適切でないか、考える。

以上

Discussion