Baixe o app para aproveitar ainda mais
Prévia do material em texto
CCT0711 - QUALIDADE E TESTE DE SOFTWARE Aula 06 Complexidade Ciclomática Complexidade ciclomática é uma métrica do campo da engenharia de software, desenvolvida por Thomas J. McCabe em 1976, e serve para mensurar a complexidade de um determinado módulo (uma classe, um método, uma função etc), a partir da contagem do número de caminhos independentes que ele pode executar até o seu fim. Um caminho independente é aquele que apresenta pelo menos uma nova condição (possibilidade de desvio de fluxo) ou um novo conjunto de comandos a serem executados. Complexidade Ciclomática O resultado da complexidade ciclomática indica quantos testes (pelo menos) precisam ser executados para que se verifique todos os fluxos possíveis que o código pode tomar, a fim de garantir uma completa cobertura de testes. Existem diferentes formas de se calcular: Usando a notação de um grafo de fluxo; Usando fluxograma; Com análise estática do código, usando uma ferramenta que automatize essa tarefa. Complexidade Ciclomática 2 Complexidade Ciclomática: Cálculo pelo Grafo de Fluxo de Controle 2 4 Complexidade Ciclomática: Através desta fórmula é possível que sejam calculados valores de complexidade ciclomática sem a necessidade de desenhar o grafo de fluxo de controle, apenas identificando quais palavras reservadas das linguagens correspondem a decisões ou retornos antes do fim do programa, método, rotina ou função. Cálculo pelo Grafo de Fluxo de Controle Complexidade Ciclomática: Este cálculo simplificado pode ser descrito da seguinte forma: 1. O valor inicia em “1” para o método, função ou rotina (com ou sem retorno) 2. Adicione mais um ponto para cada elemento abaixo: 2.1 Seleção – if, case 2.2 Loops – for, while, do-while, break e continue 2.3 Operadores – “&&”, “||”, “?” 2.4 Exceções – catch, throw e throws 2.5 Fluxo – return que não seja o último Obs: else, default, finally, “:” e o último return não incrementam a contagem Cálculo por palavra reservada Complexidade Ciclomática: Cálculo por palavra reservada CC → Complexidade Ciclomática CC = 17 arestas – 13 nós + 2 = 6 ou CC = 5 Regiões + 1 = 6 Complexidade Ciclomática: Complexidade Ciclomática: Exemplo de contagem em código Java feito pelo SonarQube Complexidade Ciclomática: Exemplo de contagem em código Java feito pelo SonarQube O cálculo do exemplo dá um valor total de 5, pois soma-se um ao método (linha 7), mais um pelo primeiro “IF” (linha 8), mais um pelo “return” que não é o último, mais um pelo “while” e pelo “&&” (linha 14). Repare que o último “return” não conta. Uma vez que se conheça a forma de cálculo baseado em palavras reservadas é possível calcular complexidade ciclomática em várias linguagens da mesma forma, basta identificar as palavras reservadas que representam uma decisão ou saída precoce do programa. Complexidade Ciclomática: Como reduzir Substituir ninhos de condicionais por cláusulas de proteção: Para tirar a complexidade do entendimento do caminho de execução. double getPayAmount() { double result; if (_isDead) result = deadAmount(); else { if (_isSeparated) result = separatedAmount(); else { if (_isRetired) result = retiredAmount(); else result = normalPayAmount(); }; } return result; }; Complexidade Ciclomática: Como reduzir Agora faz assim: double getPayAmount() { if (_isDead) return deadAmount(); if (_isSeparated) return separatedAmount(); if (_isRetired) return retiredAmount(); return normalPayAmount(); }; Complexidade Ciclomática: Como reduzir Decompor condicional: Quando se têm uma estrutura condicional muito complicada com diversos if-elseif-else, pode-se extrair métodos dos resultados dessas condições e invocá-los. if (date.before(SUMMER_START) || date.after(SUMMER_END)) { charge = quantity * _winterRate + _winterServiceCharge; } else { charge = quantity * _summerRate; } // melhor assim if (notSummer(date)) { charge = winterCharge(quantity); } else { charge = summerCharge(quantity); } Complexidade Ciclomática: Como reduzir Substituir condicional por polimorfismo: Tendo um comando condicional que a partir do tipo de objeto escolhe diferentes comportamentos, você pode tornar o método original abstrato e mover essas condicionais para suas próprias subclasses. class Bird { //... double getSpeed() { switch (type) { case EUROPEAN: return getBaseSpeed(); case AFRICAN: return getBaseSpeed() - getLoadFactor() * numberOfCoconuts; case NORWEGIAN_BLUE: return (isNailed) ? 0 : getBaseSpeed(voltage); } throw new RuntimeException("Should be unreachable"); } } Complexidade Ciclomática: Como reduzir abstract class Bird { //... abstract double getSpeed(); } class European extends Bird { double getSpeed() { return getBaseSpeed(); } } class African extends Bird { double getSpeed() { return getBaseSpeed() - getLoadFactor() * numberOfCoconuts; } } class NorwegianBlue extends Bird { double getSpeed() { return (isNailed) ? 0 : getBaseSpeed(voltage); } } // Somewhere in client code speed = bird.getSpeed(); } https://www.youtube.com/watch?v=mIvKV08100Q https://www.youtube.com/watch?v=nz_UTenHnck https://www.youtube.com/watch?v=na3lyi0MU6E https://artesoftware.com.br/2019/02/09/complexidade-ciclomatica/ https://www.sonarqube.org/ import javax.swing.JOptionPane; public class Potencia_teste_correcao { public static void main(String[] args) { float base, expoente, resultado, potencia; base = Integer.parseInt(JOptionPane.showInputDialog(null,"Digite a base: ")); expoente = Integer.parseInt(JOptionPane.showInputDialog(null,"Digite o expoente: ")); if(expoente < 0) { potencia = 0 - expoente; } else { potencia = expoente; } resultado = 1; while(potencia != 0) { resultado = resultado * base; potencia = potencia - 1; } if(expoente < 0 && base !=0) { resultado = 1/resultado; }else { if(base == 0) { JOptionPane.showMessageDialog(null, "A Potencia é um numero infinito."); } } JOptionPane.showMessageDialog(null, "A Potencia é: "+resultado); System.exit(0); } } /*1*/ import javax.swing.JOptionPane; /*1*/ public class Potencia_teste { /*1*/ public static void main(String[] args) { /*1*/ float base, expoente, resultado, potencia; /*1*/ base = Integer.parseInt(JOptionPane.showInputDialog(null,"Digite a base: ")); /*1*/ expoente = Integer.parseInt(JOptionPane.showInputDialog(null,"Digite o expoente: ")); /*1*/ if(expoente < 0) { /*2*/ potencia = 0 - expoente; /*3*/ } else { /*3*/ potencia = expoente; /*4*/ } /*4*/ resultado = 1; /*4*/ while(potencia != 0) { /*5*/ resultado = resultado * base; /*5*/ potencia = potencia - 1; /*5*/ } /*6*/ if(expoente < 0 && base !=0) { /*7*/ resultado = 1/resultado; /*8*/ }else { /*8*/ if(base == 0) { /*9*/ JOptionPane.showMessageDialog(null, "A Potencia é um numero infinito."); /*9*/ } /*10*/ } /*10*/ JOptionPane.showMessageDialog(null, "A Potencia é: "+resultado); /*10*/ System.exit(0); /*10*/ } /*10*/ } CC = Arestas - Nós + 2 CC = 13 – 10 + 2 CC = 5 ou CC = 4 Regiões + 1 = 5 https://www.youtube.com/watch?v=zzFEdLiE1P4 Como reduzir a complexidade ciclomática do código usando Polimorfismo com C# https://learn.microsoft.com/pt-br/visualstudio/code-quality/code-metrics-cyclomatic- complexity?view=vs-2022 Slide 1 Slide 2 Slide 3 Slide 4 Slide 5 Slide 6 Slide 7 Slide 8 Slide 9 Slide 10 Slide 11 Slide 12 Slide 13 Slide 14 Slide 15 Slide 16 Slide 17 Slide 18 Slide 19 Slide 20 Slide 21 Slide 22 Slide 23
Compartilhar