リーダブルコード読書メモ~その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
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が起こらない確率を引く」というほうがすんなり求まるケースがあります。こういう考え方をでコードを書くとまたわかりやすいのかなと思いました。
終わりに
巨大な式を分割する、というタイトルの章でしたが、総じて言いたいことは「式が分かりにくそうな場合は、細かく変数を定義し、それを使う」ということかなと思いました。「こういう判定のための変数」とか「こういう意味を持つ変数」という変数を定義し、そこに取得した値により式を組みたて、代入するほうが可読性は上がります。コードが長くなるというデメリットがありますが、わかりやすさを取ったほうがいいでしょう。