読者です 読者をやめる 読者になる 読者になる

Jの衝動書き日記

さらりーまんSEの日記でございます。

リーダブルコードの読書メモ

技術

リーダブルコードを読んだので、重要だと思ったことをメモしておく。本自体は非常にわかりやすく書かれており、毎日ちょっとづづ読んでも苦にはならない。もう3回は読んだ。いや、いつの間にかそれぐらい読んでいた、が正しいかも。

個人的にはプログラム初級者は、この本を読む前にまずはあれこれ書いてみた方がいいとおもう。まずはプログラムを書くことになれた方がいい。スクリプト程度でいいのでまずは書いてみよう。

慣れてくると、クラスやメソッドの名前の付け方に悩むかもしれない。綺麗なソースはどういうのか悶々とするかもしれない。そんな気持ちになった時に読むのが一番効果的だろう。きっとすぐ色々試したくなるはずだ。仕事として楽しくなってくるというおまけもついてくる。

さて、以下は大切なことのメモ書きである。

第1部 表面上の改善

  • コードは理解しやすくなければいけない
  • コードは他の人(遠い先の自分も含む)が最短時間で理解できるように書かなければいけない
  • 名前に情報を詰め込む
    • 明確な単語を選ぶ → シソーラス類語辞典)を活用する
    • 汎用的な名前を避ける
      •  tmpという名前の使いどき
        • 生存期間が短くて、役割が一時的な保管
    • 抽象的な名前よりも具体的な名前を使う
    • 接尾辞や接頭辞を使って情報を追加する
      • 値の単位
        • 秒→_secs
        • バイト数→_mb
      • 状況を追加
        • 値がプレインテキストだと明示→plaintext_password
        • エスケープする必要があるコメント→unescaped_comment
    • 名前の長さを決める
      • スコープが小さければ短い名前でよい(すぐわかるから)
      • 省略形は自明のもののみにする string→strなど
      • 不要な単語は切り捨てる
    • 名前のフォーマットで情報を伝える
      • 大文字やアンダースコアなどに意味を含める
      • インスタンス変数には_を末尾に付けるなど→プロジェクトの規約による
  • 誤解されない名前を付ける
    • 名前が「他の意味と間違えられることはないだろうか?」と何度も自問自答する
    • 限界値を含めるときはmin とmax を使う
    • 範囲を指定するときはfirst とlast を使う
    • 包含/排他的範囲にはbegin とend を使う
    • ブール値の変数名は、頭にis・has・can・should などをつけて肯定形にする
    • 誤解を招きやすい例
      • get,size → 値の単純な取得を期待する。時間がかかるような処理には付けない
  • コードを美しく保つ原則
    • 読み手が慣れているパターンと一貫性のあるレイアウトを使う
      • 一貫性のある簡潔な改行位置
      • 縦の線をまっすぐにする → 同じ列は空白などで位置をあわせる
    • 似ているコードは似ているように見せる
    • 関連するコードをまとめてブロックにする → 段落に分割する
  • コメントの目的は、書き手の意図を読み手に知らせることである
    • コメントするべきでは「ない」こと
      • コードからすぐにわかることをコメントに書かない
      • ひどい名前はコメントをつけずに名前を変える → 優れたコード > ひどいコード + 優れたコメント
    • コードを書いているときの自分の考えを記録する
      • コードの欠陥にコメントをつける
      • 定数にコメントをつける → 値の決め方、根拠などを書いておく
    • 読み手の立場になって何が必要になるかを考える
      • 何故?と意図がわかりにくい箇所に書いておく
      • ハマりそうな罠を告知する → 誤用を避けさせる
    • コメントは簡潔に正確に書く
      • 文章で書きにくい場合は実例を示しておく
        • 単純な例ではなく、いろんなケースが混ざったようなものを示すのがよい(使い方に疑問があるようなケース)

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

  • 条件やループなどの制御フローはできるだけ「自然」にする。コードの読み手が立ち止まったり読み返したりしないように書く。
    • 条件式の引数の並び順
      • 左側:調査対象の式:値は変化する
      • 右側:比較対象の式:値はあまり変化しない
    • if/else ブロックの並び順
      • 条件は否定形よりも肯定形を使う。例えば、if (!debug) ではなく、if(debug) を使う。
      • 単純な条件を先に書く。if とelse が同じ画面に表示されるので見やすい。
      • 関心を引く条件や目立つ条件を先に書く。
  • 迷ったら、行数を短くするよりも、他の人が理解するのにかかる時間を短くすることを意識せよ
  • なるべく使わない方がいいもの
    • 三項演算子→素直にif/elseで書く
    • do/while→たいていwhileで書ける
  • 関数から早めに返す。返せるタイミングでさっさと返そう → ネストを浅くするためにも
  • 変数の原則
    • 役に立たない一時変数は削除する → 説明用変数として使う場合は名前が適切かどうかチェック
    • 変数のスコープは縮める
    • 変数の変更箇所はできるだけ少なくする → 変更不可と明示するのも手(final宣言など)

第3部 コードの再構成

  • プログラムの主目的と関係のない「無関係の下位問題」を抽出する。
    • 抽出の考え方
      1. 関数やコードブロックを見て「このコードの高レベルの目標は何か?」と自問する。
      2. コードの各行に対して「高レベルの目標に直接的に効果があるのか? あるいは、無関係の下位問題を解決しているのか?」と自問する。
      3. 無関係の下位問題を解決しているコードが相当量あれば、それらを抽出して別の関数にする。
    • グルーコード(関数の事前処理や事後処理)は抽出候補の処理
  • コードを再構成して、一度に1 つのことをやるようにする。
    • 考え方
      1. コードが行っている「タスク」をすべて列挙する。この「タスク」という言葉はユルく使っている。「オブジェクトが妥当かどうかを確認する」のように小さなこともあれば、「ツリーのすべてのノードをイテレートする」のようにあいまいなこともある。
      2. タスクをできるだけ異なる関数に分割する。少なくとも異なる領域に分割する。
  • 最初にコードを言葉で説明する。その説明を元にしてキレイな解決策を作る。
    • 手順
      1. コードの動作を簡単な言葉で同僚にもわかるように説明する。
      2. その説明のなかで使っているキーワードやフレーズに注目する。
      3. その説明に合わせてコードを書く。
  • 定期的にすべてのAPI を読んで、標準ライブラリに慣れ親しんでおく。

終わりに

本ではテストコードもわかりやすく書くことを推奨しているが、個人的にはこれは限界があるなと思う。時間という壁が。納期という壁が。あまりに凝り過ぎると稼働過多になり、体にもプロマネの胃にも優しくない。程々にしておこう。

ただ、テストコードの更新だけは忘れずに。通るテストを残しておかねばならい。更新してない綺麗なテストコード <<<<< 汚いが通るテストコードである。通りさえすれば、後で直すことも可能だが、通らないものを直すのは色々と大変だ。

本を読み終わった頃、かつて自分が書いたコードを直す衝動にかられるかもしれない。だが、いきなり直すのはNGだ。ここでテストコードが重要になってくる。Javaプログラマなのであれば、「リファクタリング―プログラムの体質改善テクニック」も読んで見ることを強く薦めたい。

参考資料

リーダブルコード ―より良いコードを書くためのシンプルで実践的なテクニック (Theory in practice)

リーダブルコード ―より良いコードを書くためのシンプルで実践的なテクニック (Theory in practice)

※PDF版も出てるので、そっちがオススメ。