Refactoring Java Code Arno HaaseHaaseConsulting com Arno Haaseacm
- Slides: 134
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 2
„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 3
Refactoring: Definition „Refactoring ist die Verbesserung der Qualität von vorhandenem Quelltext ohne Veränderung der Funktionalität. “ 4
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 5
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 6
Demonstration • Ein Quelltext sagt mehr als tausend Folien. . . § Der Quelltext ist im Internet verfügbar: www. haase-consulting. com/download/oop 2002 7
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 8
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 9
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 10
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 11
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. 12
Übersicht • Einführung Das Umfeld für Refactoring • „Code Smells“ als Wegweiser • Automatisierte Tests mit JUnit • Konkrete Refactorings • Beispiel • Toolunterstützung 13
Altersschwäche • Software kann an Altersschwäche sterben. § Design wächst nicht mit den Anforderungen § Wartung als Albtraum § Manchmal schon vor Inbetriebnahme. . . 14
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) 15
Traditionelles Vorgehen • Das Wasserfall-Modell ist immer noch sehr verbreitet. § Änderungen werden mit der Zeit teurer § Risiko minimieren 16
Änderungen billig machen • Agile Vorgehensmodelle unterstützen späte Änderungen § Z. B. e. Xtreme Programming § Weniger Gewicht auf Planung am Anfang § System profitiert von wachsender Erfahrung 17
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. 18
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 19
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 20
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. 21
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“ 22
Versionsverwaltung • Eine Versionsverwaltung ist eine wichtige Voraussetzung für Refactoring, besonders im Team. § Reversibilität von Refactorings § Kurze Check-In-Zyklen 23
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 24
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 25
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. “ 26
„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 27
„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 28
„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. 29
„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. . . 30
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 31
Grenzen des Refactoring • Es gibt Situationen, wo Refactoring nicht gut funktioniert. § Relationale Datenbanken § Fixierte Schnittstellen § Hoffnungslos kaputtes System 32
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! 33
Übersicht • Einführung • Das Umfeld für Refactoring „Code Smells“ als Wegweiser • Automatisierte Tests mit JUnit • Konkrete Refactorings • Beispiel • Toolunterstützung 34
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? 35
„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 36
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 37
Datenklasse • Eine Klasse, die nur Daten und keine Logik enthält, ist ein Indiz für Verbesserungspotential § Oft gibt es Funktionalität, die im Wesentlichen auf diesen Daten operiert § Andernfalls ist vielleicht die Klasse schlecht geschnitten 38
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 39
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 40
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 41
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 42
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 43
Monster-Klasse • Eine zu große Klasse wird unübersichtlich. § Zu viele Attribute führen leicht zu Code. Duplizierung 44
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$ 45
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$ 46
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 47
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 48
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 49
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 50
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 51
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 52
Vermittler • Wenn viele Methoden einer Klasse den Aufruf einfach nur durchreichen, macht das Interface unnötig kompliziert. § Der Client sollte stattdessen direkt mit dem inneren Objekt reden 53
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 54
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 55
Übersicht • Einführung • Das Umfeld für Refactoring • „Code Smells“ als Wegweiser Automatisierte Tests mit JUnit • Konkrete Refactorings • Beispiel • Toolunterstützung 56
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. 57
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 58
Beispiel • Ein dummes aber einfaches Beispiel. . . § Der Quelltext ist im Internet verfügbar: www. haase-consulting. com/download/oop 2002 59
Integration in IDE • Der Aufruf von JUnit ist einfach. § junit. jar in den Class. Path § junit. swingui. Test. Runner als Main-Klasse § Den Namen des Testfalls als Kommandozeilenparameter 60
Eine Testklasse je Klasse • Typischerweise schreibt man zu jeder Klasse eine Testklasse. § Testklasse erbt von junit. framework. Test. Case § Per Namenskonvention endet der Name der Testklasse mit „Test“ Test. Case Briefmarke. Test 61
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 62
Assertions • Die eigentlichen Tests erfolgen als Aufrufe der assert. . . -Methoden von Test. Case. § Wenn die Bedingung erfüllt ist, passiert nichts § Wenn die Bedingung nicht erfüllt ist, wird dieser Test abgebrochen und als fehlgeschlagen vorgemerkt 63
Test. Suite • Mehrere Tests können als Test. Suite zusammengefasst werden. § Klasse junit. framework. Test. Suite § Eine Test. Suite kann Test. Cases und Test. Suites enthalten Test. Case 1. . * Test. Suite 64
Beispiel (2) • Eine zweite Klasse mit Tests kommt dazu. § Der Quelltext ist im Internet verfügbar: www. haase-consulting. com/download/oop 2002 65
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 66
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 67
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 68
Beispiel (3) • Das Beispiel wird noch einmal erweitert. § Der Quelltext ist im Internet verfügbar: www. haase-consulting. com/download/oop 2002 69
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 70
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ß 71
Zusammenfassung • • Refactoring Das Umfeld von Refactoring „Code Smells“ JUnit 72
Übersicht • Einführung • Das Umfeld für Refactoring • „Code Smells“ als Wegweiser • Automatisierte Tests mit JUnit Konkrete Refactorings • Beispiel • Toolunterstützung 73
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 74
Change Inconsistent Layout • Quelltext ist inkonsistent formatiert, insbesondere eingerückt. § Layout an Quelltextrichtlinien anpassen § Möglichst toolgestützt § NICHT den eigenen Geschmack aufzwingen! 75
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 76
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 77
Rename Method (1) • Der Name einer Methode spiegelt nicht (mehr) ihren Inhalt wieder. § Den Namen ändern § Analog Parameter hinzufügen oder entfernen 78
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 79
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 80
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 81
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 82
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“ 83
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 84
Remove Assignments to Parameters • Eine Methode enthält eine Zuweisung an einen Parameter. § Stattdessen temporäre Variable verwenden § Erhöht Übersichtlichkeit 85
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 86
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 87
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 88
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 89
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 90
Move Field (1) • Ein Feld wird in einer anderen Klasse mehr benutzt § Dorthin verschieben § Bessere Kohäsion und schlankere Schnittstelle § Eventuell Methoden mitverschieben 91
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 92
Extract Class (1) • Eine Klasse macht die Arbeit von zweien. § Neue Klasse anlegen und Felder und Methoden hineinverschieben § Übersichtlichkeit durch klare Aufgabenteilung 93
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) 94
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 95
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 96
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 97
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 98
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 get-Methode überschreibt § Typcode-Attribut aus der Basisklasse entfernen 99
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 100
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 101
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 102
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 103
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 104
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 105
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 106
Remove Control Flag • Ein Flag kontrolliert den Ablauf einer Schleife. § Besser break, continue und return verwenden § Kürzer und übersichtlicher 107
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 108
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 109
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 110
Parameterize Method • Mehrere Methoden tun das Gleiche mit unterschiedlichen fest verdrahteten Werten. § Zusammenführen in eine einzige Methode mit Parameter § Vermeidet Code-Duplizierung 111
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 112
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 113
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 114
Introduce Parameter Object (1) • Mehrere Parameter bilden eine natürliche Einheit. § Zu einem neuen Typ zusammenfassen § Wertsemantik § Typsicher, besser lesbar 115
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 116
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 117
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 118
Pull Up Method • Unterklassen haben Methoden mit dem gleichen Ergebnis. § Methoden in die Basisklasse verschieben § Code-Duplizierung vermeiden § Eventuell unterschiedliche Algorithmen 119
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 120
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 121
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 122
Form Template Method (2) • Konkrete Schritte: § § Methoden zerlegen Methodensignaturen vereinheitlichen Jeweils compilieren und testen Ursprüngliche Methode in Basisklasse ziehen 123
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 124
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! 125
Übersicht • Einführung • Das Umfeld für Refactoring • „Code Smells“ als Wegweiser • Automatisierte Tests mit JUnit • Konkrete Refactorings Beispiel • Toolunterstützung 126
Beispiel • Ein praktisches Beispiel der Refactorings § Der Quelltext ist im Internet verfügbar: www. haase-consulting. com/download/oop 2002 127
Übersicht • Einführung • Das Umfeld für Refactoring • „Code Smells“ als Wegweiser • Automatisierte Tests mit JUnit • Konkrete Refactorings • Beispiel Toolunterstützung 128
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 129
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 130
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). . . 131
Toolunterstützung praktisch • Demonstration für toolgestütztes Refactoring § So einfach kann Refactoring in der Praxis sein. 132
Literatur • Folgende Quellen sind gute Startpunkte für eine Vertiefung: § § „Refactoring“, Martin Fowler www. refactoring. org www. junit. org „Extreme Programming Explained“, Kent Beck 133
Zusammenfassung • • • Refactoring Das Umfeld von Refactoring „Code Smells“ JUnit Refactoring-Katalog Toolunterstützung 134
- Bài thơ mẹ đi làm từ sáng sớm
- Cơm
- Refactoring: improving the design of existing code
- Code refactoring
- Java compiler translates java source code into
- Joshua kerievsky
- Refactoring vs shimming
- Bascop
- Software refactoring beratung
- Extreme programming refactoring
- Refactoring and restructuring methods
- A survey of software refactoring
- Busceral
- 1900-1450
- Istituto comprensivo galvaligi solbiate arno
- Arno kumagai
- Arno hernadi
- Fmvft equipment at controlled station has
- Arno gildemeister
- Arno wonisch
- Arno rosemarin
- Arno rosemarin
- State various types of track electrification system
- Arno wonisch
- Affluenti fiume arno
- Calor seb
- Arno boersma
- Arno hintersteininger
- Arno hintersteininger
- Arno holz rote dächer
- Verruca seborrhoica dermatoscopie
- Le protecteur arno breker
- Arno klarsfeld et carla bruni
- Import java.util.*
- Import java.util.*
- Import java.awt.*
- Import.java.util
- Import java.io.file
- Gcd java
- Str2str 使い方
- Java import java.io.*
- Java import java.util.*
- Java thread import
- Perbedaan swing dan awt
- Import java.awt.event.*;
- Rmi javatpoint
- Ricart-agrawala algorithm code in java
- Java code symbols
- Java runtime code generation
- Syntax analyzer source code in java
- Java code review checklist pdf
- Mlfq scheduler
- Code playground java
- Eclipse erd
- C++ yahtzee program code
- Java minesweeper code
- How to code autonomous frc java
- Code in java
- Uml china
- Runtime code generation
- Code java
- Programming language level virtualization
- Digital bank robbery
- Java code
- Neerja bhatnagar
- Documenting java code
- Code élaboré code restreint
- Managed code unmanaged code
- Language translator
- Difference between source code and machine code
- Linguistic repertoire definition
- Trace the code genetic code table
- Java soap xml 파싱
- Java xml
- West java leaders reading challenge
- Java array to list
- Jux java
- Vadim java
- Math scanner
- App inventor java bridge
- Extends and implements difference
- Array list and vector in java
- Java.net package
- Palabras claves de java
- Object mentor
- Gonewdoc
- Java truth table
- Ift nc
- Java sequential search
- Recursive descent parser java
- Open source java games
- Math functions in java
- Java hyper text
- Sub java.me
- Language java
- Java fft
- Bisection method in java
- String vs character
- Mockolás
- Java ful
- Operatory w js
- 10000
- Tcp/ip sockets in java: practical guide for programmers
- Tail recursive
- Member info
- Sun java certification
- Suffix array java
- Boost tokenizer example
- Import java.util.string
- String manipulation java
- What is lexicographically in java
- Konsep stream
- Java deadlock detection
- Josephus problem using queue
- Worms java
- Access specifiers in java
- Java client server tutorial
- Socket java example
- Socket java example
- Sobre carga de operadores
- Sumbu koordinat pada java menyatakan titik (0,0) pada ...
- Copy constructor in java
- Abstract
- Import java.util.stringtokenizer;
- Java secure coding
- иерархия collection java
- Java exception checked vs unchecked
- Property design patterns for java beans
- Standard deviation formula java
- Regex meaning java
- Reflection vs introspection java
- Generische doppelt verkettete liste java
- How recursion works
- Small n design
- Flow control