今日コードいじってたら思い出したので
悪いコード
public class C{ public static final int flg0 = 0, flg1 = 1, flg2 = 2, flg3 = 3; public void method(int flg){ switch(flg){ case flg0: //hoge break; } }
このコードには問題点があるわけです。
- フラグがint型(new C().method(0)っていう書き方をしてもOKになってしまう。本当はフラグを入れないといけないのに)
- switch(フラグが増えるほど、専用の処理をmethodに長々と書かないといけない。しかも同一スコープなので容易にスパゲティに)
フラグがint型
Javaならenumに置き換えましょう。
オブジェクト指向がサポートされている言語なら、数値の代わりに空のオブジェクトを入れましょう。
そうする事で、メソッドの引数に入れるべき値が何であるかが明確になります。少なくともint型よりは。
switch
フラグが数個ならswitchでもいいと思いますが、以下の状況では不適切です。
- フラグが大量にある(約4個以上になるのならswitchは不適切だと思います)
- 今はフラグが少ないが、のちのち増える事が予見出来る
- 分岐処理のコードがそこそこ長め
つまりこうしろ
enum Flg{ flg0{ public void method(){} }, flg1{ public void method(){} }; public abstract void method(); }
public class C{ public void method(Flg flg){ flg.method(); }
これで引数に間違った値を入れる事も、switchでスパゲティコードをつくりこんでしまうこともないはずです。
また、状態が増えてもC.methodを修正する可能性が少なくなります。
状態遷移が決まってるなら
enum Flg{ flg0{ public Flg method(){return flg1;}//flg1に状態遷移 }, flg1{ public Flg method(){return flg0;}//flg0に状態遷移 }; public abstract Flg method(); }
public class C{ private Flg flg; public C(Flg f){ flg = f; } public void method(){ flg = flg.method();//とある状態のメソッドを実行した後、次の状態へ遷移する } }
こういうのもアリかもしれません。
状態遷移をフラグ側が受け持てば、C.methodはさらに修正する手間が減るでしょう。