徒然技術日記

Object.prototype.__noSuchMethod__

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

社会人になる前に読もうと思って春休みに購入し,そのまま積んでいたリーダブルコードを今更ながら読んだ.

よく新卒になる前に/なったら読んでおけという本のリストに必ずといっていいほど入っている本であるが,結論から言うとやはりもっと早く読んでおくべきだったと若干後悔している.

以下読書メモ.

第1章: 理解しやすいコード

  • 理解しやすいコードとは何か?
    • 他人が最短時間で理解できるコード
    • 簡潔なコードが理解しやすいとは限らない
  • 自分は入社してから「意図が伝わりやすいコード」を心がけるようになった
    • 「他人が最短時間で理解できるコード」と同じような感じかもしれない
    • コードに加えて,コミットメッセージ・コミットの内容も「意図が伝わる変更」を意識している
      • 例えば:
        • バグ修正の時は先に fail するテストをコミットしてから修正のコミットをする
        • リファクタリングでは各コミットでテストが通ることを確認する(その旨を PR のメッセージも書いておく)

第2章: ネーミング

第3章: ネーミングその2: 誤解されない名前の付け方

  • check が曖昧なのはよく知られているが,他にも例示されていたので勉強になった
    • filter -> select / exclude: JS の Array#filter があるので意識したことがあまりなかったが,言われてみると確かに曖昧
    • clip -> truncate: truncate はなかなか思いつかない単語なので脳内リストに入れておきたい
    • first/last の last は inclusive だが begin/end の end は non-inclusive なのは知らなかった
    • ブール値の値に is/has をつけるのは意識しているものの, 否定形の単語を避ける のは意識していなかったので注意したい
      • 自分の観測範囲では日本人が書くコードで is + 形容詞 + 名詞 となっているのをよく見かける.これはなぜなのか...
        • 形容詞によっては意味が通ることもあるが,コードで出てくる場合はだいたい叙述用法 is + 名詞 + 形容詞 が適切な場合が多い

第4章: コードの美しさ

  • この章は形式的な美しさのみを扱っている
  • 今日では formatter が解決する部分が多い
    • 書かれている内容が実現できない場合もあるものの(縦で揃えるなど),しばしば bikeshedding な議論になるので formatter に任せるのが便利
  • コードを意味段落ごとに改行する,宣言を意味ごとにまとめる,などは割とやっているかも

第5章: コメントに書くべきこと,書いてはいけないこと

  • コメントには「自分の考えを記録する」
    • 5.2. 定数にコメントをつける
      • これは意識できていなかったので注意したい
      • 確かにコメントがないとその定数を変えるのが難しくなる...
    • 5.3. 全体像のコメント,要約コメント
      • 個人的にはこの辺りは適切なネーミング(ファイル名,クラス名,変数名)とメソッドへの分割で担保したいと考えている部分も大きい
      • どちらがいいのかは自分の中でまだ結論が出ていない...

第6章: 簡潔なコメントを書く方法

  • 最近はコメントを英語で書いているので,ここの部分は原著で読んだほうがよかったかもしれないと思った
  • 6.4. 関数の動作を正確に記述する
    • 下手すると関数の中身を逐一説明することになりそうなのでいいコメントが書けるようになるには修練が必要そうに感じた
  • 6.5. コーナーケースの例を書く
    • ユニットテストで例示する方法もありかなと思った
      • コメントに例を書く方法では常に正しい例なのかどうかが検証できないが,テストコードではその心配がない

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

  • if condition の順序,if/else の順序,ネストの深さ,early return など
    • この章の内容は馴染み深いものだった

第8章: 式の分割

  • 8.1, 8.2. 説明変数,要約変数
    • 今までも無意識にやっていたけれど,概念に名前がつくと意識できてよい
    • 機能追加が重なっていくと複雑な if になることが結構あるので,意識的に変数で説明的にしていきたい
  • 8.5. if の条件を考えるのに「反対から考える」と条件が簡潔になることがある
    • e.g.) 2つのオブジェクトが「重なる条件」→「重ならない条件」を考える
    • 数学の「余事象」に似ていると思った
      • コーディングしているときは大抵「やりたいことをそのまま表現できるコードを」と思って書いているので,余事象を考えるのは割と盲点だった

第9章: 変数と読みやすさ

  • 不要な変数の削除,変数のスコープを小さく保つこと, const を使うこと
    • JS に const が導入された当初はいわゆる「定数」のみ const で定義することが多かったように記憶しているけれど,ここまで「必要がなければ const で定義する」ことが広まったのは感慨深い
    • Object.freeze and Object.seal syntax がもし入ればそれを使うことが一般化するのだろうか...?

第10章: 無関係の下位問題を抽出する

  • プロジェクト固有のコードから汎用コードを分離することについて
    • utils/ に切り出すようなイメージ
  • 「無関係の下位問題」という概念を初めて知った
    • これまで結構やらかしてそうで怖い
  • 気になった箇所 (p.137, 強調は自分):

make_url_friendly() はどこに置けばいいのだろう? 汎用的な関数なので util/ ディレクトリに入れてもいいと思う.でも,この正規表現アメリカのビジネス名だけを対象にしているので.元のファイルと同じ場所に置いたほうがいいかもしれない. 大切なことじゃないので,あとで決めてもいいだろう.

「どこにファイルを置くか」というのは 大切な問題 と思う.ビジネスの特定ドメインに紐つく処理なのか,そうではなくもっと汎用的な処理なのかは厳密に区別されるべきで,これが曖昧になるとアプリケーションの規模が大きくなった時にどこに何があってどれがどれに依存しているのか判断しにくくなってしまう.

おそらく原著がドメイン駆動設計の「再発見」より前に書かれていることと,本の流れとしてファイルを置く場所について言及すると脱線気味になってしまうことがさらっと流している理由かなと思うものの,自分は 大切なことじゃない という意見には共感できなかった.

第11章: タスク単位での分解

  • コードをタスク単位で小さく分割し,ブロックやメソッドをタスク単位で記述することについて
    • だらだらと処理が書かれているコードはなんとなく読みにくいと感じていたが,それは「複数のタスクが入り混じっているコードだから」と腑に落ちた
    • 今後わかりにくいコードを見つけたらタスク単位で分解するのを試してみたい

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

  • 行いたい処理の内容を簡潔な言葉で説明することでリファクタリングを行う方法について
    • 頭の中だけでは考えきれない場合にノートに図などを書いて整理することはやっていたものの,リファクタリングに対してはやってみたことがなかった
    • リファクタに限らずコードが複雑になりそうな場合は言葉で説明してみるというのは有用そうに思った

第13章: 短いコードを書く

  • いかにコードを書かないで済ませるか?という話
    • 要求を正確に捉えて,無駄な処理を実装しない
      • 要は YAGNI の原則を説明したものと理解した
    • 言語機能,ライブラリなどで使えるものはないかを意識する
      • 新しく使う言語,慣れていない言語では重要そう

第14章: テストと読みやすさ

  • コード改善の実例: テストコードの改善方法について
    • テストコードの読みやすさを気にかける余裕がなかなかないのが辛いところ...
    • 「一つの巨大なテストケース」は生み出したことがあるので反省(この前ちょうど1つ改善した)