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

こちらの続きです8章から見ていきます

https://blog.hatena.ne.jp/hatek47320/hatek47320.hatenablog.com/edit?entry=26006613775078778hatek47320.hatenablog.com

今回は複雑な式を分割し、理解しやすいコードにする、という話です。

前提:人間は一度に3~4のものしか考えられない。一度に考えることを少なくすることを意識してコードを書くこと。

  • 変数の工夫
    • 例えば条件分岐では変数を細かく定義して理解しやすくする。
      if hoge.split[0] == 'hoge'
      end

上記はif文の変数が一瞬何を示しているかがわかりにくい。そのため、条件の変数を別に定義する(条件を説明するための変数)

     hogeflag = hoge.split[0]
     if hogeflag
     end
  • 条件分岐で変数がたくさん出てくるときは要約できないか考える
   if hoge == hogeflag
     hoge
   end
   if hoge == !hogeflag
     fuga
   end

flagがtrueかfalseかで条件を書いているが、これを一つにまとめる(hogeがtrueかfalseかを変数に持たせ、それで条件分岐する)

  hoge == hogeflag
  if hoge
    hoge
  end
  if !hoge
    fuga
  end

ja.wikipedia.org

  if(!(hoge && !fuga)) return hoge

これはドモルガンの法則により以下の通りになる

  if (!hoge || fuga) return hoge
  • なんでも短くしようとしない
    • 条件判定で1行ですべて収めようとしたくなるが、複数行でわかりやすさを重視すること
    • 以下のコードは1行で完結しているが、()が多すぎたり、メソッド、変数が3,4種類あったり、など理解するのに時間がかかりそう
  assert((!(bucket = FindBucket(key))) || !bucket->isOccupied());

以下は2行になっているが、読むほうにしてみれば上のコードよりスムーズと思われる。

  bucket = FindBucket(key);
  if (bucket != NULL) assert(!bucket->IsOccupied());
  • 余事象的な発想を試みる
    • 判定ロジックが複雑な場合は、真正面から正直に書くのではなく、裏をかいて「いくつかの判定をかいくぐってきた残り」という考え方で乗り切れないか考える。

https://ja.wiktionary.org/wiki/%E4%BD%99%E4%BA%8B%E8%B1%A1

  • 補足:リーダブルコードでは「複雑なロジックと格闘する」というサブタイトルでした。Rangeクラスというある値がクラスで定義された値の外、中かを判定するようなものを改善していますが、 説明が冗長でちょっとわかりにくかったので、勝手に「余事象的」と解釈しました。確率の問題では、ある事象Aが起こる確率について、真正面からその確率を求めるより「100%から事象Aが起こらない確率を引く」というほうがすんなり求まるケースがあります。こういう考え方をでコードを書くとまたわかりやすいのかなと思いました。

終わりに

巨大な式を分割する、というタイトルの章でしたが、総じて言いたいことは「式が分かりにくそうな場合は、細かく変数を定義し、それを使う」ということかなと思いました。「こういう判定のための変数」とか「こういう意味を持つ変数」という変数を定義し、そこに取得した値により式を組みたて、代入するほうが可読性は上がります。コードが長くなるというデメリットがありますが、わかりやすさを取ったほうがいいでしょう。