Software Engineering. 4. Unit Testing und Refactoring. Franz-Josef Elmer, Universität Basel, HS 2007

Ähnliche Dokumente
Software Engineering. 3. JUnit und ANT. Franz-Josef Elmer, Universität Basel, HS 2012

Testen mit JUnit. Motivation

Babeș-Bolyai Universität Cluj Napoca Fakultät für Mathematik und Informatik Grundlagen der Programmierung MLG5005. Testing

Test-Driven Design: Ein einfaches Beispiel

Swp08-6 Verantwortliche: Yundensuren, Baigalmaa. Testkonzept

Das Test-Framework JUnit ETIS SS04

SEP 114. Design by Contract

am Beispiel von JUnit

Fortgeschrittenes Programmieren mit Java. Test Driven Development

Verhindert, dass eine Methode überschrieben wird. public final int holekontostand() {...} public final class Girokonto extends Konto {...

Java: Vererbung. Teil 3: super()

Programmiertechnik II

Javadoc. Programmiermethodik. Eva Zangerle Universität Innsbruck

Objektorientierte Programmierung

Testen von graphischen Benutzeroberflächen. 26. Juni 2013

Objektorientierte Programmierung. Kapitel 12: Interfaces

Programmieren in Java

Programmierkurs Java

Software-Engineering Software-Management

Das erste Programm soll einen Text zum Bildschirm schicken. Es kann mit jedem beliebigen Texteditor erstellt werden.

Einführung in die Programmierung

JUnit - Test Driven Development. Bernhard Frey, Thorsten Stratmann, Jackson Takam, Michel Müller 1

Testen von graphischen Benutzeroberflächen. 24. Juni 2015

Software Engineering. 9. Refactoring und Entwurfsmuster. Franz-Josef Elmer, Universität Basel, HS 2011

Software Engineering Klassendiagramme Assoziationen

Unit Tests und Fehlersuche

Einführung in die Java- Programmierung

Einführung in die Informatik Tools

Große Übung Praktische Informatik 1

Objektorientierte Programmierung

Vorkurs C++ Programmierung

3 Objektorientierte Konzepte in Java

Distributed Computing Group

Einführung in Javadoc

Beispiel: DB-Mock (1/7)

Java Kurs für Anfänger Einheit 5 Methoden

Beispiel: Methode mit einem Fehler. Diese Methode wird problematisch, wenn von außen eine Dauer von 0 Sekunden angegeben wird, etwa im Aufruf

Prinzipien Objektorientierter Programmierung

Client-Server-Beziehungen

Java Einführung Collections

Klassenentwurf. Wie schreiben wir Klassen, die leicht zu verstehen, wartbar und wiederverwendbar sind? Objektorientierte Programmierung mit Java

Testen mit JUnit. Apcon Workplace Solutions Member of itelligence. Testen von Java-Code mit JUnit. ÿstruktur eines Testfalls

Software - Testung ETIS SS05

Einführung in die objektorientierte Programmierung mit Java. Klausur am 19. Oktober 2005

Pragmatik von Programmiersprachen

Javakurs zu Informatik I. Henning Heitkötter

Programmieren in Java

Diplomarbeit. Konzeption und Implementierung einer automatisierten Testumgebung. Thomas Wehrspann. 10. Dezember 2008

TDD für iphone OS. xpdays Tammo Freese

Gliederung Grundlagen Schlüsselworte try-catch Fehlerobjekte Fehlerklassen Schlüsselwort finally Schlüsselwort throws selbst erstellte Exceptions

Objektorientierte Programmierung für Anfänger am Beispiel PHP

Nathan Burgener. Design by Contract. Modul SWE

Software Engineering. Zur Architektur der Applikation Data Repository. Franz-Josef Elmer, Universität Basel, HS 2015

Assoziation und Aggregation

Lösungsvorschläge. zu den Aufgaben im Kapitel 4

Java Kurs für Anfänger Einheit 4 Klassen und Objekte

Innere Klassen in Java

Problemstellung. Informatik B - Objektorientierte Programmierung in Java. Vorlesung 24: Reflection 1. IDE und automatische Tests.

II. Grundlagen der Programmierung. 9. Datenstrukturen. Daten zusammenfassen. In Java (Forts.): In Java:

Einführung in die Java- Programmierung

Allgemein: Klassen testbar machen. 5. Mocking. Mocks programmieren. Zusammenspiel von Klassen testen

Einführung in die Programmierung für Wirtschaftsinformatik

Programmieren I. Strategie zum Entwurf von Klassen. Beispiele. Design von Klassen. Dr. Klaus Höppner. Beispiel: Bibliothek

Algorithmen und Datenstrukturen

5. Tutorium zu Programmieren

Markus Wichmann. Testen von Java Code mit. JUnit

Grundlagen von Python

Drei-Schichten-Architektur. Informatik B - Objektorientierte Programmierung in Java. Vorlesung 16: 3-Schichten-Architektur 1 Fachkonzept - GUI

Typumwandlungen bei Referenztypen

Praktische Übung 'JUnit-Test'

Arbeiten mit UMLed und Delphi

Java Einführung Umsetzung von Beziehungen zwischen Klassen. Kapitel 7

Einführung in die Programmierung Blockkurs Java

Testphase. Das Testen

Unit Tests mit Junit 4. Dario Borchers

Java Einführung Abstrakte Klassen und Interfaces

Objektorientierte Programmierung

3 Objektorientierte Konzepte in Java

Übung Grundlagen der Programmierung. Übung 03: Schleifen. Testplan Testergebnisse

Fachdidaktik der Informatik Jörg Depner, Kathrin Gaißer

Erreichbarkeit von Klassenelementen. Daten verstecken und kapseln

Unit Testing mit JUnit. Dr. Andreas Schroeder

Prof. Dr. Uwe Schmidt. 21. August Aufgaben zur Klausur Objektorientierte Programmierung im SS 2007 (IA 252)

Software Engineering in der Praxis

Übungen Programmieren 1 Felix Rohrer. Übungen

Vorlesung Informatik II

Studentische Lösung zum Übungsblatt Nr. 7

Synchronisation in Java. Invisible Web

Vorkurs Informatik WiSe 15/16

Einfache Arrays. Annabelle Klarl. Einführung in die Informatik Programmierung und Softwareentwicklung

5. Abstrakte Klassen. Beispiel (3) Abstrakte Klasse. Beispiel (2) Angenommen, wir wollen die folgende Klassenhierarchie implementieren:

Folge 18 - Vererbung

Kapitel 6. Vererbung

Grundlagen der Programmierung Prof. H. Mössenböck. 14. Schrittweise Verfeinerung

Planung für Organisation und Technik

Software-Engineering und Optimierungsanwendungen in der Thermodynamik

Aufgabenblatt Nr. 5 Generizität und TicTacToe

Info: Standard DO-178B. 5. Mocking. Zusammenspiel von Klassen testen. Allgemein: Klassen testbar machen

Abschnitt 12: Strukturierung von Java-Programmen: Packages

Einführung in Java. PING e.v. Weiterbildung Andreas Rossbacher 24. März 2005

Transkript:

Software Engineering 4. Unit Testing und Refactoring Franz-Josef Elmer, Universität Basel, HS 2007

Software Engineering: 4. Unit Testing und Refactoring 2 Unit Testing Unit Test: Automatischer Test welcher eine Einheit (z.b. Modul, Klasse, Komponente etc.) testet. Unit Testing: Erstellen, Verwalten und Ausführen aller Unit Tests. Unit Tests werden gleichzeitig mit dem produktiven Code geschrieben. Motto: Code a little, test a little. Produktiver Code Test Code Gebrochene Unit Tests werden sofort geflickt. Unit Testing ist das Fundament aller agilen Softwareentwicklungsmethodologien. Zeit

Software Engineering: 4. Unit Testing und Refactoring 3 JUnit: Unit Testing Framework für Java Ein Test ist eine Methode einer Testklasse (Subklasse von TestCase) mit einer der beiden folgenden Signaturen: public void testxxx() public void testxxx() throws YYY Dabei ist XXX beliebig und YYY ist eine beliebige Subklasse von Throwable. Ein Test Runner führt alle Testmethoden der Test Klasse aus (Reihenfolge ist unbestimmt). Ein Test ist erfolgreich wenn die Testmethode kein Throwable wirft. Die Methode fail wirft ein AssertionFailedError. Alle Methoden von TestCase, die mit assert beginnen, prüfen einen erwarteten Wert mit dem aktuellen Wert und werfen ein AssertionFailedError.

Software Engineering: 4. Unit Testing und Refactoring 4 Beispiel TemperaturConverterTest /** * Temperature converter between Fahrenheit and Celcius. * Conversion is based on the formula * <pre>fahrenheit = 9 * Celcius / 5 + 32</pre> */ public class TemperatureConverter { /** Converts the specified temperature from Celsius to Fahrenheit. */ public double converttofahrenheit(double temperature){ return 1.8 * temperature + 32; /** Converts the specified temperature from Fahrenheit to Celsius. */ public double converttocelcius(double temperature) { return (temperature 32) / 1.8;

Software Engineering: 4. Unit Testing und Refactoring 5 TemperatureConverterTest import junit.framework.testcase; public class TemperatureConverterTest extends TestCase { private static final double TOL = 1e 6; public void testconverttofahrenheit() { TemperatureConverter converter = new TemperatureConverter(); assertequals(32, converter.converttofahrenheit(0), TOL); assertequals(86, converter.converttofahrenheit(30), TOL); public void testconverttocelcius() { TemperatureConverter converter = new TemperatureConverter(); assertequals(0, converter.converttocelcius(32), TOL); assertequals(30, converter.converttocelcius(86), TOL); public static void main(string[] args) { junit.textui.testrunner.run(temperatureconvertertest.class);

Software Engineering: 4. Unit Testing und Refactoring 6 Test Setup und Tear Down TestCase hat zwei überschreibbare Methoden, die vor bzw. nach jedem Test aufgerufen werden: protected void setup() throws Exception protected void teardown() throws Exception TestRunner «create» YYYTest setname( testxxx ) runbare() setup() testxxx() teardown()

Software Engineering: 4. Unit Testing und Refactoring 7 Erwartete Exceptions testen Es sollten auch Tests geschrieben werden, die das korrekte Verhalten auf Verletzung der Vorbedingungen überprüfen. Test Code: Typisch: Verletzung der Vorbedingungen Exception Verletzung in try catch Klammer provizieren. Vor dem catch Statement wird fail() Methode aufgerufen. Im catch Teil kann die Exception weiter untersucht werden. Beispiel: public void testparseinvalidinteger() { try { Integer.parseInt("blabla"); fail("numberformatexception expected"); catch (NumberFormatException e) { asserttrue(e.getmessage().indexof("blabla") >= 0);

Software Engineering: 4. Unit Testing und Refactoring 8 Beispiel StackTest import java.util.*; public class Stack<E> { private final List<E> _stack = new ArrayList<E>(); /** Pushs the specified element onto the stack. * @param element Any object of type E. <code>null</code> is allowed. */ public void push(e element) { _stack.add(element); /** Returns <code>true</code> if the stack is empty. */ public boolean isempty() { return _stack.isempty(); /** Removes and returns the element on the top of the stack. * @throws IllegalStateException if the stack is empty. */ public E pop() { if (isempty()) { throw new IllegalStateException("Can not pop from an empty stack."); return _stack.remove(_stack.size() 1);

Software Engineering: 4. Unit Testing und Refactoring 9 StackTest import junit.framework.testcase; public class StackTest extends TestCase { public void testisempty() { Stack<String> stack = new Stack<String>(); asserttrue(stack.isempty()); stack.push("hello"); assertfalse(stack.isempty()); stack.pop(); asserttrue(stack.isempty()); public void testpushpop() { Stack<String> stack = new Stack<String>(); stack.push("hello"); stack.push(null); stack.push("world"); assertequals("world", stack.pop()); assertnull(stack.pop()); assertequals("hello", stack.pop()); public void testpopfromemptystack() { Stack<String> stack = new Stack<String>(); try { stack.pop(); fail("illegalstateexception expected"); catch (IllegalStateException e) {

Software Engineering: 4. Unit Testing und Refactoring 10 Test Suite Test Cases werden in Test Suiten zusammengefasst. TestSuite ist Subklasse von TestCase hierarchische Organisation aller Tests. Beispiel: import junit.framework.*; public class AllTests { public static Test suite() { TestSuite suite = new TestSuite("Test for junitexample"); suite.addtestsuite(temperatureconvertertest.class); suite.addtestsuite(stacktest.class); return suite; public static void main(string[] args) { junit.textui.testrunner.run(alltests.suite());

Software Engineering: 4. Unit Testing und Refactoring 11 JUnit Konventionen Der Name einer Testklasse beginnt mit dem Name der zu testenden Klasse und endet mit Test. Beispiel: Klasse: Stack, Testklasse: StackTest Die Testklasse ist im selben Paket wie die zutestende Klasse: Vorteil: Testklasse hat Zugriff auf package-protected Attribute und Methoden. Alle Klassen mit den Test Suiten heissen AllTests. Enhält Testklasse des selben Pakets und Test Suiten der Unterpakete. Beispiel: public static Test suite() { TestSuite suite= new TestSuite(); suite.addtestsuite(jcckit.svgplottertest.class); suite.addtest(jcckit.transformation.alltests.suite()); suite.addtest(jcckit.util.alltests.suite()); return suite;

Software Engineering: 4. Unit Testing und Refactoring 12 Vorurteile Tests schreiben ist minderwertiges Programmieren, dass kann man ruhig den Testern oder Junior- Programmieren überlassen. Unit Tests schreiben ist mindestens so anspruchsvoll wie produktiven Code schreiben. Alle Designprinzipien sollten auch beim Schreiben von Testcode einfliessen. Tests schreiben ist eine langweilige und stupide Tätigkeit. Unit Tests programmieren ist genau so kreative und macht genauso viel Spass wie produktiven Code schreiben. Unit Tests sind Zeitverschwendung. Unit Tests sind ein Sicherheitsnetz unter dem Trapezakt Softwareentwicklung. Unit Tests verbessern das Design des produktiven Codes.

Software Engineering: 4. Unit Testing und Refactoring 13 Die Kunst des Unit Testing Unit Testing hat Einfluss auf das Design. Der zu testende Code muss testbar sein, d.h. es ist möglich automatische Tests zu schreiben. Wenn ein Bug gefunden wurde: 1.Finde die Ursache. 2.Schreibe einen Unit Test, der wegen des Bugs scheitert. 3.Fixe den Bug bis der Unit Test nicht mehr fehlschlägt. Unit Tests sind Test Cases und sollten deshalb so leicht lesbar sein wie manuelle Test Cases. Keine Verzweigungen in der Test Methode. Klare Trennung von Testdaten und Testcode. Komplexere Überprüfungen in eigene assert Methoden auslagern. Beispiel: CommandLineTest

Software Engineering: 4. Unit Testing und Refactoring 14 Beispiel CommandLineTest import java.util.*; public class CommandLine { private final Set<String> _options; private final List<String> _arguments; public CommandLine(String[] args) { Set<String> options = new HashSet<String>(); List<String> arguments = new ArrayList<String>(); for (String arg : args) { if (arg.startswith(" ")) { options.add(arg.substring(1)); else { arguments.add(arg); _options = Collections.unmodifiableSet(options); _arguments = Collections.unmodifiableList(arguments); public List<String> getarguments() { return _arguments; public Set<String> getoptions() { return _options;

Software Engineering: 4. Unit Testing und Refactoring 15 CommandLineTest public class CommandLineTest extends TestCase { public void testwithoutoptions() { checknooptions(new String[] {"hello"); checknooptions(new String[] {"hello", "world"); public void testwithoptions() { check(new String[] {"b", "c", new String[] {"hi", new String[] {" b", "hi", " c"); private void checknooptions(string[] args) { check(new String[0], args, args); private void check(string[] expectedoptions, String[] expectedarguments, String[] args) { CommandLine commandline = new CommandLine(args); assertequals(expectedoptions, commandline.getoptions().toarray()); assertequals(expectedarguments, commandline.getarguments().toarray()); private void assertequals(object[] array1, Object[] array2) { for (int i = 0, n = Math.min(array1.length, array2.length); i < n; i++) { assertequals("array[" + i + "]", array1[i], array2[i]); assertequals(array1.length, array2.length);

Software Engineering: 4. Unit Testing und Refactoring 16 Die Kunst des Unit Testing Unit Tests müssen reproduzierbar sein. Dazu braucht es eine wohldefinierte Testumgebung (Testfixture). Ein Unit Test sollte den Zustand seiner Umgebung vor dem Test wieder herstellen. Vermeidet Seiteneffekte. Tests sind reproduzierbar unabhängig der Reihenfolge ihrer Ausführung. Problem: Statische Attribute von Klassen, die ihren Zustand ändern.

Software Engineering: 4. Unit Testing und Refactoring 17 Der Sinn von setup() und teardown() Wiederverwendung von Code, den jede Testmethode vor bzw. nach dem eigentlichen Test ausführen muss. Bereitstellung bzw. Freigabe von externen Resourcen. Z.B.: Temporäre Dateien, Datenbankverbindungen. Erzeugung bzw. Entfernung von Testfixtures. Z.B.: setup() spielt Testdaten in eine Datenbank ein und teardown() löscht diese wieder. Beispiel: LineCounterTest

Software Engineering: 4. Unit Testing und Refactoring 18 Beispiel LineCounterTest Die Klasse LineCounter zählt die Zeilen einer Textdatei: import java.io.*; public class LineCounter { public int countnumberoflines(file file) throws IOException { FileReader reader = null; try { reader = new FileReader(file); BufferedReader bufferedreader = new BufferedReader(reader); int count = 0; while (bufferedreader.readline()!= null) { count++; return count; finally { if (reader!= null) { reader.close();

Software Engineering: 4. Unit Testing und Refactoring 19 LineCounterTest Die Testklasse muss eine Beispieldatei erzeugen und wieder wegräumen: public class LineCounterTest extends TestCase { private static final String TEMP_FILE = "temp.txt"; protected void setup() throws Exception { super.setup(); FileWriter writer = null; try { writer = new FileWriter(TEMP_FILE); writer.write("hello\nworld"); finally { writer.close(); protected void teardown() throws Exception { super.teardown(); new File(TEMP_FILE).delete(); public void test() throws IOException { assertequals(2, new LineCounter().countNumberOfLines(new File(TEMP_FILE)));

Software Engineering: 4. Unit Testing und Refactoring 20 Refactoring Definition: Verbesserung des Codes ohne Änderung des Verhaltens. Allgemeine Erfahrung: Code Qualität Code Qualität Zahl der Features Zeit Zahl der Features Refactoring Phasen Zeit

Software Engineering: 4. Unit Testing und Refactoring 21 Refactoring Refactoring ist riskant, deshalb Risiko mindern durch gute Unit Test Abdeckung Immer in kleinen Schritten: Ein Refactoring Schritt Testen Nächster Refactoring Schritt Testen usw. Häufiger Wechsel zwischen Implementation eines neuen Features und Refactoring Neue Features Refactoring Zeit

Software Engineering: 4. Unit Testing und Refactoring 22 Ziele des Refactoring Lesbarkeit des Codes erhöhen. Refactoring kann parallel zu einem Code Review erfolgen. Design verbessern (sogenannte Bad Smells beseitigen). Code so umbauen, dass es möglich ist, Unit Tests zu schreiben. Code so vorbereiten, dass neue Features implementiert werden können.

Software Engineering: 4. Unit Testing und Refactoring 23 Reengineering Bestehende (Alt)Software (engl. legacy software) fit machen für Erweiterungen neue Umgebung Performance Optimierungen etc. Zwei Strategien: Viele kleine Schritte: Refactoring im Grossen. Zwei grosse Schritte: 1.Reverse Engineering: Von der Implementierung zurück zur Abstraktion und dem Design 2.Forward Engineering: Redesign und neue Implementierung

Software Engineering: 4. Unit Testing und Refactoring 24 Bad Smell Bad Smells sind Stellen im Code die stinken, d.h. es gibt Probleme wegen Verstoss gegen Design Prinzipien schlecht lesbarem Code. Die wichtigsten Bad Smells: Duplizierter Code Hoher Wartungsaufwand da Änderungen überall nachgeführt werden müssen. Lange Methode Schwierig zu verstehen Schlechte Wiederverwendbarkeit Ursache von Code Duplikationen Grosse Klasse Oft schlechte Wiederverwendbarkeit da die Klasse viele verschiedene Dinge machte Ursache von Code Duplikationen Lange Parameter Liste Schwierig zu lesen Switch Statements bzw. if-else-if Ketten Möglicherweise unflexibel für Erweiterungen Gleichartige Switch Statements: Code Duplikationen

Software Engineering: 4. Unit Testing und Refactoring 25 Refactoring Katalog Katalog der verschiedenen möglichen Refactorings. Wichtigster Katalog für objekt-orientiertes Refactoring: Format: Martin Fowler et al.: Refactoring Improving the Design of Existing Code. Addison-Wesley (2000) Name Zusammenfassung: Kurze Problembeschreibung Kurze Lösungsbeschreibung Einfaches Vorher-Nachher Beispiel Motivation: Beschreibung warum und warum nicht. Mechanik: Schritt-für-Schritt Anleitung. Beispiele: Grössere(s) Beispiel(e).

Software Engineering: 4. Unit Testing und Refactoring 26 Methode extrahieren (Extract Method) Ein Codefragment kann zusammengefasst werden. Setze das Fragment in eine Methode, deren Name den Zweck bezeichnet. void printowing(double amount) { printbanner(); //print details System.out.println ("name: " + _name); System.out.println ("amount " + amount); void printowing(double amount) { printbanner(); printdetails(amount); void printdetails(double amount) { System.out.println ("name: " + _name); System.out.println ("amount " + amount);

Software Engineering: 4. Unit Testing und Refactoring 27 Methode extrahieren (Extract Method) Motivation: Verbesserung der Lesbarkeit. Indiz: Kommentarzeile vor dem Fragment das extrahiert werden kann. Codeduplikation: Verschiedene Codefragmente tun (fast) dasselbe. Name der neuen Methode sollte selbstsprechend sein. Nicht möglich wenn mehr als eine lokale Variable im Fragment geändert wird aber danach noch benötigt wird. Mechanik: 1.Neue Methode erzeugen. 2.Zu extrahierendes Codefragment dort hin kopieren. 3.All lokalen Variablen, die gelesen werden, werden Methodenparameter. 4.Die lokale Variable, die geändert wird, wird der Rückgabewert. 5.Compiler laufen lassen und Fehler beheben. 6.Zu extrahierenden Code entfernen und durch Aufruf der neuen Methode ersetzen. 7.Compiler laufen lassen und Fehler beheben. 8.Unit Test der Klasse (besser alle Unit Tests) ausführen.

Software Engineering: 4. Unit Testing und Refactoring 28 Methode extrahieren (Extract Method) Beispiel: void handlearguments(string[] args) { try { _width = Integer.parseInt(args[0]); catch (Exception e) { _width = DEFAULT_WIDTH; try { _height = Integer.parseInt(args[1]); catch (Exception e) { _height = DEFAULT_HEIGHT; Refactored: void handlearguments(string[] args) { _width = getintegerargument(args, 0, DEFAULT_WIDTH); _height = getintegerargument(args, 1, DEFAULT_HEIGHT); int getintegerargument(string[] args, int index, int defaultvalue) { try { return Integer.parseInt(args[index]); catch (Exception e) { return defaultvalue;

Software Engineering: 4. Unit Testing und Refactoring 29 Beschreibende Variable einführen (Introduce Explaining Variable) Es gibt einen komplizierten Ausdruck. Setze den Ausdruck (oder Teile) in eine lokale Variable deren Name den Zweck erklärt. if ( (platform.touppercase().indexof("mac") > 1) && (browser.touppercase().indexof("ie") > 1) && wasinitialized() && resize > 0 ) { // do something final boolean ismacos = platform.touppercase().indexof("mac") > 1; final boolean isiebrowser = browser.touppercase().indexof("ie") > 1; final boolean wasresized = resize > 0; if (ismacos && isiebrowser && wasinitialized() && wasresized) { // do something

Software Engineering: 4. Unit Testing und Refactoring 30 Methode umbenennen (Rename Method) Der Name einer Methode macht ihre Absicht nicht deutlich. Ändere den Name der Methode. Customer +getinvcdlimit() Customer +getinvoicablecreditlimit()

Software Engineering: 4. Unit Testing und Refactoring 31 Methode hochziehen (Pull Up Method) Es gibt Methoden mit identischen Ergebnissen in den Unterklassen. Verschiebe die Methoden in die Oberklasse. Superclass Superclass +method() SubclassA +method() SubclassB +method() SubclassA SubclassB

Software Engineering: 4. Unit Testing und Refactoring 32 Template Method einsetzen (Form Template Method) Zwei Methoden in Unterklassen führen ähnliche aber im Detail verschiedene Schritte in derselben Reihenfolge aus. Extrahiere die Schritte in Methoden gleicher Signatur, so dass die ursprünglichen Methoden identisch werden. Verschiebe diese dann in die Oberklasse.

Software Engineering: 4. Unit Testing und Refactoring 33 Form Template Method Site ResidentialSite getbillableamount():double LifelineSite getbillableamount():double double base = _units * _rate; double tax = base * Site.TAX_RATE; return base + tax; double base = _units * _rate * 0.5; double tax = base * Site.TAX_RATE * 0.2; return base + tax; Site getbillableamount():double getbaseamount():double gettaxamount():double return getbaseamount() + gettaxamount(); ResidentialSite getbaseamount():double gettaxamount():double LifelineSite getbaseamount():double gettaxamount():double

Software Engineering: 4. Unit Testing und Refactoring 34 Parameterobjekt einführen (Introduce Parameter Object) Ein Gruppe von Parametern die zusammengehören. Ersetze diese Parameter durch ein Objekt. Customer +amountinvoicedin(start:date, end:date) +amountreceivedin(start:date, end:date) +amountoverduein(start:date, end:date) Customer +amountinvoicedin(range:daterange) +amountreceivedin(range:daterange) +amountoverduein(range:daterange)

Software Engineering: 4. Unit Testing und Refactoring 35 Refactoring in IDEs Viele integerierte Entwicklungsumgebungen (IDEs) unterstützen automatisches Refactoring. Vorteile: Einfach und schnell Zuverlässig High-level source code editing Nachteile: Unzuverlässig Unerwartete Seiteneffekte

Software Engineering: 4. Unit Testing und Refactoring 36 Links JUnit Home Page: http://www.junit.org/ Refactoring Home Page http://www.refactoring.com/ Joel Spolsky: Rub a dub dub (2002) Eine Geschichte von erfolgreichem Refactoring (nicht in Java) http://www.joelonsoftware.com/articles/fog0000000348.html David Gallardo: Refactoring for everyone - How and why to use Eclipse's automated refactoring features (2003) http://www-128.ibm.com/developerworks/library/os-ecref/