Okay, dann würde ich sagen, lasst uns anfangen.
Herzlich willkommen zur zwölften Vorlesung. Ich muss kurz vorweg einen kleinen Disclaimer machen.
Wer jetzt kein Blut sehen kann, sollte vielleicht nicht auf
das Bild gucken. Also es wird nicht zu eklig,
aber ich bin heute Morgen Rad gefahren und bin dann irgendwie
hingefallen und habe mir irgendwie die Hand ziemlich aufgeschürft.
Das ist jetzt ganz gut getaped und so. Ich bin ja ganz friedlich,
aber also der Blutverlust war nicht sehr hoch,
aber Bremsen mit der Hand ist keine gute Idee.
Es lag eher daran, dass ich,
also ich kann Rad fahren, nicht dass ihr das jetzt glaubt,
dass ich irgendwie so ein alter Mann bin,
der ja nicht mehr richtig Rad fahren sollte,
sondern es lag tatsächlich eher daran,
dass ich mit einer Hand gefahren bin.
Also so an der Hand hatte ich irgendwie nicht verstauen konnte und dann zwar kein Handy.
Ja. Das nur als kleine Erläuterung, weil ich bin fit,
ja, aber ich habe so das Gefühl,
ich bin so ein bisschen müde, so ein bisschen kaputt ist.
Also ich bin dem Tod von der Schippe gesprungen heute Morgen quasi
und habe mir dann auch gleich erzählen lassen von anderen Leuten,
die mich dann verarztet haben, dass andere sich da schon tief vorbeigebrochen haben,
wenn sie so vorne über vom Rad gesprungen sind.
Also ich habe mir nur das Kind so ein bisschen aufgeschlagen,
aber es ist nicht blutig.
So, das nur so als vorweg kleine Anekdote.
Heute geht es ums Thema Refactoring
Ich werde ein bisschen was darüber erzählen, warum man Refactoring
überhaupt als Thema inzwischen in der Informatik Ärzt nimmt.
Wir werden uns den Begriff Refactoring etwas genauer ansehen.
Dann werden wir uns ansehen, was üble Gerüche sind.
Also genau der Grund, die genau der Grund sind,
warum man Refactorings ansetzen sollte.
Dann werden wir uns ziemlich genau mal die Mechanik von ein,
zwei Refactorings ansehen, um sozusagen genauer zu verstehen,
was da alles so passiert, wenn refacted wird.
Dann gucken wir uns die Werkzeugunterstützung an. Das ist,
was ihr so kennt, auch aus den Clips teilweise.
Und zum Schluss dann noch einen Ausblick auf große Refactorings
Als Literaturhinweise ganz explizit und klar der Fauler,
das ist quasi die Referenz zum Thema Refactoring.
Auf jeden Fall der beste Einstieg, wenn man objektorientierte Entwürfe beherrschen will,
dann sollte man auch den Fauler mal gelesen haben,
um zu sehen, was es so alles für Möglichkeiten gibt,
schlechtere Entwürfe, in bessere Entwürfe umzuwandeln.
Er nennt das Improving the Design of Existing Code.
Wie gesagt, ist sehr empfehlenswert,
wenn ihr in der vorlesungsfreien Zeit das Gefühl habt,
ihr seid geistlich unterverversorgt,
dann ist das mit mindestens eines der Bücher,
das ich empfehlen kann
Es ist sowieso ganz schlau, Bücher zu lesen. Ich weiß nicht,
ob das noch so angesagt ist, unbedingt,
aber tatsächlich gibt es gute Bücher und teilweise ist es einfach sehr hilfreich,
mal so die Klassiker herzunehmen und das ist bestimmt einer von denen.
Also ein moderner Klassiker, kann man sagen. Dann gibt
es noch ein Buch von Stefan Ruck und Martin Lippert,
das sind ehemalige Kollegen vom Arbeitsbereich Software-Technik.
Die haben ihre Erfahrungen in großen Software-Projekten,
insbesondere große Refactoring-Stars haben sie einfach mal festgehalten. Groß heißt,
so ein Refactoring läuft dann über mehrere Tage,
Wochen vielleicht oder auch Refactorings von Datenbanken,
also bei komplexeren Systemen hat man nicht mehr nur die reine OO-Welt,
sondern auch Datenbanken mit eingebunden und auch da muss man natürlich Fallen Strukturen ändern.
Dass er, wie gesagt, weiterführt. Wäre mir lieb
, wenn ihr nicht so laut redet. Ich höre leider
relativ viele Leute reden. Das ist ein bisschen lästig,
weil dann die Leute, die zuhören wollen, nicht gut zuhören können.
Einfach draußen unterhalten, einfach rausgehen. Ich bin nicht
böse, wenn ihr nicht in der Vorlesung sitzt.
Ich bin nur böse, wenn ihr hier sitzt und redet.
Okay, diese Folge habe ich, glaube ich, schon zweimal gezeigt.
Software ist keine Prosa, die einmal geschrieben wird,
dann fertig ist, sondern Software wird erweitert, korrigiert,
gewartet, portiert,
adaptiert und so weiter
Was ganz wichtig ist, das machen eben halt üblicherweise nicht eine dieselbe Person,
sondern durchaus wechselnde Teams, arbeiten mit der Software, das geht teilweise über Jahrzehnte.
Also es ist jetzt wirklich kein Blödsinn,
es gibt ganz viel Software, die seit 20,
seit 30 Jahren in Betrieb ist und vermutlich auch noch weitere 20,
30 Jahre auch einen Buckel behalten muss.
Und da ist es dann schon ganz wichtig, dass man in der Lage ist,
die Software auch zu warten und auch zu verändern und anzupassen.
Es gibt nur zwei Optionen, klar,
entweder sie wird gewartet oder sie stirbt,
das ist eine Jahre Ansage, die wir hier machen,
dass wir sagen, Software, die man loslässt,
die man in Ruhe lässt, die man liegen lässt,
die wird irgendwann einfach hinfällig sein.
Software ist leider genau von dieser Art.
Ich hatte letzte Woche oder vorletzte Woche,
als ich diese Folie ähnlich drauf hatte, ein Zitat von Herrn Parnas.
Diesmal habe ich ein Zitat von Martin Fauler,
auch aus diesem Buch, aus diesem Refactoring-Buch.
Das finde ich ganz schön. Any fool can right
code that the computer can understand. Good program as right
code that humans can understand. Das ist ziemlich genau der
Geist dieses Buches
Es ist ein bisschen arrogant im Sinne von Annie Fool,
can right coater, the computer can our stand.
Das ist die eine Seite des Programmierens. Das ist die Seite,
ich bringe den Computer dazu, dass er das macht, was ich will.
Das ist nicht so einfach. Er sagt zwar,
natürlich, das ist nur ein Teil der Geschichte.
Also zu verstehen, wie ein Computer arbeitet, zu verstehen,
welches Problem man muss und das dann richtig zu probieren,
das ist schon ganz ohne. Aber, und das ist eben das,
was er sagt, was dann die Qualität ausmacht,
ist, dass man das dann so schreibt,
dass andere Leute das auch noch lesen können,
verstehen können, warten können, weiterentwickeln können.
Das ist schon ein sehr knappes, passendes Zitat,
was das ganz gut widerspiegelt, was er vertritt.
Okay, er motiviert seine Refacts,
was das genau ist, werden wir gleich noch sehen.
Über üble Gerüche in Software. Das ist einfach so,
wenn sich Software verändert,
wenn sie angepasst werden muss,
dann muss sie häufig
auch intern restrukturiert werden
Und hoffe ich ist es eben halt so,
dass ein bestimmter Entwurf, den wir mal gemacht haben,
durch die veränderten Anforderungen nicht mehr ganz passt.
Und wenn wir einen Entwurf haben, also ein bestehendes System,
das uns Änderungen erschwert, dann sollten wir den Entwurf tatsächlich auch überdenken.
Das heißt, Änderungen erschwert, naja, also es gibt manchmal so Situationen,
da möchte man etwas hinzubauen zu einem System und stellt fest,
oh, wenn wir das jetzt machen, dann wird es richtig hässlich.
Ich weiß nicht, ob ihr das schon mal hattet,
aber wenn ihr dann mehr Programmiererfahrung seid, werdet ihr merken,
es gibt einfach immer wieder so Situationen, da merkt man,
das, was jetzt dazukommt, das passt nicht mehr in die Struktur,
das ist irgendwie komisch.
Und dann ist halt immer die Frage,
baut man es dann einfach dazu und das ist dann hässlich oder überlegt man,
ob man den Entwurf Über dich, überdingt.
Und vielleicht ändert und so. Und die Frage ist natürlich immer,
wann werden denn Änderungen erschwert? Wann ist es denn schwierig,
einen bestehenden Entwurf zu ändern oder zu erweitern? Die Hinweise,
die es so gibt, eher so auf der, naja,
relativ einfachen Seite, sowas, was hier erwähnt ist,
jetzt, das sind ja nur Beispiele,
eine Methode ist zu lang, auf den Bildschirm überblicken zu können.
Das deutet darauf hin, dass irgendjemand da mal eine
kleine Methode geschrieben hat, die dann immer größer wurde,
da wurde immer mehr reingeschmissen und dann geht sie nicht mehr auf einen Bildschirm.
Wir haben immer so als Heuristik hier eine Bildschirmseite mehr größer sollte, eine Methode nicht sein.
Kommt natürlich auf die Größe des Bildschirms an, ja,
in Zeiten von immer größeren Bildschirmen, kann man auch immer größere Methoden schreiben.
Aber im Prinzip ist es schon so, man möchte eigentlich
als Mensch das überblicken können. Man möchte sehen können,
was die Methode macht von oben bis unten. Oder auch sowas,
wenn dieselbe Fallunterscheidung an mehreren Stellen in einem System vorgenommen wird,
Code-Duplizierung habe ich schon erwähnt, als eine Entwurfsschwäche, ist halt ein klassischer Bad Smell.
Wenn ich irgendwie sehe, oh Mensch, diesen Code,
den habe ich doch irgendwie schon mal gesehen,
dann geht man in eine andere Klasse,
dass ich dann den gleichen Code irgendwie fünf 10,
20 Zeilen sehen sehr ähnlich aus, vielleicht sogar identisch,
dann ist das eindeutig ein schlechter Geruch.
Dann riecht das einfach komisch. Das ist ganz interessant,
so diese Metapher mit den Gerüchen, das ist etwas,
was man nur mit der Zeit bekommt,
so ein Gefühl dafür, wann etwas nicht schön ist.
Und das ist eben halt auch, da braucht man einfach
viel Entwurfserfahrung. Also es kommt nicht von alleine,
dass man jetzt irgendwie hier Regeln anwendet,
sondern es ist auch tatsächlich viel, ja,
diese Entwurfsregeln immer wieder ausprobieren, immer wieder anwenden,
immer wieder bei einem Entwurf darüber nachdenken,
welche Entwurfsregeln können hier greifen.
Und dann mit der Zeit wird das
irgendwie relativ automatisch passieren
Ja, und generell sind Verstöße gegen bekannte Entwurfsregeln meist Kandidaten für üble Gerüche.
Das ist also relativ eng zusammenhängend. Die Frage von Refactorings
und Entwürfen. Hier ist mal die, sagen wir,
die allerknappeste Definition, was überhaupt im Refactoring heißt.
Wir sind ja in der Uni immer schön Definitionen.
Also Refactoring bedeutet, die interne Struktur einer Software zu verbessern,
ohne ihr beobachtbares Verhalten zu verändern.
Aha, also ich ändere etwas an einer Software und die
Änderung wird aber für einen Benutzer der Software nicht sichtbar.
Das heißt, das Einfügen zusätzlicher Funktionalität ist definitiv kein Refactoring.
Also es ist immer gut
Auch gut, etwas zu definieren über das, was es
nicht ist. Das ist es auf jeden Fall nicht.
Also wenn ich neue Funktionalitäten zubaue, ist das kein Refactoring.
Also im Sprachgebrauch wird das stellenweise ein bisschen verwässert. Dass man sagt,
ja, der Refactoring lassen bauen das da ein, so,
das ist so das Gleiche, ist nicht das Gleiche.
Neue Funktionalität, kein Refactoring. Auch Bugfixing, wir heben von Fehlern,
ist kein Refactoring. Wenn man Fehler in einer Software behebt,
dann ist das Bugfixing, aber nicht Refactoring. Refactoring,
es kann passieren, dass man beim Refactoren Fehler findet,
wenn man genau auf einen Entwurf drauf guckt und dann feststellt,
oh,
da müssen wir auch
Fehler beheben
Aber das ist sozusagen überwendig auf die Software draufschaue,
kann ich einen Fehler finden und muss ihn dann beheben.
Das ist komplett unabhängig von Refactoring.
Und auch wenn ich tatsächlich das Layout einer Gui verändere,
ich meine, da kann man schon sagen,
da sieht der Benutzer ja auch was,
das ist ja tatsächlich auch eine Veränderung.
Aber das ist auch dann keine Änderung. Also um das
die Funktionalität sich ändert. Ich habe einfach nur das Layout
ein bisschen angepasst, aber die Funktionalität der Software,
was sie macht, was sie leistet, bleibt die gleiche.
Haben wir ja auch schon gesehen, dass man durchaus
dieselbe Funktionalität recht unterschiedlich darstellen kann in einer Gui.
Und auch das ist ein Refactoring.
Was aber ein Refactoring sein kann bei einer GUI ist,
wenn ich dasselbe Layout mit verschiedenen Layout-Managern erreichen kann.
Kann ja durchaus sein, dass ich, dass die Layout-Manager teilweise ähnliche Funktionalität ermöglichen.
Ich kann also irgendwie vielleicht drei Manager ineinander schachteln oder ich kann
das alles mit einem Manager hinkriegen, der ein bisschen mächtiger ist.
Solange das Layout das Gleiche bleibt, also sich der richtige Teil
des Fensters größer zieht, ist es wieder ein Refactoring.
Da habe ich tatsächlich nur den Code geändert unter der Haube und nach außen
hin ist nichts beobachtbar, dass sich irgendwas geändert hat.
Also ihr seht, es geht um diese innere Qualität von Software,
also das, was ein Nutzer der Software nicht sieht,
sondern nur das, was wir als Softwareentwickler zu sehen bekommen.
Wir sehen halt den Quelltext und wir sehen da Entwurfsschwächen oder ähnliches.
Das ist ganz interessant. Ich habe dieses Zitat nochmal dazugenommen
. Das ist, glaube ich, nicht im Skript.
Refactoring is a very specific technique founded on using small behavior,
preserving transformations. Themselves called refactorings. Das ist ein Zitat von
dem Fowler. Der ist ja immer noch sehr aktiv.
Und da ist es interessant, dass er sehr klar sagt,
es sind kleine seine Verhaltenserhaltende Änderungen verführt.
Transformationen. Diese Betonung auf dem Kleinen,
die passt auch in dem Buch ganz gut.
Er hat wirklich viele Refactorings in dem Buch beschrieben. Ich glaube,
es sind so 60 oder mehr, 70, irgendwie sowas.
Aber alle relativ klein und die Definition von großen Refactorings,
die ich dann dann zum Schluss nochmal so ein bisschen anreißen werde,
da geht es tatsächlich eher darum,
dass man über mehrere Tage oder Wochen tatsächlich etwas refacted.
In dem Sinne ist es eben halt aus fauler Sicht
dann kein Refactoring mehr
If you're doing refactoring your system, should not be broken
for more than if you minutes at the time.
And I don't see, how you do it on
something that doesn't have a well, defined behavior.
Okay. Das heißt also, wenn ich diese Definition habe,
ich beobachtbare Verhalten, soll nicht geändert werden.
Dann muss ich dieses beobachtbare Verhalten schon ziemlich genau spezifiziert haben.
Also, wenn ich da nicht so eine ganz klare Vorstellung
von habe, dann wird es auch wieder grauzonig.
Also, ist das jetzt noch ein Refactoring oder ist es schon eine Funktionalitätsänderung?
Also, das ist etwas, was er da nochmal so als Hinweis dazu gibt.
Man sollte das schon Ja. Immer messen daran,
was heißt denn dieses beobachtbare Verhalten, wenn man das nicht scharf hat,
kann man auch nicht schärfer definieren, was Refactoring ist.
Okay, wir differenzieren den Begriff etwas genauer,
und zwar irgendwie auf drei Art und Weisen hier. Das erste ist,
wenn ich in einem konkreten System eine konkrete Methode ändere,
sodass dann sich irgendetwas in der Struktur der Software ändert,
aber nach außen beobachtbar nichts, ich habe also hier ein Beispiel,
ich habe eine Methode, füge ein,
die gehört zur klasse Liste,
und die nenne ich um in Einfügen
Dann habe ich genau eine konkrete Methode,
die nenne ich um, versehe sie mit einem anderen Namen.
Alle Klienten müssen diesen veränderten Namen natürlich dann auch benutzen.
Das ist ein konkretes Refactoring. Ein direkt benennbares Refactoring.
Da mache ich dies, ende die Namen von da nach da.
Dann kann ich aber auch natürlich mit einem Refactoring bezeichnen,
alles, was zu einer Klasse von Restrukturierung gehört.
Also so eine konkrete Restrukturierung ist ein Refactoring.
Aber dann kann ich auch sagen, dieses Umbenennen einer Methode,
Renaine Method oder sowas, das ist ein abstraktes Ding,
dass man natürlich auf jede Methode dieser objektionierten Welt anwenden kann.
Ich habe also ganz viele Methode in meinem System.
Und jede, die kann ich irgendwie umbenennen in eine andere.
Und allein dieses Konzept von, eine Methode umbenennen,
ist eben halt eine ganze Klasse von Restrukturierung.
Also wieder dieser Zusammenhang zwischen Exemplar und auch Klasse,
ja, also das ist sozusagen hier die Klasse von Restrukturierung.
Und die kann man eben halt auch katalogisieren. Das heißt,
der Fauler beschreibt natürlich nicht in diesem einen System habe ich
das und das und das umbenannt oder habe ich das und das gemacht,
sondern allgemein, wenn man eine Methode umbenennen will, sollte man diese Schritte beachten.
Weil es tatsächlich in verschiedenen Systemen auch unterschiedlich schwer sein kann,
so etwas zu tun. Und man muss da relativ viel bedenken,
so eine Methode umbenannt wird. Methode umbenennen ist ein Beispiel,
das wir uns gleich ansehen werden. Und dann ist es
eben halt auch so, wir reden auch gerne von Refactoring,
wenn wir einfach nur von der Tätigkeit sprechen.
Also beim Refactoring haben wir festgestellt, da sind noch einige
Leichen im Keller, die Entwurf ist wirklich ganz schrecklich.
Da muss man mal richtig aufräumen. Also tatsächlich die Tätigkeit,
dann das konkrete Umstellen und die Klasse von Umstellungen,
die in eine bestimmte Kategorie fallen können.
Drei verschiedene Verwendungen des Begriffs Refactoring. Es gibt auch eine
deutsche Literatur, so Übersetzungen, die ich rennen,
schrecklich finde, refaktorisierung, kreuseln sich mir die Nackenhaare.
Gut, ist Geschmackssache. Also wir versuchen das dann,
Restrukturierung zu nennen, weil das irgendwie ganz gut passt.
Man ändert die interne Struktur einer Software. Also es ist
eine Restrukturierung. Gut, dann ist es häufig so,
dass Refactoring sich rechtfertigen muss. Ich habe in verschiedenen Projekten gearbeitet,
da hat man dann externe Kunden und so einem externen Kunden,
der natürlich primär daran interessiert ist,
dass seine Software eine bestimmte Funktionalität kriegt,
also dass sie wirklich das macht, was sie machen soll,
was der Kunde will,
dem zu erklären,
ja,
wir müssen jetzt nochmal so
eine Woche lang refactern
Ja, was bedeutet das? Ja, wir müssen unsere interne Struktur überarbeiten.
Da wird der Kunde sagen, hier, das bezahle ich nicht.
Dass ihr euch eine Woche lang hier eure Nägel putzt.
Ist aber tatsächlich ein Missverständnis, weil der Kunde,
dem Kunden ist es möglicherweise egal, welche Qualität die Software hat,
solange sie das leistet, was sie leisten soll.
Aber wenn man Software entwickelt, seriös,
sollte man eben im Blick behalten, dass man,
dass die Software eben halt bestimmten Qualitätsansprüchen genügt.
Und diese Ausdeutung, also man sagt Refactoring,
was heißt denn Refactoring, naja, es gibt halt so Quelltextkonventionen,
wir sehen hier in einem System, sind die Quelltextkonventionen nicht eingehalten.
Also refactern wir mal, dass jetzt die Methodennamen wieder zu
den Quelltextkonventionen passen
Da kann man nicht sagen, boah, langweilig,
Quelltextkonventionen sind sowieso langweilig. Kann man so deuten im Sinne von,
nein, wir machen halt unsere Wohnung ein bisschen hübscher.
Wir hängen Bilder auf, dann ist das alles ein bisschen netter,
Quelltextkonventionen, alle wissen, wie es aussieht, das ist irgendwie hübsch.
Das wird aber den Begriff Refecting überhaupt nicht gerecht.
Das ist also eine schlechte Metapher für Refactoring. Also wir
haben Refactoring so versteht, der hat es nicht verstanden.
Und es bleibt das Problem,
dass man einem Kunden gegenüber irgendwie klarmachen muss,
dass dieses Refactoring notwendig ist,
aber üblicherweise muss man das innerhalb des Entwicklungsteams organisieren,
dass diese Refactorings mit einfließen
Das ist eine Frage. Wir tun,
das klar zu machen, und wir meistens sagen,
wir zahlen sonst jetzt in die 50 auf, ist der Bruder,
jedes Jahr 20 Tore zu setzen, zu bauen.
Ja, also er sagt, der beste Weg,
dem Kunden das zu erklären, ist doch zu sagen,
naja, du zahlst entweder jetzt 50.000 für Refactoring oder in
den nächsten Jahren jedes Jahr 20.000 für Wartung.
Richtiger Einwurf. Es ist natürlich auch relativ, sagen wir
, schwarz-weiß jetzt. Es gibt ja nicht nur Kunden,
die keine Ahnung von Softwareentwicklung haben.
Also das ist ja, das verändert sich ja auch.
Und gerade agile Softwareentwicklungsmethoden haben das Refactoring sehr stark auf
ihre Fahnen geschrieben
Immer mehr, sagen wir, registriert die Welt da draußen,
dass Softwareentwicklung, was Komplexes ist und dass eben so etwas auch mit dazugehört.
Und wenn man eben halt klarmachen kann,
dass die Qualität der Software sehr viel besser ist und damit die Wartungsauf,
der Wartungsaufwand hoffentlich in Zukunft kleiner wird,
dann kann man den Kunden vielleicht damit kriegen.
Aber es gibt auch Leute, die sagen, nö,
50.000, jetzt ist mir zu viel.
Egal, was in zwei Jahren ist,
bin ich hier kein Projektleiter mehr oder so.
Klar. Das heißt, die sehr viel bessere Metapher,
wie ich finde, ist,
Refactoring ist wie Müll raustragen
So ein bisschen so wie hier unsere Quelltext, und das ist wie in einer Küche,
wir verrichten sehr viele alltägliche Dinge im Quelltext, wir schneiden hier was ab, wir fügen da was ein, wir rühren da Sachen zusammen. Ich weiß nicht,
ob ihr schon mal gekocht habt, aber wahrscheinlich schon,
da kommt schon einiges zusammen,
was so liegen bleibt und wenn man das nicht wegräumt,
dann wird es irgendwie, dann wird das Messer da irgendwie,
bleibt dreckig liegen und die Teller werden nicht weggeräumt und mit der Zeit entsteht dann viel Müll und irgendwann macht es einfach keinen Spaß mehr in der Küche zu arbeiten und da kommt man auch nicht mehr voran,
also in so einer ganz versifften Büche,
ich hatte mal das Erlebnis in,
als ich noch in Ulm war, als Promotionsstudent,
dass ich da auf einer Party war und in der Küche,
ich glaube fünf oder sechs gelbe Säcke rumlagen,
zugebunden irgendwo in der Ecke, die rochen recht unangenehm,
weil die halt seit Monaten nicht weggebracht worden waren.
Und ja, ich weiß nicht,
ob man da viel Spaß hat in so einer Küche.
Tatsächlich ist es eher wirklich gut zu verstehen,
dieses Refactoring im Sinne von, naja, wenn wir nicht aufräumen,
dann wird sozusagen die Entropie immer weiter zunehmen.
Das ganze System wird immer weiter zerfallen in vielen Details
und wenn einfach an zu vielen Stellen unsauber wird,
dann wird es irgendwann auch nicht mehr gut funktionieren.
Insbesondere natürlich immer wieder in Hinsicht auf Wartung und Erweiterung.
Ganz schön, an dieser Stelle finde ich immer diese kurze
Einflechten der Broken Window Theory. Das ist eine Theorie,
die in den USA irgendwann mal entwickelt wurde.
Der Hauptversuch war damals, man stellt ein intaktes Auto,
mehrere Wochen auf einen Parkplatz, einen öffentlichen Parkplatz,
von einem Einkaufszentrum oder ähnliches.
Das Auto bleibt da unversehrt, steht da so rum,
rumstehende Autos und ja nicht selten ist.
Dann hat man gezielt
eine Scheibe eingeschlagen
Und es hat nur wenige Tage gedauert, dann waren die anderen Scheiben auch eingeschlagen.
Irgendwann waren die Radkappen geklaut und die Reifen wurden abmontiert.
Also das ist genau dieser Effekt,
wenn ich in einem Softwareentwicklungsteam bin und die Quelltextkonventionen werden gut eingehalten,
Leute halten sich alle dran, es wird sauber refacted,
dann werde ich animiert, das auch zu tun.
Dann fühle ich mich wohl, dann läuft das. Im Moment,
wo ich aber sehe, ich komme in ein Team von Leuten,
die haben eine Software entwickelt, die ist Kraut und Rüben,
keiner hat einen Plan, es gibt keine Architektur,
es gibt keine Architekturregeln und jeder baut irgendwie nach Gutblinken irgendwas irgendwo rein.
Das ist dann so
ein verwarztes Ding
Da habe ich auch keine Lust, irgendwie mir Mühe zu geben.
Also wenn erst mal sozusagen das System in einem Zustand ist, Entschuldigung,
dann wird man auch nicht wirklich Spaß haben, daran aufzuräumen.
Also sich dann als einziger in die Quelltextkonvention zu halten,
ist ziemlich müßig. Also weil das eben halt so ist,
also wo erst mal Beschädigung ist, dann bezieht das auch Beschädigung nach sich.
Gibt es zum Beispiel in New York diese Policy,
dass das Graffiti sofort entfernt wird. Man geht halt eigentlich davon aus,
dass dann so eine ganz weiße Wand oder eine ganz unbeschmutzte Wand nicht so leicht besprüht wird.
Ich glaube nicht, dass das wirklich funktioniert,
Hier ist mal ein Studenten vor zwei Jahren in der Folge,
der sagte, naja, das Gegenbeispiel ist ja,
wenn man sich die Polster in den S- und U-Bahn in Hamburg anguckt,
die haben so ein fieses Muster drauf,
so ein komisches Schlangenlinienmuster und hässlich,
da hat man überhaupt keine Lust mehr drauf rumzusprühen,
weil man es gar nicht erkennen würde.
Das ist die andere Theorie. Also wenn es schon dermaßen hässlich ist,
dass man gar nicht mehr noch irgendwie da, ja,
aber ihr seht, was dahinter steht,
hinter dieser Broken Window Theory, wenn Dinge erstmal nicht inpakt sind,
nicht in Ordnung sind,
das degeneriert relativ schnell so ein System.
Jetzt kommen wir zu diesem üblen Gerüchen. Und im Grunde
genommen ist das jetzt sehr viel Überschneidung mit der Entwurfsvorlesung,
die ich ja auch schon gehalten habe.
Also ein typischer, übler Geruch ist Code-Dublizierung. Habe ich
eben schon als Beispiel genannt. Wenn ein Stück fällt in identischer Form
an mehreren Stellen eines Systems definiert ist, sprechen wir von Code-Dublizierung.
Und wir wissen, dass Code-Dublizierung aus verschiedenen Gründen problematisch ist.
Erstens ist nicht an einer konkreten Stelle erkennbar, dass dieselbe Quelltext nochmal woanders steht.
Da gibt es ja keine Verbindung dazwischen. Das ist ja
irgendwie einfach nur Quelltext, der da steht.
Und wenn ich dann was ändere, an dieser einen Stelle.
Und ich weiß, dass es an einer anderen Stelle auch steht,
dann ziehe ich es an der anderen Stelle nicht nach.
Und dann sind die beiden Stellen irgendwie auseinandergelaufen. Könnte aber sein,
dass es eigentlich richtig wäre, die Änderungen,
die ich hier gemacht habe, an der duplizierten Stelle auch zu machen,
weil das eben halt hier einen Fehler korrigiert hat zum Beispiel.
Das muss dann da auch gemacht werden. Wenn ich aber gar nicht weiß,
dass ich jetzt hier gerade einen Fehler korrigiere,
der noch an drei anderen Stellen auftritt, ist das schwierig.
Also auch das macht dann wieder Wartung sehr, sehr schwierig.
Das heißt, diese Duplikate kann man leicht übersehen.
Es gibt inzwischen Werkzeuge, die Duplikate erkennen. Es gibt tatsächlich relativ gute Softwarewerkzeuge,
die genau solche Duplikate suchen einem dann irgendwie zeigen, so hier,
20 Zahlen und da hast du sie nochmal, identisch.
Und dann kann man eben halt sich überlegen, was man damit macht.
Das Problem ist tatsächlich, was macht man denn dann?
Und was hier jetzt schon angedeutet ist,
es ist ja üblicherweise ein Zeichen von niedriger Korrision.
Das heißt, wenn man zwei Stellen das Gleiche steht,
dann ist es mindestens an einer Stelle falls sich falsch platziert.
Möglicherweise muss es sogar an eine dritte Stelle und die anderen
beiden Stellen rufen das nur noch auf, was da steht.
Das heißt, die Zuständigkeit ist einfach nicht korrekt zugeordnet an
der Stelle. Also das ist ein klassischer übler Geruch
Große Einheiten, auch ein schöner übler Geruch. Ich habe schon gesagt,
Methoden, die zu lang sind, sind üblicherweise schlecht wartbar. Man kann einfach,
zum Beispiel, wenn da irgendein Ergebniswert geliefert wird,
dann besteht ganz am Ende irgendwie Return,
Result oder so und ganz oben steht dann irgendwie noch so Prüfungen und mittendrin der ganze Code und ich sehe gar nicht so richtig, was da passiert.
Sind einfach schlecht wartbar, auch große Klassen mit vielen Methoden,
keine gute Idee und das bekannteste Anti-Pattern ja hier,
die Gottklasse, also die Leute,
die Objektorientierung nicht so gut verstanden haben,
aber mit einer Objekt und Themensprache programmieren,
die machen das schon mal gerne,
dass sie irgendwie eine große Main-Methode schreiben,
in der dann alles passiert,
das kann man auch machen
Da kann man ziemlich viel Software unterbringen in so einer Main-Methode.
Das ist keine gute Idee, wir wollen das ja anders machen.
Okay, dann haben wir auch über das Law of the Mieter gesprochen. Diese Geschichte,
die ich schon mal angedeutet habe, wenn so ein Aufruf,
so eine Aufrufkette da steht, dann würde ich sagen,
da kräuselt mich nicht so ein bisschen meine Nase.
Da sehe ich irgendwie, oha, hier wird irgendwie irgendeine Struktur traversiert.
Und an der Stelle hier in dem Klienten,
der Klient hier, der diesen Aufruf macht,
der kennt den Typ Student, der kennt den Typ Record,
der kennt irgendwie Axam Entry, die muss er alle kennen,
das heißt also,
er ist mit allen diesen Dingern gekoppelt und er hat auch diesen Zusammenhang zwischen diesen Komponenten irgendwie hier ausprogrammiert.
Also dieses ist sozusagen eine Ausprogrammierung dieser ganzen Abhängigkeiten.
Da kann man eben halt sagen, hm,
ist das denn so gut? Es muss nicht schlecht sein,
aber es ist immerhin schon mal so ein Geruch,
wo man dann sagen kann, vielleicht sollte man da den Entwurf mal überlegen.
Also wir hatten das ja schon angedeutet, wie man da
Dinge dann ändern kann. Man sagt dann irgendwie sowas wie,
hier diese Ergebnisse werden irgendwie in so eine Score-Card eingetragen für irgendeinen Jahrgang.
Also hier wird erstmal so eine Score-Card angelegt und dann hat jemand
mit einem Werkzeug interaktiv, trägt da diese Noten ein.
Das muss ich zum Beispiel auch immer machen,
meistens ins Diene und dann wird dann diese wird dann durch
alle Studenten durchgegangen und dann wird bei dem,
bei jedem Studenten eingetragen, was er in der Klausur erzielt hat.
Und das wird eben halt aus dieser Scorecard dann rausgezogen.
Es ist sozusagen wieder die Zuständigkeit eines Studenten,
sich auf einer Scorecard, die Note rauszuholen.
Innerhalb eines Softwaresystems. Immer dran denken, das ist ja
hier Software und das ist nicht eine Modellierung der realen Welt.
Gut, das sind so verschiedene üble Gerüche, soweit so gut.
Der Fauler hat dann irgendwie 60, 70 Refactorings,
die dann sagen, naja, wie kann man denn,
wenn man so einen üblen Geruch hat,
das irgendwie beseitigen?
Was kann man denn
so machen
Er beschreibt diese Refactorings immer auf Basis von sogenannten Mechanics.
Also die Mechanik von Refactorings. Das sind eine knappe und präzise,
schrittweise Beschreibung, wie das Refactoring ausgeführt werden soll.
Das heißt, wir untergliedern die Refactorings in mehrere Teilschritte.
Und es ist tatsächlich ganz interessant,
wenn man Refactorings intensiv studiert, dann stellt man fest,
es gibt diese kleinen Submuster in diesen Refactorings,
die dann
immer wieder auftauchen
Ein Rename Method mache, dann lege ich erst mal
eine Methode an mit dem neuen Namen.
Also erzeuge eine neue Klasse mit einem bestimmten Namen oder eine
neue Methode mit einem bestimmten Namen.
Oder füge eine neue Methode hinzu. Das sind immer so Teilschritte,
die tauchen immer wieder auf. Und auch so Umleitungen,
wie wir sie gleich mal sehen werden, live tauchen immer wieder auf.
Also sodass man irgendwie erst mal sozusagen während des Umbaus
Aufrufe umleitet und dann irgendwann die Umleitung auch wieder wegnimmt.
Diese Schritte sollten möglichst klein gewählt werden und der Fauler empfiehlt tatsächlich,
dass man eigentlich nach jedem Schritt das System mehr oder weniger
übersetzbar halten sollte
Das ist ganz spannend. Also wie kriegt man solche Änderungen
im Entwurf sauber von A nach B in möglichst kleinen Schritten,
wobei ich bei jedem Schritt genau feststellen kann, ob noch alles läuft.
Hat den Vorteil, dass wenn dann ein Fehler passiert,
dass ich schneller lokalisieren kann, wo der Fehler aufgetreten ist.
Das ist die Gefahr von diesen automatisierten Refactorings,
die ihr ja vielleicht aus Reflips schon teilweise kennt.
Da passiert sehr viel und teilweise nicht unbedingt das, was man so möchte.
Auch das werden wir gleich nochmal ein bisschen live sehen. Okay,
also wenn wir uns jetzt hier mal so ein,
naja, Zitat ansehen von Erich Gamma, ich weiß nicht,
Erich Gamma, wer kennt den Namen Erich Gamma,
weil kann dem Namen was anfangen?
Hat den schon mal jemand gehört? Irgendwie, nö.
Ja, das ist natürlich ein Skandal. Es gibt mindestens
ein Buch, das jeder waschechte Programmierer mal gelesen haben sollte.
Das ist Design Patterns. Entwurfsmuster, habe ich vielleicht mal gehört,
haben wir ja schon hier eine Lösung hier erwähnt.
Der Erich Gamma ist einer der Autoren dieses Buches.
Das ist das erfolgreichste Buch in der Informatik
Also wirklich mit Abstand. Das meistverkaufte, meistgelesene,
da steht wirklich Hands-on-Erfahrungswissen drin, wie man objektorientierte Systeme strukturieren kann.
Und wie man das mit Entwurfsmustern gut hinkriegt. Und Erich
Gamma hat das Vorwort geschrieben, zu faul das Buch,
also hat auch dann so ein bisschen das eingeordnet,
hat halt auch gesagt, some of the refactorings may seem obvious.
Also das sind so Sachen, wo man so sagt,
naja, eine Methode umbenennen, mein Gott,
das ist doch nun irgendwie,
wo ist da der Hit?
Was ist jetzt
das Tolle daran
Ja, aber er sagt eben halt, man muss schon
ein bisschen darauf achten. Understanding the mechanic of such refactorings is
the key to refactoring in a disciplined way. Das heißt,
wenn man Refactorings können will, wenn man das gut machen will,
dann sollte man sich schon mal sehr genau angeguckt haben,
wie denn Refactories aufgebaut sind.
Und das ist tatsächlich so, wenn man diese Refactorings sich genau anguckt,
dann lernt man auch sehr viel über die Art und Weise,
wie objektuntierte Systeme ticken.
Also wie Abhängigkeiten entstehen zwischen den Einheiten eines Softwaresystems und wie
man diese Abhängigkeiten teilweise auflösen kann
Nicht nur dieses Design-Patterns-Buch geschrieben. Erich Gamma ist auch lange Jahre
der Chef des Entwicklungsteams gewesen, das Eclipse gebaut hat.
Also er ist quasi der Vater von den Clips bei OTI
, bei den OTI-Labs in Zürich. Das war mal eine
Unterecke von WM. Außerdem hat er der Unit mitentwickelt.
Falls ihr irgendwie Jay Unit schon mal gehört habt,
wehe, jetzt sagt jemand noch nie gehört.
Also Jay Unit ist unter anderem von Erich Gamma entwickelt worden.
Zusammen mit Cantback. Also auch da kann man sagen,
der Mann hat eine gewisse Außenwirkung gehabt auf die Informatik,
eher auf die praktische Informatik. Das ist ein Typ,
praktische Informatik, hat promoviert in der Informatik,
ist aber dann in die Software-Elektroindustrie gegangen und ist da auch nach wie vor munter und zufrieden.
Verdient wahrscheinlich auch ganz gutes Geld da bei WM oder bei OTI.
Ich weiß aber, jetzt ist er gerade wieder, glaube ich, gewechselt.
Er hat dann auch lange Jahre Jazz entwickelt. Das ist eine Erweiterung von Eclipse,
um eine Unterstützung für Softwareentwicklungsprozesse, also für Vorgehensmodelle,
wenn mehrere Leute auf einer Codebasis arbeiten, wie sie sich dann abstimmen,
wie sie dann ihre Updates und so weiter da einpflegen.
Und das war auch ziemlich erfolgreich. Also der Mann ist
richtig gut und wenn immer irgendwas von Erich gerne mal zu
lesen bekommt, würde ich es einfach lesen.
Es kann nicht schaden
Gut, gucken wir uns mal jetzt nochmal vor der Pause so eine Refactoring an.
Also wir nehmen ja einfach die Mechanik von Methode umbenennen.
Ich habe ja schon rangeschrieben, vereinfacht. Das,
was jetzt hier steht, ist vereinfachhemmend. Es ist tatsächlich
so, dass da eine ganze Menge mehr passieren kann.
Das ist etwas, was ihr, glaube ich,
ganz gut kennt. Ihr habt eine Methode benannt,
jetzt kommt so ein blöder Betreuer daher und sagt, oh,
der Name der Methode, den finde ich aber nicht gut,
benenne die doch mal um.
So, und man kann das,
wir sind jetzt sozusagen in den Zeiten vor Eclipse,
stellt euch das mal vor
Tut einfach so, als wenn die Eclipse nicht kennen würdet.
Ihr habt noch vielleicht Blue Jay am Laufen, erstes Semester.
Und jetzt sollt ihr tatsächlich eine Methode umbenennen. So,
jetzt kann man einfach hingehen und sagen, kein Problem,
ich mache irgendwie, suche die Methode,
benenne sie um und dann wird man schon sehen, was passiert.
Der Compiler wird ja meckern,
weil ja alle Klienten dann diese Methode nicht mehr kennen,
weil die die aufrufen, da steht es der alte Name,
in der Klassendefinition steht der neue Name,
das wird wahrscheinlich krachen.
Kann man so machen. Was der Fouler empfiehlt,
ist ein etwas anderer Weg und das ist halt hier jetzt
mal so ein bisschen ausführlich beschrieben
Also das Erste,
was er sagt, wenn ich also tatsächlich sowas habe,
ich möchte eine Methode A in B umbenennen,
um es mal ganz einfach zu erhalten, dann mache ich als erstes,
deklariere ich eine neue Methode mit dem neuen Namen.
Kopiere den alten Quelltext in die neue Methode und mache die notwendigen Anpassungen. Okay,
es ist, allein das ist schon ein wichtiger Schritt,
danach muss ich übersetzen, weil es kann ja sein,
dass der Name der neuen Methode mit irgendeiner anderen,
einem anderen Methodennamen innerhalb der Klasse oder in der Vererbungshierarchie kollidiert.
Also da ist es schon gut,
dass man schon mal erstmal prüft,
ob der Name überhaupt
eingeführt werden kann
Wenn ich das mache, also ich deklariere eine neue Methode,
es wird ja noch nirgends aufgerufen, kann also auch keinen Schaden anrichten,
kopiere den alten Quelltext in die neue Methode.
Auch das kann nicht schaden, was innerhalb einer Methode ist,
hat ja erstmal keine Auswirkungen und mache die notwendigen Anpassungen.
Teilweise muss man vielleicht irgendwelche Ergebnistypen umbenennen,
weil der so heißt, wie der Methodenname,
es gibt so Sprachen, wo das so ist.
Und dann übersetzen und sehen, ob es funktioniert.
Okay, jetzt nächster Schritt, ich ändere den Rumpf der
alten Methode so, dass er die neue Methode ruft.
Aha, also alle die Klienten rufen die alte Methode in
der alten Methode, steht jetzt ein Aufruf der neuen Methode
Und es müsste eigentlich alles funktionieren. Also auch das kann
man machen, dann kann man wieder übersetzen und testen.
Also das ist natürlich was, was uns ja immer klar ist.
Wir haben ja immer Testlassen zu unseren fachlichen Klassen mindestens,
aber auch zu technischen Klassen kann man Testlassen schreiben.
Das haben wir schon diskutiert. Und ich lasse einfach meine
Tests laufen. Und sehe halt, ob es irgendwo kracht.
Das sollte nicht krachen, aber man geht lieber auf Nummer
sicher. So, und dann kommt der nächste Schritt,
finde alle Referenzen auf die alte Methode und ändere sie so, dass auf neue Verweisen.
Übersetze und Tests nach jeder Änderung. Tatsächlich,
ich habe irgendwie eine Methode, jetzt habe ich die Methode,
die alte Methode ruft die neue auf, alle Klienten,
sagen wir, fünf Stellen im Quelltext, wo diese Methode aufgerufen wird.
Ich suche die irgendwie alle und gehe dann zu jeder Stelle
hin und ändere das. Und dann, wenn ich das
an der einen Stelle geändert habe, dann übersetze ich.
Und sehe, ob es funktioniert. Und teste. Und
das mache ich an jeder Stelle neu. Am Ende,
wenn ich alle Stellen geändert habe, dann entferne ich die alte Methode.
Weil die hat ja jetzt nur noch diese Umleitung da drin
und die braucht man ja nicht mehr.
Okay. Auch da sollte man nochmal testen,
weil vielleicht mal irgendwas übersehen, dass irgendwo implizit das Ding noch aufgerufen wird,
man weiß es nicht.
Und dann ist man fertig
Wie gesagt, die Vereinfachung ist hier, wir haben nicht
berücksichtigt, Ober- und Unterklassen. Nämlich diese Frage von,
darf ich überhaupt eine Methode so umbenennen und so weiter?
Also da kommt relativ viel Zeug zusammen, wenn man es genau nimmt.
Also wenn man versucht, Refactorings automatisiert zu implementieren,
was die ja in den Clips gebaut haben,
dann wird das alles sehr, sehr schnell kompliziert.
Okay, ich will das auch ein bisschen live zeigen und
deswegen gehen wir mal hier irgendwie in den Clips rein.
Ich habe Als Beispielsystem, das Kinokarten-Verkaufssystem.
In mehrfacher Version hier. Das ist ganz amüsant, sich
das mal anzugucken. Also das zum Beispiel hier ist Kinoticket-Verkauf
2011. Das war das System im letzten Jahr. Das ist
ziemlich genau so wie das System, was ihr jetzt habt.
Im letzten Jahr haben wir relativ viel umgestellt in SE2.
Und der Kinoticket-Verkauf gehört dazu. Aber die Veränderung vom
letzten Jahr zu diesem Jahr ist halt relativ gering.
Das heißt, das dürfte jetzt so ungefähr so aussehen,
wie ihr es kennt. Wenn wir uns den Quelltext jetzt ansehen,
dann haben wir hier mehrere Pakete, Fachwerte, Materialien,
Start-up, Werkzeuge, Start-up hier habe ich das mal sogenannt 2011,
um deutlich zu machen, welches jetzt welches ist.
Dann haben wir hier die Werkzeuge, Datumswähler, Kasse, Platzverkauf, Vorstellungswähler.
Also man sieht, das ist schon relativ ähnlich.
Ich weiß nicht jetzt genau, ob da irgendwie große Unterschiede sind,
aber da ist eben halt einiges vertraut, denke ich mal.
Fachwerte, Materialien gibt es hier, Filme, Kino, Tagesplan und so weiter.
Sieht relativ ähnlich aus und man sieht eben halt,
wenn ich das jetzt mal hier starte, also hier Start-up 2011,
das sah letztes Jahr schon genauso aus,
wie es jetzt auch aussieht, mehr oder weniger.
Also hier, man kann hier durch die Tageblättern mit diesem Datumswähler,
dann kann ich hier durch die Vorstellung und damit
auch immer implizit den Saal auswählen, der damit verknüpft ist.
Also hier Saal 3 und hier Saal 2. Und ich kann
hier irgendwas auswählen und verkaufen, das kennt ihr alles.
So sah das also im letzten Jahr aus.
Das ist auch wieder jetzt interessant aus Refactoring-Sicht,
weil die Funktionalität dieses Systems hat sich eigentlich über die Jahre nicht verändert.
Wir haben immer schon seit zig Jahren inzwischen dieses System
hier so als Vorlage für die Studierenden.
Aber es hat sich unter der Haube extrem viel geändert
Warum wir im letzten Jahr das komplett umgebaut haben,
das lag unter anderem daran, dass dieses System,
was wir schon seit, ich glaube,
seit 2002 oder 2003 einsetzen, jedes Jahr von irgendwelchen wissenschaftlichen Mitarbeitern,
von Kollegen von mir, von mir selbst,
irgendwie überarbeitet wurde, angepasst wurde.
Und jedes Mal haben andere Leute dran rumgeschraubt.
Das ist so ein klassisches Beispiel, ein System wird von
verschiedenen Leuten angefasst, überarbeitet und dann irgendwann degeneriert das.
Und das war auch so, dass die Leute,
die es ursprünglich mal gebaut haben, eine bestimmte Idee hatten,
wie die Strukturierung sein soll.
Und diese grundlegende Architekturidee,
die ist den Leuten danach nicht mehr klar gewesen,
die wurde nicht kommuniziert
Es gab keine expliziten Entwurfsregeln, wie wir sie jetzt haben.
Und deswegen haben dann andere Leute das irgendwie anders gebaut.
Man kann zum Beispiel jetzt mal hier 2010 sich das angucken,
der saß tatsächlich schon ein bisschen anders aus.
Da gab es dann irgendwie Fachwerte, gab es auch.
Dann gab es sowas wie UI,
hier standen jetzt irgendwie Sachen, die zu UI gehören.
Dann gab es Vorstellungen und irgendwie alles andere lief irgendwie in diesem Ding drin.
Also da gab es irgendwie ganz viele Sachen. Man sieht hier,
man wundert sich, wo überhaupt hier das Werkzeug ist.
Also es ist irgendwie ganz anders. Völlig anders gebaut.
Sieht aber ziemlich genauso aus. Also wenn man das jetzt mal startet,
2010, ich glaube, das sieht ziemlich genauso aus.
Ja, nicht ganz, man sieht hier, auch wieder so ein Datumswähler.
Dann hat man aber hier Standard gehoben Luxus,
könnte man also sozusagen den Kinosaal erstmal auswählen.
Und dann hat man hier nur noch die Vorstellung zu dem
Kinosaal gesehen. Das haben wir dann irgendwann auch vereinfacht,
um das Ganze ein bisschen übersichtlicher zu halten.
Aber ihr seht, im Grunde genommen ist es die gleiche Funktionalität.
Das ist jetzt nicht nur ein Refactoring, weil man sieht,
in der Funktionalität ist es ein bisschen anders.
Also in der Oberflächengestaltung, die Funktionalität,
was man damit machen kann,
ist die gleiche
So, und dann haben wir tatsächlich noch ein älteres System hier.
Das habe ich hier mal rausgekramt. Das ist das von
2008. Da war es so, genau wie jetzt in dieser Veranstaltung,
haben wir irgendwann euch Packets-Pakete, Packages beigebracht.
Also sozusagen, was sind überhaupt Pakete? Und wie kann man
die benutzen, um große Systeme irgendwie auf Pakete aufzuteilen?
Und da war damals noch die Aufgabe, das Kinoticket-Verkaufssystem auf Pakete aufzuteilen.
Also hatten wir tatsächlich hier alle Klassen in einem Namenlosen.
Das habt ihr bei der Mediathek, habt ihr das
bei uns diesmal halt so gehabt.
Also auch im letzten Jahr schon. Alles irgendwie im namenlosen Paket
. Und jetzt soll man das mal in Pakete aufteilen.
Das haben wir damals auch gemacht. Man sieht hier,
hier gibt es jetzt wieder ein Kassenwerkzeug,
ein Kassenwerkzeug,
Ist das wieder so irgendwie so Werkzeugartig und ja,
also es ist irgendwie ganz interessant zu sehen, wie so ein System sich tatsächlich,
ja, wie das so Leben entwickelt und wie das so in eine bestimmte Richtung sich bewegt und dabei das System aber nicht wirklich viel besser wird.
Ich habe hier auch nochmal, Moment, dieses 2008er-System habe ich hier nochmal als Blue-Jay-Projekt gemacht. Also man sieht hier Start-up,
Multiplex-Kino, so und man sieht,
es gab da irgendwie sowas wie ein Ticket-Service und dann gab es ein Multiplex-Ticket-Service,
der das irgendwie implementiert hat und was damals von den Leuten,
die das vorher gebraucht hatten, die Idee war,
dass man irgendwie so eine Trennung hat,
und das sieht man hier relativ deutlich,
ich kann hier so einen Strich reinziehen,
man sieht hier dieser ganze UI-Kram, also Werkzeug,
Werkzeug, UI, Platzplan, Panel, Jay Plots Button,
also das alles, was da so speziell nur für die Darstellung ist,
das ist hier abgetrennt.
Und dann gibt es hier einen Service und der Service bietet
eben halt diese ganze Funktionalität, die wir uns vorstellen.
Und damals war aber auch diese komische Idee, dass ein
Service keine Materialien rausgeht. Das heißt, die Schnittstelle,
das war noch nicht der Service in unserem Sinne,
sondern das war halt irgendwie diese Idee von einem Interface
Die Studierenden müssen erstmal, dass diese Googy nicht bauen,
sondern beschäftigen sich nur mit der Fachlichkeit hier unten.
Und diese Schnittstelle sollte überhaupt keine Materialien durchreichen. Also das
heißt, dieses Interface hier basiert komplett nur auf Ins.
Also man sieht hier, gib Anfangszeiten in Kinosaal,
Fachwerte dürfen so durchgereicht werden in so eine Googy, okay.
Aber das war wirklich so dieses Bestreben, na wir wollen eigentlich
über diese Schnittstelle zu Googy hin keine fachlichen Objekte durchreichen.
Das ist irgendwie eine ganz, ganz wichtige Regel,
dass man sich klar macht, so Googy-Komponenten,
die irgendwas anzeigen in der Oberfläche,
die sollten eigentlich keinen direkten Zugriff auf Materialien haben oder auf Services
Weil Materialien und Services ja durchaus von mehreren benutzt werden können,
wenn ich in so einem System,
wo ich mehrere Gute habe, dasselbe darstelle.
Und ich habe mehrere verschiedene Referenzen, dann kann es mir passieren,
dass der eine etwas ändert und der andere diese Änderung nicht mitbekommt.
Also es ist einfach nicht gut, Referenzen auf Materialen oder Services
in Gui-Elemente reinzugeben. Wenn, dann sollte das Werkzeug das
machen. Und diese Gui-Komponenten sollten davon komplett freigehalten werden.
Das sind so Entwurfsregeln, die, wie gesagt,
das war damals so dieses Bestreben, diese Schnittstelle so zu bauen,
dass man irgendwie das abbildet auf Ins.
Vor allem wie ganz komisch,
da musste man dann irgendwie die Kinoseele entsprechend durchnummerieren und ähnliches
Ja, und an diesem System werden wir gleich nach
der Pause so ein Contactors Refectoring Renain Method durchspielen.
Wird das erstmal in Blue Jay machen, weil Blue Jay
hat kein Refactoring Support, also keine Unterstützung für Refactoring.
Das heißt, es muss von Hand machen. Und während wir das machen,
werden wir einiges lernen über Refactorings und dann werden wir es
uns nochmal ansehen, wie das dann in den Clips aussieht.
Und da ist auch nicht alles golden.
Aber das sehen wir dann nach der Pause. Gibt es
erstmal Fragen jetzt zu dem, was ich bisher erzählt habe?
Das scheint nicht der Fall zu sein. Doch, da ist
eine Frage. Mittlerweile nach Akzeptanz testen. Er fragt,
ob man üblicherweise nach einem Refactoring nochmal einen Akzeptanztest mit dem Kunden durchführen sollte.
Also obwohl sich die Funktion nicht geändert hat.
Ich würde sagen, ja, also es ist...
Letztendlich ist es ja eine Frage, wie man seine Softwareprojekte durchführt.
Aber wenn man in regelmäßigen Abständen dem Kunden gegenüber eine Version
ausliefert und die auch von ihm abnehmen lässt,
dann wäre es schon schlau, dass man die Refactorings auch überprüft.
Aber eigentlich sollten die Refactorings überprüft werden durch die Unittests,
die man hat. Aber ein Abnahmetest kann auch nicht schaden.
Also Testen ist immer gut und ob man es jetzt mit dem Kunden machen muss,
nur wegen eines Refactorings, ist wahrscheinlich sinnvoll,
aber wahrscheinlich sollte man das vorher erstmal Entwicklungsteam intern machen.
Gibt es sonst noch Fragen jetzt zu dem, was ich bisher gesagt habe?
Das ist nicht der Fall. Dann würde ich sagen,
machen wir mal eben fünf Minuten Pause.
Dann würde ich sagen, geht es weiter.
Macht die Tür bitte wieder zu. Das wäre nett?
Oder war die auf? Ja, wenn es nicht regnet,
ist manchmal ist es ein bisschen laut von draußen,
wie geht es eigentlich?
Lass ruhig auf. Gut. Also, jetzt haha,
jetzt wollen wir mal ein bisschen konkret werden
Ich möchte ein Refactoring durchführen und zwar. Ich möchte eine
Methode umbenennen. Und ich möchte mich dabei dieses Refactoring halten.
Das heißt also, an diese Mechanik, die hier beschrieben ist
, das möchte ich jetzt einmal sozusagen exemplarisch durchführen.
Und dann werden wir so ein paar Dinge sehen. Also,
ich möchte jetzt, und das ist vielleicht etwas,
was man erst mal zeigen kann, in dem Multiplex-Ticket-Service hat das ja erläutert,
dass in dieser Version des Systems es so war,
dass es hier so ein Ticket-Service gab,
der nur sozusagen mit primitiven Typen agiert.
Und jetzt gibt es hier eine Methode Und die heißt,
ich kann mal eben suchen danach, hier, gib Film.
So, wenn ihr euch diese Methode mal genau anseht,
also hier ist irgendwie der Kommentar, liefert den Film einer Vorstellung,
Paare am Kinosaal, die Nummer des Kinosaals, Uhrzeit,
die Startzeit, Datum, das Datum.
So, und dann Require, der muss überhaupt diese Vorstellung
vorhanden sein, also hat Vorstellung.
So, jetzt gibt es hier, eine Methode heißt Gipfel.
Was liefert die nun string? Also,
die liefert gar keinen Film, wir haben eine klasse Film,
das heißt, ein Exemplar von Filmen könnten wir hier auch liefern.
Das ist aber hier gar nicht gewünscht. Hier geht es darum,
dass der Gui gegenüber etwas rausgegeben wird,
was die Gui anzeigen kann,
ein String
Okay, jetzt kann man drum streiten, ob der Name jetzt gut ist.
Das ist so ein klassischer, übler Geruch, wo man
so sagt, boah, Meisterding, den gib Film.
Was wäre ein besserer Name? Macht man einen Vorschlag.
Schmeißt mir mal was zu. Gibt einen Namen, Filmtitel,
gibt Filmdarstellung. Also irgendwie sowas wie, das soll jetzt
ja dargestellt werden. Also es geht eigentlich nur darum,
dass da irgendwie eine Bezeichnung oder Beschreibung, Filmbeschreibung,
irgendwie sowas. Okay, also nehmen wir mal an,
wir wollen das Ding jetzt unbedingt in Gibt-Filmtiteln
Das Refactoring sagt, also die Mechanik sagt hier,
deklariere eine neue Methode mit dem neuen Namen,
gruppiere den alten Quelltext in die neue Methode und machen die notwendigen Anpassungen.
Na dann, auf geht's. Also ich deklariere hier direkt dann drüber mal
eine neue Methode. Public, String gibt Filmtitel. So,
jetzt kopiere ich alles das, was hier steht,
was da unten ab, kopiere ich jetzt mal da runter,
das will ich ja jetzt genauso rüber kopieren.
So, also habe ich das hier mal so rein.
So, damit habe ich das Ding da. Jetzt ist es
natürlich so, Bitte? Ein bisschen hier breiter machen?
Nein. Der Knaller. Dann kriege ich mal in die Kasse.
Oh, das würden wir ja merken gleich. Dann würde
der Compiler ja meckern. So, aber danke für den Hinweis.
So, jetzt habe ich hier erstmal den Kommentar nicht kopiert.
Jetzt mache ich das nochmal eben so,
das ist auch ein bisschen sauberer ist.
Also dieses Ding hat ja jetzt hier auch einen Kommentar und
der Kommentar wird ja vermutlich genauso funktionieren wie da.
Da steckt ja auch der Name nicht drin.
Also müsste es ja eigentlich funktionieren. So,
also jetzt haben wir eine zweite Methode. Das erste,
was wir jetzt machen,
wir übersetzen mal
Und es lässt sich übersetzen. Ich schließe mal,
habe also hier jetzt die Übersicht, man sieht jetzt hier,
es sind jetzt verschiedene Klassen ausgegraut,
weil durch die Veränderung sich was verändert hat.
Also übersetze ich jetzt mal. Aber erstmal habe ich jetzt
gesehen, ich konnte das hier übersetzen. Das heißt,
innerhalb der Klasse gab es keine Kollision vom Namen her.
Es gab also nicht eine andere Methode, gibt Filmtitel,
die da irgendwie überladen wäre oder sonst irgendwas.
Obwohl das natürlich auch passieren könnte, dass sie überladen ist,
weil einfach nur die Paramedalisten unterschiedlich sind.
Wäre vielleicht auch schon nicht so schön. Gut,
aber auf jeden Fall haben wir das jetzt hier übersetzen können.
Jetzt übersetze ich mal das ganze System.
Das klappt auch.
So, das war jetzt also,
jetzt kann ich mal sehen, ob die Tests alle laufen.
Ich kann mal eben hier die Testwerkzeuge anzeigen lassen. Werkzeuge,
Einstellungen, Bibliotheken, diverses Testwerkzeuge, da haben wir es doch.
So, jetzt kann ich hier mir auch mal die Tests
alle starten und siehe da, die Tests laufen alle durch.
Also auch das hat funktioniert. Das war jetzt noch gar nicht gefordert,
glaube ich, an dieser Stelle in der Mechanik, da steht nur erst mal Übersetze.
So, Ende den Rumpf der alten Methode so,
dass ihr die neue Methode ruft. Okay,
das können wir auch schnell bauen,
also wieder rein in den Tickets, in den Multiplex-Ticket,
Service und jetzt sagen wir hier, hier rufen wir auf,
Return, gib Filmtitel mit den Parametern,
Kinosaal, Ur-Zeit und Datum.
Das müsste eigentlich funktionieren. Kann ich übersetzen. Okay,
also habe ich jetzt die Umleitung eingerichtet,
das heißt, wenn jetzt Klienten gibt Film aufrufen,
dann wird das umgeleitet auf,
gibt Filmtitel
Was sagt die Mechanik? Was soll ich jetzt tun?
Ändere den Rumpfübersetzer und teste, okay,
okay, ich übersetze das, schließe das hier,
übersetze wieder alles, es lässt sich alles übersetzen,
ich starte die Tests, es klappt.
Wunderbar. Also, was sagt die Mechanik? Finde
alle Referenzen auf die alte Methode und ändere sie so,
dass sie auf die neue verweisen.
So, jetzt haben wir so ein bisschen das Problem,
dass Java, Blue Jake, keine globale Suche anbietet.
Ich kann immer innerhalb des Editors suchen, aber ich kann jetzt nicht global suchen.
Das ist ein bisschen doof. Ich habe jetzt hier meinen
Windows Explorer und ich gehe jetzt mal hier in das Verzeichnis rein von diesem Kilo-Ticket-Verkauf.
Wir sind also die ganzen Klassen des Projektes, des Java-Projektes,
jetzt kriege ich hier mal oben in die Leiste rein,
kopiere diesen Pfad und jetzt kommt wieder eine meiner Lieblingseinrichtungen von Windows.
Ich mache jetzt eine Kommando-Konsole auf. So,
und jetzt kann ich hier sagen, CD,
und jetzt kann ich hier irgendwie sagen, irgendwie bearbeiten, einfügen, zack.
So, und jetzt bin ich in diesem Verzeichnis.
Das heißt, wenn wir jetzt hier dir aufrufen,
dann sehe ich hier diese ganzen Quelltexte.
Also ich bin jetzt sozusagen in dieser Kommando-Shell, bin ich jetzt in dem Verzeichnis.
Und jetzt kann ich ja einfach mal Die Suche verwenden von,
na no, hallo, geht das hier mal breiter?
Nee, geht nicht breiter. Jetzt verwende ich mal hier
die Suche von Windows, von dieser Kommandosuche.
Also es gibt da ein, es gibt da ein Feind,
ich benutze das auch eigentlich schon seit Ewigkeiten nicht mehr.
Deswegen muss ich mal wieder nachgucken. Find N,
gib Film, und zwar in Stern. Java. So,
Stern ist eine Wildcard, also in allen Dateien,
die auf Punkt Java enden, soll er suchen nach Gipfeln,
und zwar irgendwie, ich weiß gar nicht genau,
ja, mit irgendeiner Option, die man wohl braucht.
So, das mache ich jetzt mal hier und dann kommt da
ein bisschen was raus. Jetzt haben wir uns das mal anguckt,
dann gibt der anscheinend alle möglichen Informationen raus. Er sagt immer,
welche Datei angeguckt hat, also er sagt hier all test.jaba,
datum, da ist es überall nicht drin.
So, jetzt gibt es irgendwie hier das Kassenwerkzeug,
da gibt es irgendwie Ticketservice, gibt Film.
Das Kassenwerkzeug will auch ein String bekommen,
das scheint also genau der Aufruf zu sein.
Dann gibt es den Multiplex-Service, da gibt es, gibt Filmtitel.
Klar, er findet auch GIP-Filmtitel, weil das ist ja Das schickt,
das gibt Filme ja drin. Dann gibt es,
das gibt Filme selber, dann gibt es einen Test, Multiplex-Ticket-Service-Test.
Da wird also irgendwie hier, gibt Filme auch aufgerufen.
Und dann haben wir hier noch im Ticket-Service, A und Interface,
gibt es auch noch diese Operationen, gibt Filme.
Okay, kommt da noch mehr? Ah ja, okay.
Hier gibt es jetzt auch noch, Vorstellungen gibt Java,
aha, Film gibt Film, aha, oh,
oh, jetzt wird es interessant.
Es gibt also in der Klasse Vorstellung eine Methode gibt Film,
die genauso heißt,
aber was anderes macht
Da sagen wir natürlich, herzlichen Glückwunsch,
dass wir jetzt das Refactoring machen,
weil wir benennen ja jetzt verschiedene Dinge, auch in verschiedene Namen um.
Also es ist also durchaus sinnvoll, das Ding gibt Film
zu nennen, weil das liefert wirklich einen Film zurück.
Und das andere gibt Filmtitel. Okay. Und dann gibt es hier
noch einen Vorstellungstest irgendwie, hier wird auch noch die Film aufgerufen.
Aber das ist ja das, gibt Film,
was wir gar nicht ändern wollen.
Jetzt sehen wir genau schon mal einen ganz entscheidenden Punkt,
warum Refactoring ist gar nicht so einfach sind.
Ich kann jetzt nicht mit suchen und ersetzen,
einfach überall stumpf, gib Film,
durchgib Filmtitel ersetzen
Bei Gipfelm-Titel würde er nämlich dann, gibt für
einen Titel Titel draus machen. Und an allen Stellen,
an denen es zufällig textuell auch gibt, Film heißt,
aber was völlig anderes ist, würde es auch falsch machen.
So, aber wir haben jetzt ja diese Stellen erstmal identifiziert.
Das heißt, wir gehen jetzt einfach mal hier nach oben
und gehen der Reihe nach durch.
Also wir folgen jetzt mal diesen Mechaniks. Also hier gibt
es irgendwie Ticketservice, gibt Film im Kassenwerkzeug. Okay,
dann sage ich jetzt mal, gehe ich ins Kassenwerkzeug rein,
das ist irgendwo hier.
So, jetzt suche ich hier mal nach Gipfelm
So, da wird dieses Gip-Film aufgerufen. Sehr schön.
Also hier, Gip-Film. Und hier sage ich jetzt einfach mal,
ja, ich ändere das jetzt heute in den Gip-Filmtiteln.
Für den Titel haben wir ja eingeführt als Methode, mach das Gleiche.
Also, gib Filmtitel. Übersetzen? Oha. Aha,
oh, oh, aha. Hat jemand die Idee,
was schiefgelaufen ist? Ja. Ganz genau. Genau richtig
. Wir haben ja hier mal wieder eine Situation,
dass wir eine Klasse haben, die ein Interface-Implement hat.
Wir haben jetzt nur in der Klasse das Renay Method gemacht. Ist natürlich eigentlich Quatsch,
weil das Interface muss ja mitgeändert werden, weil üblicherweise ja dann,
dass diese Klasse über das Interface auch benutzt werden soll.
Okay, also, was muss ich machen? Na gut
, dann muss ich jetzt tatsächlich das Interface auch anpassen.
Ich mache das hier mal zu, Ticketservice, gehe in den Quelltext,
gib Film so und hier sage ich jetzt, es heißt, gib Filmtitel.
Das ist natürlich jetzt auch schon nicht mehr ganz sauber,
ja, also die Mechanics sind jetzt hier schon relativ unsauber für genau diesen Fall.
Also wie würde man das eigentlich vernünftigerweise machen?
Würde man es zuerst das Interface ändern oder zuerst in der Klasse,
ja, da ist eine Meldung.
Die Bedrohung gibt es hier und die wird eingeführt worden. Genau,
also das ist tatsächlich jetzt eigentlich der richtigere Weg,
dass ich hier jetzt auch diese Operation, gibt Filmtiteleinführer,
damit eben halt die ganze Umleitung weiter funktioniert,
weil die ganzen anderen Klienten, die das Interface ja auch benutzen, machen das ja auch darüber.
Das spare ich mir jetzt mal, weil das hier sonst zu lange dauert.
Im Prinzip ist es aber genau der richtige Einwand, ja.
Das habe ich nicht verstanden
Genau. Ja, genau, also wenn ich das jetzt ändere,
dann ist es natürlich so, alle anderen Klienten des Interfaces würden fehlschlagen.
Weil es dann sozusagen gar nicht mehr da ist.
Gut, wir können das ja mal machen.
Dann machen wir jetzt hier mal, mache ich das so,
copy paste und mache hier einen Gap-Filmtitel.
Das kann ich hier übersetzen. Und jetzt müsste ich auch
eigentlich alles wieder übersetzen können. Jetzt kommt da irgendwas ancheckt,
das ist aber was anderes, hat nichts mit diesem Ding zu tun hier.
Das ist einfach eine Warnung, durch Windows 7 kommt, durch Java 7.
Also hier, ich kann alles übersetzen und ich kann auch die Tests noch ausführen.
Das heißt, ich habe jetzt die erste Benutzung geändert. Okay,
wir gehen wieder in die Mechanics und sagen, finde alle Referenzen,
okay, wir haben jetzt nur die erste gefunden, Kassenwerkzeug,
dann Multiplex-Ticket-Service wissen wir ja schon, haben wir ja selbst gemacht.
Im Ticket-Service-Test, aha, im Ticket-Service-Test.
Multiplex-Ticket-Service-Test, da gibt es auch einen Abwurf von Gib-Filmen.
Test gibt Filme, Third Equals, Filmtitel, da sieht man schon,
das heißt auch Filmtitel hier, macht also durchaus Sinn.
So, jetzt müsste ich also hier den Aufruf ändern. Also,
eigentlich müsste ich jetzt wieder so vorgehen, ich ändere es hier,
übersetze, es geht, ich müsste jetzt alles übersetzen und testen,
aber ich mache das jetzt hier mal an beiden Stellen,
im Film Titel, so, auch das lässt sich übersetzen.
So, und jetzt ist es natürlich schon so,
man sieht jetzt hier einen wunderbaren Effekt,
wenn ich jetzt hier reingehe und sehe, Test gibt,
das heißt ja eigentlich hier nicht,
die Operation sollte nicht mehr heißen, Teste gibt füllen,
sondern idealerweise heißt die jetzt Teste, gibt Film,
Testet die Operation Multiplex-Ticket-Service, gibt Filmtitel.
Ist natürlich sauberer, hier die Kommentare nachzuziehen. Okay,
ich übersetze das mal, das klappt, wir schließen das,
wir übersetzen alles, wir starten die Tests und es läuft.
Wunderbar. Wir gucken nochmal auf unsere Stellen, wo wir das ändern wollen.
Ticketservice haben wir schon angepasst, wir haben das Gipfelm da reingebaut.
Es gibt Filmtitel und dann haben wir diese beiden anderen,
gibt Filmverwendungen, wo es wirklich um Filme geht.
Das heißt, eigentlich sind wir jetzt schon fertig.
Dass mit diesem Schritt, mit diesem einen Schritt hier,
finde alle Referenzen. So, jetzt entferne die alte Methode.
Okay, das müssen wir natürlich jetzt wieder sauber machen.
Erster Schritt, welches würdet ihr zuerst entfernen im Interface oder in der Implementation?
Ja, genau. Im Interface zuerst, weil wenn dann
die implementierende Methode da ist, kann ja nicht schaden,
dass sie da ist, stört ja keinen.
Und andersrum wäre es schwierig, wenn ich das andersrum mache,
würde es nicht mehr kompilieren. Also schmeiße ich zuerst aus
dem Interface raus, also habe ich jetzt hier Die Operation gibt Film,
wird rausgeschmissen, liefert den Film einer Vorstellung,
la la la, bleibt noch so,
wie es ist, schließen, alles übersetzen, ups,
da ist wieder diese Warnung, das ist ein anderes Problem.
So, na gut, und jetzt kann ich natürlich
auch einen Multiplex-Ticket-Service, endlich gibt Filme rauswerfen.
Also auch entsprechend den Kommentar hier mitentfernt, die ganze Methode
kann raus. Zack, übersetzen, lässt sich übersetzen,
lässt sich alles übersetzen und es lässt sich alles testen.
So, sehr schön. Prima, prima, prima.
Wir haben tatsächlich mal ein Refactoring durchgehühnert
Das war jetzt ein bisschen umständlich. Das war auch wenig Verwendung
. Also es hat, war jetzt nicht so schwierig,
aber es war auch ein bisschen von Hand.
Und ihr wisst natürlich, dass es in den Clips das Gleiche auch gibt.
So, jetzt gucken wir uns das Ganze mal in den Clips an.
Also ich habe jetzt hier das System von 2008,
das ist der gleiche Quelltext.
Und jetzt möchte ich hier sagen, Moment,
in diesem System hier Multiplex-Ticket-Service Java.
Da habe ich ihn
Da suche ich mal eben nach, gib Fällen.
So, und dann sehe ich hier, da ist Gipfel.
Ja, also der gleiche Code. Und hier sage ich jetzt,
und das ist jetzt Eclipse, gerechte Maustaste, Refacte, Rename.
Das ist hier also in die IDE reingebaut. Ihr seht,
es gibt da noch einige mehr, so tolle Sachen wie Pull-Up,
Push-Down, Extract-Class, was weiß ich was, Rename.
So, also, jetzt ist es hier einfach so,
intern you name, presenter to refactor.
Gut, also sage ich jetzt hier,
gib Filmtitel
Das könnte ich einfach Enter drücken, aber ich würde es
dir mal zeigen, was da so passiert.
Jetzt kann ich hier ein Preview mir anzeigen lassen. Okay,
mal schauen, jetzt zeigt er mir alle Stellen,
an denen er diese Änderung vornimmt.
Also er zeigt mir zum Beispiel im Kassenwerkzeug,
hier wird der Ticket-Service benutzt,
da wird Gipfel benutzt und dann mache ich daraus aus Gipfel,
mache, ich gebe Filmtitel.
Dann kann ich hier irgendwie zur nächsten Änderung gehen.
Hier, glaube ich, Select Next Change. So,
dann habe ich hier Kassenwerkzeug, irgendwie Ticket-Service gibt Film,
gibt Filmtitel,
das ist genau dieser Aufruf
Gehen wir nur zum nächsten. Multiplex-Ticket-Service, genau,
gibt Filme auf Gipfelmtitel. Nächste Änderung ist hier eine Testklasse
, hat er auch gefunden, wunderbar.
Aber was man hier jetzt auch schon sieht,
er schlägt mir hier vor, er will das hier umbenennen.
Also hier gibt Filme, auf Gipfelmtitel, aber interessanterweise hier
macht es nicht. Das ist wahrscheinlich die nächste Änderung.
Genau, also das ist dann hier die zweite Stelle.
Er zeigt mir immer nur ein Refactoring. Und die
kann ich alle hier abschalten. Also wenn da aus Versehen
irgendwas Falsches passiert, kann ich da noch eingreifen.
Aha, okay
Und was man aber auch sieht, ist jetzt zum Beispiel
hier, macht er natürlich keine Umbenennung von Gib Film.
Also die Methode heißt Teste Gib Film, obwohl wir jetzt
Gib Film für einen Titel aufrufen. Kann Eklips ja auch
nicht wissen, dass das jetzt irgendwie einen Zusammenhang gibt,
semantischer Art zwischen diesem Titel und dem anderen.
Auch der Kommentar hier oben wird nicht geändert.
Man kann angeben, dass auch die Kommentare mitrefacted werden,
dann wird das stellenweise noch so ein bisschen mit erschlagen.
Dann erkennt er hier, dass hier irgendwie Gib Film drinsteht und macht das auch.
Aber das ist eben halt auch ein bisschen wackelig.
Und hier auch nochmal natürlich im Ticketservice,
im Interface ändert er es auch.
So kann ich jetzt sagen,
okay,
mach mal
So, und damit ist es passiert. Und wir haben jetzt aber genau den Effekt,
den ich gerade gesagt habe, in dem Multiplex-Ticket-Service-Test,
bei dem Test, dieb Film,
da ist es jetzt so, Teste gibt Film,
das heißt, jetzt nicht Teste gibt für den Titel und auch hier steht Teste-Gib-Film.
Das Refactoring war also so halbherzig. Das ist wieder
genau so ein Beispiel für so ein kleines Stück Müll,
was da überbleibt, so ein Schnipselchen,
das aber irgendwie auf Dauer irgendwie auch unschön ist,
dass die Kommentare nicht mehr zu den Dingern passen
Bin ich oft sehr nervös, wenn Leute so mal eben
so schnell so ein Refactoring durchschießen durch ihr System.
Also einfach so, oh ja, Renate Methods,
zack, alles mal eben ändern.
Das kann relativ schnell unangenehme Effekte haben. Also ich finde schon,
man muss so ein bisschen im Blick behaben,
was man da noch so tut. Natürlich kriegt man mit der Zeit,
mit der Erfahrung dann auch ein Gefühl dafür,
was riskant ist und was nicht riskant ist.
Riskant ist das hier nicht. Das ist nur ärgerlich,
dass diese Kommentare nicht benannt sind. Gut. Ja,
also haben wir das jetzt auch mal gesehen,
dass das hier zwar funktioniert und sehr viel einfacher,
also aus vermeintlich einfacher für uns natürlich,
aber eben halt auch nicht so richtig
voll befriedigend
Ja, okay, ein anderes Refactoring ist Methode extra hier,
will ich auch noch mal kurz zeigen.
Das ist ein Refactoring zum Zertliedern von großen Methoden.
Also genau diese Idee, hm, große Methoden sind nicht schön.
Es wird also einfach ein Teil einer Methode ausgelagert. Mechanikbeschreibung inklarieren eine neue Methode mit einem sprechenden Namen,
übersetze, kopiere den zu extra hin in den Ausschnitt,
die neue Methode,
suche in der neuen Methode nach Referenzen auf lokale Variablen der alten Methode,
mache diese entweder zu Parametern oder zu lokalen Variablen der neuen Methode,
oha,
dann Übersetzer und Teste,
ersetze in der alten Methode den extrahierten Quelltext mit dem Aufruf
der neuen Methode
Okay, also wir haben zwischenzeitlich, haben wir dann Code-Duplizierung, ist klar.
Okay, das zeige ich mal an einem Beispiel.
Und zwar meine ich hier im Start-up, ist es so
ein bisschen interessant, macht das mal ein bisschen größer.
So, hier ist es jetzt so,
hier werden jetzt im Start-up so einige Dinge getan und er sieht,
er seht, diese Methode passt nicht auf eine Bildschirmseite.
Ich habe also hier, hier werden irgendwie,
wird ein Array von Kinoseelen angelegt,
da wird mir schon leicht trindel, ich mich das sehe,
warum sind das Arrays, warum sind das keine Sammlungen,
ja, wer macht denn sowas?
Gut, dann hat man hier einen Film, Array,
da werden Filme angelegt,
sondern werden hier irgendwelche Uhrzeiten erzeugen,
dann ist es so,
dass hier
Vorstellungen gebaut werden
Ein Array von Vorstellungen, da werden dann hier die
ganzen Dinge, die man vorher gebaut hat, reingestopft.
So, jetzt könnte ich mir ja sagen,
eigentlich könnte ich doch jetzt hier diesen Teil,
den hätte ich jetzt gerne mal ausgelagert.
Das möchte ich gerne in eine Methode auslagern,
die da heißt Refacte, Extract Method.
So, und die möchte ich jetzt in eine Methode auslagern,
die nenne ich mal, erzeuge Vorstellungen.
Das ist ja genau das, was da passiert. So,
auch da kann ich mir jetzt erstmal ein Preview zahlen lassen,
ich kann es aber auch jetzt einfach machen,
dann seht ihr,
was sich da geändert hat
Jetzt hat er hier, an dieser Stelle, die Methode ist jetzt groß genug,
also klein genug, dass sie auf einen Bildschirm passt.
Ihr seht es, hier ist die öffnete Klammer,
hier ist die schließende Klammer. Hier werden die ganzen Dinge erzocken,
dann wird hier, wie gesagt, Vorstellung ist gleich,
Erzeugevorstellung mit den Seelen, den Filmen und diesen verschiedenen Uhrzeiten.
Naja, und diese Erzeugevorstellung ist natürlich auch eine statische Methode,
weil es ist ja eine Main-Methode, ist ja statisch,
also muss diese Methode auch direkt aufrufbar sein.
Und dann wird hier tatsächlich, wenn dann diese ganzen Sachen übergeben, das heißt,
alles das, was in dem Code gebraucht wird, wird hier übergeben.
Also das haben wir jetzt nicht von Hand, die Mechanik nachvollzogen,
aber Eclipse hat hinter den Kulissen genau das gemacht,
was letztendlich dazu führt, dass wir jetzt hier Und diesen Code,
der auch auf einer Bildschirmseite passt,
irgendwie schön knapp haben.
Das ist ja auch irgendwie so, hier erzeuge ich die Vorstellung vorher,
habe ich irgendwelche Sachen erzeugt, die ich für die Erzeugung brauche.
Kann man also machen. Okay, das waren jetzt zwei Beispiele.
Also Renake Method, werdet ihr ziemlich viel brauchen.
Es ist auch tatsächlich so, wenn man mit oppositionierten Systemen arbeitet,
dann will man häufig irgendwie auch die Möglichkeit haben,
leicht die Methodennamen zu ändern oder die Klasse
Das ist mit FuJ zum Beispiel war das immer ein Schmerz.
Also als wir früher unsere ganzen Systeme,
die wir hier so auch in der Lehre einsetzen,
nur in Blue Jay verwaltet haben, haben wir oft Schmerzen gehabt,
wenn wir dann Sachen ändern wollten, weil dann eben halt,
wenn die Refactoring-Unterstützung fehlt, ist das schlecht.
Das heißt, die Renay Method werdet ihr ziemlich häufig benutzen,
weil ihr einfach häufig hoffentlich in euren Entwicklungsteams Diskussionen führt, was der bessere Name ist.
Es ist immer sinnvoll, sowas auch zu diskutieren. So,
Renay Method gibt es ganz viele, es gibt auch Rename-Paket,
klasse Methode, variable, konstanter, alles Mögliche,
Move, auch durchaus häufig irgendwie,
ich will eine Methode vielleicht in der Vererbungsgeräche nach oben ziehen oder nach unten oder in eine ganz andere Klasse bewegen.
Change Signature, Bewege, Extrahiere, ein Interface,
eine Methode, also was wir eben gesehen haben,
was ziemlich häufig vorkommt, ist Expertieres Interface.
Ich habe eine Klasse mit öffentlichen Operationen und ich sage so,
jetzt extrahiere mal die Schnittstelle, erzeuge mein Interface aus.
All das ist durchaus alles denkbar, dass man es benutzt.
Und da gibt es eben halt eine ganze Menge davon.
Also er setzt einen Subtyp durch einen super Typ und ähnliches
Was ich noch mal ganz so kurz vor Schluss hier noch mal
kurz ansprechen wollte, ist, es ist ganz interessant,
dass der Fauler auch zwei Refactorings in seinem Buch hat zum Thema Werte und Objekte.
Das eine heißt Change Value to Reference und das andere heißt Change Reference to Value.
Und er beschreibt das hier so, das ist ganz interessant.
You can make a useful classifification of objects in many systems.
Reference objects and Value Objects. Reference objects are things,
like customer or are account, heach objects stands for
one object in the real world, bla bla bla.
Also ihr seht, das sind so unsere Materialien, unsere Objekttypen aus letzten Vorlesungen.
Und dann Value Objects are things like date or money,
they are defined and tilly through the data Values,
you don't mind that copys exist.
Das ist das, was ich letzte Woche erzählt habe.
Diese Wertobjekte, die Werte repräsentieren,
da kannst du ruhig mehrere von geben,
solange ich nur mit Equals vergleiche, ist alles prima.
You may have hundreds of 1., 1. 2000 Object Around Your System.
You do need to to totell where that two of to objects are equal.
So you need to overright the equals method and the hash
cold method two. Das kennen wir alles. So,
the decision between reference and value is not always clear.
Das ist schön,
das kann auch schön unscharf bleiben an der Stelle
Er sagt, es gibt da sowas, das ist aber nur angedeutet.
Und das ist auch ganz lustig, dass er dann hier
tatsächlich so Refactorings dazu thematisiert. Ich würde mal sagen,
es kommt möglicherweise selten vor, dass man sich erst entscheidet,
das ist ein Objekttyp und dann stellt man fest,
ach, eigentlich ist es doch eher ein Wert.
Und das ist eine relativ fundamentale Unterscheidung,
aber auch das kann man refactern wollen, dass man feststellt,
in unserem Entwurf ist das bisher ein Objekt.
Wir machen es mal zu einem Wert, das würde
viel besser funktionieren. Also auch da wieder der Hinweis,
diese Unterscheidung von Werten und Objekten und Werttypen und Wert
Objekttypen ist nicht unbedingt jetzt was,
was nur auf unserem Mist gewachsen ist.
Was wir gesehen haben, diese starke Mechanisierung, dadurch,
dass es diese Mechanics gibt und dass man sie so genau aufschreiben kann,
ist es eben halt möglich, das durch Werkzeuge zu unterstützen.
Also neben Eclipse gibt es natürlich auch andere IDEs,
die das können. Also für Java gibt es IntelliJ IDA,
es gibt Net Beans, es gibt aber auch inzwischen in
Visual Studio für CPlus Plus und so weiter gibt es auch Refactoring-Unterstützung.
Das ist in den letzten zehn Jahren passiert.
Vor zehn Jahren war das nur in dem Refactoring-Buch von dem
Fowder drin und die IDEs hatten es nicht.
Das ist tatsächlich in den letzten zehn Jahren erst überhaupt in
die Idee reingewandert.
Und das
eben halt unterschiedlich stark
Einige haben da sehr viele Refactorings, die sie anbieten.
Also Eclipse ist da schon ziemlich weit vorne. Kein Wunder,
weil der Erich Gamma ja auch jemand ist,
der da an diese Refactoring-Serie glaubt.
Das wird auch alles kontinuierlich weiterentwickelt. Das ist aber auch nicht einfach.
Also so eine Refactoring-Unterstützung zu bauen, ist echt spannend.
Wir hatten mal einen der Mitarbeiter von Erich Gamma bei uns im Oberseminar.
Dirk Bäumer. Und der hat uns dann erzählt,
wie viel Aufwand die reinstecken, um so ein Refactoring zu implementieren.
Also sozusagen innerhalb der IDE. Und das ist erheblich.
Und man muss sich immer fragen, wie oft wird das
denn wirklich angewendet? Es gibt so Refactorings,
die passieren heute
Also Renay Method, da muss es eine Unterstützung geben,
weil es einfach so häufig vorkommt. Es gibt andere,
die sind möglicherweise komplizierter und der Aufwand lohnt sich nicht,
weil fast niemand das je benutzen wird. Aber wenn irgendwie mal so zwei,
drei Programmierer bei OTI drei Wochen investieren in so ein Refactoring,
das zahlt sich aus, wenn es Renay Method ist,
weil dann irgendwie eine Entwicklerin in der Welt diese Unterstützung dann
haben und das eben halt alles sehr viel schneller geht.
Was ganz wichtig ist,
dieser Grad der Unterstützung ist auch von der Programmiersprache abhängig.
Also das hat uns dann Dirk Bäumer auch so nebenbei erzählt.
Es ist ungleich schwieriger, eine Refactoring-Unterstützung für CPlus
zu bauen
als für Java
Java hat ein sehr sauberes Sprachmodell, eine sehr klare Typisierung.
Es ist sehr viel einfacher festzustellen, oh,
es gibt Filme mit dem Filmtitel, wo wirklich ein Film
geliefert wird und einmal, wo nur ein String geliefert wird.
Also diese Typinformationen sind sehr viel leichter abzuleiten. Das ist bei CPlus,
aber CPlus ist insgesamt einfach eine sehr viel komplexere Sprache.
Wir müssen viel mehr Sonderregeln beachtet werden,
das macht das Refactoring richtig, richtig schwierig.
Da kann man sich schon bei Wund programmieren. Das nur
noch mal so ein bisschen zur Werkzeugsunterstützung. Vorgehen beim Refactoring,
auch etwas, was im Foul dann noch mal deutlich drinsteht.
When you find you have to add a feature to a
program and the programs code is not structured in a convenient way to at the feature.
First refactor the program to make it easy to at the
feature, then at the feature. Das heißt,
wenn ihr tatsächlich in die Verlegenheit kommt,
ihr habt ein System und ihr sollt etwas Neues hinzubauen und
ihr versteht das System nicht oder ihr habt das Gefühl,
dass die Struktur das nicht hergibt,
dann trennt wirklich sauber zwischen ich refactory erstmal.
Das Verhalten sollte das Gleiche bleiben und dann in den Umständen
dann dieses neue Feature rein.
Das kann man wirklich sauber trennen
Before you start refactoring, check that you have a solid suite of tests.
These tests must be surf checking. Also das ist genau das,
was wir sagen. Also automatisierte Tests sollte man haben.
Es ist tatsächlich so, beim Refactory besteht immer die Gefahr,
dass wir neue Fehler in die Quelltext einbauen.
Wir haben das eben schon so an so Kleinigkeiten gesehen,
aber es kann durchaus hübler ausgehen. Und man kann eigentlich sagen,
Refactoring ohne ausreichende Testabdeckung ist, wie Autofahren oder Sicherheitssquad.
Also wenn es dann kracht, dann tut es richtig weh.
Sollte man vermeiden. Also Refactoring hängt sehr stark davon ab,
dass man auch eine gute Testabdeckung hat.
Man kann nicht einfach in einem Softwaresystem sagen, wow,
wir machen mal ein Refactoring
Ist halt gefährlich. Also dieses Verhaltenserhaltende ist nicht so leicht festzustellen ohne vernünftige Tests.
Gut, dann zum Schluss noch der Ausblick hier auf große Refactorings.
Diese Definition, die wir am Anfang gegeben haben,
von Refactoring, gesagt, nichts über den Umfang aus.
Der Fauler selber hat gesagt, es sind eher kleine Änderungen.
Und diese automatisierten Refactorings haben wir gerade gesehen,
die werden meist innerhalb von ein paar Sekunden ausgeführt.
Bei händischen Refactorings gibt es,
also wenn man wirklich von Hand in den Refactoring durchführt und
sich an die Mechanik hält,
so ein Entwicklerpaar,
die sollten so ein konkretes Perfectoring in meiner Hand von
zwei bis vier Stunden
durchführen können
Das ist so ein bisschen diesem agilen Vorgehen geschuldet,
dass man sagt, naja,
man sollte eigentlich alle zwei bis vier Stunden, sollte man das,
was man tut, auch wieder einchecken in das Repository.
Man sollte nicht zu lange einen ausgecheckten Stand weiterpflegen.
Also wenn man so mehrere Wochen an seinem eigenen Süppchen
kocht und das dann nach Wochen wieder versucht zu checken,
da hat sich inzwischen das ganze System komplett verändert.
Das tritt einfach so wirklich auf. Also sollte man eigentlich
relativ häufig einchecken, alle zwei bis vier Stunden.
Das kennt ihr noch nicht so,
weil wir das in der SE2 ja noch kaum thematisieren,
dass man mit einem Repository arbeitet,
also wo der Quelltext liegt und mehrere Entwickler teilen sich diesen Quelltext,
arbeiten auf dem gleichen Quelltext oder auf demselben sogar
Aber da ist es eben halt so, man sollte häufig einchecken.
Und deswegen sollten diese Refactorings auch relativ schnell ausführbar sein.
Aber es gibt in großen Projekten einfach häufig die Situation,
dass man feststellt, oh Mensch,
dieser ganze Entwurf von unseren fachlichen Materialien, der ist nicht mehr vernünftig.
Der passt nicht mehr auf die neuen Anforderungen. Wir müssen
die ganze Materialstruktur komplett umstellen. Und das kann dann sein,
dass so ein Refactoring tatsächlich, ich habe es erlebt,
ich wollte es nicht glauben, aber es ist tatsächlich vorgekommen,
dass man über mehrere Tage oder über mehrere Wochen so ein Refactoring durchzieht,
weil es einfach so viel tot ist,
dass man das nicht von Hand irgendwie oder automatisiert schon gar nicht hinkriegen kann.
Man könnte jetzt argumentieren, fauler würde sagen,
das ist dann kein Refactoring mehr
Ist Geschmackssache. Also wenn es wirklich nur darum geht,
die Struktur der Materialien zu ändern und sich für die Benutzung
nichts ändert, dann ist es eigentlich auch ein Refactoring.
Und das kann eben halt sehr, sehr schwierig sein.
Da muss man sich Konzepte einfallen lassen, wie man denn darauf hinweist,
dass da jetzt an einer bestimmten Stelle etwas in einem anderen Zustand ist,
als Zwischenstand eines großen Refactorings.
Also da müssen sozusagen alle Programmierer müssen sich bewusst sein,
oh, jetzt sehe ich, ich verstehe den Code nicht,
ah ja, da steht ja ein Kommentar, naja,
es ist gerade ein Refactoring.
Also das muss dann entsprechend markiert werden.
Also auch da gibt es dann Überlegungen,
wie man so große Refactorings auch mit Werkzeugunterstützung hinkriegen kann.
Und man sollte halt sowas haben wie Refactoring-Pläne.
Also tatsächlich an der Wand einen großen Plan aufhängen haben,
wo man dann sagt, so,
die sieben Schritte führen wir in den nächsten fünf Wochen durch.
Und der ist abgehakt und dann kann auch jeder sehen,
ah ja, da findet gerade ein großes Refactoring statt.
Das nur so als Ausblick, das werdet ihr so schnell nicht erleben,
vermute ich mal, aber es kann durchaus passieren.
Ja, da sind wir auch für heute auch schon fast durch.
Also Software wird fortlaufend verändert, das habe ich mehrfach gesagt.
Dadurch entstehen lang üble Gerüche. Eine Refactory ist
eine Restrukturierung von Software, die deren Funktionalität erhält.
Es gibt eine Reihe von etablierten Refactorings, ganz viele,
bei dem Foul dann nachzulesen.
Refactorings könnten ihrer Mechanik beschrieben werden, sehr ausführlich,
sehr detailliert
Das gehört zum Handwerkszeug der Softwareentwicklung, wenn man vernünftig objektnotierte
Systeme bauen will, dann sollte man auch Refactorings beherrschen.
Ja, eine gute IDE kann für gute,
für eine gute Programmiersprache bei vielen Refactorings automatisierte Unterstützung anbieten.
Und das ist in Eclipse für Java auf jeden Fall der Fall.
Gibt es noch Fragen jetzt zum Thema Refactoring?
Keine Frage, dann machen wir Schluss.