jtk

【読書メモ】リーダブルコード その3

リーダブルコード ―より良いコードを書くためのシンプルで実践的なテクニック 前回の続きです。

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

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

5章 コメントすべきことを知る

コメントの目的は、書き手の意図を読み手に知らせることである。

5.1 コメントするべきでは「ない」こと

コードからすぐにわかることをコメントに書かない。

下記はその悪い例

// Account クラスの定義
class Account {
  public:
  // コンストラクタ
  Account();
  
  // profit に新しい値を設定する
  void SetProfit(double profit);
  
  // この Account から profit を返す
  double GetProfit();
}
  • コードからすぐに抽出できること
  • ひどいコード(例えば、ひどい名前の関数)を補う「補助的なコメント」。
    コメントを書くのではなくコードを修正する。

5.2 自分の考えを記録する

優れたコメントというのは「考えを記録する」ためのものである。コードを書いているときに持っている「大切な考え」のことだ。

映画のDVDにはよく「監督のコメンタリー」がついてくる。映画の製作者が自分の考えや物語について語ってくれるので、作品がどのように作られたのかを理解するのに役立つ。これと同じように、コメントにはコードに対する大切な考えを記録しなければならない。
例えば、こんな感じだ。

// このデータだとハッシュテーブルよりもバイナリツリーのほうが40%速かった。
// 左右の比較よりもハッシュの計算コストのほうが高いようだ。
// このクラスは汚くなってきている。
// サブクラス `ResourceNode` を作って整理したほうがいいかもしれない。

コードの欠陥にコメントをつける

コードは絶えず進化しているので、その過程で欠陥を生む運命にある。その欠陥を文書化することを恥ずかしがってはいけない。例えば、改善が必要なときは以下のように書いておこう。

// TODO: もっと高速なアルゴリズムを使う
// TODO: JPEG 以外のフォーマットに対応する
記法 典型的な意味
TODO: あとで手をつける
FIXME: 既知の不具合があるコード
HACK: あまりキレイじゃない解決策
XXX: 危険! 大きな問題がある

定数にコメントをつける

定数を定義するときには、その定数が何をするのか、なぜその値を持っているのかという「背景」が存在する場合が多い。

const image_quality = 0.72; // 0.72 ならユーザはファイルサイズを品質の面で妥協できる

5.3 読み手の立場になって考える

本書で使っている技法は、他の人にコードがどのように見えるかを想像するものだ。「他の人」というのは、プロジェクトのことを君のように熟知していない人のことである。

  • 質問されそうなことを想像する
  • ハマりそうな罠を告知する
  • 「全体像」のコメント
    • // このファイルには、ファイルシステムに関する便利なインターフェースを提供するヘルパー関数が含まれています。
  • 要約コメント

5.4 ライダーズブロックを乗り越える

例えば、ある関数を作っていて、「ヤバい、これはリストに重複があったら面倒なことになる」と思ったとする。それをそのまま書き出せばいい。

// ヤバい、これはリストに重複があったら面倒なことになる ↓↓↓ 言い回しをもっと詳細な言葉に置き換えるともっといい // 注意:このコードはリストの重複を処理できません(実装が難しいので)。

コメントを書くという作業の手順は以下3つに分解できる。

  • 頭のなかにあるコメントをとにかく書き出す。
  • コメントを読んで(どちらかと言えば)改善が必要なものを見つける。
  • 改善する

6章 コメントは正確で簡潔に

ここは具体例多くあまり話入ってこなかったのでまとめだけ

  • 複数のものを指す可能性がある「それ」や「これ」などの代名詞を避ける。
  • 関数の動作はできるだけ正確に説明する。
  • コードの意図は、詳細レベルではなく、高レベルで記述する。

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

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

7.1 条件式の引数の並び順

if (length >= 10)
// または
if (10 <= length)

最初のほうが読みやすいが、それはなぜか?

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

英語の用法と同じで、

自然

  • 「もし君が1年間で10万ドル以上稼げるならば」
  • 「もし君が18歳以上ならば」

不自然

  • 「もし10万ドルが君が1年間で稼げる金額以下ならば」
  • 「もし18年が君の年齢以下ならば」

この自然な用法に従ってコードも書くと理解がしやすい。

if/else ブロックの並び順

if (a == b) {
  // 第1のケース
} else {
  // 第2のケース
}

if (a != b) {
  // 第2のケース
} else {
  // 第1のケース
}

と書くのは同じことだが、この並び順には優劣がある。

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

この優劣は衝突することもあるので、そのときは自分で判断しなければいけない。でも、優先度は明確に決まることが多い。

7.3 三項演算子

行数を短くするよりも、他の人が理解するのにかかる時間を短くする

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


第7章から第二部でコードの具体例書かれてきてだんだん理解が追いつかなくなってきました。。
最後のまとめは読めそうなので、読めそうな所だけ読むようにしたいと思います。