Zu Kellner mäßig und Kellner, also Roboter, Kellner, so
Roboter, Kellner klingt wieso ein Film Ey Coding Buddies Dein
Podcast rund um Softwareentwicklung und
aktueller Tech News. Herzlich Willkommen.
Halli Hallo und herzlich Willkommen zur neuen Folge des
Coding Buddies Podcast. Schön, dass du wieder
eingeschaltet hast, deine Gastgeber.
Und wie soll es anders sein? Meine Wenigkeit, der Tino und
der fantastische Fabi, der mich hier angrinst, schon der hat
Bock. Ich seh es schon förmlich.
Ich begrüße dich, fabi, was geht ab, was geht ab, Tino, wie
geht's hier steht's alles gut, alles fit, alles.
Super. Ich hab für die Anmoderation ja.
War richtig energiegeladen. Ich bin so reingerannt weißt du
immer so? Jaja, geklappt, so yeah, was
geht, was geht, was geht so ganz alleine durch den Raum gerannt,
das. Geht in meinem Kopf vor.
Nein, also ich seh wir haben Bock ich hab.
Doch ein geiles Thema, aber 1 vorweg noch ganz kurz Werbung in
eigener Sache und zwar, liebe Zuhörerin, lieber Zuhörer, falls
du noch auf der Suche nach einer richtig geilen id i bist,
empfehlen wir dir wärmstens die Jet Brains ID is.
Die haben für sämtliche Sprachenlösungen, die Mega geil
sind, die wir auch selbst verwenden kannst dich gerne
davon überzeugen, in einem von unseren Livestreams auf Twitch,
da verwenden wir sie auch immer. Und warum merke ich das an?
Weil du mit dem Code Coding Buddies 25% auf die
Jahreslizenzen sparen kannst und das sogar Stacked mit deinen
vielleicht vorhandenen Ersparnissen, die du eh schon
hast, weil nach einem Jahr zum Beispiel kriegt man eh schon
Rabatte. Ganz genau.
Und der Code ist auf jeden Fall noch mal den Shownotes verlinkt,
findet ihr aber auch auf unserer Website.
Also einfach mal reingucken und Spaß haben mit einer.
Jetbank schaut euch mal an. Genau.
Werbung Ende jetzt kommen wir zum eigentlichen Thema Fabi.
Es ist ne Weile her, schon da haben wir uns um so Coding
Principles gekümmert, was heißt gekümmert sie besprochen zum
Beispiel das jagni Prinzip. Kiss zum Beispiel.
Kiss hatten wir gemacht, genau und da würde ich heute gerne
noch mal ansetzen und ein sehr bekanntes und verbreitetes
Prinzip. Noch mal besprechen mit dir
heute, aber es geht n bisschen mehr in die Architekturrichtung
bei dem Thema. Deswegen an der Stelle ne
Triggerwarnung für alle, die Objektorientierung nicht so geil
finden. Heute wird es n bisschen
objektorientiert hier und wir versuchen es natürlich mit
Analogien und einfach zu erklären, werden aber nicht drum
rum kommen das auch so n bisschen an vereinfachten
Codebeispielen zu erklären. Und zwar fabi.
Was ist das Thema, Hau mal raus. Das Thema Es geht um Solid, das
sind ja quasi mehrere Prinzipien in der Softwareentwicklung, die
kommen auch von Robert C. Martin, also Onkel Bob, Wir
hatten ja auch mal über. Onkel Bob?
Ja, geil. Wir hatten ja auch mal eine
cleancode Reihe gehabt hier im Podcast und da kann man
vielleicht ne also. Der ist ja auch der Verfechter
Gründer von Clean Code. Genau deswegen noch mal sei, sei
das noch mal angemerkt, wenn dich das interessiert, dir liebe
zuhören, hör auch gern mal in die Reihe in die Clean Code
Reihe von uns rein, ganz genau und solid sind ja wie ich meinte
mehrere Prinzipien und es sind quasi jeder Buchstabe steht für
ein Prinzip. Ja.
Und da würd ich sagen, lass uns doch einfach mal durchgehen
durch die einzelnen Prinzipien. Das sind ja im Endeffekt sind
das ja 5 ne, also einmal für das SOLID und dann gehen wir einfach
mal durch, nehmen uns jeden Buchstaben raus, geben
vielleicht ne kleine Analogie dazu, dass man sich es erstmal
schön entspannt vorstellen kann, was das ist, beschreiben, worum
es da geht, gehen halt auch mal n bisschen auf so n paar
Codebeispiele, vereinfacht wie du meintest ein ja und ja, ja
das ist der Fahrplan. Ja, würde ich sagen, solide
vorgestellt, Fabi, sorry, der muss so sein.
Ich würde aber noch mal noch so ganz kurz um das Thema so ein
bisschen smooth einzutauchen, noch sagen, warum ist es denn
überhaupt wichtig, eine gute Softwarearchitektur zu haben,
also weil das Prinzip oder die 5 wie du gesagt hast, zielen ja
ganz klar darauf ab, genau das zu verbessern, also wirklich
eine gute Architektur umzusetzen um gewisse Vorteile daraus zu
ziehen. Und fällt dir zum Beispiel n
Beispiel, fällt dir zum Beispiel ein Beispiel ein.
Meine Güte, wo du gemerkt hast, ey, hätte ich es mal vielleicht
nach so einem Prinzipien umgesetzt, wo du gemerkt hast,
so an diesem Projekt ist die Architektur wirklich echt nicht
vorteilhaft, ich stoß hier gerade so an Grenzen, was wären
so typische Grenzen, die man da, auf die man stoßen könnte, das
wäre vielleicht mal so das Ganze noch n bisschen motivieren.
Gute Frage, da muss ich natürlich erstmal mein Gehirn
rumkramen also ich, ich glaube, dass man auf jeden Fall, gerade
wenn man irgendwann anfängt und immer weiter sag ich jetzt mal
ne, also unser Weg ja zum Beispiel Studium, da hat man ja
auch angefangen Programme zu machen, Programme zu
implementieren, die jetzt aber noch nicht so ne Architektur
benötigt haben. Sag ich jetzt mal, weil das
waren halt kleine Programme. Je größer dann ne Anwendung
Programm ne Anwendung wird, desto wichtiger ist es natürlich
sich um eben die die die Architektur zu kümmern, dass man
halt auch wirklich die Möglichkeit hat zu sagen, ich
verändere jetzt was an meiner Software, ohne dass ich aber
gleich die ganze Software umkrempeln muss und das ist ja
im Endeffekt, darauf zielen ja eigentlich diese Prinzipien ab.
Und ich überlege gerade, wo ich so was mal hatte.
Also ich hatte auf jeden Fall diese, diese diese Situation
schon mal, dass du wirklich gesagt hast, ey, ich habe jetzt
zum Beispiel eine Klasse und möchte jetzt irgendwie eine
Klasse ändern, oder ich will da noch was hinzupacken, also
angenommen, du hast vielleicht irgendwann mal eine Klasse
gehabt, die hieß zum Beispiel weiß nicht Payment Service oder
so was auch immer und und darüber wird bezahlt, so und
dann hast du einen. Payment, was du irgendwie also
eine Möglichkeit zu bezahlen und das reicht erstmal.
Und dann fügst du irgendwann noch mal was hinzu und dann
denkst du so ja OK das das passt auch erstmal so und dann sagst
du aber hast du irgendwie so n IF Else und sagst ja gut wenn es
wenn zum Beispiel der Kunde Variante 1 auswählt, dann bezahl
halt mit Variante 1 Else ne also ansonsten bezahl mit Variante 2
so und dann kommt man irgendwann relativ schnell in so n struggle
und sagt Na OK warte mal aber jetzt muss ich vielleicht
irgendwie. Noch 1 hinzufügen und dann bist
du bei einem IF LS if LS, dann sieht es irgendwie eklig aus.
Dann hast du vielleicht noch andere Verhaltensweisen, wie
sich so n bezahlservice dann im Endeffekt wirklich verhält und
dann codest du alles in ein so ne Klasse rein und denkst dir
irgendwann. Oh Gott, wenn ich das jetzt
anfasse, warte mal. Ich hab jetzt hier ne private
Funktion, die aber überall aufgerufen wird und wenn ich die
verändere, dann verändere ich ja vielleicht irgendwas anderes in
in einer Bezahlmethode, was ich gar nicht.
Möchte aber nicht genau. Also nur mal als Beispiel jetzt
ne, also es war jetzt nicht explizit das was ich erlebt
hatte, aber sowas ähnliches ne, dass du erst mal anfängst sagst
OK ich hab jetzt das so und so und.
Also ich hab jetzt eine bestimmte Sache, die muss dann
erweitert werden und dann aufgrund von muss man dann sagen
früher aufgrund fehlendem Wissens hat man erstmal drauf
los programmiert bis man dann irgendwann gemerkt hat oder bis
ich dann irgendwann gemerkt hab boah ey, das skaliert ja
überhaupt nicht ne. Und das ist halt auch schon
Gutes. Stichwort Skalierbarkeit und
Wartbarkeit. Ich mein, die Worte fallen sehr
oft bei uns im Podcast, weil sie halt in der Softwareentwicklung
so unfassbar wichtig sind. Und das sind halt so die
Erfahrung, die man glaub ich gerade als Einsteiger macht und
vielleicht auch in den ersten Projekten, wie du so schön
sagtest. So kleine Programme oder
vielleicht so kleine Prototypen und Du entwickelst sie immer
weiter, dann kommt halt noch mehr Anforderungen dazu, mehr
Funktionalität und du kommst irgendwann an den Punkt, wo du
dir denkst, oh mein Gott, jetzt ist das wirklich so.
N Spaghetti Spaghetti Code geworden, es ist so
verschachtelt und wenn ich jetzt an der Stelle die Funktion
änder. Soll sich aber nur auf A und B
auswirken, aber nicht auf C und D.
Aber so wie das hier gerade umgesetzt ist, zieht sich das
durch die ganze Software und ich hab eigentlich schon gar keinen
Überblick mehr was passiert, wenn ich jetzt diese Funktion
anfasse und das sind so Klassiker und sowas haben wir
auf jeden Fall selbst erlebt. Also wenn du dann noch keine
Tochter hast, wenn du dann noch keine Test eieieiei und die
hatte ich damals auf jeden Fall nicht.
Ich ja auch nicht. Und da denkt man sich so, ha,
wie hätte man das denn besser machen können?
Also wie hätte ich von Anfang an dafür sorgen können, nicht in
diese Falle zu laufen oder quasi mit dem Rücken zur Wand zu
stehen und sich zu denken, ich glaub ich muss von vorne
anfangen, ich bin an einem Punkt wo das erweitern schwieriger
wird als das vielleicht von Grund auf noch mal neu zu
entwickeln weißt du also ich mein da, deshalb gibt es ja auch
Neuentwicklung, weil du an diesen Punkt kommen kannst, dass
es zeitlich oder vom Aufwand her gesehen.
Besser ist es, neu zu machen, als irgendwie zu versuchen, da
noch was reinzufriemeln so in dem was du hast in der Codebasis
definitiv. Hat man auch schon öfter mal
erlebt oder kennt man vielleicht auch, hat man gehört.
Wie auch immer, aber gerade bei bei den Solid ich find das
lustig weil wie du meintest ne. Man, man wusste das vielleicht
nicht, oder? Oder wie kann man sowas
vermeiden und zu dem Zeitpunkt wo ich jetzt meinen Riesen
payment Service geschrieben hab ne wo ich Milliarden verloren
hab nein wie gesagt war ja nicht genau das Beispiel ich mir kommt
das Beispiel nicht mehr richtig in den Kopf aber deswegen hab
ich jetzt versucht das sozusagen nachzukonstruieren mit einem
anderen Beispiel aber. Ich, ich kannte zum Beispiel
Solid zu dem Zeitpunkt noch gar nicht.
Ne, also diese Prinzipien, beispielsweise ne und
irgendwann, das fand ich noch ganz lustig, da hatte ich
irgendwann mal so n Moment, da stand stand ich so ne Runde ne
mit auch so alten Kollegen irgendwo und dann meinte einer
so ja und auf jeden Fall solid dies und das und alle so hm ja
ja ja so solid ja ist auf jeden Fall wichtig danach ne und so.
Und jeder im Kopf. So was ist solid, verdammt, das
war ich, das war ich in dem. Moment, und dafür so ja, warte
mal erst mal aufschreiben, gucken.
Was soll das eigentlich? Ist so, während du noch Nickst
im Kreis das Handy rausgeholt, gegoogelt und das war so finde
ich so lustige Situation ne auch noch mal zum puncto Poster
Syndrom ich dachte mir in dem Moment natürlich ey du kennst
mal wieder gar nichts hier, alle anderen kennen das, aber ich
mein ich hab ja auch genickt so nach dem Motto so ja.
Ja, auf jeden Fall. Also vielleicht, vielleicht
waren da ja so 50% der Leute dabei, die auch sich dachten,
das muss ich mal nachgucken. Ja, sicherlich sicherlich sehr
witzig, ja, aber kenn ich so ne Situation?
Man muss natürlich sagen, die Prinzipien die wir jetzt gleich
erklären werden, also gleich geht es wirklich los, sind ja
unter dem Namen Solid bekannt, aber was dahinter steckt kennen
manche vielleicht auch ohne an Solid zu denken oder zu wissen,
dass das so in Solid alles zusammengefasst ist.
Also dann das noch mal so als Anmerkung ne, also ich denke,
dass du die Prinzipien zu dem Zeitpunkt schon kanntest, dass
man darauf achten sollte, aber vielleicht nicht als diese
Zusammenfassung und trotzdem stehst.
Steht man dann in dem Moment da, oh mein Gott, was ist das denn
jetzt schon wieder euch? Oh mein Gott, da klickt dann
wirklich so das imposter Syndrom wieder.
Aber dann kommt er noch dazu, kurz noch bevor wir jetzt ruhig
reinstarten da kommt er noch dazu, dass man es vielleicht
kennt, aber nicht anwenden kann so.
Ja. Der oder denn halt wirklich
nicht im Hinterkopf hat. Und genau das wollen wir jetzt
schärfen, denn jetzt geht es los, also kommen wir mal zum
Solid Prinzip, es ist halt wirklich sehr verbreitet und
bekannt und es wurde auch schon viel thematisiert, also an der
Stelle angemerkt, falls du, liebe Zuhörer, liebe Zuhörer
nach dieser. Grundlegenden Folge heute noch
Fragen dazu hast, kannst du dich erstens gerne bei uns dann
melden über die Podcast Mail, ansonsten können wir auch
empfehlen, einfach mal auf youtube nach dem Prinzip zu
gucken, da gibt es auch viele Videos, die das erklären und
veranschaulichen darstellen ist auch immer noch eine coole
Ergänzung und deswegen jetzt geht es los, Fabi erster
Buchstabe das S von Solid, wofür steht das?
Stell dir erstmal vor, jetzt kommt so das es rein ins Bild
Spam es. Genau, es steht für Single
Responsibility Principle. Das heißt im Grunde genommen,
dass eine Klasse jetzt immer wieder bei Klassen eine Aufgabe
übernehmen soll und auch wirklich nur eine und nicht
mehrere und das ist, finde ich ganz interessant, weil wenn man
sich jetzt mal überlegt und jetzt mal jeder auch für sich
Hand aufs Herz, ist es schon mal vorgekommen, dass man vielleicht
eine Klasse geschrieben hat, die irgendwie hieß sowas wie.
Weiß nicht irgendwas XYZ utils xyz Helper was auch immer
irgendwas ne also irgendwas Manager genau setzt das setzt
für XYZ irgendwas ein und dann hängen Utils Helper Manager
hinten dran und jetzt noch mal Hand aufs Herz ist es auch schon
mal jemandem passiert, dass diese Klasse völlig ausgeufert
ist und tausende Fachlichkeiten in.
In einer Klasse oder in einem Pfeil gebündelt hat und wenn ja,
dann wird immer Hand. Heben ja, also 2.
Hände sehe ich gerade genau. Also das ist finde ich genau,
dass der Knackpunkt an diesem Prinzip, weil es geht wirklich
darum, dass du eine Klasse hast, die sich darum kümmert, um genau
eine Verantwortlichkeit, also eine oder Fachlichkeit, wie du
es nennen möchtest und. Und nicht, dass du mehrere
Sachen ineinander sag. Ich jetzt mal verbandelst.
Also wenn du jetzt noch mal, weil wir gesagt hatten, wir
versuchen mal eine Analogie zu geben, angenommen, du hast ein
Werkzeug, ne und dieses Werkzeug ist ein Multifunktions alles
Werkzeug, du kannst damit du kannst damit schneiden, sägen,
schrauben, bohren, du kannst alles machen so.
Also bohren ist krass. Bis eben wollte ich noch sagen,
so typisches Schweizer Taschenmesser.
Ne, das Bohren wäre krasser, das ist noch viel viel.
Krasser. Damit kannst du wirklich alles
machen und. Und jetzt geht dir auf einmal
der Bohrer kaputt und du denkst dir so, ah misten echt blöd, ich
kauf mir halt wieder dieses super multifunktionale Ding,
weil es gibt ja auch nur das muss man sich natürlich
vorstellen, es gibt nur das ne, dann kaufst du dir natürlich den
Bohrer noch mal, kannst wieder bohren, aber hast dazu natürlich
noch mal wieder ne Säge und du hast wieder weiß nicht n was hab
ich gesagt akkubohrer frag mich nicht, ich weiß selber wieder
was drin war, du hast also quasi alles noch mal doppelt, obwohl
du ja eigentlich nur den Bohrer gebraucht hättest.
Ne. So, und jetzt wär es ja viel
cleverer ne einfach zu sagen ey ich mach n eigenes Werkzeug was
n Bohrer ist und n eigenes Werkzeug was ne Säge ist und so
weiter ne Oh Wunder gibt es auch, ist tatsächlich in der
Realität so und das ist halt genau der Punkt.
Du willst ja wenn dir irgendwas kaputt geht beispielsweise nicht
noch mal das Ganze dann sozusagen nachbestellen, in
diesem Fall ne ja. Das ist ne ganz gute, ne gute
Analogie. Jetzt kann sich natürlich der
eine oder andere denken, ja, aber ich möchte so n Schweizer
Taschenmesser haben, weil da halt alles dran ist und das
schön kompakt ist. Ja klar, das ist in dieser
Analogie der Vorteil, aber wenn wir das jetzt mal auf n Code
Münzen, dieses Beispiel erkennt man, dass es halt
architekturtechnisch gesehen schon Sinn macht diese
Verantwortlichkeiten aufzusplitten.
Ich würd mal als Beispiel was reinhauen, was was vielleicht
der ein oder andere kennt. Mal angenommen du hast so ne Art
Report Klasse oder log klasse oder irgendwas mit
Textverarbeitung ja. Stell dir vor, du erzeugst jetzt
ne Klasse Report und sagst ja gut was.
Was muss die jetzt können und du fängst an und sagst na ja ich
möchte, ich krieg das Halt in einem gewissen Format und möchte
das jetzt in einem für mein Programm lesbares Format
formatieren, ne, also du kriegst zum Beispiel jetzt n String rein
und willst das jetzt aufsplitten in ein Format was du.
Verarbeiten kannst. Das heißt, du hast so ne
Formatfunktion zum Beispiel, das heißt Deine Klasse Report hat
jetzt ne Formatfunktion und bietet die Funktionalität
formatieren an. Soweit so gut ist eine
Verantwortlichkeit passt, könnte man jetzt sagen Report der Name
vielleicht nicht so gut, aber lassen wir das mal so stehen.
Auf einmal denkst du dir aber, na ja, aber diese diese Formate
muss ich ja auch mal abspeichern.
Ich muss ja irgendwie diese Reports ablegen können.
Ja gut, dann ich hab ne reportklasse, dann werd ich
jetzt ne safe Funktion einbauen. Klar.
Da geb ich n Pfad rein, hab meinen meinen formatierten
Bericht ja sozusagen schon und den kann ich jetzt abspeichern.
Cool super, ganz Lean, nicht viel Code, kleine Klasse super.
Hab jetzt aber schon 2 Verantwortlichkeiten drin.
Einmal das Formatieren und das Abspeichern richtig so und dann
heißt es auf einmal ja, aber wär irgendwie cool wenn ich über die
Software diesen Bericht auch an Kollege XY schicken kann, kannst
du das nicht als Mail oder über über ne API rausschicken.
Wie auch immer, aber dass du auf einmal noch ne Funktionalität
send hast und sagst. Na ja gut, dann bereite ich
jetzt die Daten noch mal auf in ein Format, was ich verschicken
kann. Ja, so Report ist noch Platz ist
noch nicht so groß, die Klasse Hau ich da auch mit 3 sind schon
3 Verantwortlichkeiten, jetzt kann man sich denken ja gut es
ist aber ne sehr übersichtliche Klasse, das Problem ist aber was
ist wenn sich das Format ändert wenn du sagst meine
Formatfunktion ändert sich weil ich intern meine Daten anders
darstellen möchte, dann ändere ich das Format und gleichzeitig
wird meine Send. Nicht mehr funktionieren, weil
ich nicht mehr von der gleichen Datenbasis in vielleicht diese
zu übertragende Format quasi umwandeln kann.
Das heißt, du musst dann einfach schon mehrere Funktionen,
mehrere Funktionalitäten und Verantwortlichkeiten, wie das
Prinzip ja sagt, Anpassen, deshalb wäre es da, um auch
Solid einzuhalten, der bessere Ansatz zu sagen, ich splitte das
einfach in diese Verantwortlichkeiten auf und hab
zum Beispiel ne formata Klasse. Ich hab ne Art Klasse, die das
speichern, die Funktionalität und Verantwortlichkeit hab, dass
ich zum Beispiel dieses Formatieren und das Abspeichern
der Daten oder das Cent was ich jetzt meinte einfach wirklich
Kapsel und. Voneinander trenne weil dann
spielt es nämlich keine Rolle, wenn ich bei avas änder, dann
ist b davon nicht betroffen, richtig und vor allem könntest
du auch rein theoretisch in deinem Formata oder wie du den
genannt hattest ne, also dieser dieser Formatierer nenn ich den
jetzt einfach mal. Könntest du ja auch verschiedene
Funktionen einbauen. Zu sagen, ey ich möchte jetzt
aber zum Beispiel auch, also wenn du es in verschiedene
Formate formatieren möchtest, weißt du, dann kannst du ja zum
Beispiel sagen, ey, ich brauch das zum Beispiel fürs Senden,
brauch ich das oder ich brauch es zum Beispiel fürs Speichern
oder was auch immer, dann kannst du Format for send machen oder
Format for for safe oder was auch immer ne also Namen
austauschbar, aber du weißt was ich meine.
Das heißt, du hast die Möglichkeit zu sagen, okay, du
hast etwas, was formatiert für eine bestimmte, also also eine
Klasse, die sich nur um das Formatieren kümmert, und du
kannst halt sagen, was formatiert, also wie es
formatiert werden soll, zum Beispiel genau, es ist auf jeden
Fall ein sehr guter Punkt und sehr wichtig, dass man dann
genau diese Aufspaltung macht und.
Und genau das mein ich auch. Wenn du jetzt zum Beispiel so n,
sagen wir mal du also was ich am Anfang eingehends meinte, du
hast ne utils Klasse oder so ne und da haust du erstmal alles
rein so und denkst dir so ach komm hör mal, ich hab jetzt
irgendwie ne utils klasse die ach die benutze ich da noch mal
und dann hast du aber nutzt du diese utils Klasse zum Beispiel
und du hast ne Funktion da drin Funktion HBC frag mich nicht ne
und die wird aber per. Perspektivisch in über über die
Zeit der Alterung der Software, so in der in der
Implementierungszeit. Je weiter fortgeschritten die
Implementierungszeit ist, desto höher ist die
Wahrscheinlichkeit, dass diese Funktion ABC auch an ganz vielen
Stellen genutzt wird. Und wenn du jetzt aber dann
dahin kommst und sagst okay ich muss jetzt aber mal, du bist an
einer Stelle im Code anstelle a und sagst ich muss jetzt
hierfür, muss ich aber diese Funktion ändern, die Funktion
heißt. ABC, aber ich geh da mal rein
ABC, ich änder das einfach mal ne ist natürlich keine gute
Practice einfach zu sagen ich änder einfach was da drin, aber
rein theoretisch könnte es ja sein, dass wenn du ABC änderst
an 8 anderen stellen oder an noch mehr stellen im Code das
genauso verwendet wird, aber vielleicht nur an dieser einen
Stelle A, über die ich gerade geredet hab, es wichtig war,
dass eine, dass etwas anderes passiert, dass die Funktion ABC
etwas bisschen anders macht, ne? Und das ist natürlich dann
schwierig, wenn du sagst, ey, also das, das kann natürlich
fehleranfällig sein zu sagen, ich ändere jetzt hier was und
alle anderen stellen kriegen diese genau diese gleiche
Änderung, aber vielleicht ist diese Änderung, die du
eigentlich haben willst, eine fachlich ganz andere und müsste
eigentlich in eine ganz andere Klasse, also in Utils 2.
In utils 2. Genau.
Also weißt du was ich meine und das ist ja genau.
Der Punkt zu sagen und ich find das ist sehr sehr wichtig, sich
immer wieder zu fragen und das kommt heute auch ja immer noch
vor. Es ist ja nicht so, dass du
irgendwann sagst, ich weiß sofort, was meine Fachlichkeiten
sind, auch noch mal Stichwort refactoring, da kommst du ja
relativ schnell hinzu sagen. OK, warte mal.
Ich hab jetzt hier was gemacht, aber eigentlich ist das eine
Fachlichkeit und das ist ne andere Fachlichkeit.
Das heißt irgendwann vielleicht im Verlaufe dein der
Implementierung merkst du das sind ja tatsächlich 2
fachlichkeiten oder vielleicht kristallisiert sich das über die
Zeit heraus, dass du sagst, früher war es eine, aber
mittlerweile sind es eigentlich 2.
Lasst uns das mal aufsplitten. Ne.
Genau also dieses diese Awareness sag ich jetzt mal zu
haben. Und zu gucken, also immer daran
zu denken und vielleicht auch noch mal mit einem anderen Blick
später auf gleiche Klassen zurück zu gucken und sagen muss
man die vielleicht auftrennen, sind das mittlerweile vielleicht
mehr Verantwortlichkeiten als nur eine, wie es mal war.
Ja, das ist ein guter Punkt, dass genau dafür auch
refactoring da ist. Und an der Stelle auch noch mal
die Anmerkung, dass diese Prinzipien, die wir hier
erklären, ja auch Richtlinien sind.
Ja, also es heißt nicht, ich muss jetzt jede einzelne
Funktion in ne eigene Klasse packen, weil das jetzt
unterschiedliche Verantwortlichkeiten sind.
So ist es ja nicht, sondern man muss es geschickt clustern und
wie du meinst herauskristallisieren, was die
Verantwortlichkeiten sind, wo lohnt es sich es zu splitten und
wo nicht? Ja also das auch noch mal
angemerkt ne, nicht dass man so ins Extreme verfällt, das ist
auch bei den Cleancode 3 haben wir das oft erwähnt, das sind
Richtlinien und man muss es nicht immer.
Ins völlige extreme sag ich mal wirklich übertrieben umsetzen,
weil dann gehst du leider wieder ins Negative von von den
Benefits her, die bleiben dann aus sag ich mal so genau genau,
wir haben ja noch 4 Prinzipien, deswegen geh ich mal direkt zum
nächsten Let's go und zwar bei Solid.
Das O steht für Open closed principle, also OCP.
Und besagt im Prinzip, dass wenn ich ein softwaremodul hab, also
beispielsweise jetzt auch wieder unsere Klasse, dass diese offen
für Erweiterung sein soll, aber geschlossen für Modifikation.
Und das ist eigentlich auch relativ gut zu erklären, da
würde ich nämlich noch mal dein Beispiel aufgreifen, was du
eingangs quasi gebracht hattest. Vorhin mit mit dem Bezahlen.
Wie du meintest, so, es gibt eine Bezahlmöglichkeit.
Ja dann hab ich ne Funktion, die heißt Pay in meiner Payment
klasse und da bau ich jetzt den Code ein den Ich brauche um
dieses Pay auszuführen ne und dann kommst du aber zu dem
Punkt, dass du sagst ja ich muss das jetzt erweitern, es gibt
jetzt wir binden noch ne Bezahlmöglichkeit an, zum
Beispiel keine Ahnung das Erste war Kreditkarte und jetzt machen
wir auf Rechnung. Mhm.
So ja OK, warte mal. Die Pay Methode ich sehe schon
da ist die Kreditkartenzahlung drin.
Ich brauche jetzt auf Rechnung ja gut if Aids wie du meintest
zum Beispiel so gut OK ist entschieden ich hab jetzt zum
Beispiel NI Namen was sagt was quasi identifiziert was für ne
Bezahlung und fertig weiter geht es ja OK wäre aber auch echt
wirklich cool das Ganze keine Ahnung mit Paypal.
Paypal zum Beispiel zu bezahlen. So, dann bist du schon bei 345,
was alles noch mit reinkommt, ne und dann kommst du an den Punkt.
Was ist wenn jetzt irgendwas in dieser Pay angepasst werden muss
was alle betrifft, was nur eine Bezahlmöglichkeit betrifft, dann
kommst du halt in Teufelsküche wie man so schön sagt, du musst
extrem aufpassen, dass du die anderen Bezahlmöglichkeiten
nicht kaputt machst, sage ich mal.
Wenn du jetzt zum Beispiel eine ergänzt oder bei einer was
abändern muss, die anderen nicht betroffen sind.
Du musst dir überlegen, welche sind alle betroffen von meiner
Änderung in der Pay Methode und das ist richtig tricky
irgendwann und auch wirklich ein heißes Ding so also das ist
gefährlich und deswegen sagt dieses Prinzip, du musst dafür
sorgen, dass du erweiterbar bist.
Also du kannst neue Bezahlmöglichkeiten reinbringen,
aber geschlossen für Modifikation.
Du darfst nicht die bisherigen Bezahlmöglichkeiten beeinflussen
damit, und das kann man denn eigentlich sich auch ganz gut
vorstellen, indem du sagst, ich hab jetzt nicht nur ne klasse,
wo ne Pay drin ist, sondern ich erzeuge für jede
Bezahlmöglichkeiten hab ich eine eigene Klasse, die eine Pay
implementiert, das heißt ich hab jetzt zum Beispiel ne Abstrakte.
Payment Klasse. Die wird zum Beispiel abstrakt
mit einer Methode Pay und ich implementiere jetzt meine
Bezahlmöglichkeiten davon und implementiere die Pay und kann
denn abhängig von der gewählten Bezahlmöglichkeit die richtige
Pay Methode aufrufen. Ich hoffe man konnte das mir
folgen. Wie gesagt, die haben ne
Triggerwarnung gegeben. Im Endeffekt so ne Art einfach
ne Art Interface, was sozusagen implementiert wird dann am Ende.
Und dann hab ich den Vorteil, wenn ich jetzt sage, bei der
Rechnung muss ich zum Beispiel irgendwie wie ich ne Rechnung da
noch mit ranhänge oder wie ich die Ausliefer wie auch wie auch
immer, also wirklich was rechnungsspezifisches, muss ich
in der Pay jetzt anders aufrufen oder?
Kommt, wird komplett abgewandelt, dann betrifft das,
betrifft das aber nicht meine anderen Bezahlmöglichkeiten,
weil die Pay Methode ja quasi extrahiert ist.
Sozusagen. Ja, und das ist halt eine schöne
Sache dabei. Das finde ich zum Beispiel noch,
um noch mal vielleicht eine kleine Analogie noch mal da zu
lassen, falls das jetzt vielleicht zu verwirrend oder zu
objektorientier lastig war. Was auch immer.
Will nicht sagen, dass man sich versteht.
Ich habe es fantastisch verstanden.
Aber. Wenn du jetzt zum Beispiel,
sagen wir mal, du hast du den Rechner und du willst jetzt zum
Beispiel deinen deinen Speicher aufstocken, dann kannst du ja
sagen okay, ich möchte meinen Speicher erweitern, so
demzufolge kannst du zum Beispiel hast du einen extra
Slot dafür und kannst halt eben einen neuen Speicherriegel
einsetzen, relativ einfach super ohne Probleme.
Ne. Und es ist ja nicht so, dass du
erst zum Beispiel sagst, ey, ich muss jetzt aber noch irgendwie
mein Motherboard irgendwie auseinander schrauben, da noch
was dran löten sozusagen oder vielleicht den vorherigen
Speicherriegel, sozusagen die, die die Schnittstelle, wo ich es
drauf stecke, sozusagen verändern, weil der gar nicht
passt oder so ne, also diese Modifikation sollte ich mein,
das ist selbsterklärend bei einem Rechner, dass man das
nicht tut, ne, aber? Genau darum geht es halt eben zu
sagen. OK, ich kann es erweitern, aber
ich will es nicht modifizieren, weil angenommen du modifizierst
es würden ja vielleicht deine alten Speicherriegel gar nicht
mehr passen und dann hast du auch nichts gewonnen.
Und der Vorteil ist natürlich, wenn ne Pay Methode wegfällt,
zum Beispiel jetzt noch mal in dem Beispiel, dass du sie
einfach. Entfernen kannst und musst nicht
in deiner vorherigen globalen Pay Methode gucken.
Wo muss ich jetzt überall Codezeilen löschen um diese Pay
Methode rauszukriegen und funktionieren die anderen noch
zum Beispiel? Also du hast halt diese
Erweiterbarkeit, aber natürlich auch den Umkehrschluss, dass du
Sachen auch wieder sehr gut, weil sie so Gekapselt sind,
entfernen kannst. Richtig genau also wie gesagt,
ist natürlich auch wieder. Eine Richtlinie sozusagen ist
jetzt kein kein Must have. Es ist aber immer gut.
Wie gesagt, bei solchen Dingen daran zu denken und sowas im
Hinterkopf zu haben und zu sagen, okay ist es denn
vielleicht sinnvoll in diesem Moment, es nach diesem Prinzip,
nach diesem o Prinzip, dem OCP oder Open closed principle
vielleicht zu betrachten? Beziehungsweise könnte man es
einbringen, ist es an der Stelle sinnvoll.
Das ist ja sozusagen immer der Gedanke, der dann mitschwingen
könnte, sollte vielleicht um es eventuell dann besser zu machen
oder vielleicht genau das zu vermeiden, was du eingangs
beschrieben hast, sozusagen das Problem an der Sache, an der
Sache. Ja, du hast es schon gesagt, es
ist so Awareness ne, dass man einfach das im Hinterkopf hat
und dran denkt dann. Das wird schon dafür sorgen.
Allein wenn man davon gehört hat und das immer im Hinterkopf hat,
sorgt schon dafür, fortan bessere Softwarearchitekturen zu
erstellen. Definitiv auf jeden Fall, also
zumindest aus unserer Erfahrung her, wo wir uns damit, also als
wir angefangen haben, uns damit auseinanderzusetzen, hat das
dafür gesorgt, bessere Softwarearchitekturen erstellen
zu können. Ich finde, was auch auf jeden
Fall hilft ist oder was mir auf jeden Fall auch öfter mal
geholfen hat, ist einfach mal zu sagen, es gibt so ein Prinzip
und ich versuche mir jetzt aber mal.
Vom Beispiel zu nehmen, um es einfach mal nach zu
programmieren, weil ich finde, es sind es sind immer noch 2
Sachen auf der einen Seite, das kenne ich, das okay mehrere
Sachen, Entschuldigung, das ist quasi so eine Art Kette, dass du
sagst auf der einen Seite kenne ich überhaupt dieses Prinzip,
wenn ja Check super Sache, dann weiß ich wie es funktioniert
okay alles klar Check habe ich es einfach mal ausprobiert um zu
fühlen. Wie das wirklich funktioniert,
wie es sich auch anfühlt, im Code ne.
Und da ist es dann einfach hilfreich, einfach mal zu sagen,
OK, ich nehm mir mal n Beispiel Programmier das einfach mal und
kann sozusagen live mitkriegen, wie dann sozusagen.
Wie dieses Prinzip dann angewendet aussieht, selbst mal
programmiert und so weiter ne, also das ist halt einfach auch
noch mal hilfreich klingt finde ich immer sehr trivial zu sagen,
ja gut, du weißt doch wie es geht, aber einmal programmieren
einmal selber n Beispiel sag ich jetzt mal auf die Beine stellen
und dann ist es noch mal n bisschen was anderes, zumindest
geht es auf jeden. Fall.
So auf jeden Fall das da geh ich mit, so kommen wir mal zum
dritten Solid l. Das ist das lisco Substitution
Principal und da muss ich sagen das ist das Prinzip von den 5
was ich persönlich damals am schwierigsten fand.
Zu verstehen und zu verinnerlichen.
Deswegen würde ich da auch direkt mit einer Analogie
starten, nicht auf n Codebeispiel gehen, in der
Hoffnung, dass man es dann n bisschen besser greifen kann.
Ich. Bringe danach n Codebeispiel.
OK, sehr gut. Dann machen wir es diesmal so
rum und zwar möchte ich, liebe Zuhörer, liebe Zuhörer, dass du
dir mal vorstellst, wieso eine universelle Steckdose aussieht
und wie man sie quasi verwendet. Und dann stell dir vor, du hast
jetzt verschiedene Elektrogeräte wie?
Ja, was habe ich hier gerade ein Laptop, Ladekabel, ich habe
einen Kaffee, also eine Kaffeemaschine noch in der
Küche, Staubsauger, Staubsauger auch eine super Sache.
Also du hast so verschiedene Elektrogeräte mit ganz
unterschiedlichen Anwendungsfällen, die aber die
gleiche Steckdose verwenden, das heißt du kannst jedes Gerät in
diese Steckdose stecken und verwenden.
Also der Laptop lädt, die Kaffeemaschine kann Kaffee
machen und der Staubsauger saugt so.
Und das ist im Prinzip dann lisco Substitution Principle
konform, das heißt jedes Gerät ist untereinander ersetzbar mit
dieser Steckdose. Du kannst erst das Laptop
Ladekabel ranstecken, dann ziehst du es raus wenn der
Laptop geladen ist, dann steckst du die Kaffeemaschine ran,
zapfst dir einen Kaffee. Ziehst sie wieder raus, machst
einen Staubsauger ran und saugst dein Arbeitszimmer
beispielsweise. Das heißt, sie erfüllen alle die
gleichen elektrischen Anforderungen, um mit dieser
Steckdose verwendet werden zu können.
Was ist jetzt jedoch, wenn du beispielsweise ein
amerikanisches Gerät hast, was eine andere Spannung benötigt,
dann funktioniert das eben nicht mehr, weil wenn.
Ja, keine Ahnung, bis zum Kurzschluss, keine Ahnung was
passieren kann, aber es verstößt halt gegen dieses Prinzip, weil
du die Geräte nicht mehr willkürlich, was heißt
willkürlich, also wie du möchtest einfach austauschen
kannst, weil dieses amerikanische Gerät eine andere
Spezifikation der elektrischen Anforderungen hat und das würde
gegen dieses Prinzip verstoßen. Du kannst es halt nicht mehr
frei austauschen, es ist halt nicht kompatibel am Ende.
Ich mein das System in dem Sinne und so Steckdose ich mein das
fängt ja rein theoretisch genau bei der Steckdose schon an, aber
selbst wenn du den Stecker gleich machen würdest, würde ja
wahrscheinlich trotzdem irgendwas nicht funktionieren,
da bin ich kein Elektrotechniker, ich weiß nicht
genau was passieren würde, wenn man mehr oder weniger Volt dann
da reinstecken würde, du meintest ja Kurzschluss fängt
der Staubsauger da an zu brennen, ich weiß.
Es nicht versaugt richtig krass. Nein, wir werden es mal nicht so
auf die Elektrotechnik Ebene hin, weil davon haben wir keine
Ahnung. Aber da genau das ist ne gute
Anmerkung selbst. Also meistens ist ja so, dass
der Stecker dann schon gar nicht passt.
Aber selbst wenn der Stecker passt, würde es halt nicht
funktionieren, weil du halt von einer anderen Spezifikation
ausgehst. Bei dem Gerät genau als die
anderen vorher genannten. Richtig.
Und es ist ja im Endeffekt so. Also diese Ersetzbarkeit, worum
es ja in diesem Prinzip geht, ne?
Da ist es. Es ist, das bedeutet in dem
Fall, dass wenn ein Programm ne, also in dem Fall sozusagen jetzt
die Steckdose soll, nicht merken ob es quasi ne Oberklasse oder
ne Unterklasse verwendet, ne also es ist egal was verwendet
wird, es muss funktionieren an dieser Schnittstelle sozusagen
ne ja und da geht es quasi. Also das das ist ja im Endeffekt
genau diese diese Ersetzbarkeit. Aus Programmsicht natürlich als
Programmierer oder Programmieren weißt du natürlich, klar, ich
weiß jetzt, was ich da verwende, aber das Programm weiß es zum
Beispiel, dann sollte es nicht wissen, ne, also kleines
Beispiel, wenn man jetzt zum du hast zum Beispiel so so Vögel so
ne vogelklasse ne und? Es ist ja ein richtiges
Lehrbuchbeispiel, finde ich. Gut, aber.
Pass auf, weil ich finde, ich finde das wirklich gut, weil in.
Im Normalfall was. Was können Vögel?
Vögel können fliegen, ne so das weiß man so und das können ja
eigentlich alle Vögel so, aber es gibt ja zum Beispiel Vögel,
die können das dann doch nicht, ne, also sind doch nicht alle
so, ja, aber man denkt ja erstmal ne, also wenn er also
angenommen man fängt jetzt an und sagt Ey ich brauch jetzt
vielleicht für irgendein Game oder so irgendeine irgendeine
Klasse ne vogelklasse weil ich will irgendwie Gegner haben, die
Fliegen ne so und. Und es soll aber auch irgendwie
auf der anderen Seite auch wieder sehr realistisch sein.
So, dann fängst du an, denkst du so, ja, ich habe ja die und die
Vögel kämpfende Vögel kennt man, fliegen draußen die ganze Zeit
nur rum. Ultra aggressiv, immer genau.
Aber so, dann hast du halt auf einmal einen Pinguin.
So ein Pinguin kann halt vielleicht nicht fliegen, also
er kann nicht fliegen, aber vielleicht im Game auch nicht so
und dann hast du halt ne also ne du hast jetzt ne Klasse
erstellt. Vogel und dieser, diese
Vogelklasse, diese Oberklasse, diese Superklasse, die kann halt
die Funktion fliegen, so fly ja so und dann hast du jetzt diesen
Pinguin, der ja sagt Ey, ich bin aber ein Vogel, also kann ich ja
auch Fly aufrufen, weißt du so und dann hast du das Problem,
dass du aber an der Stelle ja eigentlich nicht fliegen kannst.
Also angenommen es würde ein String zurückkommen, so was wie
ja ich kann fliegen, ich bin ein Vogel, dann würde ja beim
Pinguin genauso zurückkommen. Ja, ich kann fliegen, ich bin
ein Vogel. So was nicht stimmt.
Was nicht stimmt. Genau so, das heißt, das wäre ja
in dem Fall dann falsch so, also würdest du dich ja dann
vielleicht hinstellen und sagen naja, aber ich möchte ja genau
in diesem Fall vom Fliegen möchte ich dann vielleicht eine
Exception werfen, das heißt, ich überschreibe die Funktion.
In der Klasse Pinguin und sage ja gut, pass auf ich wenn wenn
Fly aufgerufen wird, dann werf ich einfach ne Exception und
sage ja das funktioniert aber nicht weil n Pinguin kann halt
nicht fliegen, sorry. Ja, so weißt, dann ist natürlich
der Pinguin an der Stelle fein raus und sagt so, ich hab
mitgeteilt ich kann nicht fliegen, richtig, aber was ist
das Problem wenn ich jetzt in meiner Software mit genau dieser
Vogelklasse arbeiten möchte? Genau das ist nämlich das Ding.
Angenommen, du hast jetzt dein, also du du.
Arbeitest immer mit Vögeln und gehst davon aus.
Okay du hast einen Vogel, so und wie gesagt, das Programm soll
nicht wissen, ist es eine Oberklasse oder eine Unterklasse
eine Subklasse so, das heißt das Programm sagt ich nehme mir halt
irgendwas was ein Vogel ist und ruft darauf fly auf und erwarte
dann okay ich kriege jetzt, dass der Vogel fliegt, genau dass der
Vogel fliegt beziehungsweise ich meinte ja so, du kriegst
vielleicht einen String zurück um sich das einfacher
vorzustellen, da steht drin ich kann fliegen so das erwartet das
Programm und was aber bei einem Pinguin passiert es fliegt eine
Exception so. So, das heißt, das Programm kann
in dem Moment vielleicht gar nicht damit umgehen, weil man,
weil man sich als Programmierer oder Programmiererin gedacht
hat, ja, da muss ich eine Ausnahme machen und denkt aber
an einer anderen Stelle nicht, vielleicht ist man selbst für
diese Stelle gar nicht zuständig, dass da ja dann eine
Exception fliegt, die gar nicht behandelt wird und es gar nicht
vorgesehen ist, dass da eine Exception behandelt wird.
So, und dann hast du halt genau das Problem, und das kann man im
Endeffekt, oder? Wenn man sagt okay ich möchte
aber dieses Lsp, also so heißt das Prinzip ja abgekürzt, möchte
ich konform sein, dann wäre die Lösung an der Stelle zu sagen
okay, du hast eine klasse Vogel und du hast vielleicht aber auch
noch eine Klasse Flying oder oder fliegbarer Vogel Flying
Bird nenne ich das jetzt mal, der sozusagen, also ein Vogel,
der Fliegen kann, diese klasse, und die also ein fliegender
Vogel ist. Natürlich ein Vogel, das heißt
das. Also fliegender Vogel ist eine
Unterklasse von Vogel. So weit, so gut.
Wenn du jetzt aber zum Beispiel irgendeinen anderen Vogel hast,
wie zum Beispiel ein Rabe oder so ne also oder eine Möwe, wie
zum Beispiel bei unserem Flappy Buddy Programmierwettbewerb.
Genau das ist ein reales Problem.
Leute, ja genau, auch wenn es bei uns keine Pinguine gibt.
Aber angenommen, Du hast jetzt zum Beispiel Rabe oder Möwe ne
als Vogel und das sind beides Vögel, die wiederum Unterklassen
von von einem fliegenden Vogel sind.
Das heißt, Rabe ist ein fliegender Vogel und ist aber
auch ein Vogel. So genau.
Und jetzt kommt noch ein Pinguin und sagt, ein Pinguin ist ein
Vogel, was ja bedeutet, dass im Endeffekt der fliegende Vogel
die Funktion fly hat und demzufolge Rabe oder eine Möwe
auch, aber der Pinguin nicht, weil die klasse Vogel hat.
Diese Funktion fliegen nicht so, demzufolge muss oder oder hat
jeder Vogel 2. Zwar nicht die Möglichkeit,
fliegen aufzurufen, als Funktion aber n fliegender Vogel und der
Pinguin selber, der nur vom Vogel, dann sag ich jetzt mal
abhängig ist oder ne Unterklasse vom Vogel ist der dem kann man
dann vielleicht noch so ne Art schwimmen oder so verpassen, ne?
Genau, und dadurch ist quasi die die basisklasse Vogel ja nicht
verletzt am Ende durch die Unterklassen.
Wenn ich jetzt die Basisklasse in meiner Software verwende,
weil ich denn nicht mehr sagen kann Vogel Punkt fliegen oder
fly was du meintest, dann kann es nicht mehr passieren, dass
ich da auf einen Pinguin komme, der aber nicht fliegen kann,
weil ich das Halt aufgeteilt habe und das ist halt der
entscheidende Punkt dabei. Genau also.
Also du kannst dich natürlich hinstellen und sagen, OK,
Pinguin ist jetzt ne sub klasse auch von flyingbird, aber dann
macht man ganz. Andere Sachen, aber dann kannst
du, kannst es aber in deiner Software differenzieren einfach
und kannst damit dieses Prinzip einhalten.
Genau also wie gesagt noch mal an der Stelle, es ist n bisschen
komplizierter und ich hab auch damals gebraucht das so wirklich
zu verinnerlichen und zu verstehen.
Ich hoffe wir haben es gut rüber gebracht also ich konnt ihr gut
folgen, ansonsten wenn es Fragen dazu gibt lieber zur lieber zur
gerne ne Mail dann werden wir es noch mal vertiefen.
Oder noch mal kurz zur Steckeranalogie zurück sprechen.
Oder noch mal noch mal die Steckdosenanalogie.
Ansonsten würde ich sagen, gehe ich mal zum vierten Prinzip, es
kommen ja noch 2. Stimmt so, dann sind wir bei dem
I und das ist das Interface Segregation Principle, also dass
man quasi spezifische Schnittstellen verwenden soll
anstatt riesige Interfaces. Wo wir auch wieder beim Thema
sind, super klasse oder super Interface wo du alles also
wirklich wie wenn wir noch mal die Stecker nehmen, da kannst du
einfach alles anstecken und auf der anderen Seite kann auch
alles rausgehen und du hast so n riesen Konverter da, der kann
alles so ne aber keiner weiß mehr wirklich was da drin
abgeht. Oder oder stell dir ne ne ne ne
universelle Fernbedienung vor, eine Fernbedienung die alles
kann, die hat einfach 100 Knöpfe und du kannst alles damit
steuern. Hast du mal so eine gesehen?
Ich hatte wirklich mal so ne Universalfernbedienung, die
kannst du dir ja kaufen, gab es früher ja immer so für alle.
Fernseher so ne und ich hab zu Ende mal irgendwie bei einem
Kumpel oder so gesehen dachte was ist das denn Alter und
eigentlich brauchst du ja am Ende nur irgendwie wieviel.
So 5 Tasten oder so. Ich, ich tatsächlich hab ich mal
ne Fernbedienung gesehen, die konntest du umdrehen und die hat
auf der anderen Seite auch noch Knöpfe gekauft.
Das ist aber das ist halt n perfektes Beispiel, das ist
eigentlich die perfekte Analogie die wir gerade gefunden haben,
weil wie du schon so schön meintest, du hast vielleicht.
Nächstes Programm vorheriges laut, leise Mute vielleicht
noch. Also du brauchst vielleicht ne
Handvoll Knöpfe, hast dann aber so n universelles Ding mit 100
Dingern, also 100 Knöpfen, wo du theoretisch sogar noch NDVD
Player bedienen könntest. Weißt du?
Falls man noch weiß, was du hast zu Hause.
Und da ist halt genau die Frage, wäre es nicht besser eine
spezialisierte Fernbedienung und so wie man sie auch zum
Fernseher dazu bekommt? Zu haben die wirklich die auf
die Funktion des Fernsehers eingeht und nicht noch 1000
extra Funktionen, die quasi unjusted sind noch drauf zu
haben. Und genau darum kümmert sich das
Prinzip. Ist auf jeden Fall auch ein
super spannendes Prinzip. Ich habe das auch tatsächlich
auch schon öfter selber erlebt, dass man irgendwie man erstellt
ein Interface und sagt, Ja, komm, ich habe jetzt.
Also das ist aber auch wieder so n so n so n Work and progressing
weißt du, du fängst an und sagst OK ich hab ein Interface und
mein Interface hat 2 Funktionen ne und wenn du sagst OK ich
möchte jetzt dieses also irgendwie dieses Interface
implementieren, dann hab ich jetzt zum Beispiel, also wie
nehmen wir noch mal das Payment Beispiel ne und du sagst OK.
Du hast ein Interface mit Pay drin, als Beispiel ne und jede
einzelne Bezahlmöglichkeit muss ja irgendwie Pay implementieren,
vielleicht auf eine andere Art und Weise ne, dann hast dann
hast du ja im Endeffekt den, du hast es ja relativ, das ist ein
schlankes Interface, ein Payment Interface sozusagen ne wo nicht
wirklich viel dabei ist. Aber wenn du jetzt anfängst und
sagst Ey, aber da kommt jetzt zum Beispiel noch dies rein und
das rein und jenes und hast du nicht gesehen, dann.
Hast du vielleicht im Payment Service 1?
Nutzt du 2 Funktionen von 20 im Payment Service 32 nutzt du dann
was weiß ich sagen wir mal 10 Funktionen und in dem anderen
auch noch mal 10 aber eigentlich sind mindestens immer 10
Funktionen die im Interface eigentlich insgesamt verfügbar
sind ungenutzt und dann? Ne, wie gesagt, das ist manchmal
auch so. N work and progress, dass man
dann vielleicht irgendwann es es baut sich auf in deiner Software
und du denkst dir, irgendwann gibt es nicht vielleicht
irgendwie Gemeinsamkeiten wo man sagt das ist ein Interface was
rein theoretisch richtig Sinn macht, ne also dass man die
Interfaces sozusagen dass du, dass du einfach vielleicht 3
Interfaces aufsplittest, weil zum Beispiel eine Funktion,
nämlich die Pay Funktion, das ist wirklich die Funktion, die
jedes. Jeder Payment Service verwendet,
also ist das auch wirklich ein Interface, ein eigenes
Interface, ne? Ja, hast du da vielleicht ein
kleines Minimalbeispiel, was wir noch so geben könnten, weil wir
jetzt überall immer so Beispiele hatten?
Fällt dir gerade was ein? Also wenn du jetzt zum Beispiel
sagst, nehmen wir mal Roboter, kommen ja jetzt gerade, sind ja
voll im Kommen, ne. Mit KI und können dir was
abnehmen. So ja.
Geil das hau raus das Beispiel. So, und jetzt hast du zum
Beispiel, sagen wir mal in in in Lagerristen ne.
Weil ich glaube, in in, in vielen so Logistikzentren oder
so werden ja auch mittlerweile Roboter eingesetzt, die Pakete
durch die Gegend tragen. Und du hast jetzt so.
Ich war letztens kurz off topic war ich in so einem Diner, wo
mir hier dieser so n Roboter das Essen an Tisch gebracht hat.
OK, und wie fandst du das? Das war voll witzig, aber du
hast doch das als Beispiel nehmen.
Das ist auf jeden Fall, das kann ich nicht zeugen.
Aus der Realität OK, cool. Also du hast, du hast n Roboter,
also sagen wir mal du hast n Restaurant in dem.
Du Servierkräfte hast also menschliche Servierer,
Serviererin und Kellnermäßig und Kellner, also Roboter, Kellner,
so Roboter, Kellner klingt wieso ein Film, ey die Rückkehr der
Roboter, Kellner auf jeden Fall so dann diese beiden hast du und
dann hast du zum Beispiel einmal den den Arbeiter sozusagen und
einmal den Roboter so und beide könnten ja rein theoretisch auf
jeden Fall arbeiten. Also so, und dann hast du aber
zum Beispiel noch den Punkt, dass du sagst okay, aber also
ein Arbeiter, der möchte ja auch oder der Mensch, der möchte
auch, der muss ja auch essen, so was wie eine Essenspause machen,
also dass du halt einfach sagst, Mittagspause komm, ich gehe
essen, das braucht der Roboter aber nicht, der muss aber
vielleicht laden, was auch immer, vielleicht schafft er
auch den ganzen Tag, aber sagen wir mal, du hast im Endeffekt
eine Klasse, die das ist sozusagen klasse Arbeiter so im.
Im Großen und Ganzen. Und dieser Arbeiter muss
arbeiten können, logischerweise, die Funktion braucht er, weil er
arbeiten soll und er muss essen. So und jetzt hast du aber zum
Beispiel den Roboter wieder und wenn der Roboter aber ein
Arbeiter ist, genauso wie ein Mensch ein Arbeiter sein kann in
diesem Restaurant, dann kannst du ja rein theoretisch auf dem
Arbeiter wieder, weil der Arbeiter die Funktion Work und
Eat hat, also er darf arbeiten und kann essen.
Könntest du ja rein theoretisch, wenn der Roboter ein Arbeiter
ist, auch auf dem Roboter die Funktion eat aufrufen.
So und jetzt hast du natürlich wieder das so n bisschen
ähnliches Prinzip was wir vorher also vorhin hatten, ne andere
also die Subklasse macht was anderes oder?
Oder reagiert vielleicht anders weil dann vielleicht ne
Exception geworfen wird und da steht dann drin als Exception
Message Roboter müssen nicht essen so ja aber.
Hier geht es ja auf einen anderen Punkt hinaus und zwar,
dass du die Interfaces oder die Oberklassen oder wie du es
nennen möchtest ist. In dem Fall ist ein Interface
würde ich jetzt mal sagen, schlanker machst ne, das heißt
im Endeffekt spezifischer. Genau spezifischer finde ich
gut, also du hast mehr, aber spezifischer, das heißt im
Endeffekt hast du das Interface workable ne wenn wir jetzt von
Worker oder Arbeiter ausgehen, das heißt also.
Arbeitend, wenn es auf Deutsch machen willst oder so und
eatable so. Das heißt du hast sozusagen n
Interface. Was sagt OK es ist möglich zu
essen und n Interface was sagt es ist möglich zu zu.
Arbeiten so und bitte an der Stelle nicht übersetzen als n
essbarer Mitarbeiter sagen genau, aber ich weiß was du
meinst. So, und dann genau.
Und dann hast du ja zum Beispiel kannst Du sagen, OK der der
Mensch, ne der ist zum Beispiel, also der ist.
Rockable und die und der Roboter ist halt nur rockable so und
demzufolge hast du dann den Effekt, dass der Mensch 2
Interfaces implementiert, also zum Beispiel einmal das
Interface für Essen und das Interface für Arbeiten und der
Roboter hat nur das Interface für arbeiten, was aber auch
gleichzeitig in deiner Software bedeutet, dass wenn du sagst,
ey, ich möchte jetzt alle losschicken, angenommen sagen
wir mal, du hast eine kleine Simulation von dem Restaurant
und. Und du möchtest in deiner
Simulation alle Arbeiter losschicken in
Anführungsstrichen? Dann kannst du ja sagen okay,
ich nehme alle meine Instanzen von Workern sozusagen und lass
die arbeiten so und dann kann ja ein Worker, ist ja zum Beispiel
entweder ein Mensch oder ein Roboter, aber wenn du jetzt
sagst, schick mal bitte alle worker in Anführungsstrichen zum
Essen. Also beziehungsweise die die
auch essen können. Die, die sozusagen das eatable
Interface implementieren, dann funktioniert das, aber die
Roboter werden sozusagen gar nicht dann bedient an der
Stelle, weil die das ja gar nicht überhaupt nicht in ihrer
Funktionalität dann drin haben, oder halt dieses eatable
Interface gar nicht implementieren.
Genau. Und.
Jetzt kann man sich natürlich denken, OK, das sind jetzt 2
Eigenschaften, sozusagen, das Krieg ich schon noch irgendwie
verwaltet. Ne, das wär so n Grundgedanke
wenn Gedanke, wenn man quasi immer weitergeht und sagt, nee
ich brauch so ne Prinzipie nicht, das geht schon, das passt
schon so, jetzt sagst du aber irgendwann jetzt hab ich aber
auch noch Mitarbeiter die in der Pause draußen rauchen gehen, so
ne dann will ich noch wissen wer raucht von denen zum Beispiel
oder? Du baust die Aufgaben ein.
Wer bringt zum Tisch, Wer bereitet die Getränke zu, wer
geht in die Küche und so weiter und es kommen immer mehr
Eigenschaften rein in dieses Interface und es wird quasi so
riesig wie unsere Fernbedienung. Aber es gilt halt nicht für
jeden. Weil der, der draußen die Teller
abräumt, muss ja nicht noch Funktionen implementieren, wie
er Getränke zubereitet. Jemand, der nicht raucht, muss
nicht wissen, wie die Funktion aussieht, um rauszugehen und zu
rauchen. Weißt du also, das ist ja genau
das der Punkt den du meinst, weil wenn man sich so denkt ja 2
Funktionen Come on es wird 100 Pro irgendwann mehr und dann ist
es genau richtig diese spezifischen Interfaces zu
verwenden um dann auch spezifisch drauf zugreifen zu
können am Ende oder unterscheiden zu können,
richtig. Im Endeffekt hast du ja auf
jeden Fall ein gutes Beispiel. Im Endeffekt hast du ja, wenn du
es in deiner Software siehst, irgendwann Objekte, auf denen du
irgendwas aufrufen willst. Und du willst ja wissen, auf
welchen Objekten kann ich denn was aufrufen und es soll dann
auch so funktionieren. Ne, und damit du das besser auch
differenzieren kannst zwischen diesen Objekten auch
unterscheiden kannst, hast du halt eben dann auch
spezifischere Interfaces sozusagen.
Ja, genau. Ja, cool, erklärt Fabi, vielen
Dank dafür. Lass uns mal zum letzten Prinzip
kommen, wir sind auch schon n bisschen fortgeschritten in der
Zeit, aber wir müssen auf jeden Fall es noch unterbringen, das
wär jetzt so richtig mies und das nächste erfahrt ihr in der
nächsten Folge. OK, das D in Solid steht für
Dependency Inversion Principle und das finde ich sehr spannend
und auch sehr wichtig ist ne sehr gute Sache und im Prinzip
geht es um Dependency Injection als Lösung dahinter.
Aber wie kann man sich das Ganze vorstellen, wenn man sich jetzt
vorstellt, man hat zum Beispiel eine Anwendung, wo du so eine
Business Geschäftslogik drin hast, die halt wirklich intern
in deiner Software quasi regelt, wie gewisse Sachen umgesetzt
werden, verarbeitet werden und. Je mehr ich zu den Eingabe zum
Beispiel. Ich hab jetzt ganz klassisch
eingabeverarbeitung Ausgabe ne, nehmen wir mal so das Eva Ding
und diese Verarbeitungslogik ist riesig, da passiert unglaublich
viel. Wir haben sehr viele Eingaben
und jetzt erzeug ich aber Abhängigkeiten von diesen
Eingaben und bin halt so unglaublich verzwickt.
Oder man stellt sich das vor, so keine Ahnung im Webbereich, wo
ja auch viele unterwegs sind. Ich habe halt so eine API, das
ist meine Eingabe und die Verarbeitung ist wie ich auf der
Datenbank mit diesen Daten arbeite und wenn ich jetzt aber
so unglaublich verzwickt und Verwurstelt nenne ich es mal mit
der Eingabe bin, dann kriege ich halt riesenprobleme wenn ich das
ganze quasi durch diese Abhängigkeiten verändern will,
weil ich dann an allen Stellen wieder eingreifen muss.
Kannst, kannst du mir folgen? Definitiv.
Also ich hab halt das Problem, dass es nicht mehr flexibel ist,
dass es vor allem nicht mehr testbar ist, weil das ist jetzt
n riesen Punkt. Dieses Prinzip sag ich mal
fördert unglaublich die Testbarkeit, da können wir
gleich noch mal drauf eingehen und ich kann es auch nicht mehr
gut erweitern am Ende, weil ich halt diese Kopplung hab.
Und wie schaffe ich es jetzt diese Eingabe und Verarbeitung
voneinander zu entkoppeln? Und genau da greift halt die
Dependency Injection und magst du, hast du vielleicht so ein
Minimalbeispiel? Also ich finde wir können ja das
ruhig mit dieser API und Datenbank ruhig weitermachen,
weil ich glaube das ist so ein Bereich wo viele unterwegs sind
im Webbereich wie man jetzt so eine Dependency Injection
verwenden könnte dafür. Also im Endeffekt kannst du, ich
hoffe ich kann das Beispiel jetzt richtig aufgreifen was du
meinst. Also angenommen du hast jetzt
eine eine eine sagen wir mal Anwendung und diese Anwendung
hat auf jeden Fall, also hat eine Zugriff auf eine Datenbank
so ne so und dann ist diese Datenbank zum Beispiel einfach
festgeschrieben in diesem Programm, das heißt du hast so.
Sozusagen irgendwie einen Service.
Also sagen wir mal, du gehst über eine API und du hast in
dieser API eine Anfrage und du hast irgendwie einen Service,
der diese Anfrage verarbeitet und sagt zum Beispiel okay ich
muss jetzt aber diese diesen Request in meine Datenbank
schreiben oder Daten aus dieser Datenbank rausholen, genau, und
jetzt hast du in deinem Service zum Beispiel eine Datenbank
instanziiert so weil dieser Service sagt zum Beispiel okay
ich brauche eine Datenbank und wenn du jetzt aber zum Beispiel
sagst okay ich. Habe jetzt zum Beispiel eine My
SQL Datenbank, die ich über diesen Service anspreche.
Dann wird jeder request immer nur gegen eine My SQL Datenbank
gehen und wenn du aber jetzt zum Beispiel sagst ich möchte jetzt
aber eigentlich gegen eine andere Datenbank gehen, weil ich
noch eine andere habe, wie willst du das machen weil du
immer nur diesen einen Service hast der.
Quasi wo drin, wenn dieser Service hochgefahren wird oder
existiert, dann hat er eine feste Instanz von einer
Datenbank oder einen festen Zugriff auf eine Datenbank,
besser gesagt eine Connection dazu.
So und wenn du jetzt aber zum Beispiel sagst, ich möchte das
ganze Injekten sozusagen, also dependency Injection nutzen,
dann gibst du quasi die Datenbank von außen rein, das
heißt im Endeffekt sagst du okay ich möchte diesen User Service
haben mit dieser Datenbank. Das bedeutet, dass du im
Endeffekt nicht sagst, okay, ich habe jetzt eine eine feste
Datenbank, sondern ich sage diesem diesem Service, dem sage
ich pass auf, ich brauche jetzt Daten, diese Daten brauche ich
aus einer Datenbank und ich gebe dir mit, welche Datenbank das
ist, von der du diese Daten holen sollst beziehungsweise wo
wo du die Daten reinschreiben sollst.
Das ist sozusagen der kleine Unterschied.
Ja, und das kannst du ja halt auch auf allen Ebenen packen.
Also das war jetzt quasi die Funktion mit dem
Datenbankzugriff. Du kannst es aber auch genauso
eine Ebene höher packen. Wie sieht denn deine Rest api,
deine Calls, deine Requests aus und was passiert in deiner
Software? Da kannst du das ja genauso auf
der Ebene einziehen, dass du sagst, ich möchte ja nicht, dass
jeder request genau wenn ich den Entgegennehme schon quasi.
Quasi in sich selbst tragend. Die Implementierung hat, wie ich
auf der Datenbank arbeite, also wie der Service aussieht, weil
dann ist jeder Request an den Service gekoppelt, da haben wir
wieder ne Kopplung und wenn du jetzt aber sagst ich hab zum
Beispiel ne Art Controller, ist so n klassischer klassische
Klasse klassische Klasse dafür für so die für die Request die
sich nur darum kümmert auf welchen Calls nehm ich denn was
entgegen? Und gebe da den Service auch
noch mal rein. Dann hab ich das auch noch mal
entkoppelt und das ist auch dependency Injection, dass ich
sage, dieser Controller instanziiert sich keinen Service
und ist damit exakt gekoppelt an diesen Service, sondern ich gebe
von draußen einen Service rein, der dafür sorgt auf diese
Request zu reagieren und der ist austauschbar.
Ja, genauso wie dein Beispiel. Ich habe dann den Service, der
wiederum von außen die Datenbank bekommt, damit die Datenbank
austauschbar ist, dass es halt nicht in sich selbst
instanziiert und implementiert ist.
Und das ist halt n Riesenvorteil, weil wir auch
meinten, Testbarkeit angenommen, ich möchte jetzt sagen wir mal
den Controller testen. Ja, ja, also ich will jetzt
einfach, ich tue jetzt so, als wenn n request reinkommt und ich
möchte wissen, ob ich auf 200 mit 200 OK antworte, weil alles
OK war oder nen 404 beispielsweise und ich will das
jetzt testen und hab jetzt aber in dem Controller selbst diesen
Service implementiert, da muss ich diesen ganzen Rattenschwanz
irgendwie in diesen Test reinbringen, damit ich den
Abtesten kann. Wenn ich jetzt aber diesen
Service von draußen in den Controller gebe, dann kann ich
ja nen. Sag ich mal n gemobbten Service
da reingeben und simulieren wie der reagiert und kann mir so
viel besser Testfälle bauen, dass ich zum Beispiel sag, wie
sieht der Request aus, alles klar, ich tu mal so als wenn ich
in der Datenbank jetzt den Eintrag finde und ah OK 200 OK
geht zurück super der Test funktioniert jetzt tue ich so
als wenn ich den Eintrag nicht finde ja OK 404 beispielsweise.
Wenn ich das aber so nicht machen müsste, dann bräuchte ich
den richtigen Service. Dann bräuchte ich die richtige
Datenbank, um irgendwie nach oben wieder zu bekommen.
Ob der User jetzt da drin war oder nicht beispielsweise, und
das ist halt das coole an Dependency Injection und das ist
halt auch das D in Solid am Ende.
Ja, richtig. Also ich finde Dependence
Injection ist an sich auch ein relativ großes Thema, wenn man
da jetzt noch mal, wie du ja eingangs auch schon meintest,
wenn es bestimmte Themen gibt, über die wir noch mal ein
bisschen genauer eingehen sollen, Liebe zuhören, lieber
zuhören, dann schreibt uns auf jeden Fall gerne wie gesagt über
unsere Podcast Mail oder auch auf unseren Plattformen, wie
gesagt, alles in den Show Notes verlinkt, um das Ganze noch mal
abzuschließen, um das vielleicht noch mal auch ein bisschen, also
dieses D in Solid, um da noch mal ein kleines Bild vor Augen
zu rufen. Ja.
Ich meine. Guck mal, es geht ja jetzt auch
langsam wieder Richtung Sommer. Das bedeutet langsam ne, so
dauert ein bisschen noch, aber man sag ich jetzt mal
urlaubsplanung ist vielleicht ist real so und angenommen du
als Mensch jetzt ne hast du bist eine Instanz und wirst erzeugt
so und wenn du jetzt keine Dependency Injection hast und
sagst OK ich möchte jetzt aber zum Beispiel mit einem Flugzeug
fliegen so. So, dann wird dir zum Beispiel
eingeimpft, ne in in deiner DNA, du darfst nur von Hamburg
fliegen, weil du sozusagen in dir selber den Flughafen
instanziierst. Also.
Ne, also eine Instanz anlegst und das ist immer Hamburg
beispielsweise und nie was anderes.
Das bedeutet also, du könntest zwar nach Angeboten gucken und
sagen, Oh guck mal, ich könnte vielleicht von Berlin fliegen
oder von München oder was auch immer, geht nicht, weil du
darfst, genau, du darfst nur von Hamburg fliegen und von nirgends
woanders. Wenn du jetzt aber zum Beispiel
sagst, ey, ich könnte jetzt aber die dependency Flughafen
Injekten. Dann hast du die Möglichkeit zu
sagen, ich gucke erstmal, welchen Flughafen ich denn
überhaupt ansteuern möchte. Und wenn ich mir einen
ausgesucht habe, dann nehme ich diesen und gebe ihn sozusagen
von außen rein. Also ich sag jetzt mal
gedanklich, du kaufst dir die Tickets und bekommst deine
Tickets und checkst dir in die Tasche so genau und dann weißt
du ja, aber okay ich, ich kann mich entscheiden, weil ich
erstmal sage, welcher Flughafen und dann nehme ich diesen
Flughafen anstatt zu sagen, ich nehme erst den Flughafen und
dann gucke ich mal was von da fliegt und wo es hingehen könnte
so. Und das ermöglicht dir halt
diese ganze Implementierung drumrum.
Oder sagen wir mal in deinem Beispiel, diesen ganzen Ablauf,
sei es das. Stellen der Tickets, den Flug
buchen oder auch zum Beispiel, was vor Ort am Flughafen
passiert, was geführt bei jedem Flughafen gleich ist.
Ja, aber wenn ich dann immer von Hamburg aus gehe, bringt mir das
nichts. Genauso kann ich den Flughafen
von draußen reingeben, also was wir mit inject Minen, falls das
nicht ganz klar ist. Ist ja im einfachen übertragenen
Sinne n Eingabeparameter in einer Funktion zum Beispiel
richtig oder in den Konstruktor einer Klasse richtig.
Und dann hab ich halt den Vorteil, dass ich den Rest der
der Funktion nicht anpassen muss, vielleicht für so kleine
spezifische Sachen. Beispielsweise Flughafen Hamburg
parke ich direkt vor Ort, bei Flughafen Berlin kann ich nicht
direkt vor Ort weißt du so so flughafenspezifische Sachen, die
sich unterscheiden können, würden dann die ganze Funktion
beeinflussen, was aber total unnötig ist, weil vor Ort muss
ich ja trotzdem mein Gepäck aufgeben, durch ne
Sicherheitskontrolle gehen und in n Flieger steigen, was vor
allem wieder gleich ist. Weißt du deswegen das ist n
cooles Beispiel abschließend finde ich sehr gut danke dir.
So genau, und damit sind wir ja quasi jetzt einmal durch die 5
Prinzipien durch Solid ist auf jeden Fall super spannend und
wie gesagt immer eine wichtige Sache das im Hinterkopf zu
behalten. Man muss nicht strikt danach
arbeiten, es ist auch überhaupt nicht schlimm mal irgendwann in
in der Entwicklung seiner Software zu sehen um Mensch das
das sind jetzt aber zum Beispiel mehrere Fachlichkeiten, da muss
ich jetzt zum Beispiel mal was auf splitten, da muss ich
vielleicht mal wieder was refact an, aber.
Alles kein Problem, wenn man denn zum Beispiel einfach auch
mal so bestimmte Infos mal im Hinterkopf hat und und danach
vielleicht so seinen eigenen Code oder seine Software, in der
man arbeitet, scannt. Sag ich jetzt mal ne ja und dann
kann es einfach sag ich mal nachhaltig besser werden.
Ja, also auch noch mal ganz kurz abschließend die Tech Home
Message. Ich würde noch mal ganz, ganz
kurz durchgehen, noch mal so zur Zusammenfassung.
Also solid ist. Im Prinzip sind 5 Prinzipien für
jeden Buchstaben 1. Wir haben das S mit Single
Responsibility Principle im Prinzip eine Klasse, eine
Aufgabe, eine Verantwortlichkeit, dann haben
wir das Open Close principle, was im Prinzip besagt sei offen
für Erweiterung und geschlossen für Modifikation.
Drittens war das lisco Substitution principle, was im
Prinzip die Ersetzbarkeit von den Subklassen beinhaltete, das
Vogelbeispiel. Ich hoffe, man kann sich noch
dran erinnern mit den Pinguinen, viertens war Interface
Segregation Principle, was im Prinzip sagt nicht die
universelle Fernbedienung, sondern speziell für deinen
Fernseher, das heißt lieber spezifische Interfaces statt
riesige Schnittstellen und jetzt zum Abschluss hatten wir
dependency Inversion Principle mit der Dependency Injection.
Was ja im Endeffekt sagt, diese Abhängigkeiten, die man hat,
lieber auf Abstraktionsebene packen und nicht auf konkrete
Implementierung, wo du ja gerade das Flugbeispiel gebracht
hattest. Wenn ich implementiere in meiner
buchungsfunktion Flughafen oder so.
Start ist immer Hamburg ungünstig.
Richtig, ganz genau so sieht es aus, gut zusammengefasst, Kino,
dann sind wir eigentlich auch, würde ich sagen, durch wie
gesagt bei. 2 genaueren Fragen weitere weiterführenden Podcast
folgenden Themen schreibt uns einfach an.
Ansonsten danke Tino fürs für die Folge, hat Spaß gemacht und
war sehr cool. Wir haben versucht es möglichst
kurz zu halten und es ist wieder länger geworden als man denkt
wie? So immer.
Es sind aber auch 5 Prinzipien man so.
Genau. Und ansonsten würde ich sagen,
bewertet gerne den Podcast. Das würde uns mega freuen.
Empfiehlt ihn auch gerne weiter, wenn ihr sagt das ist ein Hammer
cooler Podcast. Genauso könnt ihr uns auch
unterstützen mit einem kleinen Spenden Link gibt es alles unten
in den Shownotes einfach mal reinschauen und mal durchlesen,
mal reinschnuppern sozusagen, ansonsten bleibt mir nichts
anderes übrig als zu sagen bis zum nächsten Mal, also bis zur
nächsten Woche. Wir hören uns habt einen schönen
Tag, deine Cordon balis gemeinsam besser.