Skip to main content

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.

ejemplo 132. Ejemplo
//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

ejemplo 133. Ejemplo
//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).

ejemplo 134. Ejemplo
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

ejemplo 135. Ejemplo
//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.

ejemplo 136. Ejemplo
//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.

ejemplo 137. Ejemplo
//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.

ejemplo 138. Ejemplos
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.

ejemplo 139. Ejemplos
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.

ejemplo 140. Ejemplo
//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.

ejemplo 141. Ejemplo

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.

ejemplo 142. Ejemplo: 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.



ejemplo 143. Ejemplo: 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.



ejemplo 144. Ejemplo: Declaración de bucle
// 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.



ejemplo 145. Ejemplo: Otras declaraciones

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.

ejemplo 146. Ejemplo: Control de flujo

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.



ejemplo 147. Ejemplo: Anidamiento del flujo de control

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.



ejemplo 148. Ejemplo: Expresión booleana

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.



ejemplo 149. Ejemplo: Otras declaraciones con incremento

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

ejemplo 150. Ejemplo
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.

ejemplo 151. Ejemplo
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

ejemplo 152. Ejemplo
//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 y CUBE, 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 usos FUN y CUBE, lo que resulta en un RFC de 2.

  • El bloque de funciones FB1 se llama METH y FUN, 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.

ejemplo 153. Ejemplo
// 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 de FB_Base y pasó a FB_Child (EXTENDS). la llamada en FB_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.

ejemplo 154. Ejemplo
//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 y k 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>)

ejemplo 155. Ejemplo
//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 usan c)

  • FB.ACT , FB.METH (ambos usan i)

tabla 4. La tabla muestra qué variables conectan qué objetos del FB:

pensión completa

FB.ACT

FB.METH

FB.SecondMETH

FB.SecondMETH

c

0

0

.

FB.METH

0

i

.

.

FB.ACT

0

.

.

.

FB

-

.

.

.





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)

ejemplo 156. Ejemplo
_san_img_metric_sfc_branch_count.png

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.

ejemplo 157. Ejemplo
_san_img_metric_sfc_steps_count.png

El fragmento de código en SFC tiene 10 pasos.