Pergunta

Recentemente, nossa empresa começou a medir a complexidade ciclomática (CC) das funções no nosso código em uma base semanal, e relatórios que funciona melhoraram ou pioraram. Por isso, começaram a prestar muito mais atenção à CC de funções.

Eu li que CC poderia ser informalmente calculado como 1 + o número de pontos de decisão em uma função (por exemplo, if, for loop, selecione etc), ou, ainda, o número de caminhos através de uma função ...

Eu entendo que a maneira mais fácil de reduzir CC é usar o Extract Method refatoração repetidamente ...

Existem algumas coisas que estou prestes inseguro, por exemplo, qual é a CC dos fragmentos seguinte código?

1)

for (int i = 0; i < 3; i++)
    Console.WriteLine("Hello");

E

Console.WriteLine("Hello");
Console.WriteLine("Hello");
Console.WriteLine("Hello");

Ambos fazem a mesma coisa, mas não a primeira versão têm um maior CC por causa da instrução?

2)

if (condition1)
    if (condition2)
        if (condition 3)
            Console.WriteLine("wibble");

E

if (condition1 && condition2 && condition3)
    Console.WriteLine("wibble");

Assumindo que a língua faz a avaliação de curto-circuito, como C #, então estes dois fragmentos de código têm o mesmo efeito ... mas é o CC do primeiro fragmento maior porque ele tem 3 pontos de decisão / if?

3)

if (condition1)
{
    Console.WriteLine("one");

    if (condition2)
        Console.WriteLine("one and two");
}

E

if (condition3)
    Console.WriteLine("fizz");

if (condition4)
    Console.WriteLine("buzz");

Estes dois fragmentos de código fazer coisas diferentes, mas eles têm o mesmo CC? Ou será que a instrução IF aninhada no primeiro fragmento têm uma maior CC? ou seja, aninhada if são mentalmente mais complexo de entender, mas é que reflete na CC?

Foi útil?

Solução

  1. Sim. Seu primeiro exemplo tem um ponto de decisão e sua segunda não, de modo que o primeiro tem um maior CC.
  2. Sim, talvez, o seu primeiro exemplo tem vários pontos de decisão e, portanto, uma maior CC. (Veja abaixo a explicação.)
  3. Sim, talvez. Obviamente, eles têm o mesmo número de pontos de decisão, mas existem diferentes maneiras de CC calcular, o que significa ...

... se a sua empresa está medindo CC de uma maneira específica, então você precisa para se familiarizar com esse método (espero que eles estão usando ferramentas para fazer isso). Existem diferentes maneiras de CC calcular para situações diferentes (caso declarações, operadores booleanos, etc.), mas você deve obter o mesmo tipo de informação a partir da métrica não importa o que você usa convenção.

O problema maior é o que outros já mencionados, que a sua empresa parece estar se concentrando mais em CC do que no código por trás dele. Em geral, com certeza, abaixo de 5 é grande, abaixo de 10 é bom, abaixo de 20 é bom, 21-50 deveria ser um sinal de alerta, e acima de 50 deve ser um grande sinal de alerta, mas esses são guias, não regras absolutas. Você provavelmente deve examinar o código em um procedimento que tem um CC acima de 50 para garantir que ele não é apenas uma enorme pilha de código, mas talvez haja uma razão específica para que o procedimento está escrito dessa maneira, e não é viável (por qualquer número de razões) para refatorar-lo.

Se você usar ferramentas para refatorar seu código para reduzir CC, certifique-se de entender o que as ferramentas estão a fazer, e que não está simplesmente mudando um problema para outro lugar. Afinal, você quer que seu código tem alguns defeitos, para funcionar corretamente, e ser relativamente fácil de manter. Se esse código também tem um CC baixa, bom para ele. Se o seu código atende a esses critérios e tem um CC acima de 10, talvez seja a hora de sentar-se com o que a gestão pode e defender o seu código (e talvez levá-los a examinar a sua política).

Outras dicas

Depois de navegar através da entrada na Wikipedia e no de Thomas J. McCabe original em papel , parece se os itens acima mencionados são problemas conhecidos com a métrica.

No entanto, a maioria das métricas têm prós e contras. Acho que em um programa grande o suficiente o valor CC poderia apontar para possivelmente complexas partes de seu código. Mas que a maior CC não significa necessariamente complexa.

Como todas as métricas de software, CC não é perfeito. Usado em uma base de código grande o suficiente, ele pode lhe dar uma idéia de onde pode ser uma zona problemática.

Há duas coisas a ter em mente aqui:

  1. Big suficiente base de código: Em qualquer projeto não trivial terá funções que têm um valor muito alto CC. Tão alta que não importa se em um de seus exemplos, o CC seria 2 ou 3. Uma função com uma CC de dizer Vamos mais de 300 é definitivamente algo para analisar. Não importa se o CC é 301 ou 302.
  2. Não se esqueça de usar a cabeça. Existem métodos que necessitam de muitos pontos de decisão. Muitas vezes eles podem ser reformulado de alguma forma a ter menos, mas às vezes eles não podem. Não vá com uma regra como "refatorar todos os métodos com CC> xy". Ter um olhar para eles e usar seu cérebro para decidir o que fazer.

Eu gosto da idéia de uma análise semanal. No controle de qualidade, análise de tendências é uma ferramenta muito eficaz para identificando problemas durante a sua criação . Isto é muito melhor do que ter que esperar até que eles ficam tão grandes que se tornam evidentes (ver SPC para alguns detalhes).

CC não é uma panacéia para medir a qualidade. Claramente uma declaração repetida não é "melhor" do que um loop, mesmo que um loop tem uma maior CC. A razão do circuito tem uma maior CC é que às vezes pode ter executado e, por vezes, pode ser que não, o que leva a dois "casos" diferentes que ambos devem ser testados. No seu caso, o loop irá sempre ser executada três vezes, porque você usar uma constante, mas CC não é suficiente inteligente para detectar isso.

Mesmo com o ifs acorrentados em Exemplo 2 - esta estrutura permite que você tenha uma indicação que seria executado se única condition1 e condition2 é verdade. Este é um caso especial que não é possível no caso usando &&. Assim, a cadeia se tem um maior potencial para casos especiais, mesmo se você não usar isso em seu código.

Este é o perigo de aplicação qualquer métrica cegamente. A métrica CC certamente tem muito mérito, mas como com qualquer outra técnica para melhorar o código não pode ser avaliada divorciada do contexto. Aponte a sua gestão na discussão das Linhas de medição Código de Casper Jone (gostaria de poder encontrar um link para você). Ele ressalta que, se linhas de código é uma boa medida de produtividade, em seguida, assembler desenvolvedores de idioma são os a maioria dos desenvolvedores produtivos na terra. É claro que eles não são mais produtivos do que outros desenvolvedores; ele só leva-los muito mais código para realizar o que linguagens de alto nível fazem com menos código fonte. Digo isto, como eu digo, assim que você pode mostrar a seus gestores como mudo é para aplicar cegamente métricas sem revisão inteligente do que a métrica está dizendo a você.

Gostaria de sugerir que, se eles não estão, que a sua gestão seria sábio usar a medida CC como uma maneira de detectar potenciais pontos quentes no código que deve ser revisto ainda mais. Cegamente apontando para a meta de menor CC sem qualquer referência a manutenção de código ou outras medidas de boa codificação é apenas tolo.

Cyclomatic complexidade é análoga à temperatura. Eles são as duas medidas, e na maioria dos casos sentido sem contexto. Se o referido lado de fora da temperatura foi de 72 graus, que não significa muito; mas se adicionou o facto que estava no pólo norte, o número 72 torna-se significativo. Se alguém me dissesse um método tem uma complexidade ciclomática de 10, não posso determinar se isso é bom ou ruim, sem o seu contexto.

Quando eu revisão de código um aplicativo existente, acho complexidade ciclomática um útil “ponto de partida” métrica. A primeira coisa que eu verificar se há são métodos com CC> 10. Estes “> 10” métodos não são necessariamente ruins. Eles apenas me fornecer um ponto de partida para a revisão do código.

Regras gerais quando se considera um número CC:

  • A relação entre CC # e # de testes, deverá ser CC # <= #tests
  • Refactor para CC # somente se ela aumenta manutenção
  • CC acima de 10 indica frequentemente um ou mais Código Smells

[Off topic] Se você favorecer a legibilidade sobre boa pontuação nas métricas (Foi J.Spolsky o que disse, "o que é medido, de ter feito?" - o que significa que as métricas são abusadas mais frequentemente do que não suponho), é muitas vezes melhor usar um boolean bem-nomeado para substituir sua declaração condicional complexa.

então

if (condition1 && condition2 && condition3)
    Console.WriteLine("wibble");

become

bool/boolean theWeatherIsFine =  condition1 && condition2 && condition3;

if (theWeatherIsFine)
    Console.WriteLine("wibble");

Não sou especialista neste assunto, mas eu pensei que eu iria dar meus dois centavos. E talvez isso é tudo isso vale a pena.

Cyclomatic Complexidade parece ser apenas um atalho especial automatizado para encontrar potencialmente (mas não definitivamente) trechos de código problemáticas. Mas não é o verdadeiro problema a ser resolvido um dos testes? Quantos casos de teste que o código exige? Se CC é maior, mas o número de casos de teste é o mesmo e código é mais limpo, não se preocupe com CC.

1.) Não há ponto de decisão lá. Há um e apenas um caminho através do programa lá, apenas um resultado possível com qualquer uma das duas versões. O primeiro é mais concisa e melhor, Cyclomatic Complexidade ser condenado.

1 caso de teste para ambos

2.) Em ambos os casos, você quer escrever "wibble" ou não.

2 casos de teste para ambos

3.) O primeiro pode resultar em nada, "um" ou "um" e "um e dois". 3 caminhos. Segundo um poderia resultar em nada, qualquer um dos dois, ou ambos. 4 caminhos.

3 casos de teste para o primeiro 4 casos de teste para a segunda

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top