15. März 2023

Sauberer Code – Änderbarkeit

Und weiter geht es mit Clean Code. Änderbarkeit und Erweiterbarkeit gehen Hand in Hand. Heute beschäftigen wir uns mit dem Änderbarkeit und zeigen dir was wir damit meinen und warum muss sich unser Code verändert werden muss? Du änderst bestimmt auch öfters dein Code. Damit es dir leichter fällt, stellen wir dir heute einige Praktiken und Methoden, die dazu führen, dass dein Code leichter zu ändern ist.
Macht der Craft
Macht der Craft
Sauberer Code - Änderbarkeit
Loading
/

Show Notes

Macht der Craft
Macht der Craft
Sauberer Code - Änderbarkeit
Loading
/

Dieser Episode beinhaltet keine Notizen

Matthias: [00:00:07.78] Hallo und willkommen zurück bei der Macht der Craft.

Alex: [00:00:10.54] Und unsere Miniserie über CleanCode.

Matthias: [00:00:13.48] Heute wollen wir uns Änderbarkeit näher ansehen.

Alex: [00:00:16.51] Du wirst erfahren, warum es wichtig ist, auf die Änderbarkeit einer Anwendung zu achten.

Matthias: [00:00:22.93] Und natürlich auch, welche Prinzipien dir dabei helfen können.

Alex: [00:00:26.56] Dann lass uns mal loslegen.

off: [00:00:29.97] Die Macht der Craft arbeitet für dich

Alex: [00:00:34.35] Also was als erstes für mich eine Rolle spielt, in denen die ganze Geschichte Änderbarkeit ist: Warum ändern wir Code? Warum müssen wir Code ändern? Und was verstehen wir unter Änderbarkeit? Und zwar hier in dieser Folge, weil das nicht alles das Gleiche ist. Also nicht alle Gründe, Code zu ändern, gehören für mich in diese in dieser Rubrik hier. Und deswegen würde ich gerne das ein bisschen auseinandernehmen. Was denkst du?

Matthias: [00:01:06.93] Klingt gut.

Alex: [00:01:08.34] Klingt gut. Ja, ich kann mich an ein Michael Feathers erinnern. Ich glaube, das kommt von ihm. Von dem Legacy Code Buch, die er geschrieben hat. Und da sagt er, es ist eigentlich nur vier Gründe gibt, um Code zu verändern. Das Hinzufügen von eine Funktionalität, das Korrigieren von einem Fehler, das Design der Anwendung zu verbessern oder um Optimierungsmaßnahmen vorzunehmen.

Matthias: [00:01:39.47] Ja, klingt vertraut.

Alex: [00:01:41.30] Fällt dir irgendwas an das andere Gründe oder andere Ideen? Oder kannst du vielleicht ein bisschen erzählen, was du dich unter den einzelnen Rubriken vorstellst?

Matthias: [00:01:53.16] Ja, das kann ich natürlich gerne machen. Also ich fange einfach mal mit dem Hinzufügen von dem neuen Feature an. Das ist, glaube ich, relativ selbsterklärend. Also wir wollen im Prinzip neue Funktionalität zu unserer Anwendung hinzufügen und dadurch haben wir einen Grund, den Code zu ändern. Also relativ simpel an der Stelle.

Alex: [00:02:14.63] Ja.

Matthias: [00:02:15.83] Dann hätten wir als nächstes die Fehlerbehebung. Bug-Behebung kann man auch theoretisch sagen, relativ selbsterklärend. Also ich habe einen Fehler in meiner Anwendung. Den muss ich natürlich in irgendeiner Weise korrigieren und dafür muss ich ihn, sage ich mal, 99/100 Fällen den Code ändern. Kann auch sein, dass irgendwie eine Konfiguration reicht oder sowas oder was anderes. Aber ich sage mal, in sehr, sehr vielen Fällen muss ich dafür den Code ändern. Als nächstes die Verbesserung des Designs. Da wird es wahrscheinlich ein bisschen interessanter, weil da können natürlich ganz viele unterschiedliche Gründe irgendwie vonnöten sein. Das kann zum Beispiel sein, dass ich ein neues Feature hinzufügen will. Ich stelle aber fest, das würde verdammt viel Aufwand bedeuten. Das heißt, ich muss vielleicht vorher das Design der Anwendung verändern, um überhaupt das Feature hinzufügen zu können. Und dann wäre das aber der Grund, warum ich den Code änder. Also ich will das Design verbessern, damit ich zum Beispiel neue Features besser integrieren kann. Genau das könnte dann noch darunter fallen. Grundsätzlich, wenn ich irgendwie – wie soll man sagen? – Also ich meine es so Softwareentwicklung entwickelt sich ja auch weiter und neue Sprachfeatures bringen vielleicht irgendwie neue Möglichkeiten oder bzw. ich muss vielleicht sogar auf Grund von der Aktualisierung der Programmiersprache, mit der ich arbeite, zum Beispiel irgendwelche Anpassungen durchführen. Würde ich wahrscheinlich auch in dieser Kategorie sehen. Wie siehst du das?

Alex: [00:03:59.03] Ja auch. Passt für mich.

Matthias: [00:04:01.02] Ja genau. Und ich glaube, damit wird es auch ungefähr klar, was damit gemeint ist.

Alex: [00:04:06.92] Optimierung hätten wir noch.

Matthias: [00:04:08.96] Genau. Und da werden wir dann ganz stark in den Bereich Performance und auch Memoryverwendung, also dass wir halt schauen, dass wir mit unseren Ressourcen sinnvoll umgehen.

Alex: [00:04:21.08] Für mich gibt es in den vielen Kategorien zwei Gruppen sozusagen, Die andere ist das Hinzufügen von Features und das Ändern von Bugs. Ich bin mir sicher, du kennst das auch. Heiß diskutiertes Thema. Ist das ein neues Feature oder ist das ein Bug? Ja, natürlich. Da auch sehr oft sehr viel Diskussionsbedarf, ob es ein Bug ist oder ein neues Feature. Deswegen gehören für mich sehr eng zusammen und die andere zwei gehören für mich zum Thema verbessern. Das ist die Verbesserung des Designs und die Optimisierung oder Optimierung, die Verbesserung der Laufzeit, der Speicherbedarf der Performance. Solche Themen, wie du wohl sehr gut uns erzählt hast. Und diese zwei Bereiche. Aber was verstehe ich dann unter Änderbarkeit? Oder was verstehst du unter Änderbarkeit? Welche von all diese vier gehören zu Änderbarkeit und welche nicht?

Matthias: [00:05:25.90] Na ja, also ich sag mal so direkt unter Änderbarkeit selber würde ich die letzten drei Gruppen sehen, also Fixing a Bug, improving Design und Optimizing. Aus dem einfachen Grund, weil das im Prinzip die Gründe Code zu ändern sind, die die bestehende Codebasis verändern, ohne neue Funktionalität hinzuzufügen. Und wenn ich jetzt neue Funktionalität hinzufüge, dann ändere ich eigentlich nicht meine Anwendung per se, sondern ich erweitere sie sozusagen um neue Funktionalität. Und deswegen könnte man das Hinzufügen von einem neuen Feature zum Thema Änderbarkeit ein bisschen ausgrenzen.

Alex: [00:06:10.75] Vielleicht das Thema optimieren, auch ein bisschen. Fangen wir mal an das also obwohl alle vier irgendeine Art von Änderung bedeuten, ist für mich, wie du gesagt hast, Adding a Feature oder Funktionalität hinzufügen eher das erweitern meiner Anwendung würden wir gerne in das Thema Erweiterbarkeit dann noch sehen und die Fehlerkorrekturen und das Design verbessern sind für mich die die zentrale Aspekte in diesem Bereich und das Thema Optimisierung. Ich weiß jetzt nicht mehr, wer es war, hat irgendwann einmal gesagt „optimizing is root of all evil“ und wie kann man des auf Deutsch zu übersetzen?

Matthias: [00:06:48.88] Naja ist die Wurzel allen Bösens.

Alex: [00:06:51.76] Weiß jetzt nicht mehr wer es war, aber Optimisierung, das machen wir, wenn wir, wenn wir müssen, wenn also nicht aus Prinzip einfach optimieren, sondern wenn es die Notwendigkeit besteht. Wenn mein System tatsächlich schneller sein muss, weil wir Daten haben, die belegen, dass unser System zu langsam ist, dann gerne. Aber rein aus Prinzip würde ich jetzt nicht unbedingt die Baustelle aufmachen. Also bleiben für mich jetzt als zwei zentrale Punkte, die wir uns heute widmen werden, das Thema Fehlerkorrekturen im Allgemeinen und die Verbesserung des Designs. Und da wollen wir uns Prinzipien und Techniken anschauen, die uns dabei helfen, die es uns leichter machen, dass wir den Code verändern können zu irgendeinem bestimmten Zeitpunkt. Also wir verwenden diese Techniken normalerweise oder nicht immer, um den Code zu ändern, sondern in vielen Fällen ist einfach nur so, dass wir diese Techniken vorab verwenden, damit, wenn wir was ändern müssen, es leichter ändern können. Auch das Thema Improving Design hat für mich ein eine ganz besondere Komponente, ein ganz besonderen Namen und Premium Design ist für mich hat sehr sehr sehr viel zu tun mit Refactoring und auch da gehört für mich das Thema angesiedelt. Aber gut, was meinst du, kann man uns zu den Prinzipien und Techniken mal ein bisschen anschauen?

Matthias: [00:08:21.85] Ja, auf jeden Fall.

Alex: [00:08:23.68] Dann, Du darfst Infromation-Hiding. Was ist Information-Hiding?

Matthias: [00:08:29.32] Information-Hiding, letztendlich soll diese oder was ist die Praktik von Mal lieber mal so an? Letztendlich bedeutet es ich möchte die Internas meiner zum Beispiel einer Klasse eines Objektes nicht nach außen unbedingt veräußern, sondern ich möchte klares Interface haben. Das kann diese Klasse eben leisten. Und genau, aber es sollen halt zum Beispiel irgendwelche Felder dieser Klasse nicht von außen manipulierbar sein. Nach Möglichkeit Genau. Jetzt mal ganz blöd gesagt.

Alex: [00:09:06.46] Also ich würde Information-Hiding bedeutet für mich, wir wollen Sachen vom Verwender, die Leute oder die Anwendungen, die uns nutzen oder unsere Anwendung oder unsere Klassen nutzen. Da wollen wir Sachen verstecken, Wir wollen Sachen versteckt halten, Details versteckt halten, das sie nicht brauchen. Und das ist auch eine der Grundprinzipien von die objektorientierte Programmierung mit diese ganze Klassen und diese Strukturierung Klasse in Objekten, public Methoden, private Methoden, die ganze Geschichte. Also, bevor ich irgendwas implementiere, muss ich mir klar machen, was muss mein Verwender wissen. Das bedeutet schlicht und ergreifend, ich muss auf irgendeine Art und Weise eine Schnittstelle definieren. Ein Vertrag zwischen Nutzer und Entwickler, zwischen die Leute, die meine Anwendung, die eine Klasse nutzen müssen und wir das halt schreiben.

Matthias: [00:10:08.71] Genau. Und letztendlich sollte es halt dem Verwender auch, wie soll man sagen, es darf nicht vom Verwender unserer Klasse verlangt werden, dass er bestimmte Internas aus unserer Klasse kennt. Zum Beispiel, dass er Methode X vor Methode Y aufrufen muss, sonst wirft Methode Y immer einen Fehler. Also das sind so Geschichten, die durch dieses Prinzip auch so ein bisschen unterstützt werden. Also das ist mal mein Verwender, der benutzt einfach meine Klasse. Er weiß, da gibt es eine Public Methode, doSomeReallyCool stuff und was da drinnen passiert muss er aber nicht wissen, solange der realyCoolStuff am Ende rauskommt.

Alex: [00:10:53.14] Genau. Wir können diese Information-Hiding auf unterschiedlichen Ebenen auch verwenden. Du hast jetzt Gerede von Klassen, unterschiedliche Methoden und private public. Dadurch kann ich nur die Informationen, die meine Anwender betreffen, sind public. Alles andere ist privat oder was auch immer, also versteckt von von denen. Aber auch wir können es auch größer ziehen und es auf Anwendungsebene betrachtet, in dem wir zum Beispiel Rest API Definitionen festlegen. Das ist im Endeffekt auch das gleiche. Es gibt eine öffentliche Schnittstelle, das, was man von mir oder von meiner Anwendung weiß und verlangen kann. Und das, wie genau das gemacht wird, das wird versteckt. Es ist egal, wenn wir bei dem Klassenbeispiel bleiben, ob ich zum Speichern von die Informationen, die ich speichern muss, jetzt eine Liste oder ein Stack oder ein Baum verwende. Das ist ein Implementierungsdetails. Es braucht keiner wissen, das interessiert keiner. Meine Leute wollen nur darin suchen können und welche genaue Implementierung ich dafür verwende, ist jetzt nicht von Belang. In dem Sinne also für den Verwender natürlich für. Für unsere Implementierung ist es natürlich von Belang, aber nicht für den Verwender. Und dies ist für mich was, was das Thema Information-Hiding mit sich bringt, was es bedeutet und warum machen wir das? Aber warum verstecken wir diese Informationen?

Matthias: [00:12:23.46] Naja, letztendlich würde ich mal sagen, um Fehlerquellen zu reduzieren. Ganz einfach Es ist auch nicht nur in unserem Code, sondern jetzt auch in dem Code von unserem Verwender, weil Bugs müssen uns ja von irgendjemandem gemeldet werden. Ergo die Verwender, das heißt, irgendetwas funktioniert bei ihnen nicht, weil sie zum Beispiel eben nicht wissen, dass die Methode X von Methode Y aufrufen müssen und allein das zu verhindern, was ja im Prinzip eine Bugquelle ist. Ist dieses Prinzip ultra nützlich?

Alex: [00:12:58.13] Auch finde ich, wenn ich meine interne als die Details meiner Implementierung nicht preisgebe, kann ich sie jederzeit ändern, ohne dass meine Verwender davon betroffen werden. Wenn irgendjemand weiß, dass ich eine Liste verwende für irgendwas, ja, dann kann er darauf aufbauen und Methoden und Funktionen und Sachen verwenden, die diese Liste zur Verfügung stellt. Und das ist ein Problem spätestens zu dem Zeitpunkt, wo ich keine Liste mehr verwenden möchte.

Matthias: [00:13:31.40] Hm.

Alex: [00:13:32.18] Intern und irgendwas anders, die irgendwie ganz andere Methoden hat, ganz anders verwendet wird. Also ich verstecke diese Liste, ich lasse sie nicht nach außen, ich zeige sie nicht, sodass ich später in der Lage bin, diese Liste durch einen Baum zu ersetzen. Meinetwegen, wie auch immer diese auch implementiert ist. Und dadurch erhöhe ich die Flexibilität, die ich habe und habe die Möglichkeit, einfacher, schneller Änderungen vorzunehmen, ohne dass irgendjemand anders davon betroffen wird. Das ist die Kernaussage, finde ich. Ich möchte ändern und ich möchte es gut ändern können, aber ich möchte nicht andere mit meine Änderung Anführungszeichen beglücken. Also das, was total öde ist, ist, wenn sich in irgendeiner Library ohne irgendeine Anwendung sich verändert und ich nutze diese, diese Library und ich muss jetzt drei Wochen lang oder zwei Wochen, eine Woche oder keine Handvoll, auch nur zehn Stunden völlig egal. Muss ich mein Code anpassen, weil sie was geändert haben? Das ist ja nicht zu vermeiden. Es wird immer Fälle geben, in dem so was passiert, sogenannte Breaking Changes. Aber wir sollen uns bemühen, dies auf ein Minimum zu reduzieren, vor allem, wenn wir selber die Entwickler sind, die diese Library oder diese Anwendung zur Verfügung stellen mussten. Wir sehen, dass diese Schnittstellen stabil bleiben, sind nicht verändert. Um die Detailimplementierung ist es geht uns nur an, das ist egal für den Verwender und soll eben auch nicht stören. Wenn wir was anders machen.

Matthias: [00:15:19.07] Dann können wir uns den nächsten Punkt vornehmen, würde ich sagen. Und was Sie ja gerade so erwähnt, die guten Refactorings, die fallen ja auch so ein bisschen hier rein. Also nicht nur ein bisschen, ein bisschen, sehr, sehr genau, Weil letztendlich immer, wenn wir von der Verbesserung des Designs oder der Optimierung unseres Systems sprechen, sprechen wir ja eigentlich immer von einem Refactoring.

Alex: [00:15:48.56] In meinen Augen sind Refactoring, sie haben sehr viel mit mit diesem Thema Änderbarkeit zu tun, aber sie dienen auch viele andere Themen und Gruppierungen, die wir in diese Clean-Code-Geschichte, zum Beispiel ein klassisches Refactoring wäre das Renaming und die Namensgebung war eindeutig ein Thema, die zu Lesbarkeit des Codes total viel beigetragen haben. Also in diesem Sinne, das kann man nicht komplett ausschließen, dass so diese Thema Refactoring strahlt in alle Richtungen, aber es ist in meinen Augen eine der wichtigsten Techniken, die wir haben, einen Code zu verändern, zu ändern.

Matthias: [00:16:30.65] Ja, absolut. Und wir können noch mal ganz kurz vielleicht einfach bei Themen, die unsere Folgen zu Refactorings nicht gehört hat, einfach den Einen Satz noch mal sagen, was Refactorings eigentlich per Definition sind. Mache ich genau, Weil es sind letztendlich Änderungen an unserer Code Basis, die keinerlei Funktionalität verändern oder hinzufügen. Also das System verhält sich danach exakt genauso wie vorher, nur die interne haben sich geändert.

Alex: [00:17:01.67] Also wir ändern die Form, aber nicht die Funktionalität. Okay, verstanden.

Matthias: [00:17:06.89] Genau.

Alex: [00:17:07.67] Warum machen wir so was?

Matthias: [00:17:09.03] Na ja, natürlich. Wir. Um unser Design zu verbessern oder Dinge zu optimieren.

Alex: [00:17:15.53] Warum ist das notwendig? Ich, Wenn’s geht. Es geht ja schon.

Matthias: [00:17:18.68] Never touch a running System, meinst du?

Alex: [00:17:20.09] So, Ja, das geht.

Matthias: [00:17:22.61] Ja. Also letztendlich. Ich finde, Refactorings sind tatsächlich ja ein bisschen so auch Teil meines Alltags, weil ich permanent irgendwas umbenennen, weil mir permanent irgendwie der Name doch nicht sprechend genug sind oder der Kontext ändert sich minimal und also ich habe die ganze Zeit irgendwelche Refactorings.

Alex: [00:17:44.96] Also für mich sind Refactorings sind eine Technik, die mir ermöglicht, schnell und sicher Änderungen an meinem Code vorzunehmen und deswegen nutze ich sie ja. Aber was brauche ich, damit ich gefahrlos refactoren kann? Ja, es.

Matthias: [00:18:06.44] Ist jede Menge Tests, und zwar die von der guten Sorte.

Alex: [00:18:11.42] Also es ist tatsächlich wichtig, dass wir Tests haben, die, weil es gibt einfache Refactorings natürlich, die wie das Umbenennen in eine Variable, die nur in eine Klasse verwendet wird. Aber ich habe schon Refactorings gemacht, wo ich dann danach 25 Dateien angefasst habe. Ja, weil ändert sich eine Klassenname oder wird er überall, wo diese Klasse verwendet wird und muss geändert werden und muss angepasst werden oder es verändert sich ein Interface Name gleiche. Das ist ganz schnell an ganz viele Stellen, wo du Änderungen machen musst. Und das haben wir früher, als ich noch jung war. Das haben wir per Hand gemacht. Na, wolltest du eine Variable umbenennen? Hast du die Variable umbenannt? Hast du geguckt, wo überall verwendet wird? Du hast sie dann umbenannt an alle Stellen, wo sie auch verwendet werden. Das war öfters zusammen verheiratet mit: Ich kompiliere ein paar Mal, damit ich sehe, was knallt. Dann weiß ich, wo ich es ändern muss. Aber heutzutage gibt es viele Refactorings, die wir nicht mehr manuell machen müssen, sondern automatisiert gemacht werden können. Dank unserer IDE. Und das gibt auch Sicherheit. Ich meine, die haben sich schon Gedanken gemacht, dass wenn ich irgendwas umbenennen, eine Methode extrahieren oder eine Methode von Klasse A zu Klasse B verschiebe, dass auch alle Änderungen gemacht werden, die notwendig sind. Das ändert nichts an der Tatsache, dass wir tatsächlich jede Menge Tests haben sollten, um zu prüfen, dass tatsächlich die Funktionalität danach immer noch die gleiche ist wie vorher. Wenn vorher meine alle meine Tests grün waren. Also alles ging wie geplant in Anführungszeichen und ich mache jetzt irgendwelche Refactorings. Danach muss in all meinen Tests immer noch Grund sein, weil keine Funktionalität Änderung dabei passieren dürfen, keine neue Funktionalität dazu und keine alte Funktionalität verändern. Und deswegen sind die Tests so wichtig in dem Fall.

Matthias: [00:20:17.09] Vor allem, wenn wir in den Bereich der komplexeren Refactrorings kommen.

Alex: [00:20:20.69] Ja, da wird es lustig. Und auch zum Thema Refactoring ein Begriff, die ich mal öfters gehört habe und auch manchmal gerne auch verwendet das Thema Refactoring to Patterns, das heißt, wenn ich eine Anwendung geschrieben habe oder beim Schreiben bin und sehe: Okay, ich kenne die Patterns, die Objektorientierung und denken guck mal, da könnte mal diese Pattern vielleicht funktionieren und der Aufwand ist nicht so groß. Ist jetzt so anzupassen, dass ich. Ich Refactorings verwende, um nach und nach mein Code in einem bestimmten Pattern reinzubringen, zum Beispiel keine eigenen Builder zu bauen, wenn ich irgendwelche Objekte erstelle oder eine Factory. Wenn ich mit ich nicht überall meine Objekte überall rein erstellen kann und kreieren kann, dann mache ich eine zentrale Stelle, eine Factory. Und dann habe ich es nur an der einen Stelle und kann ich es besser testen, kann ich es besser abrufen, Habe ich weniger Abhängigkeiten zwischen Klassen usw. und so fort? So auch da hilft mir das Refactoring dieser Code ändern in eine bestimmte Richtung. Es geht also nicht nur um Namens ändern oder Methoden extrahieren, sondern auch größere, komplexere Sachen wie einen bestimmten Pattern oder meine Anwendung in einem bestimmten Pattern in eine bestimmte Architektur Vorgabe reinzuzwingen, reinzubauen. Also auch da total viel über Refactorings, kann man glaube ich sehr lange sehr viel reden und diskutieren. Da gibt es tolle Bücher, kann man vielleicht ein paar. Ich kann mir vielleicht ein paar verlinken, mal unten auch gerne einen Link auf unsere Refactoring-Folgen. Aber was ist für dich das relevanteste in dem Zusammenhang, wo wir uns jetzt befinden, Änderbarkeit für dich? Bezüglich das Thema Refactoring.

Matthias: [00:22:20.35] Naja, ich sage mal die sind sehr eng miteinander verbunden, weil letztendlich fällt mir das Refactoring halt deutlich schwerer, wenn die Änderbarkeit meines Codes nicht gut ist. Weil das ist ja quasi per Definition eine Änderung meines Codes usw.. Wenn wir im komplexen Bereich von Refactoring sind es sehr, sehr mitunter tiefen Bereich meiner Anwendung. Und genau deswegen ja, also für mich ist das Wichtigste, das man mitnimmt an der Stelle, dass eine Anwendung nie aufhört sich zu verändern oder nie aufhören sollte, sich zu verändern. Also wenn irgendwo es Sinn macht an der Stelle. Also ich rede jetzt von Anwendungen, die auch nur aktiv weiterentwickelt werden, wenn etwas seit 20 Jahren stabil läuft und eh nicht mehr angefasst wird. Da kann man dann unsere Legacy Code Folge anhören. Aber wenn so was stetig weiterentwickelt wird, dann sollte in meinen Augen auch immer ein Auge auf Refactorings gehalten werden, wo man Dinge einfach ein bisschen verbessern kann.

Alex: [00:23:29.62] Das sogenannte kontinuierliches Refactoring.

Matthias: [00:23:32.68] Genau.

Alex: [00:23:33.40] Kontinuierliches alles kann man heutzutage machen.

Matthias: [00:23:37.06] Genau. Also letztendlich, wenn ich irgendwo an der Stelle im Code bin und mir fällt ein Name auf, der überhaupt nicht passt, dann ändere ich den Instant. Denkt gar nicht weiter drüber nach. Ob das jetzt meine Aufgabe ist oder nicht.

Alex: [00:23:49.60] Das tust du auch, weil es so leicht ist, weil deine IDE dir die Möglichkeit zur Verfügung stellt. Wenn du jetzt alle 250 Dateien durchforsten musstest, um zu gucken, dass die Variable nicht dort verwendet wird. Genau, dann halt eine ganz andere Sachen. Also diese automatisierte Refactoring, finde ich, sind total.

Matthias: [00:24:07.54] Wichtig und für so simple Angelegenheiten wie Umbenennung von variablen Methoden oder gar ein paar Zeilen in eine Methode auslagern. Dafür ist jetzt die Änderbarkeit noch nicht so extrem relevant. Also sie ist trotzdem relevant. Aber halt wirklich bei den komplexen Geschichten, also wo ich wirklich ganze Teile meines Systems umstrukturieren will, weil, wie du es vorhin erwähnt hast, ich zum Beispiel ein bestimmtes Pattern einziehen will, weil ich weiß, dass in Zukunft an der Stelle, wo es Sinn macht, da ist halt dann auch schon ganz wichtig, dass diese Änderbarkeit relativ hoch ist, dass das gut funktioniert.

Alex: [00:24:47.86] Zum Thema in Zukunft kommen wir gleich, wenn wir uns das Kissprinzip anschauen.

Matthias: [00:24:53.55] Ja, hat nichts mit der Rockband zu tun.

Alex: [00:24:56.59] Nein, gar nicht. Hätte aber gleich geschrieben. Also so wie Küsschen Kiss, keep it simple and stupid. Und der besagt also dieses Dieses Prinzip besagt, wir sollen die Sachen so einfach machen wie möglich.

Matthias: [00:25:12.22] Eine einfache Regel.

Alex: [00:25:13.81] Das klingt banal. Ist es aber nicht. Was ist dies, was ich oft im Leben gesehen habe? Man kriegt ein Problem. Wir wollen das Problem lösen und wir wollen das Problem lösen für alle Fälle. Das heißt, wir bauen ein recht komplexes System, um alle möglichen Fällen abzudecken, obwohl wir gar nicht wissen, ob wir es brauchen oder nicht. Aber wir machen es trotzdem gern, weil wir ja eigentlich keine Fehler verursachen wollen. Und ich muss an alles Mögliche denken, damit ich keine Fehler verursache. Und damit meine ich meine Kunden, meine Verwender, das alles kriegen, was sie brauchen. Und das ist, was in meinen Augen das KISS-Prinzip so schwer macht. Dieser Versuch, immer alle Möglichkeiten abzudecken. Und das KISS-Prinzip passen überhaupt nicht zusammen. Weil Kiss in meinen Augen propagiert Mach die Sache nur so einfach wie möglich. Nur das, was du unbedingt benötigst, das was du jetzt brauchst, jetzt machst du es. Aber bau jetzt nicht die supi dufti Architektur der Welt oder Patterns gleich einziehen, weil ich denke, das werden wir irgendwann mal brauchen, sondern lass deine Anwendung evolvieren, also mit der Zeit, wenn du es irgendwann einmal brauchst und du dein System so gebaut hast, dass er veränderbar ist, dann wird es nicht schwer sein, diese Änderungen vorzunehmen. Es wird Zeit kosten, natürlich, aber es wird nicht schwer sein, das zu machen. Und deswegen, je einfacher eine Anwendung gebaut ist, desto leichter ist auch, sie zu verändern.

Matthias: [00:27:06.98] Klingt sinnvoll.

Alex: [00:27:08.42] Klingt komisch, ist aber so. Da nimm einfach die oder nimm die einfachste Möglichkeit, die du hast, um ein Problem zu lösen und versuch dich nicht zu verkünsteln, sondern einfach einfache Methoden nehmen, wenn es sie gibt und zu den Ziel führen, die du brauchst. Problem bei der Sache ist die Codes. Komplexität wächst sehr schnell. Wir sind sehr schnell mit sehr komplexen Strukturen und Datenalgorithmen konfrontiert und diese Komplexität zu minimieren ist einfach irgendwas, das in meinen Augen durchaus sinnvoll ist und hilfreich. Je weniger Code wir schreiben müssen, um unser Ziel zu erreichen und je weniger komplex dieses Code ist, auch desto besser ist, um damit arbeiten zu können, auch zum Thema Lesbarkeit zum Beispiel relevant. Weniger Code ist besser als mehr Code. Wenn ich das gleiche Ergebnisse erziele, natürlich. Und je weniger komplex mein Code ist, desto komplex meinte ich jetzt nicht in die Struktur, nicht für die Lesbarkeit, sondern für die Strukturierung von der Aufbau. Desto leichter tue ich mich zu verändern. Deswegen KISS ist für mich auch ein Prinzip dazu führt, dass mein Code besser geändert werden kann.

Matthias: [00:28:27.38] ist logisch.

Alex: [00:28:28.94] Was meinst du -Was meinst du dazu?

Matthias: [00:28:33.70] Ja, also das ist tatsächlich eine auch für mich sehr wichtige Regel. Ich habe aber erst in jüngster Vergangenheit wieder festgestellt, dass auch wenn man sie kennt und sie gerne anwenden würde, es nicht immer leicht ist.

Alex: [00:28:48.67] Ja.

Matthias: [00:28:49.48] Weil man halt, wie du gesagt hast, echt sehr schnell in einen Komplexitätsgrad kommt, der nicht mehr auf Anhieb überschaubar ist. Und da sollte man halt dann wiederum, wenn man feststellt, dass man an einen Punkt kommt, wo man eine ist, mal darauf eine Methode ein, zum Beispiel in dieser Methode nicht mehr so was sagen, auf einen Blick verstehen kann, was da passiert. Dann sollte ich mir vielleicht Gedanken machen, ob ich es refaktorieren kann und eine bessere Struktur bekomme. Und ja, also wie gesagt, sehr wichtige Regel, die nicht leicht ist einzuhalten. Das ist absolut richtig.

Alex: [00:29:35.61] Da haben wir noch zwei Themen, womit wir uns noch ein bisschen beschäftigen wollen. Das nächste ist Tell don’t ask. Also sage, frage nicht.

Matthias: [00:29:47.16] Ja, tell don’t Ask war auch ein interessantes Thema. Da gibt es auch einen interessanten Artikel von Martin Fowler dazu. Können wir eventuell auch verlinken. Was da dahinter steckt, ist letztendlich auch ein Ansatz aus der objektorientierten Softwareentwicklung, dass du im Prinzip die Logik von die auf Daten angewendet werden soll, hin zu den Daten verschiebst. Und dann wird es ganz abstrakt gesagt. Und dass du die Daten nicht zu der Logik holen musst. Also wir können uns vorstellen, wir haben irgendwie so einen kleinen Codeblock, der irgendwas berechnen soll und dann hole ich mir erstmal per Getter die einzelnen Informationen, die ich haben will und mache dann in meinem Code Block die Logik, was damit gemacht werden soll. Und danach wird mit dem Ergebnis halt irgendwas anderes gemacht. Und nach dem Tell don’t ask- Prinzip würde ich diese Logik hin in das Objekt wo die Daten schon sind verschieben und würde diesem Objekt einfach sagen Hey, mach mal meine Businesslogik, gib mir das Ergebnis, damit ich hier weitermachen kann. Weißt du was ich mein?

Alex: [00:30:51.42] Ja, okay, Tell don’t ask hat für mich drei drei Punkte, die ich gerne mal angehen könnte oder angehen möchte. Der eine ist wir mussten unsere Klasse, unsere Objekte, unsere Funktionen, Wenn man in die funktionale Programmierung sich befindet, so designen, so dass ich denen sagen kann, was sie tun sollen. Der typische Fall ist, wie du sagst, wenn ich in meine Klasse verwendet eine andere Klasse und ich sage jetzt, wenn das und das passiert, dann mach das und das. Anstatt es so zu formulieren, kann ich einfach in der Klasse sagen Mach einfach, du wirst das schon wissen, ob du das kannst oder nicht. So, diese diese if-then-Abfragen mal einfach aus der Welt schaffen, in dem wir die Logik zur Entscheidung irgendwas passiert oder nicht passiert in der Klasse die es tut drin lassen. Auch sehr eng verbunden mit dem Information Hiding Prinzip ist Details meine Implementierung oder der interne Zustand von meine Klasse muss ich nicht nach außen geben, brauche ich nicht. Je weniger ich nach außen gebe, desto besser. Warum ist dem so? Weil, wenn ich der Zustand meine Klasse nach außen gebe, könnte es ja passieren, dass irgendjemand mein Zustand verändern, ohne dass die Klasse das mitkriegt.

Alex: [00:32:14.87] Und das wäre nicht gut. Also eine Klasse, ein Objekt muss die Entscheidungshoheit behalten über deren internen Zustand und es nicht nach außen veräußern oder nicht änderbar veräußern. Das dritte Punkt auch wieder sehr eng mit Informationen zu tun ist Die Menschen, die meine Klassen oder meine Funktionen oder Methoden oder was auch immer verwenden oder meine Anwendung verwenden. Die sollen sich nicht Gedanken darüber machen müssen, wie das Ganze implementiert ist. Das muss ihnen egal sein. Durch diese Schnittstellen Definitionen wissen Sie, dass Sie eine bestimmte Schnittstelle aufrufen und Methode, was auch immer aufrufen können mit bestimmten Parametern. Bestimmte Informationen müssen Sie zur Verfügung stellen, um bestimmte Informationen in eine bestimmte Form zu bekommen. Und das ist das, was Sie wissen müssen, wie es intern alles abläuft, ist mal wieder für den Verwender oder es sollte für den Verwender völlig irrelevant sein. Das sind für mich Facetten von und das, was Tell-Don’t-Ask bedeuten und mitbringen in dem Sinne, dass ich wie du vorher gesagt hat, ich hole mir nicht die Daten raus, entscheide dann um berechne, sondern ich überlasse es die Klasse, die die Datenhoheit hat, die diese Daten beinhaltet, auch die Berechnung und die Rückgabe von Ergebnissen usw..

Matthias: [00:33:45.76] Ja, sehr schöne Ergänzung.

Alex: [00:33:48.56] Okay, dann halten wir uns nicht länger auf mit Tell-Don’t-Ask. Das ist auch ein sehr interessantes Prinzip, das sehr viel mit Information-Hiding zu tun hat. In meinen Augen aber gehen wir auch zu einem anderen Prinzip, die in meinen Augen auch mit Information-Hiding zu tun hat. Aber nicht nur die heißt die Law of Demeter oder wie sprechen wir das aus?

Matthias: [00:34:14.84] Law of Demeter würd ich sagen.

Alex: [00:34:16.56] das Gesetz von Demeter.

Matthias: [00:34:22.07] Genau so schaut’s aus.

Alex: [00:34:23.27] Die besagt Spricht nur zu deinen nächsten Freunde. Was sagst du dazu? Was?

Matthias: [00:34:30.20] Don’t talk to strangers

Alex: [00:34:31.85] Don’t Talk to Strangers? Genau.

Matthias: [00:34:33.82] Genau. Ja, durchaus. Das ist genau. Nämlich dieses Law of Demeter. Was ich in einer der letzten Folgen mit etwas anderem durcheinandergebracht habe. Weil genau da hatte ich das Law of Demeter nämlich im Kopf. Und der Hintergrund beim Law of Demeter ist der das, Ich mache wieder das Beispiel mit einer Klasse. Ich habe eine meine Klasse A, die eine Klasse B benutzt und diese Klasse B wiederum, die hat intern eine Klasse C, die sie benutzt. Und wenn ich jetzt gegen das Law of Demeter verstoßen wollen würde, also mit Fremden spreche, würde ich in Klasse A über Klasse B auf Klasse C zugreifen und dort irgendetwas machen. Und das wäre dann ein klarer Verstoß gegen das Law of Demeter. Weil wenn ich mich dran halten würde, dann darf ich nur indirekt, also nur mit Klasse B sprechen. Und zwar wenn dann vier sagen hey, ich sag mal klasse C, dass sie mir das um das zurückgeben soll, was dann klassischerweise über eine Public Methode in Klasse B laufen würde, die ein klares Interface wieder mit Information-Hiding bereitstellt. Das ist die Internas was da jetzt irgendwie intern in Klasse B passiert vollkommen versteckt sind, aber letztendlich ich in meiner Klasse A trotzdem das Ergebnis bekomme, dass unter der Haube von Klasse C erzeugt wird.

Alex: [00:36:00.74] Und um bei deinem Beispiel zu bleiben: Wenn ich Klasse A bin Ich möchte Klasse B kennen. Klasse B ist mein Freund, aber Klasse C möchte ich gar nicht kennenlernen. Nein, ich will gar nicht wissen, ob es Klasse C oder D oder F von B verwendet wird. Ist mir egal. Ich möchte nur Ergebnis in der versprochene Form bekomme und dafür hätte ich gerne eine Methode in Klasse B und nicht, dass ich von Klasse A nach Klasse B, nach Klasse C, nach Klasse, was weiß ich was springe. Ich habe die Law of Demeter auch so als Umschreibung gehört: das Law of Demeter sagt: nur ein Punkt pro Zeile.

Matthias: [00:36:41.84] man kann auch umbrechen 😀

Alex: [00:36:45.95] Aber du verstehst was ich meine als ich und die diese diese Gesetz in Anführungszeichen stehen nicht so auf Gesetze. Was besagt es? Ich darf nur als Klasse, als Funktion und in dem Fall als Klasse nur mit ganz bestimmten Menschen reden, nämlich meine nächsten Freunde. Wer sind die der nächsten Freunden dessen ich selbst, also ich selbst bin mein beste Freund irgendwie. Also alle Methoden, Funktionen, Variablen, die ich in Klasse A definiere, dürfen von A verwendet werden. Dann darf ich auch Methoden, also direkte Methodenaufrufe auf Parameter und auf Instanzvariablen in meine Klasse, also Parameter, die mit die Methode reinkommen oder Instanz-Variablen, die ich in die Klasse hab und ich darf auch Methoden aufrufen, natürlich von Objekte, die ich selbst erzeuge innerhalb der Klasse oder die ich von Dependency Injection Container bekomme. Da darf ich auch, aber nur nur die alle andere, also Klassen, die von Klassen verwendet werden, die von Klassen verwendet werden, die ich verwende, die nicht. Das hat ein eindeutiges Vorteil, das ist, dass unsere Anwendungen weniger Kopplung haben, das heißt, wir reduzieren die Abhängigkeiten. Ich muss, wie du gesagt hast, in Klasse A nichts von Klasse C wissen, um arbeiten zu können. Deswegen sind Klasse A und Klasse C unabhängig voneinander Klasse A hängt nur von B ab und nicht von B und C. Es ist das andere Nachteil von der Geschichte. Ich brauch Wrapper Methoden. Ich brauche in Klasse B irgendeine Methode, die eventuell. Das einzige was es macht, ist eine Methode in C aufzurufen. Und manchmal wird der Code halt ein bisschen aufgebläht dadurch. Aber ja.

Matthias: [00:38:39.86] Nichts kommt umsonst.

Alex: [00:38:41.18] Genau nicht. Kommt schon, sonst gibt es irgendwelche Ausnahmen, wo du sagst, diese Law auf Demeter, die verwende ich dort nicht.

Matthias: [00:38:49.28] Also mir ist jetzt in jüngster Vergangenheit zum Beispiel mit dem Umgang mit einem Framework ist es mir so gegangen, dass ich da nicht ganz drum rum gekommen bin, gegen das Law of Demeter zu verstoßen, weil es halt dann naja, du kannst jetzt halt nicht unbedingt in jede Framework Klasse Methoden reinbringen, aber es ist halt dann schon so, dass man vielleicht ein Objekt, das so eine Framework Klasse intern hat, irgendwas drauf aufrufen muss. Also so zumindest meine Erfahrung. Also vielleicht gibt es einen Weg, das besser zu machen, der mir einfach noch nicht bekannt ist. Aber das wäre jetzt so ein Fall, wo es mir. Aufgefallen ist, dass es mir nicht gelingt, mich daran zu halten.

Alex: [00:39:33.54] Ich gebe alles auf, was ich hinaus wollte. In dem Fall war auf Fluent Interfaces.

Matthias: [00:39:40.11] Ah ja. Okay. Gut, das macht Sinn.

Alex: [00:39:43.11] Fluid Interfaces sind ein Fall, wo man einfach diese Regel nicht anwenden kann. In dem Sinne, weil du Wert von Definition. Hier ist diese Fluent, sodass du immer Punkt, Punkt, Punkt, Punkt. Aber üblicherweise ist es nicht so. Also für ein Interface sind okay, weil du dir keine Drittabhängigkeiten holst.

Matthias: [00:40:08.43] Aber ich finde Fluid Interfaces sind da noch mal ein ganz anderes Thema, weil die auch echt schwierig sind in meinen Augen, weil die müssten ja eigentlich auch so agnostisch sein, dass sie keine Reihenfolge erzwingen.

Alex: [00:40:23.97] Ja.

Matthias: [00:40:24.99] Und das ist finde ich unglaublich schwierig. Also selber ein Fluid Interface zu implementieren finde ich nicht so einfach.

Alex: [00:40:31.62] Es ist auch bestimmt nicht. Aber das Thema ist, du holst dir keine Drittabhängigkeiten, weil der Fluent ist Interface immer das gleiche Objekt. Immer wieder bist du Bild, sagst oder was auch immer. Ich suche End Objekt bekommst du du erwartest also hast du diese diese Kopplung Regel in Anführungszeichen nicht gebrochen in meinen Augen und deswegen finde ich sie okay und nutze ich sie überall, wo sie auch zu nutzen wären. Also es ist wie wie mit alle andere Regeln, die wir oder Prinzipien sind, ist ein ein Maß. Wir kennen sie und wir können sie dann anwenden, wo es sinnvoll ist und wo es nicht sinnvoll ist. Dann verwenden wir sie einfach nicht. Wir muss uns nur diese Entscheidung bewusst treffen. Das ist die. Die Sache. Dann noch mal kurz zusammenfassend Wir haben heute so Warum ändern wir Code? Was meinen wir mit mit Änderbarkeit als mal angeschaut und wichtige Thema Information-Hiding? Was bedeutet das alles? Warum brauchen wir das? Wie können wir unser Code verändern mit Refactorings? Und dann natürlich auch noch die drei Themen KISS, Tell don’t ask und Law of Demeter hast du gesagt.

Matthias: [00:41:56.42] Demeter.

Alex: [00:41:57.38] Demeter. Okay, da Law of Demeter. Bisschen unterhalten was die bedeutet, wofür die gut sind und warum wir diese Sachen machen. Und das Ziel ist, dass unser Code veränderbar bleibt, dass wir es leichter haben, den Code zu verändern. Und im Falle von den Refactorings, dass wir diese Codes, die wir so gebaut haben, dass es leicht zu verändern ist, schnell und sicher verändern können. Das wäre für mich der Resümee des heutigen Tages.

Matthias: [00:42:28.25] Ein weiteres Resümee, das man ziehen kann, ist, dass man auch heute wieder gemerkt hat, dass diese ganzen Geschichten untereinander sehr stark zusammenhängen und sich gegenseitig bedingen, teilweise unterstützen und teilweise Voraussetzung sind. Und ich wage zu prophezeien, dass es uns in den nächsten Folgen auch noch öfters auffallen wird.

Alex: [00:42:50.48] Ach nee, doch noch.

Matthias: [00:42:53.18] Na gut. Nenn mich Nostradamus. Also wenn es eintrifft, natürlich.

Alex: [00:43:00.05] Wir sind mal wieder am Ende einer Folge angekommen.

Matthias: [00:43:03.47] Du hast heute einiges über Veränderbarkeit gelernt.

Alex: [00:43:06.38] Kennst die Gründe, die es gibt, Code zu ändern.

Matthias: [00:43:09.29] Und ein paar Praktiken und Methoden, die dir dabei helfen, deinen Code zu verbessern.

Alex: [00:43:13.88] Vergiss nicht, uns weiter zu empfehlen und unser Podcast zu abonnieren.

Matthias: [00:43:18.86] Und sei auch bei unserer nächsten Folge mit dabei, wenn wir uns das Thema Effizienz ansehen werden.

Alex: [00:43:24.23] Lass es dir gut gehen. Und bis bald.

Matthias: [00:43:27.02] Bis dann. Und viel Spaß noch.

Alex: [00:43:28.82] Ciao.

Off: Die Macht der Craft arbeitet für dich.

Bleibe in Kontakt, Abonniere unsere Newsletter

Wir senden dir dann gelegentlich, wichtige Informationen und Updates
Hinweis: Du kannst Deine Einwilligung jederzeit für die Zukunft per E-Mail an mdc at soler minus sanandres dot net widerrufen. Detaillierte Informationen zum Umgang mit Nutzerdaten findest du in unserer Datenschutzerklärung

Die beste Möglichkeit nichts zu verpassen

Nutze die Schaltflächen weiter unten, um den Podcast mit dein Lieblingsanbieter zu abonnieren. Es lohnt sich.

Neue Episoden

Wir veröffentlichen etwa eine Folge pro Monat.

Möchtest du dabei sein?