はじめに
新卒エンジニアが一年目で読んで良かった本
のようなトピックで必ず挙げられる「リーダブルコード」をキャリア四年目にして今更読んだところ、これまでの開発経験で積み重なっていた点と点が線になる感覚があったので自分のための備忘録を残す。
リーダブルコード
- ※個人的要点は太字
- ※一部ごとに所感を記録
理解しやすいコード
- 読みやすいコード=理解しやすいコード
- コードは他の人が最短時間で理解できるように書かなければいけない
- 「このコードは理解しやすいだろうか?」を自問自答する
所感
上長エンジニアがよく「半年後の自分に見せて必要十分な情報が含まれているかという視点で見ろ」と言ってくれるが、適切な助言だと思う。半年後の自分はもはや他人であるから。その他人を想像して、常にフレッシュな視点をもつ。誰が読んでも最短ルートで歩けるようコードを整備しなければならない。
【第I部】表面上の改善
命名
- 名前に情報を詰め込む
- 意図を明確に表現した、簡潔な命名にする
- tmpという名前は、生存期間が短くて、一時的な保管が最も大切な変数にだけ使う
- 情報が損なわれない不要な単語は投げ捨てる(
ConvertToString()→ToString()
) - 何が起きるかを明確に表していて、誤解を生まない名前が最善である
美しさ
- 似ているコードは似ているように見せる
- 縦軸の位置を揃える
- 関連するコード(宣言など)を纏める
- コードを段落に分割する
コメント
- 適切なコメントを書く
- コードからすぐにわかることを書かない
- コメントでコードを補うのではなく、コードを修正する
- ライターズブロックを乗り越える
- 脳内にあるコメントを全て書き出す
- コメントを読んで改善が必要なものを見つける
- 改善する
// ヤバい。これはリストに重複があったら面倒なことになる。
// 注意:このコードはリストの重複を処理できません(実装が難しいため)
- 歯切れの悪い文章を、単純に短く直接的にする
これまでにクロールしたURLかどうかによって優先度を変える。
これまでにクロールしていないURLの優先度を高くする。
- 関数の動作を正確に記述する
- コメントに含める入出力の実例を慎重に選ぶ
第I部の所感
リーダブルコードの根幹部分である。表面上を改善するだけでコードの可読性は一気に向上する。社内でコードレビューをする立場になって常々思うことだが、「表面上」が整えられているコードは読みやすく、つまりは理解しやすい。凄まじく冗長な命名、不揃いのインデントは「コードを読みたい」という気持ちを損なわせる。まずは見た目の美しさを洗練すること、これが読みやすいコードの第一歩である。
【第II部】ループとロジックの単純化
制御フローを読みやすくする
- 条件やループなどの制御フローはできるだけ自然にする
- コードの読み手が立ち止まったり読み返したりしないように書く
- 左側:調査対象の式。変化する
- 右側:比較対象の式。あまり変化しない
- if/elseブロックの並び順(衝突もある)
- 条件は否定形よりも肯定形を使う
- 関心を引く条件や目立つ条件を先に書く
- 行数を短くするよりも、他の人が理解するのにかかる時間を短くする
- 変更する時にはコードを新鮮な目で見る。一歩下がって全体を見る。
巨大な式は飲み込みやすい大きさに分割する
- ド・モルガンの法則を使う
not (a or b or c) ⇔ (not a) and (not b) and (not c)
not (a and b and c) ⇔ (not a) or (not b) or (not c)
- 説明変数、要約変数の導入
- 簡潔な名前で式を説明することで、コードを文書化できる
- コードの主要な概念を読み手が認識しやすくなる
変数と読みやすさ
- 変数のスコープを縮める
- if文の中だけで使う変数はif文の条件式でその変数を定義すればよい
- 変数定義は変数を使う直前でよい
- 変数は一度だけ書き込む
- 変数を操作する場所が増えると、現在値の判断が難しくなる
第II部の所感
ここでもいかにコードを読みやすくするかという観点で述べられている。新人プログラマは制御フローをネストし、同じ変数を使い回す。これではコードは複雑化していくばかりだ。そういったコードは自然と書かなくなったが、最近では脳内知識を総動員して「目の前のコードをいかに簡単に書くか」という命題の解決に血眼になっていたので、これは自戒として記しておく。簡単なコード≠読みやすいコード。
「ロジックを簡単なコードに落とし込むことに一種の喜びを感じていた。これがコードのスピードバンプになっていた。」
【第III部】コードの再構成
-
無関係の下位問題を積極的に見つけて抽出する
- 関数やコードブロックを見て「このコードの高レベルの目標は何か?」と自問する
- コードの各行に対して「高レベルの目標に直接的に効果があるのか?あるいは、無関係の下位問題を解決しているのか?」と自問する
- 無関係の下位問題を解決しているコードが相当量あれば、それらを抽出して別の関数にする
- 関数を小さく独立したものにするメリット
- 機能追加
- 可読性の向上
- エッジケースの処理
- プロジェクト固有のコードから汎用コードを分離する
-
一度に1つのタスクを行う
- タスクをすべて列挙する
- 別の関数に分割できるタスクを見つける
- それ以外は、関数の論理的な「段落」
- コードに思いを込める
- ライブラリが何を提供してくれるかを知る
- 短いコードを書く
- 既存のライブラリで問題を解決できる
- コーディングするよりもコマンドラインを使う
第III部の所感
小説を書いたら推敲があるように、コードを書いたら再構成する余地がある。「無関係の問題を抽出して分離する」「一度に1つのタスクを行う」は言語を問わず汎用的能力である。同時に、自分が考え得る大半のコードはライブラリに用意されている。コードを抽出し、その責務から適切な場所に分離する。時にライブラリやコマンドラインを駆使する。そのようにコードを再構成できれば、読みやすいコード
はもう眼前に広がっているのではないのか。
解説
- 自然に読みやすいコードを書けるようになるための3つのステップ
- 実際にやる
- 当たり前にする
- コードで伝える
読みやすいコードを書いて、自分が書いたコードを忘れてしまっても問題ないようにする。読みやすいコードを書こう。忘れてもいいコードを書こう。
「リーダブルコード」参考記事