Refactoring Java Code Arno.Haase@Haase-Consulting.com Arno.Haase@acm.org www.Haase-Consulting.com.

Slides:



Advertisements
Ähnliche Präsentationen
Algorithmen und Datenstrukturen
Advertisements

Anzahl der ausgefüllten und eingesandten Fragebögen: 211
Programmieren im Großen von Markus Schmidt und Benno Kröger.
mit Entwicklungsumgebungen (Eclipse) Software verbessern
Vorlesung: 1 Betriebliche Informationssysteme 2003 Prof. Dr. G. Hellberg Studiengang Informatik FHDW Vorlesung: Betriebliche Informationssysteme Teil3.
LS 2 / Informatik Datenstrukturen, Algorithmen und Programmierung 2 (DAP2)
Kritische Betrachtung
PKJ 2005/1 Stefan Dissmann Vorwoche - Klasse public class Studierende { private String name, vorname, studiengang; private int matNr, semester; private.
Telefonnummer.
1 JIM-Studie 2010 Jugend, Information, (Multi-)Media Landesanstalt für Kommunikation Baden-Württemberg (LFK) Landeszentrale für Medien und Kommunikation.
= = = = 47 = 47 = 48 = =
Universität Stuttgart Institut für Kernenergetik und Energiesysteme Was ist Refactoring? Bevor man die Integration angeht, mag es angebracht sein, den.
es gibt (fast) nichts, was nicht anders gemacht werden könnte
Java: Objektorientierte Programmierung
Java: Grundlagen der Objektorientierung
Polymorphie (Vielgestaltigkeit)
Rechneraufbau & Rechnerstrukturen, Folie 2.1 © W. Oberschelp, G. Vossen W. Oberschelp G. Vossen Kapitel 2.
Internet facts 2008-II Graphiken zu dem Berichtsband AGOF e.V. September 2008.
Vorlesung: 1 Betriebliche Informationssysteme 2003 Prof. Dr. G. Hellberg Studiengang Informatik FHDW Vorlesung: Betriebliche Informationssysteme Teil2.
Institut für Kartographie und Geoinformation Prof. Dr. Lutz Plümer Diskrete Mathematik I Vorlesung Listen-
Vererbung Spezialisierung von Klassen in JAVA möglich durch
PKJ 2005/1 Stefan Dissmann Ausblick Es fehlen noch: Möglichkeiten zum Strukturieren größerer Programme Umgang mit variabler Zahl von Elementen Umgang mit.
PKJ 2005/1 Stefan Dissmann Rückblick auf 2005 Was zuletzt in 2005 vorgestellt wurde: Klassen mit Attributen, Methoden und Konstruktoren Referenzen auf.
PKJ 2005/1 Stefan Dissmann Zusammenfassung Bisher im Kurs erarbeitete Konzepte(1): Umgang mit einfachen Datentypen Umgang mit Feldern Umgang mit Referenzen.
Zusammenfassung Vorwoche
PKJ 2005/1 Stefan Dissmann Klassenhierarchie Person Kunde Goldkunde Lieferant Object.
PKJ 2005/1 Stefan Dissmann Zusammenfassung Vorwoche Methoden sind mit einem Namen versehene Programmabschnitte besitzen Rückgabetyp, Namen, Parameterliste.
eXtreme Programming (XP)
Differentielles Paar UIN rds gm UIN
Prof. Dr. Bernhard Wasmayr
Studienverlauf im Ausländerstudium
Software Design Patterns Extreme Programming (XP).
DVG Klassen und Objekte
Dieter Bergmann, Lichtenfels
Datenstrukturen, Algorithmen und Programmierung 2 (DAP2)
Datenstrukturen, Algorithmen und Programmierung 2 (DAP2)
Prof. Dr. Bernhard Wasmayr VWL 2. Semester
AWA 2007 Natur und Umwelt Natürlich Leben
Rechneraufbau & Rechnerstrukturen, Folie 12.1 © W. Oberschelp, G. Vossen W. Oberschelp G. Vossen Kapitel 12.
1. 2 Schreibprojekt Zeitung 3 Überblick 1. Vorstellung ComputerLernWerkstatt 2. Schreibprojekt: Zeitung 2.1 Konzeption des Kurses 2.2 Projektverlauf.
Prof. Dr. Gerhard Schmidt pres. by H.-J. Steffens Software Engineering SS 2009Folie 1 Objektmodellierung Objekte und Klassen Ein Objekt ist ein Exemplar.
Prof. Dr. Günter Gerhardinger Soziale Arbeit mit Einzelnen und Familien Übersicht über die Lehrveranstaltung Grundlegende Bestimmungsfaktoren der Praxis.
20:00.
Zusatzfolien zu B-Bäumen
1 Fachtagung am Seniorenorientiertes Design und Marketing ThyssenKrupp Immobilien Design for all - Anpassungen im Wohnungsbestand 1.Demographie.
Eine Einführung in die CD-ROM
Dokumentation der Umfrage
Wir üben die Malsätzchen
Syntaxanalyse Bottom-Up und LR(0)
OOP-Begriffe Abstraktion Modellieren Klasse Objekt Attribute Methoden
Der Ablauf eines Clear Rex Klärzyklus
PROCAM Score Alter (Jahre)
Ertragsteuern, 5. Auflage Christiana Djanani, Gernot Brähler, Christian Lösel, Andreas Krenzin © UVK Verlagsgesellschaft mbH, Konstanz und München 2012.
Tutorium PG Verbesserung Blatt 5 Beim instanziieren eines Fahrrades muss es möglich sein, alle benötigten Attribute dem Konstruktor zu übergeben.
Eine lllustration der Herausforderungen des Stromsystems der Zukunft
Ruby Refactoring Plug-In für Eclipse
Symmetrische Blockchiffren DES – der Data Encryption Standard
Szenisches Lernen Wie Theaterelemente den Unterricht bereichern
Zahlentheorie und Zahlenspiele Hartmut Menzer, Ingo Althöfer ISBN: © 2014 Oldenbourg Wissenschaftsverlag GmbH Abbildungsübersicht / List.
MINDREADER Ein magisch - interaktives Erlebnis mit ENZO PAOLO
Neuerungen in Java 5/6/7. Stefan Bühler für InfoPoint Überblick Java 5 neue Sprachfeatures Erweiterungen Klassenbibliothek Java 6 Erweiterungen.
Parkplatz-Orga Diese Version ist vom finale Version!
Folie Beispiel für eine Einzelauswertung der Gemeindedaten (fiktive Daten)
Forschungsprojekt Statistik 2013 „Jugend zählt“ – Folie 1 Statistik 2013 „Jugend zählt“: Daten zur Arbeit mit Kindern und Jugendlichen.
Folie Einzelauswertung der Gemeindedaten
Datum:17. Dezember 2014 Thema:IFRS Update zum Jahresende – die Neuerungen im Überblick Referent:Eberhard Grötzner, EMA ® Anlass:12. Arbeitskreis Internationale.
1 Medienpädagogischer Forschungsverbund Südwest KIM-Studie 2014 Landesanstalt für Kommunikation Baden-Württemberg (LFK) Landeszentrale für Medien und Kommunikation.
Abstrakte Klassen und das Interface-Konzept
Tutorium Software-Engineering SS14 Florian Manghofer.
 Präsentation transkript:

Refactoring Java Code Arno.Haase@Haase-Consulting.com Arno.Haase@acm.org www.Haase-Consulting.com

Übersicht  Einführung Das Umfeld für Refactoring „Code Smells“ als Wegweiser Automatisierte Tests mit JUnit Konkrete Refactorings Beispiel Toolunterstützung

„Refactoring“, Martin Fowler Dieses Tutorial beruht im Wesentlichen auf dem Buch „Refactoring – Improving the Design of Existing Code“ von Martin Fowler. Standardwerk Abweichungen im Detail

Refactoring: Definition „Refactoring ist die Verbesserung der Qualität von vorhandenem Quell- text ohne Veränderung der Funktionalität.“

Problem Das Design eines Systems neigt dazu, im Laufe der Zeit immer schlechter zu werden. Neue Funktionalität wird gefordert, alte entfällt Vorhandene Anforderungen werden geändert Das Verständnis des Systems ändert sich

Refactoring als Gegenmittel Um dem entgegenzuwirken, muss das Design mit dem System wachsen. Kleine Schritte reduzieren das Risiko Trennung zwischen Refactoring und Erweiterung des Systems hilft zu fokussieren Arbeit am System stößt auf sich ändernde Teile

Demonstration Ein Quelltext sagt mehr als tausend Folien... Der Quelltext ist im Internet verfügbar: www.haase-consulting.com/download/oop2002

Was ist geschehen? Ein Stück Software wurde überarbeitet, ohne dass sich sein Verhalten geändert hat. Auslöser: eine anstehende Änderung Code war unnötig kompliziert Änderungen in kleinen Schritten

Wann Refactoring Der richtige Zeitpunkt für Refactoring ist, wenn man sich ohnehin mit dem Quelltext beschäftigt. Beim Debugging Beim Erweitern/Ändern Wenn ein Kollege mit einer Frage kommt

Kleine Schritte Refactoring funktioniert am besten, wenn man es in kleinen Schritten tut. Schutz vor Flüchtigkeitsfehlern Man behält den Überblick Bei Problem: einfach einen Schritt zurück

Die beiden Hüte Refactoring und Erweiterung des Systems wechseln sich ab. Saubere Trennung für besseren Überblick Zettel und Stift als Gedächtnisstütze Man hat entweder den „Refactoring-Hut“ oder den „Erweiterungs-Hut“ auf

Zusammenfassung Refactoring erlaubt es, nachträglich Designentscheidungen zu ändern. Zeitpunkt: wenn man ohnehin mit dem Code zu tun hat Kleine Schritte: Entspannt bleiben, bei Problem einen Schritt zurück.

Übersicht Einführung  Das Umfeld für Refactoring „Code Smells“ als Wegweiser Automatisierte Tests mit JUnit Konkrete Refactorings Beispiel Toolunterstützung

Altersschwäche Software kann an Altersschwäche sterben. Design wächst nicht mit den Anforderungen Wartung als Albtraum Manchmal schon vor Inbetriebnahme...

Hellseherei Fixiertes Design vorab ist problematisch. Anforderungen ändern sich Das Verständnis wächst „Hellseherei“ funktioniert oft nicht Ausnahme: feste Anforderungen, erfahrenes Team (z.B. reine Migration)

Traditionelles Vorgehen Das Wasserfall-Modell ist immer noch sehr verbreitet. Änderungen werden mit der Zeit teurer Risiko minimieren

Änderungen billig machen Agile Vorgehensmodelle unterstützen späte Änderungen Z.B. eXtreme Programming Weniger Gewicht auf Planung am Anfang System profitiert von wachsender Erfahrung

Kriterien für das Vorgehensmodell Refactoring funktioniert am besten in einem Vorgehensmodell, bei dem Änderungen billig und sicher sind. Dann kann das System von der wachsenden Erfahrung profitieren.

Source-Code enthält das Design Refactoring ändert das Design schrittweise im Quelltext. Sonstige Design-Dokumentation bremst dabei. Keine Hackerei: Anforderung an den Code Je feiner die übrige Designdokumentation ist, desto problematischer „Design Freeze“ schließt Refactoring aus

Einfachheit als Wert Softwareentwicklung ist eine der kompliziertesten Tätigkeiten der Welt. Quelltexte sind primär für menschliche Leser Möglichst viele Hilfestellungen Unnötige Komplexität entfernen

Wenn du es siehst, tue es Ein Problem lieber gleich angehen als es auf die lange Bank schieben. Probleme verschwinden nicht von alleine Vorgehensmodell muss das zulassen Mut als Wert Ausnahme: kurz vor einer Deadline.

Qualität als Wert? Qualität als Wert entwickelt leicht eine Eigendynamik. Qualität ist relativ zu Maßstäben; damit lässt sich Vieles begründen Stattdessen klarer „Einfachheit“ und „Kommunikation“

Versionsverwaltung Eine Versionsverwaltung ist eine wichtige Voraussetzung für Refactoring, besonders im Team. Reversibilität von Refactorings Kurze Check-In-Zyklen

Buildprozess Nur ein wohldefinierter Buildprozess erlaubt die Überprüfung von Änderungen. An jedem Arbeitsplatz verfügbar Muss gelebt werden  Integration in IDE Früh aufsetzen und mit dem Projekt wachsen lassen

Häufige Integration Es muss immer ein funktionstüchtiger Stand des Systems verfügbar sein. Systemteile früh aneinanderschrauben, damit sie nicht auseinanderlaufen z.B. nächtlicher Build

Einwände gegen Refactoring Es gibt – teilweise tatsächliche – Hindernisse: „Design ist nicht mehr dokumentiert.“ „Refactoring lohnt sich nicht.“ „Wo sind die kurzfristigen Vorteile?“ „Es könnte etwas kaputtgehen.“

„Design ist nicht dokumentiert“ Einwand: Durch Refactoring laufen Implementierung und Designdokumentation auseinander Im sehr großen Maßstab berechtigter Einwand Ansonsten: Gesonderte Designdokumentation veraltet ohnehin Quelltext gewinnt an Klarheit: Design wird im Quelltext expliziter

„Refactoring lohnt sich nicht“ Einwand: Während des Refactorings implementiert man keine Funktionalität. Durch Refactoring gleichbleibend gutes Design System bleibt änderbar Nicht ästhetische Selbstbefriedigung

„Keine kurzfristigen Vorteile“ Einwand: Refactoring bringt langfristig Vorteile, aber nicht kurzfristig. Refactoring als Teil des jeweiligen Arbeitspakets Kein Hauruck-Redesign, sondern hier ein wenig und dort ein wenig. Vereinfacht die tägliche Arbeit und spart dabei Zeit.

„Es könnte etwas kaputt gehen“ Einwand: Refactoring könnte bestehende Funktionalität kaputt machen. JUnit-Tests In kleinen Schritten vorgehen Bei Unsicherheit lieber vorsichtig sein Andererseits: bei jeder Änderung kann etwas kaputtgehen...

Alternative: Einfach tun Wenn das Management nicht von Refactoring überzeugt ist, gibt es die Möglichkeit, es einfach zu tun Der „offizielle“ Weg ist besser Professionelle Verantwortung Es spart Zeit, wird sich also bewähren

Grenzen des Refactoring Es gibt Situationen, wo Refactoring nicht gut funktioniert. Relationale Datenbanken Fixierte Schnittstellen Hoffnungslos kaputtes System

Zusammenfassung Das Umfeld des Refactoring: Agile Prozesse erlauben es, spät Änderungen am System durchzuführen Versionsverwaltung, Build Management Es gibt Einwände, mit denen man sich auseinander setzen muss Refactoring ist lernbar: Keine Scheu!

Übersicht Einführung Das Umfeld für Refactoring  „Code Smells“ als Wegweiser Automatisierte Tests mit JUnit Konkrete Refactorings Beispiel Toolunterstützung

Wann Refactoring? Das „wie“ ist relativ einfach, aber wann und wo soll man refaktorieren? Lohnt sich ein bestimmtes Refactoring? In welche Richtung soll man gehen? Wo fängt man an? Wann soll man aufhören?

„Code Smells“ „Geruch“ von Quelltexten ist eine Metapher, um über ihre Qualität zu reden. Katalog von Gerüchen Keine präzisen Kriterien Hilfestellung für die Intuition

Duplizierter Code Wenn das Gleiche an zwei Stellen im Quelltext steht, „stinkt“ das zum Himmel. Der Quelltext ist unübersichtlich Das System ist schwer zu ändern Inkonsistenzen und damit Fehler schleichen sich ein

Datenklasse Eine Klasse, die nur Daten und keine Logik enthält, ist ein Indiz für Verbesserungs-potential Oft gibt es Funktionalität, die im Wesentlichen auf diesen Daten operiert Andernfalls ist vielleicht die Klasse schlecht geschnitten

Kommentare Kommentare an sich „riechen“ gut, sie werden aber oft als „Deodorant“ verwendet. Kommentare sind Zeichen, dass der Quelltext selbst nicht klar verständlich ist Kommentare können veralten oder in die Irre führen

Unangebrachte Intimität Zwei Klassen, die ausgiebig gegenseitig Methoden aufrufen, sind oft nicht gut geschnitten. Sie sind eng gekoppelt und schwierig unabhängig voneinander zu ändern Sie sind schwierig zu benutzen, weil sie keine klare Aufgabenteilung haben

Neid Eine Methode, die im Wesentlichen auf Attributen einer anderen Klasse operiert, ist dort wahrscheinlich besser aufgehoben. Die Signatur der Methode wird dann einfacher und die Aufgabenteilung der Klassen natürlicher

Switch Fallunterscheidungen mit „switch“ führen oft zu doppeltem Code, weil die gleichen Fälle mehrmals unterschieden werden. Switch ist nicht typsicher Man vergisst leicht Fälle Zusätzliche Fälle müssen an vielen Stellen bedacht werden

Lange Methode Lange Methoden sind aufwendiger zu verstehen als kurze. Kurze Methoden können durch ihre Namen den Quelltext dokumentieren Durch Extrahieren kurzer Methoden kann man Code-Duplizierung vermeiden und Aufgaben zwischen Klassen verschieben

Monster-Klasse Eine zu große Klasse wird unübersichtlich. Zu viele Attribute führen leicht zu Code-Duplizierung

Datenklumpen Eine Gruppe von Daten, die oft zusammen vorkommt, kann man oft als Klasse zusammenfassen. Dieser Typ kann Funktionalität bekommen und dadurch doppelten Code vermeiden Die Verwendung der Daten wird einfacher 5$ + 

Unechte Primitive Datentypen Primitive Datentypen können oft besser durch Klassen ersetzt werden. Eigene Werttypen sind typsicher und dokumentieren den Code Manchmal gibt es falsche Scheu vor „kleinen“ Klassen 5$ 

Schrotkugeln herausoperieren Wenn man viele Klassen ändern muss, um einen Aspekt zu ändern, ließe er sich vielleicht an einer Stelle lokalisieren. Man übersieht sonst leicht eine Stelle Es entsteht leicht doppelter Code

Kombinierte Abstraktionen Wenn eine Klasse von vielen verschiedenen Änderungen betroffen wird, ist es vielleicht besser, sie zu spalten. Sonst betreffen Änderungen potentiell mehr Quelltext als nötig Aufteilung macht den Code übersichtlicher

Lange Parameterliste Eine lange Parameterliste deutet auf Verbesserungspotential hin. Lange Parameterlisten sind unübersichtlich Sie neigen dazu, sich zu ändern Attribute oder Parameterobjekte sind besser

Faule Klasse Eine Klasse, die fast nichts mehr tut, kann mehr im Weg sein als nützen. Jede Klasse bedeutet Komplexität Der Nutzen kann kleiner werden als der Preis

Hellseherei Oft berücksichtigen Leute sicherheitshalber Erweiterungen, die eventuell später benötigt werden. Das Design wird komplizierter, schwieriger zu verstehen und ändern Indiz: Eine Methode oder Klasse wird nur von Tests verwendet

Methodenketten Wenn man erst eine Reihe von get-Methoden aufrufen muss, um das eigentlich interessante Objekt zu bekommen, durchbricht das die Kapselung. Änderungen der dazwischenliegenden Klassen betreffen den Client

Vermittler Wenn viele Methoden einer Klasse den Aufruf einfach nur durchreichen, macht das das Interface unnötig kompliziert. Der Client sollte stattdessen direkt mit dem inneren Objekt reden

Alternative Klassen mit verschiedenen Schnittstellen Wenn mehrere Klassen das Gleiche tun, bedeutet das Code-Duplizierung mit allen ihren Problemen. Das gilt insbesondere bei unterschiedlichen Interfaces

Ausgeschlagenes Erbe Wenn eine Unterklasse wesentliche Teile der Basisklasse ignoriert, irritiert das menschliche Leser. Wenn Implementierung ignoriert wird, ist das nicht so schlimm Wenn Teile der Schnittstelle nicht unterstützt werden, ist die Vererbung falsch

Übersicht Einführung Das Umfeld für Refactoring „Code Smells“ als Wegweiser  Automatisierte Tests mit JUnit Konkrete Refactorings Beispiel Toolunterstützung

Automatisierte Modultests Automatisierte Modultests reduzieren das Risiko beim Refactoring. automatisiert: Die Tests laufen auf Knopfdruck ab und brauchen keine Nutzeraktion. Modultests: Getestet werden die einzelnen Klassen.

JUnit JUnit ist ein Framework zur Unterstützung von automatisierten Modultests. Tests sind Java-Klassen Test-Schreiben ist kein großer Overhead www.junit.org

Beispiel Ein dummes aber einfaches Beispiel... Der Quelltext ist im Internet verfügbar: www.haase-consulting.com/download/oop2002

Integration in IDE Der Aufruf von JUnit ist einfach. junit.jar in den ClassPath junit.swingui.TestRunner als Main-Klasse Den Namen des Testfalls als Kommandozeilenparameter

Eine Testklasse je Klasse Typischerweise schreibt man zu jeder Klasse eine Testklasse. Testklasse erbt von junit.framework.TestCase Per Namenskonvention endet der Name der Testklasse mit „Test“ TestCase Briefmarke BriefmarkeTest

Tests Zu einer Test-Klasse gehören mehrere Test-Methoden. Namenskonvention: public void test... () Die Reihenfolge der Ausführung steht nicht fest Die Testmethoden müssen unabhängig voneinander sein

Assertions Die eigentlichen Tests erfolgen als Aufrufe der assert...-Methoden von TestCase. Wenn die Bedingung erfüllt ist, passiert nichts Wenn die Bedingung nicht erfüllt ist, wird dieser Test abgebrochen und als fehl- geschlagen vorgemerkt

TestSuite Mehrere Tests können als TestSuite zusammengefasst werden. Klasse junit.framework.TestSuite Eine TestSuite kann TestCases und TestSuites enthalten 1..* Test TestCase TestSuite

Beispiel (2) Eine zweite Klasse mit Tests kommt dazu. Der Quelltext ist im Internet verfügbar: www.haase-consulting.com/download/oop2002

Test vor Implementierung Man kann den Test schon beim Nachdenken über die geplante Funktionalität schreiben. Kleine Schritte: Ein wenig Testen, ein wenig Implementieren usw. Wenn der Test erfolgreich durchläuft, ist man fertig

Erst fehlschlagen lassen Das Ausprobieren des Tests vor der Implementierung gibt Sicherheit. Vielleicht klappt er ja schon... Man stellt sicher, dass er tatsächlich ausgeführt wird

Tests als Dokumentation Die Tests dokumentieren die getesteten Klassen genau. Sie zeigen die nötige Initialisierung Sie enthalten ein Beispiel für jede Methode Die Dokumentation ist nie veraltet

Beispiel (3) Das Beispiel wird noch einmal erweitert. Der Quelltext ist im Internet verfügbar: www.haase-consulting.com/download/oop2002

Tests als Sicherheitsnetz Gute Tests schützen davor, unbeabsichtigt Funktionalität zu ändern, auf die sich andere Klassen verlassen. Das ist eine Voraussetzung für zuversichtliches Refactoring Es hilft auch bei Erweiterungen und Änderungen

Wie fängt man an? Tests Schreiben braucht Übung, aber… der Einstieg ist leicht eine unvollständige Test-Suite ist hilfreich und kann organisch wachsen durch Refactoring kann man später die Tests verbessern Testen macht Spaß

Zusammenfassung Refactoring Das Umfeld von Refactoring „Code Smells“ JUnit

Übersicht Einführung Das Umfeld für Refactoring „Code Smells“ als Wegweiser Automatisierte Tests mit JUnit  Konkrete Refactorings Beispiel Toolunterstützung

Katalog Der Katalog ist Hilfestellung. Ziel ist „besserer Geruch“: Eigenes Urteil! Probieren und Fehler sind ungefährlich: JUnit-Tests Man kann alles rückgängig machen Einstieg: Problem Konkrete Schritte: damit man nichts vergisst Am Ende: Immer compilieren und testen

Change Inconsistent Layout Quelltext ist inkonsistent formatiert, insbesondere eingerückt. Layout an Quelltextrichtlinien anpassen Möglichst toolgestützt NICHT den eigenen Geschmack aufzwingen!

Replace Magic Number with Symbolic Constant In einer Methode steht eine Zahl (außer 0 und 1). Besser eine benannte Konstante einführen Name ist Dokumentation Wert ist besser änderbar Typcode, Arraylänge o.ä.? Dann Alternative wählen

Replace Temp with Query Eine temporäre Variable enthält ein Zwischenergebnis. Den entsprechenden Ausdruck in eine Methode auslagern Ursprüngliche Methode wird übersichtlicher Verfügbar im ganzen Objekt

Rename Method (1) Der Name einer Methode spiegelt nicht (mehr) ihren Inhalt wieder. Den Namen ändern Analog Parameter hinzufügen oder entfernen

Rename Method (2) Konkrete Schritte: Basis- und Unterklassen prüfen Methode mit neuem Namen anlegen, Implementierung hineinkopieren, compilieren Clients schrittweise umstellen, jeweils testen Ursprüngliche Methode löschen, Testen

Replace Constructor with Factory Method Konstruktor ist nicht flexibel genug. Besser statische create-Methode verwenden Kontrolle über Instanzierung (Unterklassen, Caching, Referenz-Semantik) Expliziter Name dokumentiert

Extract Method (1) Mehrere Statements einer Methode gehören logisch zusammen. Auslagern in eigene Methode Sprechender Name für die neue Methode Ursprüngliche Methode wird übersichtlicher

Extract Method (2) Konkrete Schritte: Neue Methode anlegen und gut benennen Implementierung hineinkopieren Notwendige Parameter anlegen und benennen Ggf. Rückgabewert einführen Compilieren Code in ursprünglicher Methode durch Aufruf ersetzen

Inline Method (1) Der Code einer Methode ist genauso klar wie ihr Name. Methode inlinen Unnötige Methode ist nur Ballast Gegenstück zu „Extract Method“

Inline Method (2) Konkrete Schritte: Prüfen, dass die Methode nicht polymorph ist Jeden Aufruf durch den Inhalt ersetzen Compilieren und testen Methode löschen Bei Komplikationen nicht inlinen

Remove Assignments to Parameters Eine Methode enthält eine Zuweisung an einen Parameter. Stattdessen temporäre Variable verwenden Erhöht Übersichtlichkeit

Replace Method with Method Object (1) Eine Methode verwendet lokale Variablen so, dass Extract Method schwierig ist. Neue Klasse anlegen, die der Methode entspricht Lokale Variablen werden zu Attributen Danach ist Refactoring leicht

Replace Method with Method Object (2) Konkrete Schritte: Neue Klasse anlegen Referenz auf ursprüngliche Klasse sowie Attribute für die lokalen Variablen einführen Konstruktor zur Initialisierung Methode „compute“ einführen und die ursprüngliche Implementierung hineinkopieren In der alten Methode an die neue delegieren

Substitute Algorithm Ein Algorithmus ist komplizierter als nötig. Durch einen einfacheren Algorithmus ersetzen Insbesondere, wenn zwei verschiedene Algorithmen für das Gleiche verwendet werden Optimierung allenfalls am Ende

Move Method (1) Eine Methode benutzt mehr Features oder wird von mehr Features einer anderen Klasse benutzt als der, wo sie definiert ist. Methode zu den Features verschieben Stärkere Kohäsion, schlankere Schnittstellen Das Original delegiert oder wird gelöscht

Move Method (2) Konkrete Schritte: Benutzte Felder und Methoden ggf. mitverschieben Vererbungshierarchie prüfen Methode in der neuen Klasse deklarieren Implementierung hineinkopieren und anpassen Compilieren Aufrufe ändern oder alte Methode umbiegen

Move Field (1) Ein Feld wird in einer anderen Klasse mehr benutzt Dorthin verschieben Bessere Kohäsion und schlankere Schnittstelle Eventuell Methoden mitverschieben

Move Field (2) Konkrete Schritte: In Zielklasse ein Feld mit get- und set-Methode anlegen Navigation von alter zu neuer Klasse sicherstellen Ursprüngliches Feld entfernen Zugriffe umbiegen (inkl. Unterklassen) Compilieren und testen

Extract Class (1) Eine Klasse macht die Arbeit von zweien. Neue Klasse anlegen und Felder und Methoden hineinverschieben Übersichtlichkeit durch klare Aufgabenteilung

Extract Class (2) Konkrete Schritte: Aufteilung planen Neue Klasse anlegen, Referenz von alter zu neuer Einzelne Felder und Methoden verschieben Schnittstellen überarbeiten Ggf. neue Klasse veröffentlichen (Referenz/Wert)

Hide Delegate Ein Client holt sich von einem Objekt ein anderes Objekt und ruft darauf eine Methode auf. Im ersten Objekt eine Methode erzeugen, die dann delegiert Dadurch bessere Kapselung

Remove Middle Man Eine Klasse delegiert eine Reihe von Aufrufen einfach an ein anderes Objekt. Stattdessen inneres Objekt herausreichen get-Methode einführen Dadurch Übersichtlichkeit erhöhen

Replace Data Value with Object Ein primitives Attribut hat eigentlich dazugehörige Funktionalität. Spezielle Klasse schaffen und deren Instanz verwenden Clients nach und nach umstellen Wert-Semantik: Identität spielt keine Rolle

Replace Type Code with Subclass (1) Eine Klasse hat einen Typcode, der über das Verhalten entscheidet. Für jeden Wert des Typcodes eine Unterklasse Grundlage für weitere Refactorings

Replace Type Code with Subclass (2) Konkrete Schritte: Auf Typcode nur durch get-Methode zugreifen statische create-Methode einführen Für jeden Wert eine Unterklasse einführen, die die get-Methode überschreibt Typcode-Attribut aus der Basisklasse entfernen

Replace Type Code with State/Strategy (1) Ein Typ-Code entscheidet über Verhalten, aber es gibt schon Unterklassen. Zweite Vererbungshierarchie für Typ-Code Als State/Strategy anbinden

Replace Type Code with State/Strategy (2) Konkrete Schritte: Den Typ-Code hinter get-Methode kapseln Neue Klasse mit Unterklassen für jeden Wert schaffen (State-Klasse) Typ-Code in die neue Klassenhierarchie verschieben Beim Setzen des Typ-Codes stattdessen State ändern Typ-Feld entfernen

Replace Conditional with Polymorphism (1) Verhalten wird über einen Typ-Code ausgewählt. Für jeden Typcode eine Unterklasse Spezifisches Verhalten jeweils in einer überschriebenen Methode Man vergisst keine Fälle und gruppiert Logik

Replace Conditional with Polymorphism (2) Konkrete Schritte: Replace Type Code with ... Ggf. Fallunterscheidung in eigene Methode Der Reihe nach: Für Unterklassen die Methode überschreiben und testen Den Fall aus der ursprünglichen Methode entfernen und testen Methode in der Basisklasse abstrakt machen

Replace Subclass with Fields (1) Unterklassen unterscheiden sich nur in Methoden, die konstante Werte liefern. Die Unterklassen entfernen und die Werte aus Attributen holen Die Unterklassen sind unnötiger Ballast geworden

Replace Subclass with Fields (2) Konkrete Schritte: Statische create-Methode einführen final Felder in der Basisklasse einführen mit protected Konstruktor, der sie initialisiert Unterklassen so ändern, dass sie diesen aufrufen Die Methoden in der Basisklasse ändern, so dass sie die Werte der Felder liefern Unterklassen entfernen

Consolidate Duplicate Conditional Fragments Ein gemeinsames Stück Code ist in allen Zweigen einer Fallunterscheidung. Gemeinsamen Code herausziehen Entweder davor oder dahinter Sonst eventuell in eigene Methode

Remove Control Flag Ein Flag kontrolliert den Ablauf einer Schleife. Besser break, continue und return verwenden Kürzer und übersichtlicher

Replace Nested Conditional with Guard Clause Eine Methode hat verschachtelte if-Statements, um ohne zweites return auszukommen. Sonderfälle am Anfang behandeln und dort direkt zurückkehren Prüflogik in eigene Methoden auslagern Normalfall wird explizit

Separate Query from Modifier (1) Eine Methode führt eine Abfrage durch und ändert gleichzeitig den Zustand des Objekts. Aufspalten in reine Abfrage und Modifikation Reine Abfrage ist vielseitig einsetzbar und leicht zu verstehen Optimieren allenfalls später Multithreading / Remote: Sonderfälle

Separate Query from Modifier (2) Konkrete Schritte: Die reine Abfrage als eigene Methode bauen In der ursprünglichen Methode das Ergebnis der Abfrage zurückgeben Compilieren und testen In Aufrufen die Abfrage in eigenen Aufruf vor die alte Methode setzen Rückgabe der alten Methode entfernen

Parameterize Method Mehrere Methoden tun das Gleiche mit unterschiedlichen fest verdrahteten Werten. Zusammenführen in eine einzige Methode mit Parameter Vermeidet Code-Duplizierung

Replace Parameter with Explicit Methods Ein Methode macht völlig verschiedene Dinge abhängig vom Wert eines Parameters. In mehrere Methoden mit sprechenden Namen zerlegen

Preserve Whole Object Eine Methode bekommt mehrere Attribute des gleichen Objekts als Parameter. Besser das ganze Objekt als Parameter hineinreichen Außer man will bewusst entkoppeln

Replace Parameter with Method Eine Methode bekommt einen Parameter, den sie auch selbst ermitteln könnte. Parameter ermitteln und aus der Signatur entfernen Durch Methode von this oder von einem anderen Parameter

Introduce Parameter Object (1) Mehrere Parameter bilden eine natürliche Einheit. Zu einem neuen Typ zusammenfassen Wertsemantik Typsicher, besser lesbar

Introduce Parameter Object (2) Konkrete Schritte: Neue Klasse leer anlegen Die Parameter als Attribute hinzufügen. Dabei die Werte immutable machen Den jeweiligen Parameter aus dem Aufruf entfernen. Compilieren und Testen Funktionalität in die neue Klasse extrahieren

Remove Setting Method Ein Feld wird nur bei der Erzeugung gesetzt und anschließend nicht mehr geändert. Ggf. Konstruktor einführen Set-Methode entfernen Feld final machen

Encapsulate Downcast Eine Methode liefert eine Referenz, die erst nach Downcast verwendbar ist (z.B. ein Element einer Collection). Downcast in der Methode durchführen und den richtigen Typ zurückliefern Erhöht die Übersichtlichkeit und Typsicherheit

Pull Up Method Unterklassen haben Methoden mit dem gleichen Ergebnis. Methoden in die Basisklasse verschieben Code-Duplizierung vermeiden Eventuell unterschiedliche Algorithmen

Push Down Method Eine Methode der Basisklasse wird nur von einer Unterklasse verwendet. Die Methode in diese Unterklasse verschieben Macht die Basisklasse einfacher Dokumentiert die Abhängigkeiten

Extract Superclass Mehrere Klassen haben teilweise die gleichen Methoden. Gemeinsamkeiten in eine Basisklasse ziehen Dokumentiert Beziehung zwischen den Klassen Öffnet den Blick für Verwendung dieser neuen Abstraktion

Form Template Method (1) Unterklassen haben Methoden, die ähnliche Schritte in der gleichen Reihenfolge durchführen. Methoden extrahieren für Schritte, die von einer neuen Methode der Basisklasse aufgerufen werden Vermeidet Code-Duplizierung, dokumentiert Beziehungen

Form Template Method (2) Konkrete Schritte: Methoden zerlegen Methodensignaturen vereinheitlichen Jeweils compilieren und testen Ursprüngliche Methode in Basisklasse ziehen

Replace Inheritance with Delegation Eine Unterklasse will nur einen Teil der Schnittstelle der Basisklasse haben. Besser Aufrufe an eine Instanz der Basisklasse durchreichen Klarere Beziehungen: Vererbung legt Polymorphie nahe

Der Code ist das Design Alle hier präsentierten Refactorings wollen das Design im Quelltext klarer ausdrücken. Namen sind sehr wichtig Klarheit und Einfachheit Compilerunterstützung Diese Ziele sind wichtiger als das Verwenden konkreter Refactorings!

Übersicht Einführung Das Umfeld für Refactoring „Code Smells“ als Wegweiser Automatisierte Tests mit JUnit Konkrete Refactorings  Beispiel Toolunterstützung

Beispiel Ein praktisches Beispiel der Refactorings Der Quelltext ist im Internet verfügbar: www.haase-consulting.com/download/oop2002

Übersicht Einführung Das Umfeld für Refactoring „Code Smells“ als Wegweiser Automatisierte Tests mit JUnit Konkrete Refactorings Beispiel  Toolunterstützung

Toolunterstütztes Refactoring Die Durchführung des Refactoring lässt sich weitgehend automatisieren. Schutz vor Flüchtigkeitsfehlern Mehr als „Suchen und Ersetzen“ Plausibilitätsprüfungen

Kriterien für Toolauswahl Folgende Punkte stellen Kriterien für die Auswahl eines Refactoring-Tools dar: Zuverlässigkeit Integration mit IDE Auf dem Parse-Baum operieren („Extract Method“ als Indiz) Geschwindigkeit

Refactoring-Tools Hier eine Auswahl von aktuellen Refactoring-Tools für Java: Idea (www.intellij.com) Xrefactory (xref-tech.com/speller) Eclipse (www.eclipse.org) ...

Toolunterstützung praktisch Demonstration für toolgestütztes Refactoring So einfach kann Refactoring in der Praxis sein.

Literatur Folgende Quellen sind gute Startpunkte für eine Vertiefung: „Refactoring“, Martin Fowler www.refactoring.org www.junit.org „Extreme Programming Explained“, Kent Beck

Zusammenfassung Refactoring Das Umfeld von Refactoring „Code Smells“ JUnit Refactoring-Katalog Toolunterstützung