Skip to main content

Metriken

Detaillierte Beschreibung der von CODESYS Static Analysis bereitgestellten Metriken

Tipp

Die Metriken Codegröße, Variablengröße, Stackgröße und Anzahl Aufrufe werden nur für Bausteine aus Bibliotheken ausgegeben, die im Projekt eingebunden sind.

Metrik: Codegröße (Anzahl Bytes)

Kategorie: Informativ, Effizienz

Anzahl Bytes, die ein Baustein zum Applikationscode beiträgt

Die Anzahl hängt auch vom Codegenerator ab. Beispielsweise erzeugt der Codegenerator für ARM-Prozessoren im Allgemeinen mehr Bytes als der Codegenerator für x86-Prozessoren.

Metrik: Variablengröße (Anzahl Bytes)

Kategorien: Informativ, Effizienz

Größe des statischen Speichers, der von dem Objekt verwendet wird

Bei Funktionsbausteinen ist dies die Größe, die für eine Instanz dieses Funktionsbausteins verwendet wird (und die je nach Speicher-Alignment auch Speicherlücken enthalten kann). Bei Programmen, Funktionen und globalen Variablenlisten ist dies die Summe der Größe aller statischen Variablen.

Beispiel
FUNCTION FUN1 : INT
VAR_INPUT
    a,b : INT;
END_VAR
VAR
    c,d : INT;
END_VAR
VAR_STAT
    f,g,h : INT;
END_VAR

Die Funktion hat 3 statische Variablen vom Typ INT (f, g und h), die jeweils 2 Byte Speicherplatz benötigen. FUN1 hat folglich eine Variablengröße von 6 Byte.

Metrik: Stackgröße (Anzahl Bytes)

Kategorien: Informativ, Effizienz, Verlässlichkeit

Anzahl der Bytes, die für den Aufruf einer Funktion oder eines Funktionsbausteins benötigt werden

Eingangsvariablen und Ausgangsvariablen werden am Speicher ausgerichtet. Dadurch kann eine Lücke zwischen diesen Variablen und den lokalen Variablen entstehen. Diese Lücke wird mitgezählt.

Rückgabewerte von aufgerufenen Funktionen, die nicht in ein Register passen, werden auf den Stack geschoben. Der größte dieser Werte bestimmt den zusätzlich zugewiesenen Speicher, der ebenfalls mit zählt. Funktionen oder Funktionsbausteine, die innerhalb der betrachteten POUs aufgerufen werden, haben ihren eigenen Stack-Frame. Deshalb zählt der Speicher für solche Aufrufe nicht mit.

Je nach verwendetem Codegenerator verwenden auch Zwischenergebnisse von Berechnungen den Stapel. Diese Ergebnisse werden nicht gezählt.

Beispiel 132. Beispiel
//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;

Annahme: Für die Berechnung wird eine CODESYS Control Win angenommen, die den x86-Codegenerator verwendet.

Das obige Beispiel hat eine Caller-Größe von 8 Bytes: 4 Byte für die beiden INT-Eingänge und 4 Byte für den Rückgabewert. Das Gerät hat ein Stack-Alignment von 4 Bytes, so dass eine Lücke von 2 Bytes entsteht. Die Caller-Größe beträgt 8 Bytes: 3 lokale Variablen mit je 2 Byte plus die 2 Byte Lücke für das Stack-Alignment. Die gesamte Stack-Größe von FUN1 beträgt somit 16 Bytes.

VAR_STAT wird nicht auf dem Stack gespeichert und erhöht daher nicht die Stack-Größe einer POU.



Metrik: Anzahl Aufrufe (Aufrufe)

Kategorie: Informativ

Anzahl der Anrufe des Programmierbausteins (POU) unter Programmiereinheit

Beispiel 133. Beispiel
//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;

Falls PLC_PRG in einer Task aufgerufen wird, wird dieser Aufruf auch mitgezählt.

FB1 hat genau einen Aufruf (in PLC_PRG).

METH hat zwei Aufrufe, beide in FB1.



Metrik: Anzahl Aufrufe aus Tasks (Tasks)

Kategorien: Wartbarkeit, Verlässlichkeit

Anzahl der Tasks (Tasks), in der die unter Programmeinheit angegebene POU aufgerufen wird

Bei Funktionsbausteinen wird die Anzahl der Tasks gezählt, in denen der Funktionsbaustein selbst oder ein beliebiger Funktionsbaustein im Vererbungsbaum des Funktionsbausteins aufgerufen wird.

Bei Methoden und Aktionen wird die Anzahl der Tasks angezeigt, in denen der (übergeordneten) Funktionsbaustein aufgerufen wird.

Beispiel 134. Beispiel
FUNCTION_BLOCK FB
//...
FUNCTION_BLOCK FB2 EXTENDS FB
//...
FUNCTION_BLOCK FB3 EXTENDS FB2
//...

Jeder Funktionsbaustein wird in einem eigenen PROGRAM aufgerufen. Jedes PROGRAM hat seine eigene Task.

Die Metrik Aufgerufen aus Tasks ergibt für FB3 1 und für FB2 2, denn die Aufrufe von FB3 und FB2 werden gezählt. Die Metrik ergibt für FB 3, denn in diesem Fall werden die Aufrufe von FB3, FB2 und FB gezählt.



Metrik: Anzahl verwendeter globaler Variablen (Globale)

Kategorien: Wartbarkeit, Wiederverwendbarkeit

Anzahl der verwendeten globalen Variable in der POU unter Programmeinheit

Beispiel 135. Beispiel
//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;

Das Programm PRG verwendet 3 Variablen aus GVL: gvla, gvlb und gvlc.



Metrik: Anzahl direkter Adresszugriffe (EAs)

Kategorien: Wiederverwendbarkeit, Wartbarkeit

Anzahl der direkten Adresszugriffe (EAs) in der Implementierung des Objekts.

Beispiel 136. Beispiel
//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

Das Beispiel hat 5 direkte Adresszugriffe.



Metrik: Anzahl lokaler Variablen (Lokale)

Kategorien: Informativ, Effizienz

Anzahl Variablen, die im VAR-Bereich der POU deklariert sind. Geerbte Variablen werden nicht gezählt.

Beispiel 137. Beispiel
//Declaration
FUNCTION_BLOCK FB
VAR_INPUT
END_VAR
VAR_OUTPUT
END_VAR
VAR
    i,j,k,l : INT;
    m,n,o : BOOL;
END_VAR

Im Funktionsbaustein sind 7 lokale Variablen deklariert.



Metrik: Anzahl Eingabevariablen (Eingänge)

Kategorien: Wartbarkeit, Wiederverwendbarkeit

Standardobergrenze für die zugehörige Regel SA0166: 10

Anzahl an Variablen, die in VAR_INPUT der Programmeinheit deklariert sind. Geerbte Eingangsvariablen werden nicht gezählt.

Beispiel 138. Beispiele
FUNCTION_BLOCK FB
VAR_INPUT
    i : INT;
    r : REAL;
END_VAR

Im Funktionsbaustein sind 2 Eingabevariablen deklariert: i und r.

METHOD METH : BOOL
VAR_INPUT
    j : INT;
    l : LREAL;
END_VAR

Die Methode hat 2 Eingänge: j und l



Metrik: Anzahl Ausgabevariablen (Ausgänge)

Kategorien: Wartbarkeit, Wiederverwendbarkeit

Standardobergrenze für die zugehörige Regel SA0166: 10

Anzahl an Variablen in VAR_OUTPUT der Programmeinheit

Bei Funktionsbausteinen ist dies die Anzahl der benutzerdefinierten Ausgangsvariablen (VAR_OUTPUT). Bei Methoden und Funktionen ist dies die Anzahl der benutzerdefinierten Ausgangsvariablen plus eins, wenn sie einen Rückgabewert haben. der Rückgabewert wird mit gezählt. Geerbte Ausgangsvariablen werden nicht gezählt.

Eine hohe Anzahl an Ausgabevariablen ist ein Zeichen für die Verletzung des Prinzips der eindeutigen Verantwortlichkeit.

Beispiel 139. Beispiele
FUNCTION_BLOCK FB
VAR_OUTPUT
    i : INT;    // +1 output
    r : REAL;   // +1 output
END_VAR

Der Funktionsbaustein hat 2 Ausgabevariablen: i und r

METHOD METH : BOOL
VAR_INPUT
    j : INT;
    l : LREAL;
END_VAR

Die Methode hat 3 Ausgänge: METH, j, l

METHOD METH1                    // +0 outputs (no return type)
VAR_OUTPUT
    ar : ARRAY[0..10] OF INT;   // +1 output
    l : LREAL;                  // +1 output
END_VAR

Die Methode METH1 hat 2 Ausgänge: ar und i



Metrik: NOS - Anzahl Anweisungen

Kategorie: Informativ

Anzahl der Anweisungen in der Implementierung eines Funktionsbausteines, einer Funktion oder einer Methode

Anweisungen in der Deklaration, leere Anweisungen oder Pragmas werden nicht gezählt.

Beispiel 140. Beispiel
//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

Das Beispiel hat 6 Anweisungen.



Metrik: Prozentsatz Kommentare (Kommentare)

Kategorie: Wartbarkeit

Prozentualer Anteil Kommentare im Quellcode

Diese Zahl wird nach der folgenden Formel berechnet:

Prozentsatz = 100 * <Buchstaben in Kommentaren> / <Buchstaben in Quellcode und Kommentaren zusammen>

Mehrere aufeinander folgende Leerzeichen im Quellcode werden als ein Leerzeichen gezählt, was eine hohe Gewichtung von eingerücktem Quellcode verhindert. Für leere Objekte (kein Quellcode und keine Kommentare) wird ein Prozentsatz von 0 zurückgegeben.

Beispiel 141. Beispiel

Deklarationsteil:

FUNCTION_BLOCK FB //comments in the declaration are counted, as well
VAR_TEMP
    hugo : INT;
END_VAR

Implementierung:

hugo := hugo + 1;
//Declaration: 40 letters non comment; 50 letters comment
//Implementation: 13 letters non comment; 152 letters comment
// 100 * 202 / 255 -> 79% comments

Die Berechnung des Prozentsatzes 100 * 202 / 255 ergibt 79 %.



Metrik: Komplexität (McCabe)

Kategorie: Testbarkeit

Empfohlene Obergrenze: 10

Die zyklomatische Komplexität nach McCabe ist ein Maß für die Lesbarkeit und Testbarkeit von Quellcode. Sie wird durch Zählen der Anzahl der binären Verzweigungen im Kontrollfluss der POU berechnet. Die zyklomatische Komplexität bestraft jedoch eine hohe Verzweigung, da eine hohe Verzweigung die Anzahl der für eine hohe Testabdeckung benötigten Testfälle erhöht.

Beispiel 142. Beispiel: IF-Anweisung
// 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

Das Codeschnipsel hat eine zyklomatische Komplexität von 4.



Beispiel 143. Beispiel: CASE-Anweisung
// 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

Das Codeschnipsel hat eine zyklomatische Komplexität von 4.



Beispiel 144. Beispiel: Schleifenanweisung
// 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

Das Codeschnipsel hat eine zyklomatische Komplexität von 4.



Beispiel 145. Beispiel: Andere Anweisungen

Auch die folgenden Anweisungen führen zu einer Erhöhung der zyklomatischen Komplexität:

//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';

Das Codeschnipsel hat eine zyklomatische Komplexität von 3.



Metrik: Kognitive Komplexität

Kategorie: Wartbarkeit

Standardobergrenze für die zugehörige Regel SA0178: 20

Die kognitive Komplexität ist ein Maß für die Lesbarkeit und Verständlichkeit von Quellcode, das von Sonarsource™ im Jahr 2016 eingeführt wurde. Sie bestraft jedoch eine starke Verschachtelung des Kontrollflusses und komplexe boolesche Ausdrücke. Die kognitive Komplexität wird nur für strukturierte Textimplementierungen berechnet.

Die folgenden Beispiele zeigen, wie die kognitive Komplexität berechnet wird.

Tipp

Mit dem Befehl Kognitive Komplexität für aktuellen Editor anzeigen können zusätzlich die Inkremente für strukturierten Text angezeigt werden.

Beispiel 146. Beispiel: Kontrollfluss

Anweisungen, die den Kontrollfluss manipulieren, erhöhen die kognitive Komplexität um 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

Das Codeschnipsel hat ein kognitive Komplexität von 4.



Beispiel 147. Beispiel: Verschachtelung des Kontrollflusses

Bei der Verschachtelung des Kontrollflusses wird für jede Stufe der Verschachtelung ein Inkrement von 1 hinzugefügt.

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

Das Codeschnipsel hat ein kognitve Komplexität von 8.



Beispiel 148. Beispiel: Boolescher Ausdruck

Da boolesche Ausdrücke eine große Rolle beim Verständnis von Quellcode spielen, werden sie auch bei der Berechnung der kognitiven Komplexität berücksichtigt.

Das Verständnis von booleschen Ausdrücken, die mit demselben booleschen Operator verbunden sind, ist nicht so schwierig wie das Verständnis eines booleschen Ausdrucks, der alternierende boolesche Operatoren enthält. Daher erhöht jede Kette von gleichen booleschen Operatoren in einem Ausdruck die kognitive Komplexität.

b := b1;    //+0: a simple expression, containing no operators, has no increment

Der einfache Ausdruck ohne Operator hat ein Inkrement von 0.

b := b1 AND b2;    //+1: one chain of AND operators

Der Ausdruck mit einer AND-Verknüpfung hat ein Inkrement von 1.

b := b1 AND b2 AND b3;    //+1: one more AND, but the number of chains of operators does not change

Der Ausdruck hat ein AND mehr. Aber da es der gleiche Operator ist, ändert sich die Anzahl der mit identischen Operatoren gebildeten Kette nicht.

b := b1 AND b2 OR b3;    //+2: one chain of AND operators and one chain of OR operators

Der Ausdruck hat eine Kette von AND-Operatoren und eine Kette von OR-Operatoren. Das ergibt ein Inkrement von 2.

b := b1 AND b2 OR b3 AND b4 AND b5;    //+3

Das Codeschnipsel hat ein Inkrement von 3.

b := b1 AND NOT b2 AND b3;    //+1: the unary NOT operator is not considered in the cognitive complexity

Der unäre Operator NOT wird bei der kognitiven Komplexität nicht berücksichtigt.



Beispiel 149. Beispiel: Weitere Anweisungen mit Inkrement

Strukturierter Text hat zusätzliche Anweisungen und Ausdrücke, die den Kontrollfluss verändern.

Die folgenden Anweisungen werden mit einem Inkrement der kognitiven Komplexität bestraft:

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- und RETURN-Anweisungen erhöhen nicht die kognitive Komplexität.



Metrik: DIT - Tiefe des Vererbungsbaums

Kategorie: Wartbarkeit

Anzahl der Vererbungen, bis ein Funktionsbaustein erreicht ist, der keinen anderen Funktionsbaustein erweitert

Beispiel 150. Beispiel
FUNCTION_BLOCK MyBaseFB
// ...
FUNCTION_BLOCK AChildFB EXTENDS MyBaseFB
// ...
FUNCTION_BLOCK AGrandChildFB EXTENDS AChildFB
// ...

MyBaseFB hat einen DIT von 0, da er selbst ein Funktionsbaustein ist, der keinen anderen Funktionsblock erweitert.

Für AChildFB ist der DIT 1, da ein Schritt erforderlich ist, um zu MyBaseFB zu gelangen.

AGrandChildFB hat einen DIT von 2: Ein Schritt wird zu AChildFB und ein weiterer zu MyBaseFB benötigt.



Metrik: NOC - Anzahl Kindobjekte

Kategorien: Wiederverwendbarkeit, Wartbarkeit

Anzahl der Funktionsbausteine, die den gegebenen Basisfunktionsbaustein erweitern. Dabei werden Funktionsbausteine, die einen Basisfunktionsbaustein indirekt erweitern, nicht mitgezählt.

Beispiel 151. Beispiel
FUNCTION_BLOCK MyBaseFB
// ...
FUNCTION_BLOCK AChildFB EXTENDS MyBaseFB
// ...
FUNCTION_BLOCK AGrandChildFB EXTENDS AChildFB
// ...

MyBaseFB hat nur ein (1) Kindobjekt: AChildFB, das wiederum das eine Kindobjekt AGrandChildFB hat. AGrandChildFB hat keine Kindobjekte.



Metrik: RFC - Antwort auf Klasse

Kategorien: Wartbarkeit, Wiederverwendbarkeit

Anzahl unterschiedlicher POUs, Methoden oder Aktionen, die aufgerufen werden und dadurch eine Antwort der unter Programmeinheit angegebene POU erzeugen

Beispiel 152. Beispiel
//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;
  • Beginnend mit FUN und CUBE haben diese Funktionen einen RFC von 0, denn keine der beiden Funktionen rufen andere Funktionen, Funktionsbausteine oder Methoden für ihre Berechnungen auf.

  • FB1.METH verwendet FUN und CUBE, was einen RFC von 2 ergibt.

  • Der Funktionsbaustein FB1 selbst ruft METH und FUN auf, was seinen RFC um 2 erhöht.

    Bei FB1 muss auch seine Methode METH berücksichtigt werden. METH verwendet FUN und CUBE. FUN ist bereits zum RFC hinzugefügt. Somit erhöht nur die Verwendung von CUBE in METH den RFC für FB1 auf 3



Metrik: CBO - Kopplung zwischen Objekten

Kategorien: Wartbarkeit, Wiederverwendbarkeit

Standardobergrenze für die zugehörige Regel SA0179: 30

Anzahl weiterer Funktionsbausteine, die in einem Funktionsbausteine instanziiert und verwendet werden

Ein Funktionsbausteine mit einer hohen Kopplung zwischen Objekten ist wahrscheinlich an vielen verschiedenen Aufgaben beteiligt und verstößt daher gegen das Prinzip der eindeutigen Verantwortlichkeit.

Beispiel 153. Beispiel
// 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
  • Die Erweiterung eines Funktionsbausteine erhöht nicht die Kopplung zwischen Objekten.

  • i_fb3 wird in der Implementierung von FB_Base instanziiert und an FB_Child vererbt (EXTENDS). Der Aufruf in FB_Child erhöht nicht die Kopplung zwischen den Objekten.

  • Der CBO von FB_Child ist 2.



Metrik: Referenzierungskomplexität (Elshof)

Kategorien: Effizienz, Wartbarkeit, Wiederverwendbarkeit

Komplexität des Datenflusses einer POU

Die Referenzierungskomplexität wird nach der folgenden Formel berechnet:

<Anzahl verwendeter Variablen> / <Anzahl Variablenzugriffe>

Es werden nur Variablenzugriffe im Implementierungsteil der POU berücksichtigt.

Beispiel 154. Beispiel
//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)

Referenzierungskomplexität im Codeschnipsel ergibt:

6Anzahl verwendete Variablen / 7 Anzahl Variablenzugriffe = 0.85

Achtung:

  • c und k werden nicht verwendet und zählen daher nicht als "verwendete Variablen".

  • Die Zuweisung k : INT := GVL.m wird nicht gezählt, da sie Teil der Deklaration des Programms ist.



Metrik: LCOM - Mangelnder Zusammenhalt in Methoden

Mangelnde Kohäsion der Methoden (LCOM)

Kategorien: Wartbarkeit, Wiederverwendbarkeit

Die Kohäsion zwischen Funktionsbausteinen, ihren Aktionen, Transitionen und Methoden beschreibt, ob sie auf die gleichen Variablen zugreifen.

Der Mangel an Kohäsion von Methoden beschreibt, wie stark die Objekte eines Funktionsbausteins miteinander verbunden sind. Je geringer der Kohäsionsmangel, desto stärker ist die Verbindung zwischen den Objekten.

Funktionsbausteine mit einem hohen Mangel an Kohäsion sind wahrscheinlich an vielen verschiedenen Aufgaben beteiligt und verletzen daher das Prinzip der eindeutigen Verantwortlichkeit.

Die Metrik wird nach folgender Formel berechnet:

MAX(0, <Anzahl Objektpaare ohne Kohäsion> - <Anzahl Objektpaare mit Kohäsion> )

Beispiel 155. Beispiel
//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);

Objektpaare ohne Verbindung (4 Paare):

  • FB, FB.ACT

  • FB , FB.METH

  • FB.ACT , FB.SecondMETH

  • FB.METH , FB.SecondMETH

Objektpaare mit Verbindung (2 Paare):

  • FB , FB.SecondMETH (both use c)

  • FB.ACT , FB.METH (both use i)

Tabelle 4. Die Tabelle zeigt, welche Variablen welche Objekte des FB verbinden:

FB

FB.ACT

FB.METH

FB.SecondMETH

FB.SecondMETH

c

0

0

.

FB.METH

0

i

.

.

FB.ACT

0

.

.

.

FB

-

.

.

.





Metrik: Anzahl AS-Verzweigungen (AS-Verzweigungen)

Kategorien: Testbarkeit, Wartbarkeit

Anzahl alternativer und paralleler Verzweigungen einer POU der Implementierungssprache AS (Ablaufsprache)

Beispiel 156. Beispiel
_san_img_metric_sfc_branch_count.png

Das obige Codeschnipsel in AS hat 4 Verzweigungen: 3 alternative und 1 parallele Verzweigung



Metrik: Anzahl AS-Schritte (AS-Schritte)

Kategorie: Wartbarkeit

Anzahl der Schritte in einer POU in Ablaufsprache AS

Es werden nur die Schritte gezählt, die in der in AS programmierten POU enthalten sind. Schritte in den Implementierungen von in POUs aufgerufenen Aktionen oder Transitionen werden nicht gezählt.

Beispiel 157. Beispiel
_san_img_metric_sfc_steps_count.png

Das Codeschnipsel in AS hat 10 Schritte.