Métrica
Descripción detallada de las métricas proporcionada por CODESYS Static Analysis
Sugerencia
El Tamaño del código, tamaño variable, Tamaño de la pila, y Número de llamadas Las métricas se informan solo para las POU de bibliotecas que están integradas en el proyecto.
Métrica: Tamaño del código (número de bytes)
Categorías: Informativo, Eficiencia
Número de bytes que un bloque de funciones aporta al código de la aplicación
El número también depende del generador de código. Por ejemplo, el generador de código para procesadores ARM generalmente genera más bytes que el generador de código para procesadores x86.
Métrica: Tamaño variable (número de bytes)
Categorías: Informativo, Eficiencia
Tamaño de la memoria estática que utiliza el objeto.
Para los bloques de funciones, este es el tamaño que se utiliza para una instancia del bloque de funciones (que puede incluir espacios de memoria, según la alineación de la memoria). Para programas, funciones y listas de variables globales, esta es la suma del tamaño de todas las variables estáticas.
Ejemplo
FUNCTION FUN1 : INT
VAR_INPUT
a,b : INT;
END_VAR
VAR
c,d : INT;
END_VAR
VAR_STAT
f,g,h : INT;
END_VARLa función tiene 3 variables estáticas de tipo INT (f, g, y h), cada uno de los cuales requiere 2 bytes de memoria. Como resultado, FUN1 tiene un tamaño variable de 6 bytes.
Métrica: Tamaño de pila (número de bytes)
Categorías: Informativo, Eficiencia, Confiabilidad
Número de bytes necesarios para llamar una función o un bloque de funciones
Las variables de entrada y las variables de salida están alineadas con la memoria. Esto puede crear una brecha entre estas variables y las variables locales. Esta brecha se cuenta.
Los valores de retorno de las funciones llamadas que no caben en un registro se colocan en la pila. El mayor de estos valores determina la memoria adicional asignada, que también cuenta. Las funciones o bloques de funciones que se llaman dentro de las POU consideradas tienen su propio marco de pila. Por tanto, la memoria para este tipo de llamadas no cuenta.
Dependiendo del generador de código utilizado, los resultados intermedios de los cálculos también utilizan la pila. Estos resultados no se cuentan.
//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;Supuesto: Para el cálculo, suponga un CODESYS Control Win que utiliza el generador de código x86.
El ejemplo anterior tiene un tamaño de llamada de 8 bytes: 4 bytes para los dos INT inputs y 4 bytes para el valor de retorno. El dispositivo tiene una alineación de pila de 4 bytes, por lo que hay un espacio de 2 bytes. El tamaño de la persona que llama es de 8 bytes: tres variables locales con 2 bytes cada una más el espacio de 2 bytes para la alineación de la pila. Como resultado, el tamaño total de la pila de FUN1 es de 16 bytes.
VAR_STAT no se almacena en la pila y, por lo tanto, no aumenta el tamaño de la pila de una POU.
Métrica: Número de llamadas (Llamadas)
Categoría: Informativo
Número de llamadas de la POU bajo Unidad de programa
//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 se llama en una tarea, entonces esta llamada también se cuenta.
FB1 tiene exactamente una llamada (en PLC_PRG).
METH tiene dos llamadas, ambas en FB1.
Métrica: Número de llamadas de tareas (Tareas)
Categorías: Mantenibilidad, Fiabilidad
Número de tareas (Tareas) donde la POU especificada en Unidad de programa se llama
En el caso de los bloques de funciones, se cuenta el número de tareas en las que se llama al propio bloque de funciones o a cualquier bloque de funciones del árbol de herencia del bloque de funciones.
En el caso de métodos y acciones se muestra el número de tareas en las que se llama al bloque de funciones (principal).
FUNCTION_BLOCK FB //...
FUNCTION_BLOCK FB2 EXTENDS FB //...
FUNCTION_BLOCK FB3 EXTENDS FB2 //...
Cada bloque de funciones se llama a su manera. PROGRAM. Cada PROGRAM tiene su propia tarea.
El Llamado en tareas rendimientos métricos en 1 para FB3 y 2 para FB2 porque las llamadas de FB3 y FB2 se cuentan. La métrica da como resultado 3 para FB porque en este caso las llamadas de FB3, FB2, y FB se cuentan.
Métrica: Número de variables globales utilizadas (Globales)
Categorías: Mantenibilidad, Reutilización
Número de variables globales utilizadas en la POU bajo Unidad de programa
//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;El PRG El programa utiliza 3 variables de GVL: gvla, gvlb, y gvlc.
Métrica: Número de accesos a direcciones directas (IO)
Categorías: Reutilizabilidad, Mantenibilidad
Número de accesos a direcciones directas (IO) en la implementación del objeto.
//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; // +1El ejemplo tiene 5 accesos directos a direcciones.
Métrica: Número de variables locales (Locales)
Categorías: Informativo, Eficiencia
Número de variables declaradas en el VAR área de la POU. Las variables heredadas no se cuentan.
//Declaration
FUNCTION_BLOCK FB
VAR_INPUT
END_VAR
VAR_OUTPUT
END_VAR
VAR
i,j,k,l : INT;
m,n,o : BOOL;
END_VAR
En el bloque de funciones se declaran 7 variables locales.
Métrica: Número de variables de entrada (Entradas)
Categorías: Mantenibilidad, Reutilización
Límite superior predeterminado para el correspondiente SA0166 regla: 10
Número de variables declaradas en VAR_INPUT de la unidad del programa. Las variables de entrada heredadas no se cuentan.
FUNCTION_BLOCK FB
VAR_INPUT
i : INT;
r : REAL;
END_VAR
En el bloque de funciones se declaran 2 variables de entrada: i y r.
METHOD METH : BOOL
VAR_INPUT
j : INT;
l : LREAL;
END_VAR
El método tiene 2 entradas: j y l
Métrica: Número de variables de salida (Salidas)
Categorías: Mantenibilidad, Reutilización
Límite superior predeterminado para el correspondiente SA0166 regla: 10
Número de variables en VAR_OUTPUT de la unidad de programa
En el caso de bloques de funciones, este es el número de variables de salida personalizadas (VAR_OUTPUT). En el caso de métodos y funciones, este es el número de variables de salida personalizadas más uno si tienen un valor de retorno. También se cuenta el valor de retorno. Las variables de salida heredadas no se cuentan.
Un número elevado de variables de salida es un indicio de una violación del principio de responsabilidad única.
FUNCTION_BLOCK FB
VAR_OUTPUT
i : INT; // +1 output
r : REAL; // +1 output
END_VAREl bloque de funciones tiene 2 variables de salida: i y r
METHOD METH : BOOL
VAR_INPUT
j : INT;
l : LREAL;
END_VAREl método tiene 3 salidas: METH, j, y l
METHOD METH1 // +0 outputs (no return type)
VAR_OUTPUT
ar : ARRAY[0..10] OF INT; // +1 output
l : LREAL; // +1 output
END_VAREl METH1 El método tiene 2 salidas: ar y i
Métrica: NOS – Número de declaraciones
Categoría: Informativo
Número de declaraciones en la implementación de un bloque de funciones, función o método
Las declaraciones en la declaración, las declaraciones vacías o los pragmas no se cuentan.
//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; //+1El ejemplo tiene 6 declaraciones.
Métrica: Porcentaje de comentarios
Categoría: Mantenibilidad
Porcentaje de comentarios en el código fuente.
Este número se calcula según la siguiente fórmula:
Porcentaje = 100 * <caracteres en comentarios> / <suma de caracteres en código fuente y caracteres en comentarios>
Varios espacios consecutivos en el código fuente se cuentan como un espacio, lo que evita una gran ponderación del código fuente sangrado. Para objetos vacíos (sin código fuente ni comentarios), se devuelve un porcentaje de 0.
Parte de la declaración:
FUNCTION_BLOCK FB //comments in the declaration are counted, as well
VAR_TEMP
hugo : INT;
END_VARImplementación:
hugo := hugo + 1; //Declaration: 40 letters non comment; 50 letters comment //Implementation: 13 letters non comment; 152 letters comment // 100 * 202 / 255 -> 79% comments
El cálculo del porcentaje 100 * 202/255 arroja 79%.
Métrica: Complejidad (McCabe)
Categoría: Comprobabilidad
Límite superior recomendado: 10
La complejidad ciclomática según McCabe es una medida de la legibilidad y comprobabilidad del código fuente. Se calcula contando el número de ramas binarias en el flujo de control de la POU. Sin embargo, la complejidad ciclomática penaliza la alta ramificación porque la alta ramificación aumenta la cantidad de casos de prueba necesarios para una alta cobertura de prueba.
IF declaración// 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_IFEl fragmento de código tiene una complejidad ciclomática de 4.
CASE declaración// 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_CASEEl fragmento de código tiene una complejidad ciclomática 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_FOREl fragmento de código tiene una complejidad ciclomática de 4.
Las siguientes declaraciones también aumentan la complejidad ciclomática:
//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';
El fragmento de código tiene una complejidad ciclomática de 3.
Métrica: Complejidad Cognitiva
Categoría: Mantenibilidad
Límite superior predeterminado para la regla SA0178 correspondiente: 20
La complejidad cognitiva es una medida de la legibilidad y comprensibilidad del código fuente introducido por Sonarsource™ en 2016. Sin embargo, penaliza el anidamiento intenso del flujo de control y las expresiones booleanas complejas. La complejidad cognitiva se calcula sólo para implementaciones de texto estructurado.
Los siguientes ejemplos muestran cómo se calcula la complejidad cognitiva.
Sugerencia
El Mostrar complejidad cognitiva para el editor actual El comando se puede utilizar para mostrar adicionalmente los incrementos del texto estructurado.
Las declaraciones que manipulan el flujo de control aumentan la complejidad cognitiva en 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_REPEATEl fragmento de código tiene una complejidad cognitiva de 4.
Al anidar el flujo de control, se agrega un incremento de 1 para cada nivel de anidamiento.
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_IFEl fragmento de código tiene una complejidad cognitiva de 8.
Dado que las expresiones booleanas desempeñan un papel importante en la comprensión del código fuente, también se tienen en cuenta al calcular la complejidad cognitiva.
Comprender las expresiones booleanas asociadas con el mismo operador booleano no es tan difícil como comprender una expresión booleana que contiene operadores booleanos alternos. Por tanto, cualquier cadena de operadores booleanos idénticos en una expresión aumenta la complejidad cognitiva.
b := b1; //+0: a simple expression, containing no operators, has no increment
La expresión simple sin operador tiene un incremento de 0.
b := b1 AND b2; //+1: one chain of AND operators
La expresión con una AND El enlace tiene un incremento de 1.
b := b1 AND b2 AND b3; //+1: one more AND, but the number of chains of operators does not change
La expresión tiene una más. AND. Pero al ser el mismo operador, el número de la cadena formada con operadores idénticos no cambia.
b := b1 AND b2 OR b3; //+2: one chain of AND operators and one chain of OR operators
La expresión tiene una cadena de AND operadores y una cadena de OR operadores. Esto da como resultado un incremento de 2.
b := b1 AND b2 OR b3 AND b4 AND b5; //+3
El fragmento de código tiene un incremento de 3.
b := b1 AND NOT b2 AND b3; //+1: the unary NOT operator is not considered in the cognitive complexity
El operador unario NOT no se considera en la complejidad cognitiva.
El texto estructurado tiene declaraciones y expresiones adicionales que cambian el flujo de control.
Las siguientes afirmaciones se penalizan con un incremento de complejidad 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 y RETURN Las declaraciones no aumentan la complejidad cognitiva.
Métrica: DIT – Profundidad del árbol de herencia
Categoría: Mantenibilidad
Número de herencias hasta alcanzar un bloque de funciones que no extiende ningún otro bloque de funciones
FUNCTION_BLOCK MyBaseFB // ... FUNCTION_BLOCK AChildFB EXTENDS MyBaseFB // ... FUNCTION_BLOCK AGrandChildFB EXTENDS AChildFB // ...
MyBaseFB tiene un DIT de 0 porque es en sí mismo un bloque de funciones que no extiende ningún otro bloque de funciones.
Para AChildFB, el DIT es 1 porque se requiere un paso para llegar a MyBaseFB.
AGrandChildFB tiene un DIT de 2: se necesita un paso para AChildFB y otro a MyBaseFB.
Métrica: NOC – Número de niños
Categorías: Reutilizabilidad, Mantenibilidad
Número de bloques de funciones que amplían el bloque de funciones básico dado. Los bloques de funciones que amplían indirectamente un bloque de funciones básico no se cuentan.
FUNCTION_BLOCK MyBaseFB // ... FUNCTION_BLOCK AChildFB EXTENDS MyBaseFB // ... FUNCTION_BLOCK AGrandChildFB EXTENDS AChildFB // ...
MyBaseFB tiene solo un (1) objeto hijo: AChildFB, que a su vez tiene un objeto secundario, AGrandChildFB. AGrandChildFB no tiene objetos secundarios.
Métricas: RFC – Respuesta para clase
Categorías: Mantenibilidad, Reutilización
Número de POU, métodos o acciones diferentes que se llaman y, por lo tanto, generan una respuesta de la POU especificada en Unidad de programa
//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;Empezando con
FUNyCUBE, estas funciones tienen un RFC de 0 porque ninguna de ellas llama a otras funciones, bloques de funciones o métodos para sus cálculos.FB1.METHusosFUNyCUBE, lo que resulta en un RFC de 2.El bloque de funciones
FB1se llamaMETHyFUN, lo que aumenta su RFC en 2.Para FB1 también hay que tener en cuenta su método METH. METH usa FUN y CUBE. FUN ya se ha agregado al RFC. Por lo tanto, sólo el uso de CUBE en METH aumenta el RFC para FB1 a 3
Métrica: CBO – Acoplamiento entre objetos
Categorías: Mantenibilidad, Reutilización
Límite superior predeterminado para la regla SA0179 correspondiente: 30
Número de otros bloques de funciones de los que se crean instancias y se utilizan en un bloque de funciones
Es probable que un bloque de funciones con un alto acoplamiento entre objetos participe en muchas tareas diferentes y, por lo tanto, viola el principio de responsabilidad única.
// 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 callLa extensión de un bloque de funciones no aumenta el acoplamiento entre objetos.
i_fb3se instancia en la implementación deFB_Basey pasó a FB_Child (EXTENDS). la llamada enFB_Childno aumenta el acoplamiento entre los objetos.La CBO de
FB_Childes 2.
Métrica: Complejidad de referencia (Elshof)
Categorías: Eficiencia, Mantenibilidad, Reutilización
Complejidad del flujo de datos de una POU
La complejidad de referencia se calcula según la siguiente fórmula:
<número de variables utilizadas> / <número de accesos a variables>
Sólo se consideran los accesos a variables en la parte de implementación de la 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)Complejidad de referencia en los resultados del fragmento de código:
6 número de variables utilizadas / 7 número de accesos variables = 0,85
Precaución:
cykno se utilizan y, por lo tanto, no cuentan como "variables utilizadas".La asignación
k : INT := GVL.mno se cuenta porque es parte de la declaración del programa.
Métrica: Falta de Cohesión de Métodos – LCOM
Falta de cohesión de métodos – LCOM
Categorías: Mantenibilidad, Reutilización
La cohesión entre bloques de funciones, sus acciones, transiciones y métodos describe si acceden o no a las mismas variables.
La falta de cohesión de los métodos describe cuán fuertemente están conectados entre sí los objetos de un bloque de funciones. Cuanto menor es la falta de cohesión, más fuerte es la conexión entre los objetos.
Es probable que los bloques de funciones con una gran falta de cohesión participen en muchas tareas diferentes y, por lo tanto, violen el principio de responsabilidad única.
La métrica se calcula según la siguiente fórmula:
MAX(0, <número de pares de objetos sin cohesión> - <número de pares de objetos con cohesión>)
//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);
Pares de objetos sin conexión (4 pares):
FB,FB.ACTFB,FB.METHFB.ACT,FB.SecondMETHFB.METH,FB.SecondMETH
Pares de objetos con conexión (2 pares):
FB,FB.SecondMETH(ambos usanc)FB.ACT,FB.METH(ambos usani)
pensión completa |
|
|
| |
|---|---|---|---|---|
|
| 0 | 0 | . |
| 0 |
| . | . |
| 0 | . | . | . |
| - | . | . | . |
Métrica: Número de sucursales de SFC
Categorías: Comprobabilidad, mantenibilidad
Número de ramas alternativas y paralelas de una POU del lenguaje de implementación SFC (diagrama de funciones secuenciales)
![]() |
El fragmento de código anterior en SFC tiene 4 ramas: 3 ramas alternativas y 1 rama paralela
Métrica: Número de pasos SFC
Categoría: Mantenibilidad
Número de pasos en una POU en SFC (gráfico de funciones secuenciales)
Sólo se cuentan los pasos que están contenidos en la POU programada en SFC. No se cuentan los pasos que se encuentran en las implementaciones de acciones o transiciones denominadas en POU.
![]() |
El fragmento de código en SFC tiene 10 pasos.

