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

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

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 и реальным интеллектом.

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


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


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; }
    ...

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