Pular para o conteúdo principal

Volume de Halstead

As métricas de Halstead são baseadas nos números de operadores e operandos.

Primeiro, precisamos decidir o que entendemos por operadores e operandos. Operadores e operandos são definidos por sua relação entre si - em geral, um operador realiza uma ação e um operando participa dessa ação. Um exemplo simples de um operador é algo que realiza uma operação usando zero ou mais operandos. Um operando é algo que pode participar de uma interação com zero ou mais operadores. Vamos olhar para o exemplo:

int x = x + 1;

x ocorre duas vezes, então se pegarmos int, x e 1 como operandos e = e + como operadores, temos 4 operandos (3 únicos) e 2 operadores (2 únicos). Tomando OP como o número de operadores, OD como o número de operandos, UOP como o número de operadores únicos e UOD como o número de operandos únicos, definimos as métricas primárias de Halstead como:

  • O Comprimento de Halstead (LTH) é: OP + OD
  • O Vocabulário de Halstead (VOC) é: UOP + UOD

O Volume de Halstead é baseado no Comprimento e no Vocabulário.

  • Volume de Halstead (VOL) é: LTH * log2(VOC)

Você pode ver isso como a massa do código - quanto informação o leitor do código tem que absorver para entender seu significado. A maior influência na métrica Volume é o Comprimento de Halstead, que causa um aumento linear no Volume, ou seja, dobrar o Comprimento dobrará o Volume. No caso do Vocabulário, o aumento é logarítmico. Por exemplo, com um Comprimento de 10 e um Vocabulário de 16, o Volume é 40. Se dobrarmos o Comprimento, o Volume dobra para 80. Se mantivermos o Comprimento em 10 e dobrarmos o Vocabulário para 32, obtemos um volume de 50.

Exemplo de Configuração

flutterando_metrics:
...
metrics:
...
halstead-volume: 150
...

Exemplo

MetricComputationResult<double> computeImplementation(
Declaration node,
Iterable<ScopedClassDeclaration> classDeclarations,
Iterable<ScopedFunctionDeclaration> functionDeclarations,
InternalResolvedUnitResult source,
) {
final visitor = HalsteadVolumeAstVisitor();
node.visitChildren(visitor);

final lth = visitor.operators + visitor.operands;

final voc = visitor.uniqueOperators + visitor.uniqueOperands;

final vol = lth * _log2(voc);

return MetricComputationResult<double>(value: vol);
}

O Volume de Halstead para a função exemplo é 138.