Metriken - Übersicht und Beschreibung
Titel in der Ansicht „Standard-Metriken“ | Beschreibung |
---|---|
Codegröße | |
Variablengröße | |
Stack-Größe | |
Aufrufe | |
Tasks | |
Globale | |
EAs | |
Lokale | |
Eingänge | |
Ausgänge | |
NOS | |
Kommentare | |
McCabe | |
Komplexität | |
DIT | |
NOC | |
RFC | |
CBO | |
Elshof | |
LCOM | |
AS-Verzweigungen (englisch: "SFC Branches") | |
AS-Schritte (englisch: "SFC Steps") |
Detaillierte Beschreibung
Codegröße [Anzahl Bytes]
Titel Kurzform | Codegröße |
Kategorien | Informativ, Effizienz |
Definition | Anzahl der Bytes, die ein Baustein zum Applikationscode beiträgt |
Weitere Informationen | 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. |
Variablengröße [Anzahl Bytes]
Titel Kurzform | Variablengröße |
Kategorien | Informativ, Effizienz |
Definition | Größe des statischen Speichers, der von dem Objekt verwendet wird |
Weitere Informationen | 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 F_Sample : 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 drei statische Variablen vom Typ INT (f, g, h
), die jeweils 2 Byte Speicherplatz benötigen. F_Sample
hat folglich eine Variablengröße von 6 Byte.
Stack-Größe [Anzahl Bytes]
Titel Kurzform | Stack-Größe |
Kategorien | Informativ, Effizienz, Verlässlichkeit |
Definition | Anzahl der Bytes, die für den Aufruf einer Funktion oder eines Funktionsbausteins benötigt werden |
Weitere Informationen | 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 mitzä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:
FUNCTION F_Sample : INT
VAR_INPUT
a,b : INT;
END_VAR
VAR
c,d,e : INT;
END_VAR
VAR_STAT
f,g,h : INT;
END_VAR
c := b;
d := a;
e := a + b;
Annahme: Für die Berechnung wird die Solution-Plattform „TwinCAT RT (x86)“ verwendet. Das Gerät besitzt ein Stack-Alignment von 4 Byte, wodurch zwischen den Variablen Lücken entstehen können.
Die gesamte Stack-Größe von F_Sample
beträgt 16 Byte und setzt sich zusammen aus:
- 2 Eingangsvariablen mit je 2 Byte = 4 Byte
- Keine Füllbytes
- Rückgabewert INT = 2 Byte
- Füllbytes für das Stack-Alignment = 2 Byte
- 3 lokale Variablen mit je 2 Byte = 6 Byte
- Füllbytes für das Stack-Alignment = 2 Byte
VAR_STAT wird nicht auf dem Stack gespeichert und erhöht daher nicht die Stack-Größe einer POU.
Anzahl Aufrufe
Titel Kurzform | Aufrufe |
Kategorien | Informativ |
Definition | Anzahl der Aufrufe der Programmiereinheit (POU) innerhalb der Applikation |
Weitere Informationen | Falls ein Programm in einer Task aufgerufen wird, wird dieser Aufruf auch mitgezählt. |
Anzahl der Aufrufe aus Tasks
Titel Kurzform | Tasks |
Kategorien | Wartbarkeit, Verlässlichkeit |
Definition | Anzahl der Tasks, in der die Programmiereinheit (POU) aufgerufen wird |
Weitere Informationen | 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 (übergeordnete) Funktionsbaustein aufgerufen wird. |
Beispiel:
FUNCTION_BLOCK FB1
FUNCTION_BLOCK FB2 EXTENDS FB1
FUNCTION_BLOCK FB3 EXTENDS FB2
Jeder Funktionsbaustein wird in einem eigenen Programm instanziiert und aufgerufen. Zudem wird jedes Programm in einer eigenen Task aufgerufen.
Die Metrik Anzahl der Aufrufe aus Tasks ergibt somit:
- Für
FB3
: 1 - Für
FB2
: 2, da die Aufrufe vonFB2
undFB3
(EXTENDS FB2
) gezählt werden - Für
FB1
: 3, da die Aufrufe vonFB1
,FB2
undFB3
gezählt werden
Anzahl verwendeter globaler Variablen
Titel Kurzform | Globale |
Kategorien | Wartbarkeit, Wiederverwendbarkeit |
Definition | Anzahl der verwendeten, unterschiedlichen globalen Variablen, die in der Programmiereinheit (POU) verwendet werden |
Anzahl Adresszugriffe
Titel Kurzform | EAs |
Kategorien | Wiederverwendbarkeit, Wartbarkeit |
Definition | Anzahl der Adresszugriffe in der Implementierung des Objekts |
Beispiel:
PROGRAM MAIN
VAR
bVar : BOOL;
bIn AT%I* : BOOL;
bOut AT%Q* : BOOL;
END_VAR
bVar := TRUE;
bOut := bIn;
bOut := NOT bOut AND bIn;
Die Anzahl der Adresszugriffe für das Programm MAIN
beträgt 5 und setzt sich aus 2 schreibenden und 3 lesenden Zugriffen zusammen.
Anzahl lokaler Variablen
Titel Kurzform | Lokale |
Kategorien | Informativ, Effizienz |
Definition | Anzahl der Variablen, die im VAR-Bereich der Programmiereinheit (POU) deklariert sind |
Weitere Informationen | Geerbte lokale Variablen werden nicht gezählt. |
Anzahl Eingabevariablen
Anzahl der Eingangsvariablen des Bausteins (VAR_INPUT).
Titel Kurzform | Eingänge |
Kategorien | Wartbarkeit, Wiederverwendbarkeit |
Definition | Anzahl der Variablen, die im VAR_INPUT-Bereich der Programmeinheit (POU) deklariert sind |
Weitere Informationen | Geerbte Eingabevariablen werden nicht gezählt. |
Standardobergrenze für die zugehörige Regel SA0166 | 10 |
Anzahl Ausgabevariablen
Anzahl der Ausgangsvariablen des Bausteins (VAR_OUTPUT).
Titel Kurzform | Ausgänge |
Kategorien | Wartbarkeit, Wiederverwendbarkeit |
Definition | Anzahl der Variablen, die im VAR_OUTPUT-Bereich der Programmeinheit (POU) deklariert sind |
Weitere Informationen | Bei Funktionsbausteinen ist dies die Anzahl der benutzerdefinierten Ausgabevariablen (VAR_OUTPUT). Bei Methoden und Funktionen ist dies die Anzahl der benutzerdefinierten Ausgabevariablen (VAR_OUTPUT) plus eins, wenn sie einen Rückgabewert haben. Der Rückgabewert wird mitgezählt. Geerbte Ausgabevariablen werden nicht gezählt. Eine hohe Anzahl an Ausgabevariablen ist ein Zeichen für die Verletzung des Prinzips der eindeutigen Verantwortlichkeit. |
Standardobergrenze für die zugehörige Regel SA0166 | 10 |
Beispiel:
METHOD METH : BOOL
VAR_OUTPUT
a : INT;
b : LREAL;
END_VAR
Die Methode METH
hat drei Ausgänge:
- Rückgabewert
METH
a
b
METHOD METH1
VAR_OUTPUT
a : ARRAY[0..10] OF INT;
b : LREAL;
END_VAR
Die Methode METH1
hat zwei Ausgänge:
a
b
Anzahl Anweisungen (NOS)
Titel Kurzform | NOS |
Kategorien | Informativ |
Definition | Anzahl der ausführbaren Anweisungen in der Implementierung eines Funktionsbausteines, einer Funktion oder einer Methode |
Weitere Informationen | NOS = Number Of executable Statements Anweisungen in der Deklaration, leere Anweisungen oder Pragmas werden nicht gezählt. |
Beispiel:
FUNCTION_BLOCK FB_Sample
VAR_OUTPUT
nTest : INT;
i : INT;
END_VAR
VAR
bVar : BOOL;
c : INT := 100; // statements in the declaration are not counted
END_VAR
IF bVar THEN //if statement: +1
nTest := 0; // +1
END_IF
WHILE nTest = 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
nTest := 2; //+1
Das Beispiel hat sechs Anweisungen.
Prozentsatz Kommentare
Titel Kurzform | Kommentare |
Kategorien | Wartbarkeit |
Definition | Prozentualer Anteil Kommentare im Quellcode Diese Zahl wird nach der folgenden Formel berechnet: Prozentsatz = 100 * <Buchstaben in Kommentaren> / <Buchstaben in Quellcode und Kommentaren zusammen> |
Weitere Informationen | 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. Zu den Anweisungen gehören beispielsweise auch Deklarationsanweisungen. |
Komplexität (McCabe)
Titel Kurzform | McCabe |
Kategorien | Testbarkeit |
Definition | Anzahl der Binärverzweigungen im Kontrollfluss der POU (beispielsweise die Anzahl an Verzweigungen bei IF- und CASE-Anweisungen sowie Schleifen) |
Weitere Informationen | 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ärverzweigungen im Kontrollfluss der POU berechnet. Die zyklomatische Komplexität bestraft eine hohe Verzweigung, da eine hohe Verzweigung die Anzahl der für eine hohe Testabdeckung benötigten Testfälle erhöht. |
Empfohlene Obergrenze | 10 |
Die folgenden Beispiele zeigen, wie die Komplexität nach McCabe berechnet wird.
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
Der Codeschnipsel hat eine zyklomatische Komplexität von 4.
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
Der Codeschnipsel hat eine zyklomatische Komplexität von 4.
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
Der Codeschnipsel hat eine zyklomatische Komplexität von 4.
Beispiel: Andere Anweisungen
Auch die folgenden Anweisungen führen zu einer Erhöhung der zyklomatischen Komplexität:
FUNCTION FUN : STRING
VAR_INPUT
bReturn : BOOL;
bJump : BOOL;
END_VAR
// every POU has an initial cyclomatic complexity of 1, since it has at least 1 branch
JMP(bJump) 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';
Der Codeschnipsel hat eine zyklomatische Komplexität von 3.
Kognitive Komplexität
Titel Kurzform | Kognitive Komplexität |
Kategorien | Wartbarkeit |
Definition | Summe der Teilkomplexitäten, die sich beispielsweise durch Verzweigungen im Kontrollfluss der POU und durch komplexe boolesche Ausdrücke ergeben |
Weitere Informationen | 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 eine starke Verschachtelung des Kontrollflusses und komplexe boolesche Ausdrücke. Die kognitive Komplexität wird nur für strukturierte Textimplementierungen berechnet. |
Standardobergrenze für die zugehörige Regel SA0178 | 20 |
![]() | Tipp Mit dem Befehl 'Kognitive Komplexität für aktuellen Editor anzeigen' können Sie die Inkremente für strukturierten Text zusätzlich direkt im Editor anzeigen. |
Die folgenden Beispiele zeigen, wie die kognitive Komplexität berechnet wird.
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
Der Codeschnipsel hat eine kognitive Komplexität von 4.
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
Der Codeschnipsel hat eine kognitive Komplexität von 8.
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: one chain of AND operators, one chain of OR operators and another chain of AND operators
Der 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: 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.
Tiefe des Vererbungsbaums (DIT)
Titel Kurzform | DIT |
Kategorien | Wartbarkeit |
Definition | Anzahl der Vererbungen, bis ein Funktionsbaustein erreicht ist, der keinen anderen Funktionsbaustein erweitert |
Weitere Informationen | DIT = Depth of Inheritance Tree
|
Beispiel:
FUNCTION_BLOCK FB_Base
FUNCTION_BLOCK FB_Sub EXTENDS FB_Base
FUNCTION_BLOCK FB_SubSub EXTENDS FB_Sub
Die Metrik Tiefe des Vererbungsbaum beträgt:
- Für
FB_Base
: 0, da er selbst ein Funktionsbaustein ist, der keinen anderen Funktionsblock erweitert. - Für
FB_Sub
: 1, da ein Schritt erforderlich ist, um zuFB_Base
zu gelangen. - Für
FB_SubSub
: 2, da ein Schritt zuFB_Sub
und ein weiterer Schritt zuFB_Base
benötigt wird.
Anzahl Kindobjekte (NOC)
Titel Kurzform | NOC |
Kategorien | Wiederverwendbarkeit, Wartbarkeit |
Definition | Anzahl der Funktionsbausteine, die den gegebenen Basisfunktionsbaustein erweitern. Dabei werden Funktionsbausteine, die einen Basisfunktionsbaustein indirekt erweitern, nicht mitgezählt. |
Weitere Informationen | NOC = Number Of Children
|
Beispiel:
FUNCTION_BLOCK FB_Base
FUNCTION_BLOCK FB_Sub EXTENDS FB_Base
FUNCTION_BLOCK FB_SubSub1 EXTENDS FB_Sub
FUNCTION_BLOCK FB_SubSub2 EXTENDS FB_Sub
Die Metrik Anzahl Kindobjekte beträgt:
- Für
FB_Base
: 1 Kindobjekt (FB_Sub) - Für
FB_Sub
: 2 Kindobjekte (FB_SubSub1, FB_SubSub2) - Für
FB_SubSub1
: 0 Kindobjekte - Für
FB_SubSub2
: 0 Kindobjekte
Antwort auf Klasse (RFC)
Titel Kurzform | RFC |
Kategorien | Wartbarkeit, Wiederverwendbarkeit |
Definition | Anzahl unterschiedlicher POUs, Methoden oder Aktionen, die von einer POU aufgerufen werden können |
Weitere Informationen | RFC = Response For Class Der Wert dient der Messung der Komplexität (im Hinblick auf Testbarkeit und Wartbarkeit). Dabei werden alle möglichen direkten und indirekten über Assoziationen erreichbaren Methodenaufrufe gewertet. Diese können verwendet werden, um auf eine eingegangene Nachricht zu antworten oder auf ein eingetretenes Ereignis zu reagieren. |
Beispiel:
Funktionsbaustein FB1:
FUNCTION_BLOCK FB1
VAR
d,x,y : INT;
END_VAR
x := METH(d+10);
y := FUN(42, 0.815);
Methode FB1.METH:
METHOD METH : INT
VAR_INPUT
i : INT;
END_VAR
METH := FUN(CUBE(i), 3.1415);
Funktion Cube:
FUNCTION CUBE : INT
VAR_INPUT
i : INT;
END_VAR
CUBE := i*i*i;
Funktion FUN:
FUNCTION FUN : INT
VAR_INPUT
a : INT;
f : LREAL;
END_VAR
FUN := LREAL_TO_INT(f*10)*a;
FUN
,CUBE
: Diese Funktionen haben einen RFC von 0, denn keine der beiden Funktionen rufen andere Funktionen, Funktionsbausteine oder Methoden für ihre Berechnungen auf.FB1.METH:
Die Methode verwendetFUN
undCUBE
, was einen RFC von 2 ergibt.FB1:
- Der Funktionsbaustein
FB1
ruftMETH
undFUN
auf, was seinen RFC um 2 erhöht. - Bei
FB1
muss auch seine MethodeMETH
berücksichtigt werden.METH
verwendetFUN
undCUBE
.FUN
ist bereits zum RFC vonFB1
hinzugefügt (siehe vorheriger Stichpunkt). Somit erhöht nur die Verwendung vonCUBE
inMETH
den RFC fürFB1
auf 3.
Koppeln zwischen Objekten (CBO)
Titel Kurzform | CBO |
Kategorien | Wartbarkeit, Wiederverwendbarkeit |
Definition | Anzahl weiterer Funktionsbausteine, die in einem Funktionsbaustein instanziiert und verwendet werden |
Weitere Informationen | CBO = Coupling Between Objects 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. |
Standardobergrenze für die zugehörige Regel SA0179 | 30 |
Beispiel:
FUNCTION_BLOCK FB_Base
VAR
fb3 : FB3; // +1 instantiated here
END_VAR
FUNCTION_BLOCK FB_Sub EXTENDS FB_Base // +0 for EXTENDS
VAR
fb1 : FB1; // +1: instantiated here
fb2 : FB2; // +1: instantiated here
END_VAR
fb3(); // +0: instantiated in FB_Base, no increment for call
- Die Erweiterung eines Funktionsbausteine erhöht nicht die Kopplung zwischen Objekten.
- fb3 wird in der Implementierung von
FB_Base
instanziiert und anFB_Sub
vererbt. Der Aufruf inFB_Sub
erhöht nicht die Kopplung zwischen den Objekten. - Somit beträgt die Metrik Koppeln zwischen Objekten für
FB_Sub
: 2
Referenzierungskomplexität (Elshof)
Referenzkomplexität = Referenzierte Daten (Anzahl Variablen) / Anzahl der Datenreferenzen
Titel Kurzform | Elshof |
Kategorien | Effizienz, Wartbarkeit, Wiederverwendbarkeit |
Definition | Komplexität des Datenflusses einer POU Die Referenzierungskomplexität wird nach der folgenden Formel berechnet: <Anzahl verwendeter Variablen> / <Anzahl Variablenzugriffe> |
Weitere Informationen | Es werden nur Variablenzugriffe im Implementierungsteil der POU berücksichtigt. |
Beispiel:
PROGRAM MAIN
VAR
i, j : INT;
k : INT := GVL.m;
b, c : BOOL;
fb : FB_Sample;
END_VAR
fb(paramA := b); // +3 accesses (fb, paramA and b)
i := j; // +2 accesses (i and j)
j := GVL.d; // +2 accesses (j and GVL.d)
Für die Metrik Referenzierungskomplexität (Elshof) ergibt sich für MAIN
:
- Anzahl verwendeter Variablen = 6
- Anzahl Variablenzugriffe = 7
- Referenzierungskomplexität (Elshof) = Anzahl verwendeter Variablen/Anzahl Variablenzugriffe = 6/7 = 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.
Mangelnder Zusammenhalt in Methoden (LCOM)
Titel Kurzform | LCOM |
Kategorien | Wartbarkeit, Wiederverwendbarkeit |
Definition | Zusammenhalt/Kohäsion = Paare von Methoden ohne gemeinsame Instanzvariablen abzüglich Paare von Methoden mit gemeinsamen Instanzvariablen Die Metrik wird nach folgender Formel berechnet: MAX(0, <Anzahl Objektpaare ohne Kohäsion> - <Anzahl Objektpaare mit Kohäsion> ) |
Weitere Informationen | LCOM: Lack of Cohesion in Methods Der Zusammenhalt bzw. 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. |
Beispiel:
Funktionsbaustein FB:
FUNCTION_BLOCK FB
VAR_INPUT
a : BOOL;
END_VAR
VAR
i,b : BOOL;
END_VAR
Aktion FB.ACT:
i := FALSE;
Methode FB.METH:
METHOD METH : BOOL
VAR_INPUT
c : BOOL;
END_VAR
METH := c;
i := TRUE;
Methode FB.METH2:
METHOD METH2 : INT
VAR_INPUT
END_VAR
METH2 := SEL(b,3,4);
Für die Metrik Mangelnder Zusammenhalt in Methoden (LCOM) ergibt sich für FB
:
- Objektpaare ohne Verbindung/Kohäsion (5 Paare):
FB
,FB.ACT
FB
,FB.METH
FB
,FB.METH2
FB.ACT
,FB.METH2
FB.METH
,FB.METH2
- Objektpaare mit Verbindung/Kohäsion (1 Paar):
FB.ACT
,FB.METH
(beide verwendeni
)- LCOM = Anzahl Objektpaare ohne Kohäsion - Anzahl Objektpaare mit Kohäsion = 5 – 1 = 4
Anzahl AS-Verzweigungen
Titel Kurzform | AS-Verzweigungen |
Kategorien | Testbarkeit, Wartbarkeit |
Definition | Anzahl alternativer und paralleler Verzweigungen einer POU der Implementierungssprache AS (Ablaufsprache) |
Beispiel:

Das obige Codeschnipsel in AS hat 4 Verzweigungen: 3 alternative und 1 parallele Verzweigung.
Anzahl AS-Schritte
Wenn der Funktionsbaustein in Ablaufsprache (AS, englisch: SFC) implementiert ist, gibt diese Codemetrik die Anzahl an Schritten im Funktionsbaustein an.
Titel Kurzform | AS-Schritte |
Kategorien | Wartbarkeit |
Definition | Anzahl der Schritte in einer POU der Implementierungssprache AS (Ablaufsprache) |
Weitere Informationen | 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:

Das obige Codeschnipsel in AS hat 10 Schritte.
Metriken, die in Versionen < TwinCAT 3.1.4026.14 verfügbar sind:
Spaltenabkürzung in der Ansicht „Standard-Metriken“ | Beschreibung |
---|---|
Prather | |
n1 (Halstead) | Halstead – Anzahl unterschiedlicher verwendeter Operatoren (n1) |
N1 (Halstead) | |
n2 (Halstead) | Halstead – Anzahl unterschiedlicher verwendeter Operanden (n2) |
N2 (Halstead) | |
HL (Halstead) | |
HV (Halstead) | |
D (Halstead) |
Verschachtelungskomplexität (Prather)
Verschachtelungsgewicht = Anweisungen * Verschachtelungstiefe
Verschachtelungskomplexität = Verschachtelungsgewicht / Anzahl Anweisungen
Verschachtelung beispielsweise durch IF/ELSEIF- oder CASE/ELSE-Anweisungen.
Halstead (n1, N1, n2, N2, HL, HV, D)
Die folgenden Metriken gehören zu dem Bereich "Halstead":
- Anzahl unterschiedlicher verwendeter Operatoren - Halstead (n1)
- Anzahl Operatoren - Halstead (N1)
- Anzahl unterschiedlicher verwendeter Operanden - Halstead (n2)
- Anzahl Operanden - Halstead (N2)
- Länge - Halstead (HL)
- Volumen - Halstead (HV)
- Schwierigkeit - Halstead (D)
Hintergrundinformationen:
- Verhältnis von Operatoren und Operanden (Anzahl, Komplexität, Testaufwand)
- Basiert auf der Annahme, dass sich ausführbare Programme aus Operatoren und Operanden zusammensetzen.
- Operanden in TwinCAT: Variablen, Konstanten, Komponenten, Literale und IEC-Adressen.
- Operatoren in TwinCAT: Schlüsselwörter, logische und Vergleichsoperatoren, Zuweisungen, IF, FOR, BY, ^, ELSE, CASE, Caselabel, BREAK, RETURN, SIN, +, Labels, Aufrufe, Pragmas, Konvertierungen, SUPER, THIS, Indexzugriff, Komponentenzugriff etc.
Für jedes Programm werden die folgenden Basismaße gebildet:
- Anzahl unterschiedlicher verwendeter Operatoren - Halstead (n1),
Anzahl unterschiedlicher verwendeter Operanden - Halstead (n2): - Anzahl der verwendeten unterschiedlichen Operatoren (h1) und Operanden (h2), zusammen die Vokabulargröße h.
- Anzahl Operatoren - Halstead (N1),
Anzahl Operanden - Halstead (N2): - Anzahl der insgesamt verwendeten Operatoren (N1) und Operanden (N2), zusammen die Implementierungslänge N.
- (Sprachkomplexität = Operatoren/Operatorenvorkommnisse * Operanden/Operandenvorkommnisse)
Hieraus werden dann die Größen Halstead-Länge (HL) und Halstead-Volumen (HV) errechnet:
- Länge - Halstead (HL),
Volumen - Halstead (HV): - HL = h1* log2h1 + h2* log2h2
- HV = N* log2h
Aus den Basisgrößen kann man verschiedene Kennzahlen berechnen:
- Schwierigkeit - Halstead (D):
- Schwierigkeit, ein Programm zu schreiben bzw. zu verstehen (beispielsweise bei einem Code-Review)
- D = h1/2 *N2/h2
- Aufwand:
- E = D*V
Die Kennzahlen stimmen meist sehr gut mit tatsächlich gemessenen Werten überein. Der Nachteil ist, dass die Methode nur einzelne Funktionen betrifft und ausschließlich lexikalische/textuelle Komplexität misst.