69
1 TIT10AIK @ WS 2012 Software-Engineering II Refactoring

1 TIT10AIK @ WS 2012 Software-Engineering II Refactoring

Embed Size (px)

Citation preview

Page 1: 1 TIT10AIK @ WS 2012 Software-Engineering II Refactoring

1 TIT10AIK @ WS 2012

Software-Engineering II

Refactoring

Page 2: 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)

Page 3: 1 TIT10AIK @ WS 2012 Software-Engineering II Refactoring

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)

Page 4: 1 TIT10AIK @ WS 2012 Software-Engineering II Refactoring

4 TIT10AIK @ WS 2012

Code QualityCode Quality Management

Frank Simon,Olaf Seng,Thomas Mohaupt

340 Seiten

ISBN: 3-898-64388-3(Deutsch)

Page 5: 1 TIT10AIK @ WS 2012 Software-Engineering II Refactoring

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

Page 6: 1 TIT10AIK @ WS 2012 Software-Engineering II 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

Page 7: 1 TIT10AIK @ WS 2012 Software-Engineering II Refactoring

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“

Page 8: 1 TIT10AIK @ WS 2012 Software-Engineering II Refactoring

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

Page 9: 1 TIT10AIK @ WS 2012 Software-Engineering II Refactoring

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

Page 10: 1 TIT10AIK @ WS 2012 Software-Engineering II Refactoring

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

Page 11: 1 TIT10AIK @ WS 2012 Software-Engineering II Refactoring

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

Page 12: 1 TIT10AIK @ WS 2012 Software-Engineering II Refactoring

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

Page 13: 1 TIT10AIK @ WS 2012 Software-Engineering II Refactoring

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

Page 14: 1 TIT10AIK @ WS 2012 Software-Engineering II Refactoring

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

Page 15: 1 TIT10AIK @ WS 2012 Software-Engineering II Refactoring

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

Page 16: 1 TIT10AIK @ WS 2012 Software-Engineering II Refactoring

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

Page 17: 1 TIT10AIK @ WS 2012 Software-Engineering II Refactoring

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

Page 18: 1 TIT10AIK @ WS 2012 Software-Engineering II Refactoring

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

Page 19: 1 TIT10AIK @ WS 2012 Software-Engineering II Refactoring

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?

Page 20: 1 TIT10AIK @ WS 2012 Software-Engineering II Refactoring

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

Page 21: 1 TIT10AIK @ WS 2012 Software-Engineering II Refactoring

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

Page 22: 1 TIT10AIK @ WS 2012 Software-Engineering II Refactoring

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!

Page 23: 1 TIT10AIK @ WS 2012 Software-Engineering II Refactoring

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

Page 24: 1 TIT10AIK @ WS 2012 Software-Engineering II Refactoring

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 );

Page 25: 1 TIT10AIK @ WS 2012 Software-Engineering II Refactoring

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

Page 26: 1 TIT10AIK @ WS 2012 Software-Engineering II Refactoring

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

Page 27: 1 TIT10AIK @ WS 2012 Software-Engineering II Refactoring

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}

Page 28: 1 TIT10AIK @ WS 2012 Software-Engineering II Refactoring

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 }}

Page 29: 1 TIT10AIK @ WS 2012 Software-Engineering II Refactoring

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

Page 30: 1 TIT10AIK @ WS 2012 Software-Engineering II Refactoring

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

Page 31: 1 TIT10AIK @ WS 2012 Software-Engineering II Refactoring

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

Page 32: 1 TIT10AIK @ WS 2012 Software-Engineering II Refactoring

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

Page 33: 1 TIT10AIK @ WS 2012 Software-Engineering II Refactoring

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 ) {…} }

Page 34: 1 TIT10AIK @ WS 2012 Software-Engineering II Refactoring

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

Page 35: 1 TIT10AIK @ WS 2012 Software-Engineering II Refactoring

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 [...]“

Page 36: 1 TIT10AIK @ WS 2012 Software-Engineering II Refactoring

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

Page 37: 1 TIT10AIK @ WS 2012 Software-Engineering II Refactoring

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

Page 38: 1 TIT10AIK @ WS 2012 Software-Engineering II Refactoring

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

Page 39: 1 TIT10AIK @ WS 2012 Software-Engineering II Refactoring

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

Page 40: 1 TIT10AIK @ WS 2012 Software-Engineering II Refactoring

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

Page 41: 1 TIT10AIK @ WS 2012 Software-Engineering II Refactoring

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

Page 42: 1 TIT10AIK @ WS 2012 Software-Engineering II Refactoring

42 TIT10AIK @ WS 2012

#15 – Message Chains

Schritt 1Das erste aufgerufene Objekt bietet die Möglichkeit sofort an die gewünschten Daten zu kommen

Page 43: 1 TIT10AIK @ WS 2012 Software-Engineering II Refactoring

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

Page 44: 1 TIT10AIK @ WS 2012 Software-Engineering II Refactoring

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

Page 45: 1 TIT10AIK @ WS 2012 Software-Engineering II Refactoring

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

Page 46: 1 TIT10AIK @ WS 2012 Software-Engineering II Refactoring

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

Page 47: 1 TIT10AIK @ WS 2012 Software-Engineering II Refactoring

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() );

Page 48: 1 TIT10AIK @ WS 2012 Software-Engineering II Refactoring

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() ); }}

Page 49: 1 TIT10AIK @ WS 2012 Software-Engineering II Refactoring

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 ) { … }}

Page 50: 1 TIT10AIK @ WS 2012 Software-Engineering II Refactoring

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

Page 51: 1 TIT10AIK @ WS 2012 Software-Engineering II Refactoring

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 ) { … }}

Page 52: 1 TIT10AIK @ WS 2012 Software-Engineering II Refactoring

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() { … }}

Page 53: 1 TIT10AIK @ WS 2012 Software-Engineering II Refactoring

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

Page 54: 1 TIT10AIK @ WS 2012 Software-Engineering II Refactoring

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

Page 55: 1 TIT10AIK @ WS 2012 Software-Engineering II Refactoring

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++ ) { … } …}

Page 56: 1 TIT10AIK @ WS 2012 Software-Engineering II Refactoring

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

Page 57: 1 TIT10AIK @ WS 2012 Software-Engineering II Refactoring

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

Page 58: 1 TIT10AIK @ WS 2012 Software-Engineering II Refactoring

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

Page 59: 1 TIT10AIK @ WS 2012 Software-Engineering II Refactoring

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

Page 60: 1 TIT10AIK @ WS 2012 Software-Engineering II Refactoring

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

Page 61: 1 TIT10AIK @ WS 2012 Software-Engineering II Refactoring

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

Page 62: 1 TIT10AIK @ WS 2012 Software-Engineering II Refactoring

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

Page 63: 1 TIT10AIK @ WS 2012 Software-Engineering II Refactoring

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

Page 64: 1 TIT10AIK @ WS 2012 Software-Engineering II Refactoring

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

Page 65: 1 TIT10AIK @ WS 2012 Software-Engineering II Refactoring

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.

Page 66: 1 TIT10AIK @ WS 2012 Software-Engineering II Refactoring

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!

Page 67: 1 TIT10AIK @ WS 2012 Software-Engineering II Refactoring

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

Page 68: 1 TIT10AIK @ WS 2012 Software-Engineering II Refactoring

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

Page 69: 1 TIT10AIK @ WS 2012 Software-Engineering II Refactoring

69 TIT10AIK @ WS 2012

http://jenkins-ci.org/

Prüft kontinuierlich auf Code-Qualität und Erfolg der Unit-Tests