Für die Berechnung der Essentiellen Komplexität wir der Kontrollflußgraph des Modules reduziert in dem alle Grundelemente der strukturierten Programmierung entfernt werden, bis keine mehr vorkommen. Dabei spielt es keine Rolle mit welchen Sprachelementen diese Strukturelemente erzeugt werden.
|
ev(G) wird z.T. auch durch die Verwendung Boolscher Operatoren in Entscheidungen erhöht.
Diese Operatoren als Elemente unstrukturierter Programmierung zu "bestrafen" ist problematisch.
Außerdem ist problematisch das die Verwendung dieser Operatoren nicht immer gleich behandelt
wird.
|
v(G) = 3 ev(G) = 3 if ( p || q ) { A; } |
v(G) = 3 ev(G) = 3 if ( p || q ) { A; } else { B; } |
Hier fällt vor allem die Ungleichbehandlung von Entscheidungen mit und ohne else-Zweig auf. |
v(G) = 3 ev(G) = 1 if ( p && q ) { A; } |
v(G) = 3 ev(G) = 3 if ( p && q ) { A; } else { B; } |
In Zuweisungen führen Boolsche Operatoren nicht zur Erhöhung von ev(G) - werden also nicht
als unstrukturiert gewertet.
|
v(G) = 3 ev(G) = 1 b = p || q || r; |
v(G) = 3 ev(G) = 1 b = p && q && r; |
Hier nun ein Beispiel für die Umformung von zusammengesetzten Prädikaten in Entscheidungen mit Hilfe von Zuweisungen zur Verringerung der Essentiellen Komplexität. |
v(G) = 4 ev(G) = 4 if ( p || q || r ) { A; } else { B; } |
v(G) = 4 ev(G) = 1 (!!) b = p || q || r; if ( b ) { A; } else { B; } |
Nun noch einige Beispiele für Graphen mir erhöhten ev(G)-Werten durch Sprunganweisungen, also Sprachelemente die tatsächlich zum unstrukturierten Programmieren gehören. Zu Sprunganweisungen gehöhren aber nicht nur die goto's zu selbst definierten Marken sondern auch die Sprunganweisungen mit vordefinierten Marken:
Bei diesen Strukturen muß beachtet werden, daß sie nur dann ev(G) erhöhen wenn sie nicht in die Muster der Struktirierten Programmierung passen. Dazu passt das Beispiel vom Anfang: eine mit gotos simulierte Schleife. Zum break in C/C++ ist zu sagen, daß im switch-Statement das break keine unstrukturierte Sprunganweisung ist, sondern im Gegenteil, das Fehlen zu unstruktiruerten Strukturen führt. In den folgenden Beispielen sind jeweils die unstrukturierten Programmteile und eine mögliche Umformung angegeben. Die umgeformten Varianten sind nicht notwendigerweise wirklich "schöner". Ich denke in Maßen angewendet führen die definierten Sprunganweisungen zu kompakterem und übersichtlicherem Code. |
v(G) = 3
ev(G) = 3 while ( p ) { ... if ( q ) { continue; } A; ... } |
v(G) = 3
ev(G) = 1 while ( p ) { ... if ( !q ) { A; ... } } |
v(G) = 3 (2)
ev(G) = 3 (2) while ( true ) { A; if ( p ) { break; } B; } |
v(G) = 3
ev(G) = 1 // wenn B p nicht verändert p = false; while ( !p ) { A; if ( !p ) { B; } } |
v(G) = 3
ev(G) = 3 while ( p ) { A; if ( q ) { B; break; } C; } Die Umformungen dieses Codes ist für
Es wird für das Beispiel angenommen,
|
v(G) = 4
ev(G) = 1 r = p; // r neue variable while ( r ) { A; if ( q ) { B; } else { C; } r = !q && p; } In diesem Bsp. konnte ev(G) nur
| |||
Das geht aber nur auf Kosten
// wenn q in A bestimmt wird q = true; while ( p && !q ) { A; if ( q ) { B; } else { C; } } Damit ist zwar das break entfernt
|