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_VAR
La 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; // +1
El 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_VAR
El bloque de funciones tiene 2 variables de salida: i
y r
METHOD METH : BOOL VAR_INPUT j : INT; l : LREAL; END_VAR
El 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_VAR
El 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; //+1
El 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_VAR
Implementació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_IF
El 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_CASE
El 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_FOR
El 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_REPEAT
El 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_IF
El 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
FUN
yCUBE
, 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.METH
usosFUN
yCUBE
, lo que resulta en un RFC de 2.El bloque de funciones
FB1
se llamaMETH
yFUN
, 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 call
La extensión de un bloque de funciones no aumenta el acoplamiento entre objetos.
i_fb3
se instancia en la implementación deFB_Base
y pasó a FB_Child (EXTENDS
). la llamada enFB_Child
no aumenta el acoplamiento entre los objetos.La CBO de
FB_Child
es 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:
c
yk
no se utilizan y, por lo tanto, no cuentan como "variables utilizadas".La asignación
k : INT := GVL.m
no 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.ACT
FB
,FB.METH
FB.ACT
,FB.SecondMETH
FB.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.