Métrique
Description détaillée des métriques fournies par CODESYS Static Analysis
Astuce
Le Taille du code, Taille variable, Taille de la pile, et Nombre d'appels les métriques ne sont signalées que pour les POU des bibliothèques intégrées au projet.
Métrique : Taille du code (nombre d'octets)
Catégories : Informatif, Efficacité
Nombre d'octets qu'un bloc fonctionnel contribue au code d'application
Le numéro dépend également du générateur de code. Par exemple, le générateur de code pour les processeurs ARM génère généralement plus d'octets que le générateur de code pour les processeurs x86.
Métrique : Taille variable (nombre d'octets)
Catégories: Informatif, Efficacité
Taille de la mémoire statique utilisée par l'objet
Pour les blocs fonction, il s'agit de la taille utilisée pour une instance du bloc fonction (qui peut inclure des espaces mémoire, en fonction de l'alignement de la mémoire). Pour les programmes, les fonctions et les listes de variables globales, il s'agit de la somme de la taille de toutes les variables statiques.
Exemple
FUNCTION FUN1 : INT VAR_INPUT a,b : INT; END_VAR VAR c,d : INT; END_VAR VAR_STAT f,g,h : INT; END_VAR
La fonction possède 3 variables statiques de type INT
(f
, g
, et h
), dont chacun nécessite 2 octets de mémoire. Par conséquent, FUN1
a une taille variable de 6 octets.
Métrique : Taille de la pile (nombre d'octets)
Catégories: Informatif, Efficacité, Fiabilité
Nombre d'octets nécessaires à l'appel d'une fonction ou d'un bloc fonctionnel
Les variables d'entrée et les variables de sortie sont alignées sur la mémoire. Cela peut créer un écart entre ces variables et les variables locales. Cet écart est compté.
Les valeurs de retour des fonctions appelées qui ne rentrent pas dans un registre sont placées sur la pile. La plus grande de ces valeurs détermine la mémoire supplémentaire allouée, qui compte également. Les fonctions ou blocs fonctionnels appelés dans les POU concernés ont leur propre cadre de pile. Par conséquent, la mémoire de ces appels ne compte pas.
Selon le générateur de code utilisé, les résultats intermédiaires des calculs utilisent également la pile. Ces résultats ne sont pas comptabilisés.
//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;
Hypothèse : Pour le calcul, supposons un CODESYS Control Win qui utilise le générateur de code x86.
L'exemple ci-dessus a une taille d'appelant de 8 octets : 4 octets pour les deux INT inputs
et 4 octets pour la valeur de retour. L'appareil a un alignement de pile de 4 octets, de sorte qu'il y a un espace de 2 octets. La taille de l'appelant est de 8 octets : trois variables locales de 2 octets chacune plus l'espace de 2 octets pour l'alignement de la pile. En conséquence, la taille totale de la pile de FUN1
fait 16 octets.
VAR_STAT
n'est pas stocké sur la pile et n'augmente donc pas la taille de la pile d'un POU.
Métrique : Nombre d'appels (Appels)
Catégorie: Informatif
Nombre d'appels du POU sous Unité de programme
//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;
Si PLC_PRG
est appelé dans une tâche, alors cet appel est également compté.
FB1
a exactement un appel (en PLC_PRG
).
METH
a deux appels, tous deux en FB1
.
Métrique : Nombre d'appels depuis des tâches (Tâches)
Catégories : Maintenabilité, Fiabilité
Nombre de tâches (Tâches) où le POU spécifié sous Unité de programme est appelé
Dans le cas des blocs fonctionnels, le nombre de tâches est compté dans lequel le bloc fonctionnel lui-même ou n'importe quel bloc fonctionnel dans l'arbre d'héritage du bloc fonctionnel est appelé.
Pour les méthodes et les actions, le nombre de tâches dans lesquelles le bloc fonctionnel (parent) est appelé est affiché.
FUNCTION_BLOCK FB //...
FUNCTION_BLOCK FB2 EXTENDS FB //...
FUNCTION_BLOCK FB3 EXTENDS FB2 //...
Chaque bloc fonction est appelé individuellement PROGRAM
. Chaque PROGRAM
a sa propre tâche.
Le Tâches appelées la métrique renvoie en 1 pour FB3
et 2 pour FB2
parce que les appels de FB3
et FB2
sont comptés. La métrique donne 3 pour FB
parce que dans ce cas, les appels de FB3
, FB2
, et FB
sont comptés.
Métrique : Nombre de variables globales utilisées (globales)
Catégories: Maintenabilité, Réutilisabilité
Nombre de variables globales utilisées dans le POU sous Unité de programme
//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;
Le PRG
le programme utilise 3 variables de GVL
: gvla
, gvlb
, et gvlc
.
Métrique : Nombre d'accès directs aux adresses (IO)
Catégories : Réutilisabilité, Maintenabilité
Nombre d'accès à l'adresse directe (IO) dans la mise en œuvre de l'objet.
//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; // +1
L'exemple dispose de 5 accès directs aux adresses.
Métrique : Nombre de variables locales (Locals)
Catégories: Informatif, Efficacité
Nombre de variables déclarées dans le VAR
zone du POU. Les variables héritées ne sont pas comptées.
//Declaration FUNCTION_BLOCK FB VAR_INPUT END_VAR VAR_OUTPUT END_VAR VAR i,j,k,l : INT; m,n,o : BOOL; END_VAR
Dans le bloc fonction, 7 variables locales sont déclarées.
Métrique : Nombre de variables d'entrée (entrées)
Catégories : Maintenabilité, Réutilisabilité
Limite supérieure par défaut pour le SA0166 règle : 10
Nombre de variables déclarées dans VAR_INPUT
de l’unité de programme. Les variables d'entrée héritées ne sont pas comptées.
FUNCTION_BLOCK FB VAR_INPUT i : INT; r : REAL; END_VAR
Dans le bloc fonction, 2 variables d'entrée sont déclarées : i
et r
.
METHOD METH : BOOL VAR_INPUT j : INT; l : LREAL; END_VAR
La méthode a 2 entrées : j
et l
Métrique : Nombre de variables de sortie (sorties)
Catégories : Maintenabilité, Réutilisabilité
Limite supérieure par défaut pour le SA0166 règle : 10
Nombre de variables dans VAR_OUTPUT
de l'unité de programme
Dans le cas des blocs fonction, il s'agit du nombre de variables de sortie personnalisées (VAR_OUTPUT
). Dans le cas des méthodes et des fonctions, il s'agit du nombre de variables de sortie personnalisées plus une si elles ont une valeur de retour. La valeur de retour est également prise en compte. Les variables de sortie héritées ne sont pas comptées.
Un nombre élevé de variables de sortie indique une violation du principe de responsabilité unique.
FUNCTION_BLOCK FB VAR_OUTPUT i : INT; // +1 output r : REAL; // +1 output END_VAR
Le bloc fonction possède 2 variables de sortie : i
et r
METHOD METH : BOOL VAR_INPUT j : INT; l : LREAL; END_VAR
La méthode a 3 sorties : METH
, j
, et l
METHOD METH1 // +0 outputs (no return type) VAR_OUTPUT ar : ARRAY[0..10] OF INT; // +1 output l : LREAL; // +1 output END_VAR
Le METH1
La méthode a 2 sorties : ar
et i
Métrique : NOS – Nombre d’instructions
Catégorie: Informatif
Nombre d'instructions dans l'implémentation d'un bloc fonctionnel, d'une fonction ou d'une méthode
Les instructions dans la déclaration, les instructions vides ou les pragmas ne sont pas comptés.
//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; //+1
L'exemple comporte 6 instructions.
Métrique : Pourcentage de commentaires
Catégorie : Maintenabilité
Pourcentage de commentaires dans le code source
Ce nombre est calculé selon la formule suivante :
Pourcentage = 100 * <caractères dans les commentaires> / <somme des caractères dans le code source et des caractères dans les commentaires>
Plusieurs espaces consécutifs dans le code source sont comptés comme un seul espace, ce qui évite une pondération élevée du code source indenté. Pour les objets vides (pas de code source ni de commentaires), un pourcentage de 0 est renvoyé.
Partie déclaration :
FUNCTION_BLOCK FB //comments in the declaration are counted, as well VAR_TEMP hugo : INT; END_VAR
Mise en œuvre:
hugo := hugo + 1; //Declaration: 40 letters non comment; 50 letters comment //Implementation: 13 letters non comment; 152 letters comment // 100 * 202 / 255 -> 79% comments
Le calcul du pourcentage 100 * 202 / 255 renvoie 79%.
Métrique : Complexité (McCabe)
Catégorie : Testabilité
Limite supérieure recommandée : 10
La complexité cyclomatique selon McCabe est une mesure de la lisibilité et de la testabilité du code source. Il est calculé en comptant le nombre de branches binaires dans le flux de contrôle du POU. Cependant, la complexité cyclomatique pénalise le branchement élevé, car le branchement élevé augmente le nombre de cas de test requis pour une couverture de test élevée.
IF
déclaration// 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_IF
L'extrait de code a une complexité cyclomatique de 4.
CASE
déclaration// 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_CASE
L'extrait de code a une complexité cyclomatique de 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_FOR
L'extrait de code a une complexité cyclomatique de 4.
Les déclarations suivantes augmentent également la complexité cyclomatique :
//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';
L'extrait de code a une complexité cyclomatique de 3.
Métrique : complexité cognitive
Catégorie : Maintenabilité
Limite supérieure par défaut pour la règle SA0178 correspondante : 20
La complexité cognitive est une mesure de la lisibilité et de l'intelligibilité du code source introduite par Sonarsource™ en 2016. Cependant, elle pénalise une imbrication importante du flux de contrôle et des expressions booléennes complexes. La complexité cognitive est calculée uniquement pour les implémentations de textes structurés.
Les exemples suivants montrent comment la complexité cognitive est calculée.
Astuce
Le Afficher la complexité cognitive pour l'éditeur actuel La commande peut être utilisée pour afficher en plus les incréments du texte structuré.
Les instructions qui manipulent le flux de contrôle augmentent la complexité cognitive de 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_REPEAT
L'extrait de code a une complexité cognitive de 4.
Lors de l'imbrication du flux de contrôle, un incrément de 1 est ajouté pour chaque niveau d'imbrication.
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_IF
L'extrait de code a une complexité cognitive de 8.
Les expressions booléennes jouant un rôle majeur dans la compréhension du code source, elles sont également prises en compte lors du calcul de la complexité cognitive.
Comprendre les expressions booléennes associées au même opérateur booléen n'est pas aussi difficile que comprendre une expression booléenne contenant des opérateurs booléens alternés. Par conséquent, toute chaîne d’opérateurs booléens identiques dans une expression augmente la complexité cognitive.
b := b1; //+0: a simple expression, containing no operators, has no increment
L'expression simple sans opérateur a un incrément de 0.
b := b1 AND b2; //+1: one chain of AND operators
L'expression avec un AND
le lien a un incrément de 1.
b := b1 AND b2 AND b3; //+1: one more AND, but the number of chains of operators does not change
L'expression a un de plus AND
. Mais comme il s'agit du même opérateur, le numéro de la chaîne formée avec des opérateurs identiques ne change pas.
b := b1 AND b2 OR b3; //+2: one chain of AND operators and one chain of OR operators
L'expression a une chaîne de AND
opérateurs et une chaîne de OR
les opérateurs. Cela donne un incrément de 2.
b := b1 AND b2 OR b3 AND b4 AND b5; //+3
L'extrait de code a un incrément de 3.
b := b1 AND NOT b2 AND b3; //+1: the unary NOT operator is not considered in the cognitive complexity
L'opérateur unaire NOT
n’est pas considéré dans la complexité cognitive.
Le texte structuré contient des instructions et expressions supplémentaires qui modifient le flux de contrôle.
Les énoncés suivants sont pénalisés par un accroissement de complexité cognitive :
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
et RETURN
les déclarations n’augmentent pas la complexité cognitive.
Métrique : DIT – Profondeur de l’arbre d’héritage
Catégorie : Maintenabilité
Nombre d'héritages jusqu'à ce qu'un bloc fonction soit atteint qui n'étend aucun autre bloc fonction
FUNCTION_BLOCK MyBaseFB // ... FUNCTION_BLOCK AChildFB EXTENDS MyBaseFB // ... FUNCTION_BLOCK AGrandChildFB EXTENDS AChildFB // ...
MyBaseFB
a un DIT de 0 car il s’agit lui-même d’un bloc fonction qui n’étend aucun autre bloc fonction.
Pour AChildFB
, le DIT est 1 car une étape est nécessaire pour arriver à MyBaseFB
.
AGrandChildFB
a un DIT de 2 : une étape est nécessaire pour AChildFB
et un autre à MyBaseFB
.
Métrique : NOC – Nombre d’enfants
Catégories : Réutilisabilité, Maintenabilité
Nombre de blocs fonctionnels qui étendent le bloc fonctionnel de base donné. Les blocs fonctionnels qui étendent indirectement un bloc fonctionnel de base ne sont pas pris en compte.
FUNCTION_BLOCK MyBaseFB // ... FUNCTION_BLOCK AChildFB EXTENDS MyBaseFB // ... FUNCTION_BLOCK AGrandChildFB EXTENDS AChildFB // ...
MyBaseFB
n'a qu'un (1) objet enfant : AChildFB
, qui à son tour a un objet enfant, AGrandChildFB
. AGrandChildFB
n'a pas d'objets enfants.
Métriques : RFC – Réponse pour la classe
Catégories : Maintenabilité, Réutilisabilité
Nombre de POU, méthodes ou actions différentes qui sont appelées et génèrent donc une réponse du POU spécifié sous Unité de programme
//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;
Commençant par
FUN
etCUBE
, ces fonctions ont un RFC de 0 car aucune d'entre elles n'appelle d'autres fonctions, blocs fonctionnels ou méthodes pour leurs calculs.FB1.METH
les usagesFUN
etCUBE
, ce qui donne un RFC de 2.Le bloc fonctionnel
FB1
appelle lui-mêmeMETH
etFUN
, ce qui augmente son RFC de 2.Pour FB1, sa méthode METH doit également être prise en compte. METH utilise FUN et CUBE. FUN a déjà été ajouté à la RFC. Par conséquent, seule l’utilisation de CUBE dans METH augmente le RFC pour FB1 à 3
Métrique : CBO – Couplage entre objets
Catégories : Maintenabilité, Réutilisabilité
Limite supérieure par défaut pour la règle SA0179 correspondante : 30
Nombre d'autres blocs fonctionnels instanciés et utilisés dans un bloc fonctionnel
Un bloc fonctionnel avec un couplage élevé entre les objets est susceptible d'être impliqué dans de nombreuses tâches différentes et viole donc le principe de responsabilité unique.
// 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 call
L'extension d'un bloc fonction n'augmente pas le couplage entre objets.
i_fb3
est instancié dans la mise en œuvre deFB_Base
et transmis à FB_Child (EXTENDS
). L'appelFB_Child
n'augmente pas le couplage entre les objets.Le CBO de
FB_Child
est 2.
Métrique : Complexité de référence (Elshof)
Catégories : Efficacité, Maintenabilité, Réutilisabilité
Complexité du flux de données d'un POU
La complexité du référencement est calculée selon la formule suivante :
<nombre de variables utilisées> / <nombre d'accès aux variables>
Seuls les accès aux variables dans la partie implémentation du POU sont pris en compte.
//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)
Référencement de la complexité dans les résultats de l'extrait de code :
6 nombre de variables utilisées / 7 nombre d'accès aux variables = 0,85
Prudence:
c
etk
ne sont pas utilisées et ne comptent donc pas comme « variables utilisées ».La tâche
k : INT := GVL.m
n'est pas compté car il fait partie de la déclaration du programme.
Métrique : Manque de cohésion des méthodes – LCOM
Manque de cohésion des méthodes – LCOM
Catégories : Maintenabilité, Réutilisabilité
La cohésion entre les blocs fonction, leurs actions, transitions et méthodes décrit s'ils accèdent ou non aux mêmes variables.
Le manque de cohésion des méthodes décrit la force avec laquelle les objets d’un bloc fonctionnel sont connectés les uns aux autres. Plus le manque de cohésion est faible, plus la connexion entre les objets est forte.
Les blocs fonctionnels présentant un manque élevé de cohésion sont susceptibles d'être impliqués dans de nombreuses tâches différentes et violent donc le principe de responsabilité unique.
La métrique est calculée selon la formule suivante :
MAX(0, <nombre de paires d'objets sans cohésion> - <nombre de paires d'objets avec cohésion>)
//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);
Paires d'objets sans connexion (4 paires) :
FB,
FB.ACT
FB
,FB.METH
FB.ACT
,FB.SecondMETH
FB.METH
,FB.SecondMETH
Paires d'objets avec connexion (2 paires) :
FB
,FB.SecondMETH
(les deux utilisentc
)FB.ACT
,FB.METH
(les deux utilisenti
)
|
|
| ||
---|---|---|---|---|
|
| 0 | 0 | . |
| 0 |
| . | . |
| 0 | . | . | . |
| - | . | . | . |
Métrique : Nombre de succursales SFC
Catégories : Testabilité, Maintenabilité
Nombre de branches alternatives et parallèles d'un POU du langage d'implémentation SFC (sequential function chart)
![]() |
L'extrait de code ci-dessus dans SFC comporte 4 branches : 3 branches alternatives et 1 branche parallèle.
Métrique : Nombre d'étapes SFC
Catégorie : Maintenabilité
Nombre d'étapes dans un POU dans SFC (diagramme de fonctions séquentielles)
Seules les étapes contenues dans le POU programmé dans SFC sont comptées. Ne sont pas comptées les étapes qui se trouvent dans la mise en œuvre d'actions ou de transitions appelées dans les POU.
![]() |
L'extrait de code dans SFC comporte 10 étapes.