jtk

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

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

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

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

8章 巨大な式を分割する

巨大な式は飲み込みやすい大きさに分割する

8.1 説明変数

式を簡単に分割するには、式を表す変数を使えばいい。この変数を「説明変数」と呼ぶこともある。式の意味を説明してくれるからだ。

var str = 'root:'
if (str.replace(':','') === 'root') {
  ...
}

// ↓↓↓ 説明変数を使う

  var str = 'root:'
var username = str.replace(':','');
if (username === 'root') {
  ...
}

これを使うと、

  • 巨大な式を分割できる。
  • 簡潔な名前で式を説明することで、コードを文書化できる。
  • コードの主要な「概念」を読み手が認識しやすくなる。

8.2 要約変数

式を説明する必要がない場合でも、式を変数に代入しておくと便利だ。大きなコードの塊を小さな名前に置き換えて、管理や把握を簡単にする変数のことを要約変数と呼ぶ。

if (request.user.id === document.owner_id) {
}

// ↓↓↓ 要約変数を使う

var userOwnDocument = request.user.id === document.owner_id;
if (userOwnDocument) {
  ...
}

8.6 巨大な文を分割する

  • タイプミスを減らすのに役立つ
  • 横幅が縮まるのでコードが読みやすくなる。
  • クラス名を変更することになれば、一箇所を変更すればいい。

これまでに無意識でやるときとやらない時がありましたが、ちゃんとやろうと思いました。

var update_highlight = function (message_num) {
  if($("#vote_value" + message_num).html() === "Up") {
    $("#thumbs_up" + message_num).addClass("highlighted");
    $("#thumbs_down" + message_num).removeClass("highlighted");
  } else if ($("#vote_value" + message_num).html() === "Down") {
    ...
};

// ↓↓↓ 同じ式は要約変数として関数の最上部に抽出する

var update_highlight = function (message_num) {
  var thumbs_up = $("#thumbs_up" + message_num);
  var thumbs_down = $("#thumbs_down" + message_num);
  var vote_value = $("#vote_value" + message_num).html();
  var hi = "highlighted";

  if(vote_value === "Up") {
    thumbs_up.addClass(hi);
    thumbs_down.removeClass(hi);
  } else if (vote_value === "Down") {
    ...
};

9章 変数と読みやすさ

  1. 変数が多いと変数を追跡するのが難しくなる。
  2. 変数のスコープが大きいとスコープを把握する時間が長くなる。
  3. 変数が頻繁に変更されると現在の値を把握するのが難しくなる。

9.1 変数を削除する

8章で 説明変数要約変数 を使って巨大な式を分割して説明文のようにしたため、読みやすくなった。
逆に、複雑な処理を分割していない変数などは変数にする必要はない。

now = datetime.datetime.now()
root_message.last_view_time = now

この now を使う意味があるだろうか?意味がない理由を以下に挙げよう。

  • 複雑な式を分割していない。
  • より明確になっていない。 datetime.datetime.now() のままでも十分に明確だ。
  • 一度しか使っていないので、重複コードの削除になっていない。

9.2 変数のスコープを縮める

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

これあんまり理解できなかったのですが、

  • グローバル変数は避ける
  • アクセスはできるだけ制限して、変数のことが「見えてしまう」コードを減らすのがいいとされている。

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

で触れられている

変数は一度だけ書き込む

というルールは、ES5では constlet でだいぶ解決されたのかなと思う。

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

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

本章のアドバイスは、無関係の下位問題を積極的に見つけて抽出する ことだ。

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

という技法で大幅にコードを改善できる。
とのこと。あまり上位/下位問題など考えたことなかったので新しい発見です。

10.3 その他の汎用コード

ajax_post({
  url: '',
  data: data,
  on_success: function (response_data) {
    var str = "{";
    for(var key in response_data) {
      str += " " + key + " = " + response_data[key] + "¥n";
    }
    alert(str + "}");
    // 引き続き response_dataの処理
  }
});

このコードの高レベルの目標は「サーバをAjaxで呼び出してレスポンスを処理する」である。
でも、このコードの大部分は「ディクショナリをキレイに印字(pretty printする)」という「無関係の下位問題」を解決しようとしている。

var format_pretty = function(obj) {
  var str = "{";
  for(var key in response_data) {
    str += " " + key + " = " + response_data[key] + "¥n";
  }
  return str + "}";
}

こうすると、

  • 呼び出し側のコードが簡潔になる
  • format_pretty() をあとから再利用できる
  • コードが独立していれば、format_pretty() の改善が楽になる

という恩恵を受けることができる。(特に最後の「改善が楽になる」が大事)


11章〜15章は省略。。

全体の感想など

これまで全く意識していなかったこと、少しは意識していたけど言語化できなかったり、論理的に考えていなかったことが発見できて良かったです。

まだ勉強不足で読んでもしっくりこない箇所もありましたが、これからのコーディングをしていくなかでの指針みたいなもの(困ったらすがるもの)ができたので、そこが一番よかったことかなと思います。