🎉

リーダブルコード第7・8・9章読んでみた

2024/04/18に公開

ご挨拶

前回の続きでリーダブルコードの第7・8・9章を読んでみたのでアウトプットしていきます!

リーダブルコードについて

エンジニアの必読書と書かれていたため、最初の一冊として読んでみることにしました。
この本の目標は「理解しやすいコードを書くこと」です!
気になる方は是非読んでみてください!
https://amzn.to/3VWXZbp
https://a.r10.to/hPU6pe

この記事の対象者

  • 制御フローをわかりやすく書きたい人
  • 理解しやすいコーディングを目指す人

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

  • 条件式の引数の並び順
  • if/elseの並び順
  • do-whileループを避ける
  • 関数から早く返す
  • ネストを浅くする

それぞれ詳しく見ていきましょう。

条件式の引数の並び順

調査対象の式は左側に
例えば、以下のようなコードがあったとする。

if (length > 10)

if (10 < length)

この2つであれば上の方が読みやすいはずだ。

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

if/elseの並び順

  • 条件は否定形よりも肯定形を使う。例えばif (!debug)ではなくif (debug)を使う
  • 単純な条件を先に書く

do-whileループを避ける

do-whileループは最低1回実行されてしまう。whileループであれば実行される条件が一目でわかるのでdo-whileループはwhileループに置き換える。

関数から早く返す

関数から早く返すようなコードは以下の通りだ。

public boolean Contains = (String str, String substr) => {
  if (str == null || substr == null) return false; 
  if (substr.equals("")) return true;
  //処理
};

ネストを浅くする

関数から早く返すと同様に、失敗ケースを早めに返すようにすることでネストを浅くしよう。

第7章まとめ

  • 条件式において調査対象の式は左側に
  • if/elseを使用する際は否定形ではなく肯定形を使う
  • do-whileループを避ける
  • goto文は使わない
  • 関数から早く返す
  • ネストを浅くする

第8章「巨大な式を分割する」

  • 説明変数を利用する
  • 要約変数を利用する
  • ド・モルガンの法則を使う
  • 複雑なロジックと格闘する

それぞれ確認していきましょう。

説明変数を利用する

例えば、以下のようなコードがあったとする。

if line.split(':')[0].split() == "root":
//処理
};

説明変数を使えば以下のようになる。

username = line.split(':')[0].split()
if username == "root":
//処理
};

要約変数を利用する

例えば以下のようなコードがあったとする。

if (request.user.id == document.owner_id){
  // ユーザーはこの文書を編集できる
}

if (request.user.id != document.owner_id){
  // 文書は読み取り専用
}

このコードが言いたいのは「ユーザーは文書を所持しているか?」ということである。そこで、要約変数を追加してコードを書く。

final boolean user_owns_document = (request.user.id == document.owner_id);
if (user_owns_document);
  // ユーザーはこの文書を編集できる
}

if (!user_owns_document){
  // 文書は読み取り専用
}

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

ド・モルガンの法則を使用して分かりやすくする。
ド・モルガンの法則は以下の通りだ。

  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)
    覚えにくい場合は
    notを分配してand/orを反転する
    と覚えておこう。

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

if文のロジックが複雑になりすぎた場合にはより優雅なロジックにするよう考えてみよう。
例えば、以下のようなコードがあったとする。

if (// 複雑なロジック);
  return true;
}
else {
  return false;
}

この場合、複雑なロジックを読まなければならない。そこで複雑なロジックではない条件を考えてみよう。すると以下のように変更できる場合もあるだろう。

if (// 簡単なロジック);
  return false;
}
if (// 簡単なロジック);
  return false;
}
else {
  return true;
}

第8章まとめ

  • 説明変数を利用する
  • 要約変数を利用する
  • ド・モルガンの法則を使う。覚え方はnotを分配してand/orを反転する
  • 複雑なロジックと格闘する際には複雑なロジックではない側のロジックを検討しよう。

第9章「変数と読みやすさ」

  • 不要な変数を削除する
  • 変数のスコープを小さくする
  • 変数の書き換えはあまり行わないようにする

それぞれ確認していきましょう。

不要な変数を削除する

例えば、Pythonで以下のようなコードがあったとする。

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

この場合のnowは必要ないだろう。なぜならば、datetime.datetime.now()でも十分明確だったからだ。
よってこのコードは以下のように書き換えると良い。

root_message.last_view_time = datetime.datetime.now()

この例以外にも中間結果を削除すると良い。例えばfor文の中でtrue,falseに切り替えてからfor文終了後にif文を入れる必要はないということだ。

変数のスコープを小さくする

例えば、以下のようなコードがあったとする。

string str_;

void Method1() {
  str_ = "fjfj"
  method2();

void Method2(){
  // str_を使用している
  }

void Method3(){
  // str_を使用していない
};

この場合、str_を以下のようにローカル変数に変換すると良い。

void Method1() {
  string str = "fjfj"
  method2();

void Method2(){
  // strを使用している
  }

void Method3(){
  // このメソッドはstrが見えない
}

第9章まとめ

  • 不要な変数を削除する
    • 十分意味が明確で複雑な式を分割しているわけではない変数は消そう
    • 中間結果は消せるなら消そう
  • 変数のスコープを小さくする
  • 変数の書き換えはあまり行わないようにする

Discussion