Как я могу уменьшить цикломатическую сложность этого?

У меня есть метод, который получает объект и делает что-то в зависимости от того, какой тип объекта он обнаруживает:

void receive(Object object) {
    if (object instanceof ObjectTypeA) {
        doSomethingA();
    }
    else {
        if (object instanceof ObjectTypeB) {
            doSomethingB();
        }
        else {
            if (object instanceof ObjectTypeC) {
                doSomethingC();
            }
            else {
                if (object instanceof ObjectTypeD) {
                    doSomethingD();
                }
                else {
                    // etc...
                }
            }
        }
    }
}

Как я могу уменьшить цикломатическую сложность? Я искал вокруг, но не мог найти ничего слишком полезного.

5 ответов

Решение

Разве вы не можете использовать объектно-ориентированный подход для этого? Создайте интерфейс, который имеет doSomething() Затем метод создать подклассы, которые реализуют желаемое поведение? Потом звоню object.doSomething() будет выполнять соответствующее поведение?

Цикломатическая сложность - это мера, основанная на графовой структуре кода. В частности, он основан на количестве возможных путей через код; смотрите здесь для более подробной информации. Хотя существует связь между CC и тем, что типичный программист считает сложностью кода, это не одно и то же. Например:

  • CC не принимает во внимание семантику кода; например, что делает тот или иной метод, который вызывается, или математические свойства алгоритма.

  • CC не принимает во внимание дизайн и шаблоны кодирования. Таким образом, то, что CC говорит, является сложным, может быть простым для того, кто понимает используемый паттерн.

Можно сказать, что взаимосвязь между CC и реальной сложностью кода подобна взаимосвязи между IQ и реальным интеллектом.

Таким образом, Cyclomatic Complexity следует рассматривать как показатель того, где находятся сложные части вашего кода... не как истинную меру сложности или качества кода. Действительно, очень сложный код не обязательно низкого качества. Часто сложность присуща, и попытка избавиться от нее только усугубляет ситуацию.


В этом конкретном примере высокая мера CC не соответствует чему-то, что вызовет у типичного программиста какие-либо трудности. Лучший ответ (IMO) - оставить метод в покое. Считай это ложным срабатыванием.

void receive(ObjectTypeA object) {
        doSomethingA();
}

void receive(ObjectTypeB object) {
        doSomethingB();
}

void receive(ObjectTypeC object) {
        doSomethingC();
}

...

// Your final 'else' method
void receive(Object object) {
        doSomethingZ();
}

Почему нужно уменьшить сложность? Это достаточно простой шаблон, который любой компетентный разработчик посчитал бы его тривиальной функцией.

Я бы наверное так написал

    if (object instanceof ObjectTypeA) 
    {
        doSomethingA();
    }
    else if (object instanceof ObjectTypeB) 
    {
        doSomethingB();
    }
    else if (object instanceof ObjectTypeC) 
    {
        doSomethingC();
    }

Если для удовлетворения некоторой эзотерической потребности "CC должно быть меньше, чем x", то общее правило, согласно которому существуют стандарты для обеспечения поддерживаемого кода, будет означать, что это приемлемо независимо от того, как высоко поднимается CC.

Никогда не было цели "уменьшить цикломатическую сложность", хотя были времена, когда мне платили LOC.

Ваш код "достаточно хорош". Мой взгляд наткнулся на квадратные скобки, поэтому я пожертвовал немного производительностью и сделал следующее (при условии, что типы A, B и т. Д. Не находятся в одной иерархии):

receive(Object object) {
    if (object intanceof ObjectTypeA) doSomethingA();
    if (object instanceof ObjectTypeB) doSomethingB();
    ...

или (если они находятся в одной иерархии):

receive(Object object) {
    if (object intanceof ObjectTypeA) { doSomethingA(); return; }
    if (object instanceof ObjectTypeB) { doSomethingB(); return; }
    ...

Не знаю, уменьшит ли это цикломатическую штуковину, и все равно.

Другие вопросы по тегам