【全エンジニア必読の書】『リーダブルコード より良いコードを書くためのシンプルで実践的なテクニック』書評
「地獄とは、他人のコードのことだ」
ジャン・ポール・サルトル
プログラマーなら誰でも上手なコーディングをしたいと思うはずだ。
可能な限り少ない行数で、明解なロジックと高い効率性を実現したコードを書きたい。
しかし、「読みやすいコードを書きたい」という願望を抱いているプログラマーはそれほどいないようだ。
少ない業務経験の中で、幾度となく読みづらいコードに苦しまされてきた。
コメントが無いのは当たり前。意味も用途も不明な変数名、何処で更新されているのか分からないグローバルなフラグ、
「->」を使ってあちこちのクラスを跨いで呼び出されるメソッド、
各ブロックのステップ数が2000行近いif-else文……
何故製品として出荷されるはずのコードが、こんなにもクソで読みづらいのか、最初は分からなかった。
そして、何故コードがクソのまま放置されているのかも理解出来なかった。
一目見て明らかにイケてないのだから、誰かが気づいたら直してしまえばいいのに。
業務経験を積むにつれて、それらの理由が少しずつ分かってきた。
コードが読まれるまでには時間がかかる
まず、自分が書いたコードが他人に読まれるのは、コードを書き終えてしばらく経った後だ。
製造~単体テストのフェーズは全員自分のコードを書くのに必死で、他人のコードを読んでる余裕があまりないからだ。
また、コードレビューは必ず実施されるとは限らない。PMは一人残らず全員多忙で、タスクがパンク状態だ。
下手すれば合計何万行もあるコードを、全部読んでレビューする時間なんて無い。
PMの監視の目が無くなると、プログラマーは「動けばいい」もしくは「この実装方法こそが正しい」の信念の元に
設計書にも載っていない関数/クラス/ファイルを勝手に作り始める。
それも、決して読みやすくないコードで。
そして、問題が出た時に初めて、他のエンジニアがそれらのコードを"解読"する羽目になる。
気づいた時にはもう手遅れ
コードが読みづらければ直してしまえば良い。普通の神経をしている人はそう思うだろう。
しかし実際のところ、コードを勝手に直す事は出来ない。
まず第一に、直す時間が無いからだ。
例えば処理の書き方がイケてない関数があって、それを綺麗に書き直したいと思ったとしよう。
もしその関数と同じような書き方の関数が、色んなクラスのあちこちに存在していたら、
修正範囲は「修正対象の関数と、それと似たような関数全て」となる。
果たしてそれら全て修正して動作確認するまでに、どれほどの工数が必要だろうか?
また、コードの修正には常に「修正前は正常に動作していた機能が動かなくなる」というリスクが伴う(これをデグレードという)。
「読めないけど動くコード」はジェンガみたいなもので、少しいじっただけで一気に崩れて動かなくなる危険性があるのだ。
人から読まれる前に、読めるコードを書く
上に書いたような事態を未然に防ぐためには、他人に読まれる前からリーダブルなコードを書く必要がある。
一度書いてしまったコードが直せない以上、コードの品質は時間の経過と共に悪くなる。
ならば、書き終えた時点でのコードの品質を少しでも向上させるしかない。
それに、コードが鮮やかじゃないと、読んでても書いててもつまらない。
感想
結論は、読む前も読んだ後も変わらなかった。
エンジニアは全員この本を読むべきだ。
絶対に役立つ、そして直ぐに使えるコードを読みやすくするためのノウハウが理解しやすく、そして面白く書かれている。
この本そのものがリーダブルだった。
コードを書く人達全員がこの本を読んで、1つでも多く本のノウハウを実践したら、
この業界のコストはどれだけ小さくなるだろうか?
だから、もしこの本を読んでいないエンジニアがいたら、是非この本を読んで欲しい。
必ず役に立つはずだ。
ただ、8章、11章、15章等、自分に取って理解に時間がかかる章がいくつかあった。
また、この本はあくまで「人間がコードを読みやすくするためのノウハウ」を説明するための本なので、
パフォーマンスを出すための実装方法や、デザインパターンと呼ばれる実装におけるベストプラクティス等については紹介していない。
それらについては、別の書籍で学習する必要がある。
すぐに実践出来そうなTips
「すなわち、われわれの主な仕事がコンピュータに何をさせるかを命令する事だと思わずに、
人間に対してコンピュータに何をしてほしいかを説明する事に集中するべきである。」
ドナルド・E・クヌース
本の中で紹介されていた、コードを読みやすくするためのノウハウ、考え方をいくつか紹介する。
詳細や具体的な修正例は本を買って確かめて頂きたい。
コードは、他の人が最短時間で理解できるようにしなければならない
ここでの「理解できる」とは、すぐに変更できる、バグを見つけられるという意味
名前に情報を詰め込む。
出来るだけ具体的に。例えば、平文のパスワードの場合、「plain_」を付ける等
コメントの目的は、書き手の意図を読み手に知らせる事
ここでの「読み手」は、一ヶ月後の自分も含む
コードからすぐに分かる事をコメントに書かない
例えば、fileUpload関数のコメントに「ファイルをアップロードする」等(これをやってコメントを書いてる気になってる人がどれほど多いか!)
優れたコード > ひどいコード + 優れたコメント
あまりにひどいコードはコメントで補うのではなく直してしまおう。優れたコメントを添えて
コードの欠陥にコメントを付ける
記法 | 典型的な意味 |
TODO: | あとで手を付ける |
FIXME: | 既知の不具合があるコード |
HACK: | あまり綺麗じゃない解決法 |
XXX: | 危険!大きな問題がある |
関数の動作を具体的に記述する
どういう処理を何を用いて行い、どんな戻り値を返すのか等
実例をコメントに記述する
例えば引数numberをとるsumOne関数のコメントに「1 -> 2を返す」と書く等
ネストを浅くする
特にif文のネストは出来る限り避けましょう
説明変数(条件を表す変数)を使う
説明変数は、大きなコードの塊を小さな名前に置き換えて、管理や把握を簡単にする変数
変数のスコープを縮める
グローバル変数は出来るだけ作らずに、変数を定義する行と変数を使う行は出来るだけ近づける。
イミュータブルな変数を使う
あまりに自分の気持ちを代弁していたので貼らせて頂く。
JavaScript の let と const についての僕の気持ちです: pic.twitter.com/wLwHuYOxIf
— ドッグ (@Linda_pp) May 14, 2016
変数を雑に扱わない方がいい。どこで値が変更されるか分からない変数はコードを読む人を不安にさせる。
値が変更される事のないイミュータブルな変数だと分かれば、後はその変数がどのように使用されるかを調べるだけで済む。
すべてのAPIの仕様書に目を通す
車輪の再開発は出来るだけ避けよう。
今自分が実装しようとしている処理を提供しているAPIが、既に存在する可能性がある。それも、結構な確率で!
一度でもAPIの仕様書をざっと目を通していたら、いざという時に「そういえばこんな事出来るヤツがあったな」と思い出せる。
ライブラリは偉大だ。ほぼ間違いなく正確に動くし、仕様書をいつでもどこでも参照できる。
何よりも、テストの手間を省く事が出来る。
「ガード節」をつけて、関数からすぐに値を返す
「ガード節」とは、異常値が引数にセットされた場合に、
関数の頭で失敗結果をreturnする事だ。
これがある事によってコードの後半に本質的な処理を集中させる事が出来る。
ガード節に限らず、単純な条件判定や事前処理は関数の先頭で片づけてしまった方が良い。
リファレンス
Qiitaに、コードを書く上での注意点をまとめた素晴らしい記事があったので共有させて頂く。
リーダブルコードとは別の視点で、本質的には同じ内容を分かりやすく説明している。
是非読んで頂きたい。
The Art of Readable Code: Simple and Practical Techniques for Writing Better Code (English Edition)