くそコードが無くなる日を目指して

実例はC++/Javaがメインです|良いコードは健康を増進します

コードをずっと書いていると、目が疲れてくるので薦められて最近こんなの買いました。

これのいいところは電子レンジで30秒チン(600W)するだけで
あの、蒸気で…とは違って何回も使えるところ。
 
みなさんもよかったら是非。

コードの生産性が上がります。多分。。。

コードを書いているときは目的の機能を早く完成させたくなるがゆえに、細かいとこに気がいきにくくなりがちですが、それは危険です。
よく言われることですが、最終的にそうして出来上がったコードはそのときだけ 動く、汎用性の低いものになっていて、次の機能を追加するときに問題(=バグ)を引き起こします。
もちろん無視してそのようなコードを書き続けてもいいですが、そのサイクルが続けば続くほど汎用性は下がり、どこかの時点で破綻します。

でも、決して汚くしようとしてしているわけではないのに、なぜ問題が大きくなるまで放置してしまうのでしょうか?
これは破綻が突然起きるのではなく、すごく小さなほころびの積み重ねが原因となっているからです。

ちょっと簡単な例を見ながら、どういったところがほころびなのか見てみましょう。

まず、次のような消費税込みの値段を計算するメソッドがあったとします。

class TaxCalculator {
    ...
    public int calculateTaxIncludedPrice(int price) {
        return price * 1.05;
    }
    ...
}
税率を5%としてみました。この時点ですでにほころびがありますが、未来永劫コードに変更がなければおそらく問題は起きません。
しかし、2014年から税率が8%になることがわかり、2014年以降の計算を変更しなければいけなくなったとします。
ここで、問題が発生します。なぜか、上のコードを見た人はきっと、
あー要するに2014年から1.05が1.08になるだけだよね。つまりこうでしょ!
class TaxCalculator {
    ...
    public int calculateTaxIncludedPrice(int price) {
        Calendar date = Calendar.getInstance();
        if (2014 <= date.get(Calendar.YEAR)) {
            return price * 1.08;
        }
        return price * 1.05;
    }
    ...
}
と、考える可能性が高いです。これでだいぶ問題が大きくなりました。
でも、最初の、ほころびが小さいので、これで何が、どうだめになったのかよくわからないかもしれません。

上のコードの問題点は、直接的には1.05、1.08という数字がハードコードされていることなのですが、根本的にはそもそも消費税込みの計算をするということがどういうことかきちんと考えられてない点にあります。
つまり、税込みの値段というのは本当は、
物の値段×税率
であるべきなのに、
物の値段×なんらかの数字
という表現がコード上されてしまっているのが問題です。

物の値段×税率という考え方が最初からあれば、上のコードたちはこうなっていたはずです。
class TaxCalculator {
    private static final float TAX_RATE = 1.05f;
    ...
    public int calculateTaxIncludedPrice(int price) {
        return price * TAX_RATE;
    }
    ...
}
class TaxCalculator {
    private static final float TAX_RATE;
    static {
        Calendar date = Calendar.getInstance();
        if (2014 <= date.get(Calendar.YEAR)) {
            TAX_RATE = 1.08;
        } else {
            TAX_RATE = 1.05;
        }
    }
    ...
    public int calculateTaxIncludedPrice(int price) { 
        return price * TAX_RATE;
    }
    ...
} 
もし、別になにも変化がないと思うようでしたら、世界中の様々な国の税率に対して計算をすることを考えてみてください。
前者では、計算式そのものの部分に変更が加わります、でも後者は国別に税率を設定するだけで済みます。
計算式の部分に変更がはいると、そもそも税率が変わるだけなのに、計算式をいじるという意味的なおかしさが生じる上、なんかのきっかけで掛け算が足し算に変わったり、各国ごとの計算があっているのかといった不要な不安を覚えることにあります。

コードを書くときは、そもそもこの計算は何なのか、何が目的なのかそういう意識をもって書くことを心がけてみてください。

こんばんは。
今日は短めに。こんなのはやめましょうという話。
 
    try {
        exceptionThrower();
    } catch (Exception e) {
        // Catch everything
    }

ExceptionがexceptionThrower(注:これはこの例のために作ったメソッドです)から投げられて、なんかtry〜catchを書かないとコンパイルが通らないという理由で上のように書くのはやめましょう。 めんどくさいからとりあえず、Exceptionでキャッチしとけ!はやめましょう。 最初想定したExceptionだけキャッチするようにしましょう。 全部キャッチしてしまうと、想定外のバグが埋もれたり、変なところに影響がでて迷宮入りしやすくなります。

↑このページのトップヘ