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