Metrica
Descrizione dettagliata delle metriche fornite da CODESYS Static Analysis
Suggerimento
IL Dimensione del codice, Dimensione variabile, Dimensione della pila, E Numero di chiamate le metriche vengono riportate solo per le POU delle librerie integrate nel progetto.
Metrica: Dimensione del codice (numero di byte)
Categorie: Informativo, Efficienza
Numero di byte con cui un blocco funzione contribuisce al codice dell'applicazione
Il numero dipende anche dal generatore di codice. Ad esempio, il generatore di codice per i processori ARM generalmente genera più byte rispetto al generatore di codice per i processori x86.
Metrica: Dimensione variabile (numero di byte)
Categorie: Informativo, Efficienza
Dimensione della memoria statica utilizzata dall'oggetto
Per i blocchi funzione, questa è la dimensione utilizzata per un'istanza del blocco funzione (che può includere lacune di memoria, a seconda dell'allineamento della memoria). Per programmi, funzioni ed elenchi di variabili globali, questa è la somma delle dimensioni di tutte le variabili statiche.
Esempio
FUNCTION FUN1 : INT
VAR_INPUT
a,b : INT;
END_VAR
VAR
c,d : INT;
END_VAR
VAR_STAT
f,g,h : INT;
END_VARLa funzione ha 3 variabili statiche di tipo INT (f, g, E h), ognuno dei quali richiede 2 byte di memoria. Di conseguenza, FUN1 ha una dimensione variabile di 6 byte.
Metrica: Dimensione dello stack (numero di byte)
Categorie: Informativo, Efficienza, Affidabilità
Numero di byte necessari per richiamare una funzione o un blocco funzione
Le variabili di ingresso e le variabili di uscita sono allineate alla memoria. Ciò può creare un divario tra queste variabili e le variabili locali. Questo divario viene conteggiato.
I valori restituiti delle funzioni chiamate che non rientrano in un registro vengono inseriti nello stack. Il maggiore di questi valori determina la memoria aggiuntiva allocata, che conta anch'essa. Le funzioni o i blocchi funzionali richiamati all'interno delle POU in questione dispongono di un proprio stack frame. Pertanto, la memoria per tali chiamate non viene conteggiata.
A seconda del generatore di codice utilizzato, anche i risultati intermedi dei calcoli utilizzano lo stack. Questi risultati non vengono conteggiati.
//Declaration
FUNCTION FUN1 : INT
VAR_INPUT
a,b : INT;
END_VAR
VAR
c,d,e : INT;
END_VAR
VAR_STAT
f,g,h : INT;
END_VAR
//Implementation
c := b;
d := a;
e := a+b;Ipotesi: per il calcolo, supporre a CODESYS Control Win che utilizza il generatore di codice x86.
L'esempio precedente ha una dimensione del chiamante di 8 byte: 4 byte per i due INT inputs e 4 byte per il valore restituito. Il dispositivo ha un allineamento dello stack di 4 byte, quindi c'è uno spazio di 2 byte. La dimensione del chiamante è 8 byte: tre variabili locali con 2 byte ciascuna più il gap di 2 byte per l'allineamento dello stack. Di conseguenza, la dimensione totale dello stack è di FUN1 è di 16 byte.
VAR_STAT non viene memorizzato nello stack e pertanto non aumenta la dimensione dello stack di una POU.
Metrica: Numero di chiamate (chiamate)
Categoria: Informativo
Numero di chiamate della POU sotto Unità di programma
//Declaration PLC_PRG
PROGRAM PLC_PRG
VAR
myFB : FB1;
END_VAR
//Implementation
myFB(b := FALSE);//Declaration FB1
FUNCTION_BLOCK FB1
VAR_INPUT
b : BOOL;
END_VAR
VAR
i : INT;
END_VAR
//Implementation
METH(i);
IF b THEN
METH(i*i);
END_IF
//Declaration FB1.METH
METHOD METH : BOOL
VAR_INPUT
i : INT;
END_VAR
//Implementation
METH := i >= 42;Se PLC_PRG viene chiamato in un'attività, viene conteggiata anche questa chiamata.
FB1 ha esattamente una chiamata (in PLC_PRG).
METH ha due chiamate, entrambe in entrata FB1.
Metrica: Numero di chiamate da attività (attività)
Categorie: Manutenibilità, Affidabilità
Numero di compiti (Compiti) dove il POU specificato sotto Unità di programma è chiamato
Nel caso dei blocchi funzione viene contato il numero di task in cui viene chiamato il blocco funzione stesso o qualsiasi blocco funzione nell'albero ereditario del blocco funzione.
Per i metodi e le azioni viene visualizzato il numero di task in cui viene richiamato il blocco funzione (principale).
FUNCTION_BLOCK FB //...
FUNCTION_BLOCK FB2 EXTENDS FB //...
FUNCTION_BLOCK FB3 EXTENDS FB2 //...
Ogni blocco funzione viene richiamato autonomamente PROGRAM. Ogni PROGRAM ha il suo compito.
IL Chiamato nei compiti restituisce la metrica in 1 per FB3 e 2 per FB2 perché le chiamate da FB3 E FB2 vengono contati. La metrica risulta in 3 per FB perché in questo caso le chiamate da FB3, FB2, E FB vengono contati.
Metrica:Numero di variabili globali utilizzate (globali)
Categorie: Manutenibilità, Riutilizzabilità
Numero di variabili globali utilizzate nella POU sotto Unità di programma
//GVL
VAR_GLOBAL
gvla : INT;
gvlb : INT;
gvlc : INT;
END_VAR/PRG declaration
PROGRAM PRG
VAR
x : INT := GVL.gvlc;
y : INT;
END_VAR
//PRG implementation
x := GVL.gvla;
y := GVL.gvla*GVL.gvlb;IL PRG il programma utilizza 3 variabili da GVL: gvla, gvlb, E gvlc.
Metrica: Numero di accessi diretti agli indirizzi (IO)
Categorie: Riutilizzabilità, Manutenibilità
Numero di accessi diretti all'indirizzo (IO) nell'implementazione dell'oggetto.
//Declaration
PROGRAM PRG
VAR
xVar : BOOL:= %IX0.0; // +1 direct address access
byVar : BYTE;
END_VAR
//Implementation
xVar := %IX0.0; // +1 direct address access
%QX0.0 := xVar; // +1
%MX0.1 := xVar; // +1
%MB1 := byVar; // +1L'esempio ha 5 accessi diretti all'indirizzo.
Metrica: Numero di variabili locali (locali)
Categorie: Informativo, Efficienza
Numero di variabili dichiarate nel VAR zona del POU. Le variabili ereditate non vengono conteggiate.
//Declaration
FUNCTION_BLOCK FB
VAR_INPUT
END_VAR
VAR_OUTPUT
END_VAR
VAR
i,j,k,l : INT;
m,n,o : BOOL;
END_VAR
Nel blocco funzione vengono dichiarate 7 variabili locali.
Metrica: Numero di variabili di input (input)
Categorie: Manutenibilità, Riutilizzabilità
Limite superiore predefinito per il corrispondente SA0166 regola: 10
Numero di variabili dichiarate in VAR_INPUT dell'unità di programma. Le variabili di input ereditate non vengono conteggiate.
FUNCTION_BLOCK FB
VAR_INPUT
i : INT;
r : REAL;
END_VAR
Nel blocco funzione vengono dichiarate 2 variabili di ingresso: i E r.
METHOD METH : BOOL
VAR_INPUT
j : INT;
l : LREAL;
END_VAR
Il metodo ha 2 input: j E l
Metrica: Numero di variabili di output (output)
Categorie: Manutenibilità, Riutilizzabilità
Limite superiore predefinito per il corrispondente SA0166 regola: 10
Numero di variabili in VAR_OUTPUT dell'unità di programma
Nel caso dei blocchi funzione, questo è il numero di variabili di uscita personalizzate (VAR_OUTPUT). Nel caso di metodi e funzioni, questo è il numero di variabili di output personalizzate più uno se hanno un valore restituito. Viene conteggiato anche il valore restituito. Le variabili di output ereditate non vengono conteggiate.
Un numero elevato di variabili di output è indice di una violazione del principio di unicità della responsabilità.
FUNCTION_BLOCK FB
VAR_OUTPUT
i : INT; // +1 output
r : REAL; // +1 output
END_VARIl blocco funzione ha 2 variabili di uscita: i E r
METHOD METH : BOOL
VAR_INPUT
j : INT;
l : LREAL;
END_VARIl metodo ha 3 output: METH, j, E l
METHOD METH1 // +0 outputs (no return type)
VAR_OUTPUT
ar : ARRAY[0..10] OF INT; // +1 output
l : LREAL; // +1 output
END_VARIL METH1 il metodo ha 2 output: ar E i
Metrica: NOS – Numero di dichiarazioni
Categoria: Informativo
Numero di istruzioni nell'implementazione di un blocco funzione, funzione o metodo
Le istruzioni nella dichiarazione, le istruzioni vuote o i pragma non vengono conteggiate.
//Declaration:
FUNCTION POU : BOOL
VAR_INPUT
END_VAR
VAR
c : INT := 100; // statements in the declaration are not counted
END_VAR
VAR_OUTPUT
test : INT;
i : INT;
END_VAR
//Implementation:
IF TRUE THEN //if statement: +1
test := 0; // +1
END_IF
WHILE test = 1 DO //while statement: +1
; // empty statements do not add to the statement count
END_WHILE
FOR c := 0 TO 10 BY 2 DO //for statement: +1
i := i+i; // +1
END_FOR
{text 'simple text pragma'} //pragmas are not counted
test := 2; //+1L'esempio ha 6 istruzioni.
Metrica: Percentuale di commenti
Categoria: Manutenibilità
Percentuale di commenti nel codice sorgente
Questo numero viene calcolato secondo la seguente formula:
Percentuale = 100 * <caratteri nei commenti> / <somma dei caratteri nel codice sorgente e dei caratteri nei commenti>
Più spazi consecutivi nel codice sorgente vengono conteggiati come uno spazio, il che impedisce un peso elevato del codice sorgente con rientro. Per gli oggetti vuoti (senza codice sorgente e senza commenti), viene restituita una percentuale pari a 0.
Parte della dichiarazione:
FUNCTION_BLOCK FB //comments in the declaration are counted, as well
VAR_TEMP
hugo : INT;
END_VARImplementazione:
hugo := hugo + 1; //Declaration: 40 letters non comment; 50 letters comment //Implementation: 13 letters non comment; 152 letters comment // 100 * 202 / 255 -> 79% comments
Il calcolo della percentuale 100 * 202 / 255 restituisce 79%.
Metrica: Complessità (McCabe)
Categoria: Testabilità
Limite superiore consigliato: 10
La complessità ciclomatica secondo McCabe è una misura della leggibilità e testabilità del codice sorgente. Viene calcolato contando il numero di rami binari nel flusso di controllo della POU. Tuttavia, la complessità ciclomatica penalizza l’elevata ramificazione perché l’elevata ramificazione aumenta il numero di casi di test richiesti per un’elevata copertura del test.
IF dichiarazione// every POU has an initial cyclomatic complexity of 1, since it has at least 1 branch
IF b1 THEN // +1 for the THEN branch
;
ELSIF b2 THEN // +1 for the THEN branch of the IF inside the else
;
ELSE
IF b3 OR b4 THEN // +1 for the THEN branch
;
END_IF
END_IFLo snippet di codice ha una complessità ciclomatica pari a 4.
CASE dichiarazione// every POU has an initial cyclomatic complexity of 1, since it has at least 1 branch
CASE a OF
1: ; // +1
2: ; // +1
3,4,5: ; // +1
ELSE // the ELSE statement does not increase the cyclomatic complexity
;
END_CASELo snippet di codice ha una complessità ciclomatica pari a 4.
// every POU has an initial cyclomatic complexity of 1, since it has at least 1 branch
WHILE b1 DO // +1 for the WHILE loop
;
END_WHILE
REPEAT // +1 for the REPEAT loop
;
UNTIL b2
END_REPEAT
FOR a := 0 TO 100 BY 2 DO // +1 for the REPEAT loop
;
END_FORLo snippet di codice ha una complessità ciclomatica pari a 4.
Anche le seguenti affermazioni aumentano la complessità ciclomatica:
//Declaration
FUNCTION FUN : STRING
VAR_INPUT
condition_return : BOOL;
condition_jmp : BOOL;
END_VAR
VAR
END_VAR
//Implementation
// every POU has an initial cyclomatic complexity of 1, since it has at least 1 branch
JMP(condition_jmp) lbl; //Conditional jumps increase the cyclomatic complexity by 1
FUN := 'u';
RETURN(condition_return); //Conditional returns increase the cyclomatic complexity by 1, too
lbl:
FUN := 't';
Lo snippet di codice ha una complessità ciclomatica pari a 3.
Metrica: Complessità cognitiva
Categoria: Manutenibilità
Limite superiore predefinito per la corrispondente regola SA0178: 20
La complessità cognitiva è una misura della leggibilità e della comprensibilità del codice sorgente introdotto da Sonarsource™ nel 2016. Tuttavia, penalizza l'annidamento pesante del flusso di controllo e delle espressioni booleane complesse. La complessità cognitiva viene calcolata solo per le implementazioni di testo strutturato.
Gli esempi seguenti mostrano come viene calcolata la complessità cognitiva.
Suggerimento
IL Mostra complessità cognitiva per l'editor corrente Il comando può essere utilizzato per visualizzare ulteriormente gli incrementi per il testo strutturato.
Le affermazioni che manipolano il flusso di controllo aumentano la complessità cognitiva di 1
IF TRUE THEN // +1 cognitive complexity
;
END_IF
WHILE TRUE DO //+1 cognitive complexity
;
END_WHILE
FOR i := 0 TO 10 BY 1 DO //+1 cognitive complexity
;
END_FOR
REPEAT //+1 cognitive complexity
;
UNTIL TRUE
END_REPEATLo snippet di codice ha una complessità cognitiva pari a 4.
Quando si annida il flusso di controllo, viene aggiunto un incremento di 1 per ogni livello di annidamento.
IF TRUE THEN //+1 cognitive complexity
WHILE TRUE DO //+2 (+1 for the loop itself, +1 for the nesting inside the IF)
FOR i := 0 TO 10 BY 1 DO //+3 (+1 for the FOR loop itself, +2 for the nesting inside the WHILE and the IF)
;
END_FOR
END_WHILE
REPEAT //+2 (+1 for the loop itself, +1 for the nesting inside the IF)
;
UNTIL TRUE
END_REPEAT
END_IFLo snippet di codice ha una complessità cognitiva pari a 8.
Poiché le espressioni booleane svolgono un ruolo importante nella comprensione del codice sorgente, vengono prese in considerazione anche nel calcolo della complessità cognitiva.
Comprendere le espressioni booleane associate allo stesso operatore booleano non è così difficile come comprendere un'espressione booleana che contiene operatori booleani alternati. Pertanto, qualsiasi catena di operatori booleani identici in un'espressione aumenta la complessità cognitiva.
b := b1; //+0: a simple expression, containing no operators, has no increment
L'espressione semplice senza operatore ha un incremento pari a 0.
b := b1 AND b2; //+1: one chain of AND operators
L'espressione con un AND il collegamento ha un incremento di 1.
b := b1 AND b2 AND b3; //+1: one more AND, but the number of chains of operators does not change
L'espressione ne ha uno in più AND. Ma poiché si tratta dello stesso operatore, il numero della catena formata con operatori identici non cambia.
b := b1 AND b2 OR b3; //+2: one chain of AND operators and one chain of OR operators
L'espressione ha una catena di AND operatori e una catena di OR operatori. Ciò si traduce in un incremento di 2.
b := b1 AND b2 OR b3 AND b4 AND b5; //+3
Lo snippet di codice ha un incremento di 3.
b := b1 AND NOT b2 AND b3; //+1: the unary NOT operator is not considered in the cognitive complexity
L'operatore unario NOT non è considerato nella complessità cognitiva.
Il testo strutturato dispone di istruzioni ed espressioni aggiuntive che modificano il flusso di controllo.
Le seguenti affermazioni vengono penalizzate con un incremento di complessità cognitiva:
aNewLabel: x := MUX(i, a,b,c); //+1 for MUX operator y := SEL(b, i,j); //+1 for SEL operator JMP aNewLabel; //+1 for JMP to label
EXIT E RETURN Le affermazioni non aumentano la complessità cognitiva.
Metrica: DIT – Profondità dell'albero dell'ereditarietà
Categoria: Manutenibilità
Numero di eredità fino al raggiungimento di un blocco funzione che non estende nessun altro blocco funzione
FUNCTION_BLOCK MyBaseFB // ... FUNCTION_BLOCK AChildFB EXTENDS MyBaseFB // ... FUNCTION_BLOCK AGrandChildFB EXTENDS AChildFB // ...
MyBaseFB ha un DIT pari a 0 perché è esso stesso un blocco funzione che non estende nessun altro blocco funzione.
Per AChildFB, il DIT è 1 perché è necessario un passaggio per arrivare a MyBaseFB.
AGrandChildFB ha un DIT pari a 2: è necessario un passaggio AChildFB e un altro a MyBaseFB.
Metrica: NOC – Numero di bambini
Categorie: Riutilizzabilità, Manutenibilità
Numero di blocchi funzione che estendono il blocco funzione base indicato. I blocchi funzione che estendono indirettamente un blocco funzione base non vengono conteggiati.
FUNCTION_BLOCK MyBaseFB // ... FUNCTION_BLOCK AChildFB EXTENDS MyBaseFB // ... FUNCTION_BLOCK AGrandChildFB EXTENDS AChildFB // ...
MyBaseFB ha solo un (1) oggetto figlio: AChildFB, che a sua volta ha l'unico oggetto figlio, AGrandChildFB. AGrandChildFB non ha oggetti figlio.
Metriche: RFC – Risposta per classe
Categorie: Manutenibilità, Riutilizzabilità
Numero di diversi POU, metodi o azioni che vengono richiamati e che quindi generano una risposta del POU specificato sotto Unità di programma
//Declaration FB1
FUNCTION_BLOCK FB1
VAR
d,x,y : INT;
END_VAR
//Implementation
x := METH(d+10);
y := FUN(42, 0.815);//Declaration FB1.METH
METHOD METH : INT
VAR_INPUT
i : INT;
END_VAR
//Implementation
METH := FUN(CUBE(i), 3.1415);//Declaration CUBE
FUNCTION CUBE : INT
VAR_INPUT
i : INT;
END_VAR
//Implementation
CUBE := i*i*i;//Declaration Function FUN
FUNCTION FUN : INT
VAR_INPUT
a : INT;
lr : LREAL;
END_VAR
//Implementation
FUN := LREAL_TO_INT(lr*10)*a;Iniziare con
FUNECUBE, queste funzioni hanno un RFC pari a 0 perché nessuna di esse chiama altre funzioni, blocchi funzione o metodi per i propri calcoli.FB1.METHusiFUNECUBE, che si traduce in un RFC di 2.Il blocco funzione
FB1stesso chiamaMETHEFUN, che aumenta il suo RFC di 2.Per FB1 occorre tenere conto anche del relativo metodo METH. METH utilizza FUN e CUBE. FUN è già stato aggiunto alla RFC. Pertanto, solo l'uso di CUBE in METH aumenta la RFC per FB1 a 3
Metrica: CBO – Accoppiamento tra oggetti
Categorie: Manutenibilità, Riutilizzabilità
Limite superiore predefinito per la corrispondente regola SA0179: 30
Numero di altri blocchi funzione istanziati e utilizzati in un blocco funzione
Un blocco funzione con un elevato accoppiamento tra oggetti è probabile che sia coinvolto in molti compiti diversi e quindi violi il principio di responsabilità unica.
// Declaration
FUNCTION_BLOCK FB_Child EXTENDS FB_Base objects // +0 for EXTENDS
VAR_INPUT
END_VAR
VAR_OUTPUT
END_VAR
VAR
i_fb1 : FB1; // +1 instantiated here
i_fb2 : FB2; // +1 instantiated here
END_VAR
//Implementation
i_fb3(); // +0 instantiated in FB_Base, no increment for callL'estensione di un blocco funzione non aumenta l'accoppiamento tra gli oggetti.
i_fb3è istanziato nell'implementazione diFB_Basee passato a FB_Child (EXTENDS). La chiamataFB_Childnon aumenta l'accoppiamento tra gli oggetti.Il CBO di
FB_Childè 2.
Metrica: Complessità di riferimento (Elshof)
Categorie: Efficienza, manutenibilità, riusabilità
Complessità del flusso dati di una POU
La complessità di riferimento viene calcolata secondo la seguente formula:
<numero di variabili utilizzate> / <numero di accessi alle variabili>
Vengono considerati solo gli accessi variabili nella parte di implementazione della POU.
//Declaration
PROGRAM PRG
VAR
i, j : INT;
k : INT := GVL.m;
b, c : BOOL;
myFB : FB;
END_VAR
//Implementation
myFB(paramA := b); // +3 accesses (myFB, paramA and b)
i := j; // +2 accesses (i and j)
j := GVL.d; // +2 accesses (j and GVL.d)Fare riferimento alla complessità nei risultati dello snippet di codice:
6 numero di variabili utilizzate /7 numero di accessi variabile = 0,85
Attenzione:
cEknon vengono utilizzate e pertanto non contano come "variabili utilizzate".L'incarico
k : INT := GVL.mnon viene conteggiato perché fa parte della dichiarazione del programma.
Metrica: Mancanza di Coesione dei Metodi – LCOM
Mancanza di coesione dei metodi – LCOM
Categorie: Manutenibilità, Riutilizzabilità
La coesione tra i blocchi funzione, le loro azioni, transizioni e metodi descrive se accedono o meno alle stesse variabili.
La mancanza di coesione dei metodi descrive quanto fortemente gli oggetti di un blocco funzione sono collegati tra loro. Minore è la mancanza di coesione, più forte è la connessione tra gli oggetti.
È probabile che i blocchi funzionali con un'elevata mancanza di coesione siano coinvolti in molti compiti diversi e quindi violino il principio della responsabilità unica.
La metrica viene calcolata secondo la seguente formula:
MAX(0, <numero di coppie di oggetti senza coesione> - <numero di coppie di oggetti con coesione>)
//Declaration
FUNCTION_BLOCK FB
VAR_INPUT
a : BOOL;
END_VAR
VAR_OUTPUT
END_VAR
VAR
i,b : BOOL;
END_VAR
//Implementation
i := 42;
//FB.ACT
i:= 0;//FB.METH Declaration METHOD METH : BOOL VAR_INPUT c : BOOL; END_VAR //Implementation METH := c; i := 1;
//FB.SecondMETH Declaration METHOD SecondMETH : INT VAR_INPUT END_VAR //Implementation SecondMETH := SEL(c,3,4);
Coppie di oggetti senza connessione (4 coppie):
FB,FB.ACTFB,FB.METHFB.ACT,FB.SecondMETHFB.METH,FB.SecondMETH
Coppie di oggetti con connessione (2 coppie):
FB,FB.SecondMETH(entrambi usanoc)FB.ACT,FB.METH(entrambi usanoi)
FB |
|
|
| |
|---|---|---|---|---|
|
| 0 | 0 | . |
| 0 |
| . | . |
| 0 | . | . | . |
| - | . | . | . |
Metrica: Numero di rami SFC
Categorie: Testabilità, Manutenibilità
Numero di rami alternativi e paralleli di una POU del linguaggio di implementazione SFC (sequential function chart).
![]() |
Il frammento di codice sopra in SFC ha 4 rami: 3 rami alternativi e 1 ramo parallelo
Metrica: Numero di passaggi SFC
Categoria: Manutenibilità
Numero di passi in una POU in SFC (diagramma funzionale sequenziale)
Vengono contati solo i passi contenuti nella POU programmata in SFC. Non vengono conteggiati i passaggi presenti nelle implementazioni di azioni o transizioni richiamate nelle POU.
![]() |
Lo snippet di codice in SFC ha 10 passaggi.

