読者です 読者をやめる 読者になる 読者になる

リーダブルコードを読みました。

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

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

プログラミングの作法はmustな(こうしなければならない)コードの決まりごと
Code Completeはshouldな(こうすべき)コードのルール、
リーダブルコードはhad betterな(こうしたほうが良い)コードのマナー
って感じの印象を受けました。
そこまで強制力はないけどココに書いてあることはやっておいたほうが良いし、読みやすいコードにしたほうが未来の自分たちのためだよ、というメッセージとして受け取れます。


ここで、Readable(読みやすい)の定義は

他の人が最短時間で理解できる

というところです。

行数が少なければ読む箇所は少なくなります、ただしコメントが入っていなければロジックをちゃんと追う必要が出てきて結局時間がかかります。とはいえコメントが多くても問題。適切な文量でないとその分読む時間が長くなります。


本書は上記のような問題に対してのhowtoを教えてくれます。
この本を読んでいるときは実際にコードを書いている時だったので、沢山感銘を受けました。

最も感銘を受けた所を例として紹介します。

ちょうど本書にも出てくるこんな感じのコードで悩んでいたのを覚えています。

struct Range {
    int begin;
    int end;
    // Range同士が重なっているかどうか
    // 例えば、 [0, 5)は[3, 8)と重なっている。
    bool OverlapsWith(Range other);
}

実際はJavaだし、作っていたものも違うのですが、とりあえず、巨大なif/elseの式を書くようなものでした。
ここのOverlapsWithの実装をどう書くか、というのである同僚がこう書いてきました。

bool OverlapsWith(Range other) {
    if (begin <= other.begin && end >= other.end) {
        return true;
    } else if (begin >= other.begin && begin < other.end) {
        return true;
    } else if (end > other.begin && end <= other.end) {
        return true;
    } else {
        return false;
    }
}

レビュワーである僕はとりあえず、こうするように指示しました。

bool OverlapsWith(Range other) {
     return (begin <= other.begin && end >= other.end) ||
              (begin >= other.begin && begin < other.end) ||
              (end > other.begin && end <= other.end)
}

このコードを指示した時に、あー、もっと絶対キレイにかけるのに。
とか思ったことを覚えています。

これの解決策はReadableコードの第8章、「巨大な式を分割する」に出てきます。
「反対」から考えて、その条件を満たす式から書くのではなく、満たさない式から書けば、もっとキレイに書けるんです。

bool OverlapsWith(Range other) {
    if (other.end <= begin) {
        return false;
    }
    if (other.begin >= end) {
        return false;
    }
    return true;
}

どうでしょう、最初の式よりもずっと単純だし、読みやすくなっていると思います。
コードの式が複雑になってきたら一つ、反対に考えてみるのもありかと思います。

一般的なことだと思う人もいるかもしれませんが、こういう内容のコードを綺麗に書くためのhowtoがまとまっているので、ご一読をオススメ致します。