Refactoring

Transcription

Refactoring
Seminar: CASE-Tools
WS 06/07
31.01.2007
Refactoring
Thomas Löffler
Überblick
„
1. Einführung:
„
„
„
„
2. Vorgehen
„
„
„
„
„
Wo wird refactorisiert?
Beispiele
3. Refactoringtools
„
„
Refactoring – Was ist das?
Warum Refactoring?
Ziele
Eclipse
RefactorIT
4. Kritik am Refactoring
5. Übung in Eclipse
2
Refactoring - Was ist das?
„
Definition:
„
„
„ A change made to the internal structure of software to make
it easier to understand and cheaper to modify without changing
its observable behaviour.“ (Martin Fowler)
Also:
Umstrukturieren einer Software, ohne ihr
beobachtbares Verhalten zu ändern
„ Verbessert das Design der Software
„
1. Einführung
3
Warum Refactoring?
„
„
„
„
„
Verbesserung und Pflege des Designs
Software wird verständlicher
Designfehler werden gefunden
Unbekannte Codefehler werden gefunden
Hilfe, um schneller zu programmieren
1. Einführung
4
Ziele
„
Verbesserung der
Lesbarkeit
„ Übersichtlichkeit
„ Verständlichkeit
„ Erweiterbarkeit
„ Vermeidung von Redundanz
„ Testbarkeit
„
1. Einführung
5
Wo wird refactorisiert?
„
Bad smells in Code
„If code stinks, change it.“
„ Dort wo der Code den größten „Gestank“ ausbreitet
„ Eher intuitiv als wissenschaftlich
„
„
Aber: Es gibt einen ganzen Katalog von „code
smells bad“
2. Vorgehen
6
Beispiele für Code smells bad (1)
„
Redundanter Code
Gleiche Codestruktur an mehr als einer Stelle im
Code
„ Besser:
„
„ Methode extrahieren (wenn exakt derselbe Ausdruck
vorkommt)
„ Abstrakte Methode in einer Oberklasse (wenn nur
ähnlich)
2. Vorgehen
7
Beispiele für Code smells bad (2)
„
Lange Methode
erledigen in der Regel viele verschiedene Aufgaben
„ Gesamte Funktionalität schwer überschaubar
„ Besser:
„
„ Funktion in mehrere kleinere Funktionen unterteilen Æ
Methode wird leichter verständlich und
Wiederverwendbarkeit steigt.
2. Vorgehen
8
Beispiele für Code smells bad (3)
„
Große Klasse
Klasse mit vielen Funktionen und Instanzvariablen
„ Sind in der Regel sehr unübersichtlich
„ Neigen dazu, redundanten Code zu haben
„ Besser:
„
„ Klasse in mehrer Klassen sinnvoll aufteilen
„ Instanzvariablen in extra Datenklassen kapseln
2. Vorgehen
9
Beispiele für Code smells bad (4)
„
Schrotschuss Operation (Shotgun Surgery):
Bei Änderungen einer Klasse müssen viele kleine
Änderungen in anderen Klassen gemacht werden
„ Bei Änderungen müssen alle Programmteile
gefunden werden, die eine Änderung benötigen.
„ Besser:
„
„ Programmteile in einer Klasse bündeln
2. Vorgehen
10
Beispiele für Code smells bad (5)
„
Neid um Leistungsmerkmale (Feature Envy):
Eine Methode einer Klasse interessiert sich mehr für
Daten einer anderen Klasse
„ Besser:
„
„ Verschiebe die Methode (oder einen Teil davon) in die
andere Klasse.
2. Vorgehen
11
Vorgehen
„
„
„
„It is essential for refactoring that you have good tests. [...] Before
you start refactoring, check that you have a solid suite of tests.
These tests should be self checking.” (Martin Fowler)
Test sollte vor dem Refactoring geschrieben sein
Iteratives Vorgehen:
„
„
Kleiner Refactoring-Schritt
Testen
2. Vorgehen
12
Beispiel: Entwurfsmuster vor
Refactoring
2. Vorgehen
13
Beispiel: Entwurfsmuster nach
Refactoring
2. Vorgehen
14
Refactoringtools
„
Es gibt ca. 70 Refactoring - Standardprozeduren.
„
„
„
Rename, Move, Pull up, Push down ...
Einige davon können leicht von Tools bearbeitet werden.
Tools gibt es sehr viele, z.B.
„
„
„
„
„
„
„
„
Eclipse (Java)
RefactorIT (Java)
IntelliJ (Java)
SlickEdit (C++)
Smalltalk Refactoring Browser (Smalltalk)
Bicycle Repair Man (Python)
HaRe (Haskell)
Modell Maker (Delphi)
3. Refactoringtools
15
Refactoring in Eclipse
„
Es können drei Blöcke
zusammengefasst werden:
„
„
„
„
„
Äußerliche Struktur
Klassenstruktur
Struktur in einer Klasse
Eigene Undo/Redo
Funktion für Refactorings.
Preview-Funktion
„
„
3. Refactoringtools
Bevor Refactoring auf den
Code angewandt wird, können
alle Änderungen betrachtet
werden
Auch Probleme werden vorher
berichtet
16
Refactoring in Eclipse: Äußerliche
Struktur(1)
„
Eclipse bietet hier folgende Hilfen an:
„
„
Rename: Ändert alle Variablen oder Methodennamen im
Projekt.
Move: verschiebt Pakete, Klassen/Interfaces, Felder oder
Methoden in eine andere Klasse.
3. Refactoringtools
17
Refactoring in Eclipse: Äußerliche
Struktur(2)
„
Change Method Signature:
„ Änderungen an der Signatur der Methode.
„ z.B. Parameter hinzufügen oder entfernen.
„
Convert anonymous class to nested:
„ konvertiert eine anonyme in eine innere Klasse.
public static void main(String[] args )
{
System.out.println( new Object() {
public String toString(){
return "Hello World!";
}
}.toString() );
}
Æ
private static final class HelloWorld {
public String toString(){
return "Hello World!";
}
}
public static void main(String[] args )
{
System.out.println(new HelloWorld().toString());
}
3. Refactoringtools
18
Refactoring in Eclipse: Äußerliche
Struktur(3)
„
Convert Nested Type to Top Level (Eclipse 2) /
Move Member Type to New File (Eclipse 3):
„
erzeugt aus einer inneren Klasse eine eigene TopLevel-Klasse.
class MyClass {
class MyClass {
public class Hello {
private static final class HelloWorld {
public String toString(){
return "Hello World!";
}
}
Æ
public static void main(String[] args ) {
System.out.println(
new HelloWorld().toString() );
}
}
};
final class HelloWorld {
public String toString(){
return "Hello World!";
}
}
public class Hello {
public static void main(String[] args ) {
System.out.println(
new HelloWorld().toString() );
}
}
};
3. Refactoringtools
19
Refactoring in Eclipse :
Klassenstruktur(1)
„
Pull Up:
„
„
Verschiebt Methoden oder Variablen einer Klasse ihre Superklassen
Push Down:
„
„
Gegenteil von Pull Up.
Verschiebt Methoden oder Variablen einer Klasse bzw. in alle ihre
direkten Unterklassen.
3. Refactoringtools
20
Refactoring in Eclipse :
Klassenstruktur(2)
„
Extract Interface:
„
„
erzeugt zu einer Klasse ein Interface.
Die Methoden, die im Interface deklariert werden sollen,
können vom Benutzer ausgewählt werden.
3. Refactoringtools
21
Refactoring in Eclipse :
Klassenstruktur(3)
„
Generalize Type (Eclipse 3):
„
Ändert den Typ eines Objekts bei der Deklaration einer Variablen durch
den Typ einer seiner Superklassen.
Engeneer myEmployee = new Engeneer();
„
Æ
Employee myEmployee = new Engeneer();
Use Supertype where possible:
„
Ersetzt, falls möglich, Instanzen einer Klasse durch Instanzen einer ihrer
Superklassen oder eines ihrer Interfaces.
3. Refactoringtools
22
Refactoring in Eclipse : Struktur in
einer Klasse(1)
„
Inline
„
Auf lokale Variablen angewandt:
Jedes Vorkommen einer ausgewählten lokalen Variablen
wird durch ihren initialen Wert ersetzt.
int x;
int refactore = 12 + x;
int y = 345 + refactore;
„
Æ
int x;
int y = 345 + (12 + x);
Auf Methoden angewandt:
Ersetzt jeden Methodenaufruf durch ihren Code. Die
Methode wird gelöscht.
public int aMethod(int x) {
return x + 12;
}
Æ
public void anotherMethod() {
int aMethod = 10 + 12;
}
public void anotherMethod() {
aMethod(10);
}
3. Refactoringtools
23
Refactoring in Eclipse : Struktur in
einer Klasse(2)
„
Extract Method:
„
Setzt ein Codefragment in eine neue Methode.
void print() {
System.out.println(“Name: “ + name);
System.out.println(“Vorname“ + vorname);
printData();
}
Æ
void printName() {
System.out.println(“Name: “ + name);
System.out.println(“Vorname“ + vorname);
}
void print() (
printName();
printData();
}
„
Extract Local Variable:
„
Ersetzt einen Ausdruck durch eine lokale Variable.
int x = 26 + 84 + 985;
int y = 26 + 85 + 985;
Æ
int z = 26 + 84 + 985;
int x = z;
int y = z;
3. Refactoringtools
24
Refactoring in Eclipse : Struktur in
einer Klasse(3)
„
Extract Constant:
„
Ersetzt einen Ausdruck durch eine statische Variable
(Schlüsselwörter: static und final)
void aMethod {
int x = 26 + 84 + 985;
int y = 26 + 85 + 985;
}
„
private static final int z = 26 + 84 + 985;
Æ
void aMethod {
int x = z;
int y = z;
}
Introduce Paramenter:
„
erzeugt aus einem Ausdruck einen neue Methodenparameter.
public void aMethod() {
int z = 12 + 48 + 59;
}
public void anotherMethod() {
aMethod();
}
Æ
public void aMethod(int x) {
int z = x;
}
public void anotherMethod() {
aMethod(12 + 48 + 59);
}
3. Refactroingtools
25
Refactoring in Eclipse : Struktur in
einer Klasse(4)
„
Introduce Factory:
„
Ersetzt alle Aufrufe eines Konstruktors mit einer
entsprechenden statischen Factory - Methode.
class MyClass {
class MyClass {
public MyClass() {
// ...
}
private MyClass() {
// ...
}
Æ
public static MyClass createMyClass() {
return new MyClass();
}
public static void main(String[] args) {
MyClass myClass = new MyClass();
// ...
}
public static void main(String[] args) {
MyClass myClass = createMyClass();
// ...
}
};
};
3. Refactoringtools
26
Refactoring in Eclipse : Struktur in
einer Klasse(5)
„
Convert Local Variable to Field:
„
Ersetzt die lokale Variable durch eine statische Variable auf
Klassenebene.
void myMethod() {
int x =24;
// ...
}
„
private static int x;
Æ
void myMethod() {
x = 24;
// ...
}
Encapsulate Fields:
„
Erzeugt Setter- und/oder Getter - Methoden für ein Attribut und ersetzt
alle Referenzen auf dieses Feld durch die entsprechenden
Methodenaufrufe. Die Sichtbarkeit des Attributes wird private.
3. Refactoringtools
27
RefactoringIT
„
Als alleinstehendes Programm oder als
Plugin
„
„
„
„
„
„
Verschiedene Lizenzarten (je noch
Projektgröße)
„
„
Eclipse
NetBeans
Oracle JDeveloper
Borland JBuilder
Borland JBuilder
Frei für OpenSource-Community
Zusätzliche Funktionen:
„
„
Hilfe zur Codeanalyse
Metriken dienen zur „Bewertung“ des
Codes.
3. Refactoringtools
28
RefactorIT: Hilfe zur Codeanalyse(1)
„
Where Used
„
„
Not Used
„
„
Typ-bezogene Suche: Findet alle Felder, Parameter oder Returnwerte vom
angegebenen Typ.
Subtypes
„
„
Findet und listet alle nicht verwendeten Klassen, Interfaces, Methoden,
Konstruktoren und Felder in einer Klasse, eimem Package oder einem ganzen
Projekt.
Structure Search
„
„
Findet und listet alle Referenzen einer ausgewählten Klasse, Interface, Methode,
Konstruktor, Feld, lokale Variable.
Listet alle Subklassen einer angegebenen Klasse bzw. alle Implementationsklassen
eines angegebenen Interfaces.
Type Explorer
„
Zeigt den Vererbungsbaum für eine ausgewählte Klasse in einem Explorer View.
3. Refactoringtools
29
RefactorIT: Hilfe zur Codeanalyse(2)
„
Draw Dependencies
„
Zeigt alle Typen, Methoden, Konstruktoren von denen die ausgewählte
Einheit (Package, Klasse, Methode) abhängt. Die entsprechenden
3. Refactoringtools
30
RefactorIT: Metriken(1)
„
„
„
„
Helfen bei der Analyse von unbekanntem Source-Code
Masszahlen wie Anzahl der Codezeilen oder Anzahl der Klassen
Hinweise auf die Komplexität des Codes und seine innere Struktur
Helfen bei der Abschätzung von Wiederverwendbarkeit von Aufwand von
Funktiontests sowie Wartungsarbeiten.
3. Refactoringtools
31
RefactorIT: Metriken(2)
Einige Metriken, die von RefactoringIT berechnet werden:
„ Einfache Metriken:
„
„
„
„
„
„
OO-Metriken:
„
„
„
„
Gesamtzahl der Codezeilen (LOC)
Gesamtzahl der echten Codezeilen ohne Kommentare (NCLOC)
Gesamtzahl der Kommentarzeilen im Code (CLOC)
Kommentardichte (DC = CLOC / LOC)
Anzahl der Parameter in der Signatur der jeweiligen Methode (NP)
Verhältnis von abstrakten Klassen oder Interfaces zur Gesamtzahl der Klassen (A)
Position der Klasse in der Vererbungshirarchie gemessen als Abstand von der Wurzel (DIT)
Anzahl der Klassendefinitionen in der Klasse (NOT)
Qualitätsmetriken:
„
„
„
„Cyclomatic Complexity’“: Komplexität auf Basis aller möglichen verschiedenen
Ausführungspfade, die in einer Methode durchlaufen werden können ( v(C) )
Komplexität der Klasse: Summe der ‘Cyclomatic Complexities’ V(G) aller Methoden der
jeweiligen Klasse (WMC)
Anzahl der Methoden und Konstruktoren, die innerhalb der jeweiligen Klasse aufgerufen
werden(RFC).
3. Refactoringtools
32
RefactorIT: Audit(1)
„
„
„
„
Meldet verdächtigen und nutzlosen Code.
Über 200 sog. „Audits“
Ergebnissen haben unterschiedliche Prioritäten
Einige Meldungen können automatisch korrigiert werden
3. Refactoringtools
33
Kritik am Refactoring
„
Kein Allheilmittel
„
„
Kann teilweise nur schwer eingesetzt werden
„
„
„
Im Zusammenhang mit Datenbanken, da unter Umständen Änderungen
am Datenmodell vorgenommen werden müssen.
Bei Echtzeitsystemen, da Refactoring unter Umständen zu
Performanceverlust führt
Auf Refactoring sollte verzichtet werden, wenn
„
„
„
schlecht entworfene Software kann nicht immer durch Refactoring
verbessert werden.
Die Software ganz, oder in Teilen nicht funktioniert
Zwang zur kurzfristigen Einhaltung einer Deadline
Auswahl von vielen verschiedenen Refactorisierungen
„
Es ist viel Erfahrung notwendig, um richtig zu refactorisieren
4. Kritik am Refactoring
34
Habt ihr noch Fragen?
35
Vielen Dank für eure
Aufmerksamkeit.
36