La metrica di complessità Halstead consente di misurare la complessità di un programma software senza eseguire il programma stesso.
Questa metrica è un metodo di test statico dove le proprietà software misurabili vengono identificate e valutate. Il codice sorgente viene analizzato e suddiviso in una sequenza di token. I token vengono quindi classificati e conteggiati come operatori o operandi.
La metrica di complessità Halstead non dipende da alcun linguaggio di programmazione specifico e può essere applicata a codice sorgente IEC-61131-3.
Gli operatori e gli operandi sono classificati e conteggiati come indicato di seguito:
Parametro |
Descrizione |
---|---|
n1 |
Numero di operatori distinti |
n2 |
Numero di operandi distinti |
N1 |
Numero totale di operatori |
N2 |
Numero totale di operandi |
Vi sono diversi valori di metriche che è possibile calcolare per rappresentare diversi aspetti della complessità:
oHalstead Difficulty (D)
oHalstead Length (N)
oHalstead CalculatedLength (Nx)
oHalstead Volume (V)
oHalstead Effort (E)
oHalstead Vocabulary (n)
Complessità Halstead per POU implementate in Testo strutturato (ST)
La complessità Halstead è stata sviluppata inizialmente per linguaggi di testo (come C, C++, Pascal,...) ed è applicabile alle POU implementate in testo strutturato (ST).
NOTA: per impostazione predefinita, viene visualizzata la Halstead Difficulty.
Complessità Halstead per POU implementate nel Diagramma a blocchi funzione(FBD)
Il diagramma a blocchi funzione (FBD) appartiene al gruppo dei linguaggi grafici di implementazione e non si basa su testo. Una POU consiste di più reti FBD. È quindi necessario adattare la metrica di complessità Halstead per poter essere applicata ai linguaggi grafici. Il concetto di base è lo stesso. Operandi e operatori e rispettiva frequenza (per rete FBD) sono considerati come presentati all'utente (vedere l'esempio per diagramma a blocchi funzione (FBD)).
I risultati di complessità Halstead calcolati per rete FBD vengono aggregati tra le reti FBD e allegati al livello della POU (programma, blocco funzione, funzione, metodo o proprietà).
NOTA: i valori Halstead calcolati (per rete FBD) sono FBD Network Halstead Difficulty e FBD Network Halstead Length.
I seguenti tipi di aggregazione vengono applicati per valori di metrica Halstead di rete FBD (Halstead Difficulty e Halstead Length):
oMedia
oMinimo
oMassimo
oSomma
oCoerenza
NOTA: i valori aggregati più rilevanti sono FBD Halstead Difficulty Network Max, FBD Halstead Difficulty Network Consistency, FBD Halstead Length Network Max e FBD Halstead Length Network Consistency. Tutte le altre combinazioni (Min, Sum e Media) vengono calcolate e allegate al modello ma non visualizzate per impostazione predefinita.
Valore |
Formula |
---|---|
Halstead Difficulty (D) |
D = (n1 / 2) * (N2 / n2) |
Halstead Length (N) |
N = N1 + N2 |
Halstead CalculatedLength (Nx) |
Nx = n1 * log2(n1) + n2 * log2(n2) |
Halstead Volume (V) |
V = N * log2(n) |
Halstead Effort (E) |
E = V * D |
Halstead Vocabulary (n) |
n = n1 + n2 |
NOTA: un'espressione in una dichiarazione IF <expression> THEN non deve avere parentesi. Sono considerate come sempre disponibili nel codice sorgente IEC-61131-3 .
I risultati della metrica come FBD Network Halstead Difficulty e FBD Network Halstead Length vengono aggregati tra le reti FBD di una POU.
I values sono l'elenco di valori della stessa metrica (ad esempio, FBD Network Halstead Length) di tutte le reti FBD di una POU.
Il valore di coerenza è un risultato del coefficiente Gini. Il coefficiente Gini è una misura di dispersione statistica. Misura la differenza tra i valori di una distribuzione frequente. Un coefficiente Gini di 0 esprime perfetta eguaglianza, dove tutti i valori sono uguali. Un coefficiente Gini di 1 esprime la massima differenza tra i valori.
Esempio per testo strutturato (ST)
Esempio di calcolo Halstead per codice IEC-61131-3 (per il calcolo viene considerata solo la parte di implementazione):
IF (xInit = FALSE) THEN
PerformInitialization();
xInit := TRUE;
ELSE
FOR i := 1 TO 5 DO
iAxisId := i + 7;
sAxisName := Standard.CONCAT('MyAxis ', INT_TO_STRING(iAxisId));
// Do some math calculations for each axis here
udiResult := CalculateStuff(sName := sAxisName, iID := iAxisId);
END_FOR
END_IF
Elenco di operatori e relative frequenze:
Operator Frequency
======== =========
(operators)
If 1
Then 1
LeftParenthesis 6
RightParenthesis 6
Equal 1
Semicolon 5
Assign 7
Else 1
For 1
EndFor 1
Do 1
Plus 1
Period 1
INT_TO_STRING 1
Colon 2
EndIf 1
(n1) 16 (N1) 37
Elenco di operandi e relative frequenze:
Operand Frequency
======= =========
(variables/methods/functions)
xInit 2
PerformInitialization 1
i 2
iAxisId 3
sAxisName 2
Standard 1
CONCAT 1
udiResult 1
CalculateStuff 1
sName 1
iID 1
(constants)
FALSE 1
TRUE 1
INT#1 1
INT#5 1
INT#7 1
'MyAxis ' 1
(n2) 17 (N2) 22
Risultato difficoltà Halstead
Halstead Difficulty (D = (16/2) * (22/17) = 10.3529411764706
Esempio per diagramma a blocchi funzione (FBD)
Esempio di calcolo Halstead per codice IEC-61131-3 implementato in FBD (per il calcolo viene considerata solo la parte di implementazione):
Elenco di operatori e relative frequenze:
Operator Frequency
======== =========
(operators)
Assign 4
Set2 1
And 1
Negation2 2
Or 1
Eq 1
(n1) 6 (N1) 10
Elenco di operandi e relative frequenze:
Operand Frequency
======= =========
(variables/methods/functions/constants)
xResult 1
TON 1
fbTON 1
xEnable 1
T#1s 1
IN 1
PT 1
Q 1
ET 1
xTray1Empty 1
xTray2Empty 1
xInHomePosition 1
xBeltFull 1
xGroupReady 1
uiMasterStart 1
5 1
(n2) 16 (N2) 16
Risultato difficoltà Halstead rete FBD
FBD Network Halstead Difficulty (D) = (6/2) * (16/16) = 3
Lunghezza Halstead rete FBD
FBD Network Halstead Length (D) = 10 + 16 = 26