『リーダブルコード』第10章 無関係の下位問題を抽出する

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

エンジニアリングとは、大きな問題を小さな問題に分割して、それぞれの解決策を 組み立てることに他ならない。

無関係の下位問題を積極的に見つけて抽出すること

  1. 関数やコードブロックを見て「このコードの高レベルの目標は何か?」と自問する。
  2. コードの各行に対して「高レベルの目標に直接的に効果があるのか? あるいは、無関係の下位問題を解決しているのか?」と自問する。
  3. 無関係の下位問題を解決しているコードが相当量あれば、それらを抽出して 別の関数にする。

まとめると、プロジェクト固有のコードから汎用コードを分離すること。

※この章は、実際のコード例が多数出てくるので、要約よりも本の現物を読んだほうが良い。

『リーダブルコード』 第9章 変数と読みやすさ

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

変数を削除する

役に立たない一時変数

  • 複雑な式を分割していない
  • より明確になっていない
  • 重複コードの削除になっていない

中間結果を削除する

配列から値を削除するJavaScript関数の例:

index_to_removeという変数は中間結果を保持するためにだけ使っている。index_to_removeを削除すると、以下のようにすっきりさせることができる。

制御フロー変数を削除する

以下の例のdoneのような変数は、プログラムの実行を制御するためだけの変数(制御フロー変数)であり、実際のプログラムに関係のあるデータは含まれていない。うまくプログラムすれば、制御フロー変数は削除することができる。

変数のスコープを縮める

鍵となる考え:変数のことが見えるコード行数をできるだけ減らす。

スコープを縮めるための具体的な実装は、言語により異なる。JavaSctiptなら『JavaScript: The Good Parts』や『JavaScriptパターン』が参考になる。PHPでWebアプリを作るなら、MVCフレームワークを使い、ファットコントローラーを避け、メソッドを細かく分割するようにすれば個々の変数のスコープは小さくなる。

変数は一度だけ書き込む

鍵となる考え:変数を操作する場所が増えると、現在値の判断が難しくなる。

変数の値は一度設定したら書き換えないようにする。言語が定数やイミュータブルな値をサポートしている場合は、必要に応じてこれらを使用する。

『リーダブルコード』 第8章 巨大な式を分割する

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

鍵となる考え:巨大な式は飲み込みやすい大きさに分割する。

説明変数

は、

と分割することができる。

要約変数

は、

とすれば、より明確に意図を表現できる。

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

  1. not (a or b or c) ⇔ (not a) and (not b) and (not c)
  2. not (a and b and c) ⇔ (not a) or (not b) or (not c)

は、

と書き直せる。

短絡評価の悪用

は、ひと目では処理の意図がつかめない。

ならすぐに分かる。

どうして 1 行で書こうとしたのだろう? そのときは「オレは頭がいい」と思っていたのだ。ロジックを簡潔なコードに落とし込むことに一種の喜びを感じていた。 この気持ちはみんなにも理解してもらえると思う。まるでパズルを解いているような感じだ。仕事は楽しくやりたいからね。問題は、これがコードのスピードバンプになっていたことだ。

鍵となる考え:「頭がいい」コードに気を付ける。あとで他の人がコードを読むときにわかりにくくなる。

複雑なロジックと格闘する

驚くほど複雑なロジックのコードになってしまった。こういう場合には、もっと簡単な方法があるのだ。

「反対」から問題を解決してみるという手がある。

『リーダブルコード』 第7章 制御フローを読みやすくする

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

鍵となる考え:条件やループなどの制御フローはできるだけ「自然」にする。コードの読み手が立ち止まったり読み返したりしないように書く。

条件式の引数の並び順

よりも、

の方が読みやすい。

左側:「調査対象」の式。変化する。
右側:「比較対象」の式。あまり変化しない。

※個人的には、数学の記法(1 < 2 < 3)の流れで、不等号の向きを決め打ち(<)にすることが多いのだけど、等号・不等号も含めた包括的なルールとしては、「左が調査対象、右が比較対象」の方が良いかも。

あと、

というバグを防ぐために

とする記法(本書では「ヨーダ記法」と呼ばれている)は、現代のコンパイラは if (obj = NULL)と書くと警告を出してくれるので、過去のものになりつつあるとされているけど、コンパイラを介さないインタプリタ言語では現代でも実用性がある。

if/else ブロックの並び順

  • 条件は否定形よりも肯定形を使う。例えば、if (!debug)ではなく、if (debug) を使う。
  • 単純な条件を先に書く。if と else が同じ画面に表示されるので見やすい。
  • 関心を引く条件や目立つ条件を先に書く。

三項演算子

鍵となる考え:行数を短くするよりも、他の人が理解するのにかかる時間を短くする。

基本的には if/else を使おう。三項演算子はそれによって簡潔になるときにだけ使おう。

do/while ループを避ける

私の経験では、do-statement は、エラーや混乱の原因になることが多い。(中 略)私は条件が「前もって」書かれている方が好きだ。そのため、私は do- statement を避けることが多い。

関数から早く返す

ガード節

悪名高き goto

C言語以外では、goto はほとんど必要ない。

ネストを浅くする

ネストが増える仕組み:既存のコードの変更を少なくしつつ条件分岐を付け足す、といった場合に増えやすい

対策:変更するときにはコードを新鮮な目で見る。一歩下がって全体を見る。

実行の流れを追えるかい?

コードの流れを追いにくくする構成要素:

  • スレッド
  • 例外
  • 関数ポインタと無名関数
  • 仮想メソッド

『リーダブルコード』第6章 コメントは正確で簡潔に

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

鍵となる考え方:コメントは領域に対する情報の比率が高くなければいけない

コメントを簡潔にしておく

シンプルに説明できることをダラダラ書かない。

あいまいな代名詞を避ける

// データをキャッシュに入れる。ただし、先にそのサイズをチェックする。

// データをキャッシュに入れる。ただし、先にデータのサイズをチェックする。

歯切れの悪い文章を磨く

コメントを正確にする。

// これまでにクロールした URL かどうかによって優先度を変える。

// これまでにクロールしていない URL の優先度を高くする。

関数の動作を正確に記述する

// このファイルに含まれる行数を返す。

// このファイルに含まれる改行文字(‘n’)を数える。

入出力のコーナーケースに実例を使う

関数・メソッドの機能を全て見せることのできる実例をコメントで示す。

コードの意図を書く

「名前付き引数」コメント

Pythonなど、名前付き引数をサポートしている言語の場合、以下のように書くことができる。

名前付き引数をサポートしていない言語では以下のように書くことで、引数の名前を示すことができる。

全ての関数に名前付き引数コメントを使用する必要は無いが、よくわからない引数には使ったほうがよい。

情報密度の高い言葉を使う

// このクラスには大量のメンバがある。同じ情報はデータベースにも保管されている。ただし、
// 速度の面からここにも保管しておく。このクラスを読み込むときには、メンバが存在してい
// るかどうかを先に確認する。もし存在していれば、そのまま返す。存在しなければ、データベー
// スから読み込んで、次回のためにデータをフィールドに保管する。

// このクラスの役割は、データベースのキャッシュ層である。