Upload
irmingild-henkels
View
108
Download
2
Embed Size (px)
Citation preview
1 TIT10AIK @ WS 2012
Software-Engineering II
Refactoring
2 TIT10AIK @ WS 2012
Themenübersicht» Objektorientierung» Aspektorientierung» Vorgehensmodelle» UML» Analyse- & Entwurfsmuster» Objektorientiertes Testen» Versionsverwaltung» Refactoring» Labor (Praktischer Teil)
3 TIT10AIK @ WS 2012
RefactoringRefactoring, Improving The Design Of Existing Code
Martin Fowler
ISBN: 0-201-48567-2412 Seiten(Englisch)
ISBN: 3-827-32278-2(Deutsch)
4 TIT10AIK @ WS 2012
Code QualityCode Quality Management
Frank Simon,Olaf Seng,Thomas Mohaupt
340 Seiten
ISBN: 3-898-64388-3(Deutsch)
5 TIT10AIK @ WS 2012
Refactoring
„Refactoring is the process of changing a software system in such way that it does not alter the external behaviour of the code yet improves its internal structure“
M. Fowler, Refactoring
6 TIT10AIK @ WS 2012
Grundsätze
» Bestehender Quellcode wird verbessert
» Die Funktionalität des Quellcodes wird nicht verändert
» Refactoring entspricht dem Aufräumen von Quellcode
» Bietet standardisierte Lösungen für Standard-Probleme
7 TIT10AIK @ WS 2012
Weshalb sollte man das tun?
Geläufige Argumente gegen Refactoring:
1. „Der Code funktioniert doch. Weshalb sollte man ihn ändern?“
2. „Never touch a running system“
3. „In dieser Zeit könnte man Sinnvolles entwickeln“
8 TIT10AIK @ WS 2012
1) Der Code funktioniert doch!
» Viele Software-Projekte werden zu Beginn mit einem großen Aufwand in Planung und Design programmiert
Gut entworfenes Software-System
Funktion 1a
Funktion 2
Funktion 1b
Funktion 3
9 TIT10AIK @ WS 2012
1) Der Code funktioniert doch!
» Ohne Refactoring wird das Design der Software mit der Zeit schlechter
» Änderungen am Quellcode tragen dazu bei, dass der Quellcode seine Struktur verliert
» Vor allem wenn es um kurzzeitige Ziele geht
Software-System nach einiger Zeit ohne Refactoring
Funktion 1a
Funktion 2
Funktion 1b
Funktion 3
10 TIT10AIK @ WS 2012
1) Der Code funktioniert doch!
» Refactoring entspricht dem Aufräumen von Quellcode
Software-System nach einem Refactoring
Funktion 1aFunktion 2Funktion 1b
Funktion 3
11 TIT10AIK @ WS 2012
1) Der Code funktioniert doch!
» Je schwieriger es ist, das Konzept im Quellcode zu erkennen, desto schwieriger ist es, dieses Konzept zu verfolgen
Gebräuchlicher Fehler in der SW-Entwicklung:» Redundanter Quellcode:
» Bei späteren Modifikationen müssen alle Stellen angepasst werden
» Je mehr Code-Zeilen, desto schwieriger wird es» Je weniger redundante Stellen, desto geringer die Wahrscheinlichkeit etwas zu vergessen
12 TIT10AIK @ WS 2012
2) Never touch a running system
» Daraus folgt i.d.R:» Man hat nicht genügend Kenntnis bzw. Kontrolle über den Quellcode
» Der Quellcode ist unflexibel geschrieben oder wird nicht komplett verstanden
» Gerade in diesem Fall sollte der Quellcode angepasst werden
13 TIT10AIK @ WS 2012
3) „In dieser Zeit könnte man Sinnvolles entwickeln“» Oft Verteidigungsbedarf gegenüber den Vorgesetzten
» Zeit für Refactoring ist keine verschwendete Zeit
» Mit Hilfe von Refactoring kann Software schneller entwickelt werden» Verbessert Design und Lesbarkeit» Gutes Design ist entscheidend für schnelle Software-Entwicklung
» Ohne gutes Design können für eine Weile gute Fortschritte gemacht werden, bald jedoch wird die Entwicklung langsamer werden
» Kann Fehler verringern oder aufdecken, erhöht damit die Qualität
14 TIT10AIK @ WS 2012
Grundvoraussetzung
» Wir wollen keine neuen Fehler einbauen!» Automatisierte Tests sind deshalb Grundvoraussetzung
» Die Testabdeckung (Code-Coverage) der zu ändernden Stelle muss hervorragend sein
15 TIT10AIK @ WS 2012
Der richtige Zeitpunkt
» Kein fester Termin» (Wie Z.B. 2x pro Woche)
» Wenn beim Entwickeln der Quellcode zu schwer zu verstehen ist
» Wenn das bisherige Design zu unflexibel ist
» Beim Finden von Bugs » Bugs sind oft ein Zeichen, dass der Quellcode dem Entwickler nicht klar genug war
» Bei Code Reviews
16 TIT10AIK @ WS 2012
„The Two Hats“, K. Beck
Refactoring New Features
Software-Entwickler
» Der Entwickler trägt zur selben Zeit immer nur einen „Hut“
» Beim Entwickeln neuer Features wird die Struktur des Quellcodes nicht angepasst
» Beim Refactoring werden keine neuen Funktionen entwickelt
» Die „Hüte“ können beim Software-Entwickeln oft in kurzen Abständen gewechselt werden
17 TIT10AIK @ WS 2012
Der falsche Zeitpunkt
» Wenn der Quellcode nicht funktionsfähig ist» Wenn der komplette Teil einfacher komplett neu
geschrieben werden könnte» Aber: Kompromisse möglich!
» Fehlerhafte Codestellen in logische Teile trennen und Segment für Segment entscheiden, ob es refactort wird
18 TIT10AIK @ WS 2012
Rolle des Refactoring für Code Reviews
» Code Reviews: Helfen, Wissen in einem Entwicklerteam zu verbreiten
» Refactoring hilft, Quellcode anderer besser zu verstehen
» Normale Code Reviews:» Reviewer schaut sich den Quellcode an» Reviewer gibt Vorschläge
» Code Reviews mit Refactoring:» Reviewer refactort den Quellcode» Reviewer bekommt dadurch Ideen, an die er zuvor nicht gedacht hätte
» Dem Reviewer wird sofort klar, ob die Vorschläge praktikabel sind oder nicht
19 TIT10AIK @ WS 2012
Refactoring vs. Design?
» Grundsätzlich: Nein!» Software-Design ist meist der wichtigste Teil
professioneller Softwareentwicklung» Programmierer werden im Vergleich zu Software-
Architekten oft als „Mechaniker“ bezeichnet – keine intellektuelle Herausforderung
» Es gibt jedoch Ansätze, bei denen zu Beginn ohne extensives Software-Design entwickelt wird
» Bei eXtreme Programming wird oft zunächst ein Prototyp entworfen
» Aber auch bei eXtreme Programming werden grundlegende Design-Überlegungen zuerst gemacht
Ersetzt Refactoring die Planungs- und Entwurfsphase bei der Software-Entwicklung?
20 TIT10AIK @ WS 2012
YAGNI» „You Ain‘t gonna need it“» Prinzip bei XP» Oft wird versucht, schon zu Beginn das
„Perfekte Design“ zu entwerfen» Die Architektur wird unnötig kompliziert» Komplexere/flexiblere Systeme sind
schwieriger zu warten» Durch das Anwenden von Refactoring ist es
legitim, weniger flexiblere Systeme zu entwerfen» Das System kann an die Gegebenheiten angepasst werden
» Weniger Druck, zu Beginn die ultimative Lösung zu finden
» Die Lösungen sollten einfach sein» Nach wie vor: Stellen, die sich häufig ändern, isolieren und flexibel machen
21 TIT10AIK @ WS 2012
Refactoring – aber was?
» Große Herausforderung» Was ist guter, was ist schlechter Code?» Welche Stellen des Codes sollen refactort werden?
» Martin Fowler definiert 22 Indikatoren für schlechten Quellcode: „Bad Smells In Code“
» Die Kenntnis dieser „Smells“ dient auch dazu, solche Fehler von vorne herein zu vermeiden
22 TIT10AIK @ WS 2012
#1 - Duplicate Code» Identische Codestrukturen an verschiedenen Stellen
» Bester Indikator für schlechten Code
public void movieEvening() { Dude x = this.findMovieFan(); Movie m1 = this.findMovie(1); Movie m2 = this.findMovie(2); x.drinkBeer(); x.watchTV( m1 ); x.drinkBeer(); x.watchTV( m2 );}
public void soccerEvening() { Dude x = this.findSoccerFan(); Movie m1 = this.get1stSoccerHalf(); Movie m2 = this.get2ndSoccerHalf(); x.drinkBeer(); x.watchTV( m1 ); x.drinkBeer(); x.watchTV( m2 );}
Harmloses Beispiel! Oft werden komplette Funktionen kopiert!
23 TIT10AIK @ WS 2012
#1 - Duplicate Codepublic void movieEvening() { Dude x = this.findMovieFan(); Movie m1 = this.findMovie(1); Movie m2 = this.findMovie(2); x.drinkBeer(); x.watchTV( m1 ); x.drinkBeer(); x.watchTV( m2 );}
public void soccerEvening() { Dude x = this.findSoc..(); Movie m1 = this.get1stSo.. Movie m2 = this.get2ndSo.. x.drinkBeer(); x.watchTV( m1 ); x.drinkBeer(); x.watchTV( m2 );}
» Wird die prinzipielle Abendbeschäftigung geändert, müssten alle Stellen angepasst werden
» Je mehr Stellen es gibt, desto höher die Wahrscheinlichkeit, dass etwas vergessen wird
24 TIT10AIK @ WS 2012
#1 - Duplicate Code
» Abhilfe im konkreten Fall:» Duplikaten Quellcode in eine separate Methode extrahieren
public void movieEvening() { Dude x = this.findMovieFan(); Movie m1 = this.findMovie(1); Movie m2 = this.findMovie(2); x.drinkBeer(); x.watchTV( m1 ); x.drinkBeer(); x.watchTV( m2 );}
public void soccerEvening() { Dude x = this.findSoc..(); Movie m1 = this.get1stSo.. Movie m2 = this.get2ndSo.. x.drinkBeer(); x.watchTV( m1 ); x.drinkBeer(); x.watchTV( m2 );}
this.spendTVEvening( x, m1, m2 );
25 TIT10AIK @ WS 2012
#2 – Long Methods
» Lange Methoden sind» Schwer zu verstehen» Schwer zu warten
» Richtlinie:» Sobald Bedarf da ist, den Code mit Inline-Kommentaren (//) zu erklären
» Abhilfe:» Methode aufteilen in kurze Methoden, die genau einen Zweck erfüllen
26 TIT10AIK @ WS 2012
#3 – Large Class
» Große Klassen sind » Schwer überschaubar» Verstoßen meistens gegen das Design-Prinzip „Separation of Concerns“ - eine Klasse soll genau einem Zweck dienen
» Abhilfe» Codeblöcke in zusätzliche Klassen oder in Subklassen auslagern
» Dadurch Separation of Concerns gewährleisten
27 TIT10AIK @ WS 2012
#4 – Long Parameter List
» Methoden bekommen sehr viele Parameter übergeben» Bei objektorientierter Programmierung unüblich
» Macht Methodenaufrufe komplizierter und schlecht wieder verwendbar
void doSomething( int x1, int x2, int x3, int x4, … ) { // use x1 .. x4}
28 TIT10AIK @ WS 2012
Ausnahme:Wenn eine starke Bindung auf jeden Fall vermieden werden muss (Dependency Injection)
#4 – Long Parameter List» Abhilfe:
» Objekt, das aufgerufen wird, besitzt Informationen direkt oder durch Objekte
class SomeClass { void setX1( int x1 ) { this.x1 = x1; } void setX1( int x2 ) { this.x2 = x1; }
void doSomething() { // use this.x1 .. this.x4 }}
29 TIT10AIK @ WS 2012
#5 – Divergent Change
» Bei der Änderung verschiedener Eigenschaften am System müssen viele Methoden einer Klasse angepasst werden
» Abhilfe:» Stellen, die sich häufig ändern, identifizieren und in eine separate Klasse isolieren
30 TIT10AIK @ WS 2012
#6 – Shotgun Surgery
» Ähnlich wie #5 – Divergent Change» Jedes Mal, wenn eine Änderung gemacht wird, müssten viele kleine Änderungen an vielen Dateien gemacht werden
» Problematisch, da dann häufig Stellen vergessen werden
» Abhilfe:» Methoden, die sich häufig ändern identifizieren und in eine separate Klasse verschieben
31 TIT10AIK @ WS 2012
#7 – Feature Envy
» Eine Methode (im Beispiel someOperation) verwendet mehr Attribute von einer anderen Klasse als von der, in der sie sich befindet
» Hinweis: » Das Prinzip der Kapselung sei hier vorausgesetzt» Ein direkter Zugriff auf als public markierte
Attribute macht das Design unflexibel
32 TIT10AIK @ WS 2012
#7 – Feature Envy
» Lösung: Methode in die „beneidete“ Klasse verschieben
Problem: Abhängigkeiten von mehreren ObjektenAnsatz: Methode partitionieren oder mit Hilfe von Design Patterns neu strukturieren
33 TIT10AIK @ WS 2012
#8 – Data Clumps
» Oft treten die gleichen Datentypen gleichzeitig auf» In Methodensignaturen» In Klassenattributen einiger Klassen
class Jukebox { String currentSongName; String currentArtistName; .. int playtime;
void play( String songName, String artistName ) {…} }
34 TIT10AIK @ WS 2012
class Song { String songName; String artistName;}
class Jukebox { Song currentSong; int playtime;
void play( Song song ) {…} }
#8 – Data Clumps
» Abhilfe: Zusammenhängende Attribute gehören in eine gemeinsame Klasse
35 TIT10AIK @ WS 2012
#9 – Primitive Obsession
» Für die Speicherung von Daten werden primitive Datentypen extensiv verwendet
public class MovieRental { int price; int currency;
int ZIPCode;
Date rentalStart; Date rentalEnd;}
Währungen
Spezial-zahlen
Ranges
Abhilfe: Spezielle Objekte erstellen
Konkret:Class Money, Class ZIPCode, Class RentalRange
M. Fowler:„You can move out of the caveInto the centrally heated worldOf objects [...]“
36 TIT10AIK @ WS 2012
#10 – Switch Statements
» Switch-Anweisungen sind ein Zeichen von nicht objektorientiertem Quellcode
» Oft die gleichen Anweisungen für alle Bedingungen im Quellcode verteilt» Code Duplizierung
» Wird Ausprägung geändert, müssen alle Switch-Statements angepasst werden
» Die Lösung ist meist Polymorphismus» State Pattern» Behaviour Pattern» Template Method
» Gibt es nur wenige Ausprägungen, könnte Polymorphismus ein Overkill sein
37 TIT10AIK @ WS 2012
#11 – Parallel Inheritance Hierarchies
» Spezialfall von Shotgun Surgery» Wenn eine Subklasse von einer Klasse gemacht wird, muss auch eine Subklasse von einer anderen gemacht werden
» Durch das Verschieben der gemeinsamen Eigenschaften der Klassen in eine gemeinsame Methode kann die Abhängigkeit gelöst werden
38 TIT10AIK @ WS 2012
#12 – Lazy Class
» Klassen, die nahezu keine Funktionalität besitzen» Folge von Refactoring – Aufgaben wurden in andere Klassen verschoben
» Folge von im voraus geplanten Features, die nie entwickelt oder gebraucht wurden
» Diese sollten eliminiert werden» Methoden in Klassen verschieben, die ähnliches bereits erledigen
39 TIT10AIK @ WS 2012
#13 – Speculative Generality
» Der Entwickler hat gegen das YAGNI-Prinzip verstoßen» Es werden für die Zukunft vermeintlich nützliche Sachen implementiert
» Wenn benötigt, sind sie sehr hilfreich, sie waren ja auch im Gesamt-Design eingeplant
» Wenn nicht benötigt sollte man sie loswerden - das System wird ansonsten komplexer und schwerer wartbar
» Erkennbar daran, dass die Methoden ausschließlich von Testklassen aufgerufen werden
40 TIT10AIK @ WS 2012
#14 – Temporary Field
» Es gibt Instanzvariablen, welche nur in bestimmten Methoden verwendet werden» Nur in einem Teil einer Klasse» Als Zwischenvariablen
» Attribute, die nur in bestimmten Kontexten gültig sind, sind schwer erkennbar und können andere Entwickler verwirren
» Ansatz:» Den Teil der Klasse in eine separate Klasse extrahieren
» Null-Objekte einführen, die bei einem undefinierten Zustand definierte Aktionen durchführen
41 TIT10AIK @ WS 2012
#15 – Message Chains
» Der Client holt von einem Objekt ein anderes Objekt, welches es nach einem Objekt fragt, von dem es ein Objekt …
» Jede Änderung an der Beziehung zwischen den Objekten erfordert eine Änderung am Client
42 TIT10AIK @ WS 2012
#15 – Message Chains
Schritt 1Das erste aufgerufene Objekt bietet die Möglichkeit sofort an die gewünschten Daten zu kommen
43 TIT10AIK @ WS 2012
#15 – Message ChainsSchritt 2Ggf. die weiteren Klassen auch direkt mit den Daten versorgen
So kann die „Bekanntschafts-beziehung“ zwischen Client und den Klassen gering gehalten werden
Ändert sich die Beziehung zw. Klasse2 und Klasse3, hat dies weder Einfluss auf den Client noch auf Klasse1
44 TIT10AIK @ WS 2012
#16 – Middle Man
» Kapselung ist in der OOP ein wichtiger Faktor
» Dadurch wird es zunächst irrelevant, ob die Daten aus der eigenen oder mithilfe einer Delegate-Klasse zurückgegeben werden
» Bei Middle Man delegiert eine Klasse einen Großteil ihrer Methoden an Delegate-Klassen
» Diese Umweg sollte man Entfernen» Lösung: Mittelmann entfernen und Client-Klasse direkt mit dem Delegate kommunizieren lassen
45 TIT10AIK @ WS 2012
#17 – Inappropriate Intimacy
» Eine Klasse verwendet Attribute einer anderen Klasse sehr ausgiebig
» Das führt dazu, dass die Klasse sehr anfällig für Veränderungen der anderen Klasse wird
» Ansätze:» Wenn es nur einige Methoden sind, diese in die andere Klasse verschieben
» Wenn ausschließlich diese Klasse auf die Attribute der anderen Klasse zugreift, das Attribut in diese Klasse verschieben
» Wenn beide Klassen gemeinsame Interessen haben, diese Stellen in eine separate Klasse extrahieren
46 TIT10AIK @ WS 2012
#18 – Alternative Class with different Interfaces
» Klassen, die dem selben Zweck dienen, sollten gleich heißen
» Methoden, die eine unterschiedliche Signatur aber die selbe Funktion haben, sollten gleich heißen
» Sind diese Methoden in unterschiedlichen Klassen, führe sie zusammen
» Wenn es sich um zwei benachbarte Subklassen handelt, überführe die Funktionalität in die Superklasse
47 TIT10AIK @ WS 2012
#19 – Incomplete Library Class
» Third-Party-Libraries haben oft eine zu geringe Funktionalität
» Entwickler tendieren dazu, Funktionalität direkt im verwendenden Code hinzuzufügen
» Benötigt man die Funktionalität erneut muss der Code kopiert werden
Date contractStart = … ;…Date nextYear = new Date( contractStart.getYear() +1, contractStart.getMonth(), contractStart.getDay() );
48 TIT10AIK @ WS 2012
#19 – Incomplete Library Class
» Ein oft gesehener Ansatz sind Helper-Klassen
» Akzeptabler Ansatzclass DateHelper{ public static Date getNextYear( Date current ) { return new Date( current.getYear() +1, current.getMonth(), current.getDay() ); }}
49 TIT10AIK @ WS 2012
#19 – Incomplete Library Class
» Statische Helper-Klassen erlauben keine OOP Methodiken» Ableitung und Vererben der Funktionalität nicht möglich
» Delegation der Funktionalität nicht möglich
class DateHelper{ public static Date getNextYear( Date current ) { … }}
50 TIT10AIK @ WS 2012
#19 – Incomplete Library Class
» Bester Ansatz:» Eigene Klasse schreiben» Entweder von der Library-Klasse ableiten oder eine Wrapper-Klasse für sie schreiben
class MyDate extends Date{ public Date nextYear() { … }}
class MyDate{ public MyDate( Date referral ) { … } public Date nextYear() { … }}
oder
51 TIT10AIK @ WS 2012
#20 – Data Class
» Data Classes („Beans“) sind Klassen, die lediglich Daten speichern
» Sie haben nur „Getter“ und „Setter“ haben
» Prinzipiell in Ordnung
class Subscription{ public Date getValidUntil() { … } public void setValidUntil( Date date ) { … }}
52 TIT10AIK @ WS 2012
#20 – Data Class
» Sie erfüllen keinen tatsächlichen Zweck
» Wird häufig eine Funktionalität in Verbindung mit den gespeicherten Daten benötigt, ist es besser, Methoden in die Data Class zu integrieren
class Subscription{ public Date getValidUntil() { … } public void setValidUntil( Date date ) { … } public boolean isStillValid() { … } public int daysLeft() { … }}
53 TIT10AIK @ WS 2012
#21 – Refused Bequest
» „Verweigertes Vermächtnis“
» Eine Subklasse will viele Methoden der Superklasse nicht unterstützen
» Indikator dafür, dass die Vererbungshierarchie ungünstig ist
Methoden werden überschrieben
54 TIT10AIK @ WS 2012
#21 – Refused Bequest
» Ansatz:» Versuchen, eine „Geschwister“-Klasse zu erzeugen, die auch von der Superklasse erbt und die unvereinbaren Fähigkeiten der Basisklasse beinhaltet
Gemeinsame Implementierung oder abstrakt
Jeweilige Implementierungen
55 TIT10AIK @ WS 2012
#22 – Comments
» Inline-Kommentare(//): » Grundsätzlich natürlich gut!» Indikator für unverständlichen Quellcode» Entschuldigen komplexe Sub- Algorithmen inmitten von langen Methoden
void doSomething{ … // sort data with QuickSort for( int i = 0; i < … ; i++ ) { … } …}
56 TIT10AIK @ WS 2012
#22 – Comments
» In der Regel schreien Inline-Kommentare förmlich danach, dass diese Code-Stellen in neue Methoden ausgelagert werden sollten
» Auch bei einzeiligen Anweisungen kann dies Sinn machen:
// Calculate next yearDate y = new Date(x.getYear()+1,x.getMonth(),x.getDay());
Beispiel für Extraktion der Methode in diesem Beispiel:Siehe #19 – Incomplete Library Class
57 TIT10AIK @ WS 2012
Aufspüren von Referenzen
» Beim Refactoring ist es essentiell zu wissen, welche Klassen bestimmte Methoden oder Attribute verwenden
» Wird eine Methode umbenannt oder verschoben, müssen alle Referenzen angepasst werden
» Moderne IDEs:» Unterstützen das Auffinden von Aufrufs- auf Verwendungshierarchien» CTRL-ALT-H / CTRL-H bei Eclipse
» Alternative:» Methode temporär auskommentieren» Compile errors suchen» Problemfall: Methoden, die Methoden aus Superklassen überschreiben,
hier wird kein Syntaxfehler auftreten!» Bei schwach typisierten Programmiersprachen:
» Suchfunktion des Editors» Automatisches Search/Replace ist nicht empfehlenswert, es könnten
ungewollt andere Anweisungen überschrieben werden» Vorsicht:
» Wird die Reflection API verwendet, um Methoden aufzurufen, kann dies die beste IDE nicht feststellen
58 TIT10AIK @ WS 2012
Code-Metriken
» Maß für eine bestimmte Einheit bei einer Software
» Viele der Code Smells können in Metriken ausgedrückt werden» Duplicate Code» Long Method» Huge Class» Long Parameter List
» Weitere Metriken definieren Eigenschaften von qualitativ hochwertigem Quellcode
59 TIT10AIK @ WS 2012
Coupling (Kopplung)
» Der Grad zu welchem die Klassen voneinander Abhängig sind
» Eine hohe Kopplung ist schlecht für die Wartbarkeit der Software
» Abhängigkeiten entstehen durch Methodenaufrufe, Vererbung und Zugriff auf öffentliche Attribute
60 TIT10AIK @ WS 2012
Cohesion (Kohäsion)
» Misst, wie stark verwandt oder fokussiert die Aufgaben eines Elementes (Klasse) sind
Klasse
m1 m2 m3 m4Methoden
a1 a2Attribute
Attribut-Zugriff
61 TIT10AIK @ WS 2012
Cohesion (Kohäsion)
» Je höher die Kohäsion, desto weniger abgetrennte Bereiche gibt es in einer Klasse
» Die Wahrscheinlichkeit, dass eine Klasse mit hoher Kohäsion genau nur einen Zweck erfüllt, ist hoch
» Eine größtmögliche Kohäsion ist anzustreben
62 TIT10AIK @ WS 2012
McCabe-Metrik (Cyclomatic Complexity)
» Misst die Komplexität von Kontrollflüssen in Methoden
» Bestimmt den Aufwand, der benötigt wird, die Methode zu testen
» „Lange“ Methoden sind nicht unbedingt komplex
» Methoden mit einer hohen Cyclomatic Complexity sind schwerer zu warten
» Berechnung basierend auf das Aktivitätsdiagramm» CC( method ) = E – N + 2» E: Anzahl der Kanten im Diagramm» N: Anzahl der Knoten im Diagramm
63 TIT10AIK @ WS 2012
McCabe - Beispiele
CC( method ) = E – N + 2
CC = 1 - 2 + 2 = 1 CC = 4 - 4 + 2 = 2CC = 2 - 3 + 2 = 1
64 TIT10AIK @ WS 2012
McCabe - Verzweigungen» Zu Verzweigungsknoten werden Keywords, die den Kontrollfluss ändern können» if, for, while, case, catch ,&&, ||, ?, else if
» Die folgenden Keywords erhöhen die Komplexität nicht» try, switch, else, default, finally
65 TIT10AIK @ WS 2012
McCabe – Method Returns
...
...
void test()void test(){{ ...... if( ... )if( ... ) {{ returnreturn;; }} ...... returnreturn;;}}
CC(X) = E-N+2 CC(X) = E-N+2 = 3-3+2 = 3-3+2 = 2= 2
Es gibt 2 Pfade!Es gibt 2 Pfade!
McCabe sieht nur je McCabe sieht nur je einen Start- und einen Start- und Endpunkt vor. Endpunkt vor. Andere Endpunkte Andere Endpunkte werden zum Ersten werden zum Ersten zurückgeführt.zurückgeführt.
66 TIT10AIK @ WS 2012
McCabe – Method Returns - Begründung
...
...
CALL FUNC
NEXT STMT
CC(X) = E-N+2 CC(X) = E-N+2 = 6-6+2 = 6-6+2 = 2= 2
Es gibt 2 Pfade!Es gibt 2 Pfade!
67 TIT10AIK @ WS 2012
McCabe-Metrik
» Eine gewisse Komplexität ist normal und kann nicht vermieden werden» Es ist utopisch, nur Methoden mit einer zyklomatischen Komplexität von 2 zu haben
» Methoden mit einer Komplexität > 10 sollten jedoch betrachtet werden
» Ein Continuous Integration System kann diesen Wert überwachen
68 TIT10AIK @ WS 2012
Wie kann ich das alles überblicken?
» Continuous-Integration-Systeme wie Jenkins können kontinuierlich Tests auf Coding Guideline Violations durchführen
» Der Entwickler wird direkt nach dem Commit über das Verletzungen der Richtlinien informiert
69 TIT10AIK @ WS 2012
http://jenkins-ci.org/
Prüft kontinuierlich auf Code-Qualität und Erfolg der Unit-Tests