5

メソッドが、かなり大きな列挙型の値に応じてアクションを選択するとします。私たちのソナーは、このメソッドの高いサイクロマティックな複雑さ (当然、case ステートメントの数について) について不平を言っています。

大規模な switch case ステートメントは OOP で実際に最適なスタイルではないことはわかっていますが、複雑なオブジェクト ツリーを構築する代わりにそれらを使用するのが適切な場合があります (私の場合は演算子トークンを評価するパーサー)。

私の懸念は今、それに対処する方法ですか?そのようなスイッチケースを意味のあるように分割する設計パターンはありますか? または、CC の測定からクラスを除外できますか (また、CC の測定から除外する必要があります) (高い CC を簡単に回避できる他の方法が含まれている可能性があるため)。

それは本当に重要なことではありません。プロジェクトに削除できないという警告が表示されるのが嫌いです ;o)

編集:コードサンプル

String process()
    String fieldName = this.getField() != null ? this.getField().getSchemaName() : null;
    String result = "";
    switch (op) {
    case PHRASE:
        result = "";
        if(!value.isEmpty() && value.get(0) != null) {
            result = value.get(0).toString();
        }
        break;
    case EQUALS:
    case GT:
    case GTE:
    case LT:
    case LTE:
    case NOT_EQUALS:
        result = prepareSingleParameterStatement(fieldName);
        break;
    case BETWEEN_EXC:
    case BETWEEN_INC:
        result = prepareDoubleParameterStatement(fieldName);
        break;
    case IN:
    case NOT_IN:
    case ALL_IN:
        result = prepareCollectionStatement(fieldName);
        break;
    case AND:
    case OR:
        result = prepareLogicalStatement();
        break;
    case NOT:
        result = prepareNotStatement();
        break;
    default:
        break;
    }
    return result;
}
4

3 に答える 3

7

大きな switch ステートメントを使用する代わりに、列挙型を使用してステート マシンを構築できます。あなたがすることは、コードを取得して各ケースブロックのテキストを解析し、これを各列挙状態のメソッドに入れることです。

例から

enum States implements State {
    XML {
        public boolean process(Context context) {
            if (context.buffer().remaining() < 16) return false;
            // read header
            if(headerComplete)
                context.state(States.ROOT);
            return true;
        }
    }, ROOT {
        public boolean process(Context context) {
            if (context.buffer().remaining() < 8) return false;
            // read root tag
            if(rootComplete)
                context.state(States.IN_ROOT);
            return true;
        }
    }
}

public void process(Context context) {
    socket.read(context.buffer());
    while(context.state().process(context));
}

列挙型をステートマシンとして使用することから

于 2014-05-23T08:21:20.753 に答える
3

大きなスイッチをハッシュマップ/辞書とコマンドオブジェクトに置き換えることをお勧めします:

Map<Op, Command> ops = new EnumMap<op>{{
  //initialize with different command objects implementing same interface
}};
command = ops.get(result);
result = command.prepare();
于 2014-05-23T08:21:12.383 に答える