Estou usando o SonarLint for Eclipse desde recentemente, e isso me ajudou muito. No entanto, levantou-me uma questão sobre a complexidade ciclomática.
O SonarLint considera aceitável um CC de 10 e há alguns casos em que estou além dele, cerca de 5 ou 6 unidades. Essas partes estão relacionadas aos mapeadores em que os valores se baseiam em diferentes variáveis, por exemplo:
- O campo A se baseia na String sA;
- O campo B depende da string sB;
- O campo C conta com String sC;
- etc ...
Não tenho outra escolha que colocar um if
para cada campo. Felizmente, essa não é minha escolha, mas um sistema já existente e complexo que não posso mudar sozinho.
O núcleo da minha pergunta é: por que é tão importante não ter um CC muito alto em um único método ? Se você mover algumas de suas condições em um ou mais sub-métodos para reduzir a complexidade, isso não reduzirá o custo de sua função geral, está apenas movendo o problema para outro lugar, eu acho?
(Desculpe por pequenos erros, se houver).
EDITAR
Minha pergunta não se refere à complexidade ciclomática global, mas apenas à complexidade de um método e à divisão de métodos (eu tenho um tempo difícil para explicar o que exatamente quero dizer, desculpe). Eu estou perguntando por que é permitido dividir suas condições em métodos menores se ainda pertencer a um 'super método', que apenas executará todos os sub-métodos, adicionando complexidade ao algoritmo.
O segundo link, no entanto ( sobre o anti-padrão ) é de grande ajuda.
fonte
Respostas:
A principal coisa aqui: "capacidade cerebral".
Veja bem, uma das principais funções do código é ... ser lida . E o código pode ser fácil de ler e entender; ou difícil.
E ter um CC alto simplesmente implica muitos "níveis" em um método. E isso implica: você, como leitor humano, terá dificuldade em entender esse método.
Quando você lê o código-fonte, seu cérebro automaticamente tenta colocar as coisas em perspectiva: em outras palavras - ele tenta criar alguma forma de "contexto".
E quando você tem um método pequeno (com um bom nome) que consiste apenas em algumas linhas e CC muito baixo; então seu cérebro pode facilmente aceitar esse "bloqueio". Você lê, você entende; FEITO.
Por outro lado, se seu código tiver CC alto, seu cérebro gastará muitos "ciclos" mais para deduzir o que está acontecendo.
Outra maneira de dizer isso: você sempre deve preferir uma rede complexa de coisas simples a uma rede simples de coisas complexas. Porque seu cérebro é melhor para entender pequenas coisas.
fonte
CC, como todas as outras regras práticas para odores de código, é uma heurística . Não é um critério à prova de falhas que diz uma verdade absoluta. Se assim fosse, a coisa mais razoável a fazer seria simplesmente tornar esses métodos ilegais no idioma e forçar as pessoas a alcançar seus fins de outra maneira.
Mas não é assim que os indicadores funcionam. Na maioria das vezes, sua função é alertar as pessoas sobre coisas que elas não estavam cientes. No seu caso, você está ciente de que a lógica é complicada e as soluções alternativas a tornam ainda mais complicada. Portanto, não faz sentido tentar satisfazer a regra básica primitiva, quando seu principal objetivo é emitir avisos para pessoas que não estão cientes de que há um problema.
fonte
Resumindo: trata-se de legibilidade e, portanto, de manutenção do seu código.
Se você tem um método longo e complexo com muitos (aninhados)
if
, fica difícil dizer o que realmente faz. Se você extrair alguns métodos particulares e nomeá-los de maneira significativa, é muito mais fácil.fonte
A complexidade ciclomática de um método está relacionada ao número de casos de teste necessários para um método. Especificamente, uma complexidade ciclomática de 10 significa que 10 é o limite superior para que os casos de teste tenham cobertura total de ramificação para seu método. Também está relacionado ao número de caminhos que devem ser testados, menos os caminhos impossíveis.
Além disso, concordo com as outras respostas para outras considerações - capacidade mental de um desenvolvedor ou um indicador de possíveis problemas ou refatoração ou uma medida de legibilidade e manutenção do código .
fonte
O CC é apenas uma heurística, e o quão ruim é uma pontuação específica depende de muitas coisas.
Dito isto, você sempre deve ver um CC alto como algo que destaca o código que pode / deve ser refatorado. Você diz que mover a
if
instrução para outro método está ocultando o problema - mas existe um padrão que você pode abstrair em vez de copiar e colar n vezes? Se for umaif-else
cadeia longa , você pode transformá-la em uma declaração de troca, ou talvez usar polimorfismo, ou algo mais? Se houver um aninhamento profundo, algumas de suas cláusulas condicionais podem ser unidas ou indica responsabilidades separadas que devem ser divididas em diferentes classes?fonte
Eu vejo a complexidade ciclomática como um aviso. Se você pode ler o código e não é muito complexo para entender, então eu não me preocuparia muito com isso, provavelmente há coisas mais importantes com as quais se preocupar, sempre há.
Uma maneira de reduzir o tipo de CC que você menciona é usar o polimorfismo, pois você marcou sua pergunta com a tag Java. Portanto, em vez de os caminhos de código serem digitados em seqüência, você pode usar classes bem nomeadas. Isso pode ajudar, mas às vezes é um exagero e pode tornar seu código ainda mais difícil de entender.
No entanto, pode ser um sinal de código difícil de manter. Ao ler o método, é fácil ver qual caminho de código você seguirá para cada caso? Você poderia ignorar esse método se não conhecesse bem a base de código e estivesse procurando algo relacionado, mas mais adiante no código? Eu sei que algumas pessoas defendem a divisão de métodos em muitos métodos de 1/2 linha com nomes descritivos, mas às vezes acho que é ainda mais difícil de ler do que o código que ele deveria substituir.
Por fim, a manutenção é um problema difícil e cabe a você decidir qual você acha que será mais fácil de ler. O fato de você estar pensando sobre isso significa que você está no caminho certo. Lembre-se de que o mantenedor que precisa tentar decifrar esse código dentro de alguns anos pode ser você. Portanto, torne o mais fácil possível para eles.
fonte
Tudo se resume a quanto tempo é gasto olhando (ciclos cerebrais) para o código e compreendendo o que o código está fazendo.
Métodos maiores também são mais difíceis de testar e mais previsíveis que tipo de comportamento pode ocorrer.
A complexidade ciclomática é uma medida. Nesse caso, valores mais altos são indicadores de problemas em potencial. O código complexo leva mais tempo para compreender o entendimento e provavelmente não é testado tão completamente quanto os métodos menos complexos. Portanto, é importante observar quais áreas do código são complexas com essa medida para fins de refatoração e manutenção.
Outra coisa a considerar é a atualização de código complexo. Ao fazer a análise, um desenvolvedor pode relatar que alterar o código é mais ou menos arriscado, analisando sua complexidade.
Portanto, há muito valor para medir a complexidade que pode ser alavancada e usada para fins de tomada de decisão.
fonte