Scharf 1 habe ich jetzt irgendwie ein Halstuch verfasst.
Gala ich denke mir jetzt gerade irgendwas aus und scharf 2 hat
auf einmal auch ein Halstuch um was ist da los?
Beides schon nach scharf. Coding Buddies Dein Podcast rund
um Softwareentwicklung und aktueller Tech News.
Herzlich Willkommen einen wunderschönen guten Tag
und herzlich willkommen. Schön, dass du wieder
eingeschaltet hast. Zur neuen Folge vom Coding
Buddies Podcast. Und zwar mit mir, mit fabi und
mit Tino. Er sitzt mir hier virtuell
wieder gegenüber, er nickt schon, er grinst schon, er hat
Bock, hoff ich zumindest. Wie geht's dir?
Was geht ab? Fabi?
Ja ich hab mega Bock, ich hab richtig Bock ja das ist richtig
gute Laune, das wird richtig wird unangenehm heute für dich.
Super. Ja, das das trifft sich gut.
Ich hab richtig, richtig schlechte Laune.
Ja, das ich gleich das aus. Oh nee, das wär aber weißt du,
das ist halt auch so n Ding, muss ich ganz ehrlich sagen das
das das ich weiß hat man wahrscheinlich irgendwie auf dem
Schirm, aber wenn du so n Podcast machst ne dann gibt es
ja auch mal Tage wo man sich so denkt so oh weißt du heute ist n
Podcast aufnehmen dran aber heute hab ich irgendwie fühl ich
mich nicht so ne. So, und dann die.
Abstimmung. Ja, genau so.
Aber dann muss man halt irgendwie umschalten und
trotzdem mal sagen so ne doch ich hab jetzt gute Laune,
hinterher kannst du ja wieder schlechte Laune haben, ne ja.
Das Gute ist, dass ich, selbst wenn ich das Gefühl hab, oh,
jetzt n keine Ahnung, Zeitdruck oder so, jetzt noch n Podcast
aufnehmen, wenn diese Gedanken aufkommen, wird dann aber
anfangen, also auch wie jetzt zum Beispiel gut, heute hab ich
nie Bock gehabt, ja, aber dass man sich dann denkt, so ah nee
doch ist geil macht Spaß Podcast aufnehmen macht Spaß also ich
rede ja sehr gerne mit dir über diese Themen und allein das
Feedback so aus der Community motiviert mich extrem muss ich
sagen. Da denn halt auch immer wieder
on Point zu sein sozusagen. Ja, das ist ja auch nicht so,
dass ich mir denke, so, ich hab meistens keinen Bock auf Podcast
sozusagen aufzunehmen, sondern es ist halt eher so, dass ich
mir dann so denke, so irgendwie ist es viel an dem Tag, ne,
irgendwie ist sowieso irgendwie, man hat den Kopf voll oder so
und dann ist man irgendwie vielleicht nicht so in Stimmung,
so ne, also was kann ja vorkommen, finde ich nur also.
Ich weiß nicht, also mir ist das letztens erstmal so bewusst
geworden, so ne, aber eigentlich wie du sagst ne man fängt an
Podcast irgendwie aufzunehmen und dann hat man so denk mal so
ja komm ist irgendwie geil hab ich habt ihr auch immer macht
ihr auch immer Spaß mit dir zu zu quatschen Tino und das ist
gut. Das ist ne gute Voraussetzung
für diesen Podcast. Ja, auf jeden Fall ne.
Aber bevor also wir wollen ja jetzt mal wirklich anfangen ne
und auch wirklich jetzt mal starten in die Folge rein.
Ganz kurz noch, weil das ist ja unsere klassische Erinnerung, ne
Liebe zu lieber zu, wenn du sagst, geiler Podcast, da will
ich nichts verpassen. Ja, vielleicht hast du den auch
gerade erst entdeckt, dann abonnier den Podcast auf jeden
Fall und vielleicht, falls du es noch nicht gemacht hast, mach
das Glöckchen an, weil dann verpasst du auch keine Folge
mehr. Es gibt gerne ne Bewertung da
das hilft uns enorm, das muss man einfach sagen.
Es ist halt unglaublich wichtig für einen Podcast auf dem
Plattform auch ne Bewertung zu bekommen.
Ja, das stimmt. Gut, dass du es sagst, Tino,
heute geht es ja mal wieder um eine bestimmte Reihe, die wir
ins Leben gerufen haben, die auch schon sehr wichtig ist
insgesamt für die Softwareentwicklung, und zwar
geht es um die Design Pattern Folge und heute ist ja mal die
ist. Ja, auch mittlerweile schon gut
fortgeschritten. Ne, also wir haben schon so n
paar Meter gemacht, cool. Haben wir auch gutes Feedback
dazu bekommen und ich muss sagen ich find es halt auch immer echt
cool jedes Pattern noch mal so n bisschen, also nicht jedes alle
werden wir nicht schaffen. Es gibt aber viel zu viele, ja,
aber die wir so rauspicken noch mal durchzuarbeiten find ich
schon ziemlich cool muss ich sagen.
Man kann auch immer selber noch was lernen, weil manchmal ist
man ja auch so eingefahren und denkt sich so.
Ja, zum Beispiel wie beim Factory Pattern beispielsweise,
da dacht ich mir auch so, ah OK, cool, ja ich hab zum Beispiel
noch nie so krass über n. Was war das?
Dieses, dieses, dieses krasse Endgame, Factory Pattern,
nachgedacht, Endgame. Factory.
Die Abstract. Factory, dass es halt einfach 3
Stufen gibt davon ja. Ja, richtig.
Also so als Beispiel ne man man lernt selber auch noch was und
ich hoffe Liebe zu Liebe zu du lernst auch was davon, ansonsten
hast du vielleicht auch einfach nur Bock den Podcast zu hören,
dann ist es natürlich auch super.
Fakt ist aber Tino, worum geht es denn, welches Pattern ist
denn heute dran? Ja, also heute geht es um
Pattern, da muss ich gleich mal vorwegnehmen, das hab ich selbst
sehr selten verwendet, umso cooler finde ich es, dass wir es
heute mal besprechen, weil durch sag ich mal so die Vorbereitung
auf die Folge hab ich mich oder wir uns zusammen ja noch mal mit
dem Pattern auseinandergesetzt und schon Anwendungsfälle
gefunden dafür auch für uns, was wir vielleicht demnächst mal auf
Twitch wirklich mal bei einem Projekt verwenden können oder wo
es Sinn macht dieses Pattern zu verwenden und zwar geht es
heute. Um das prototype pattern.
Ja, also wir wären heute quasi ne Art Clone Wars führen, nerve
alle Star Wars Fans hier. Es geht nämlich heute darum, es
klingt erstmal nerdig, aber es geht im Prinzip darum, dass wir
heute mal so copy Paste 2.0 etablieren und zeigen warum es
sinnvoll ist, manchmal komplexe Objekte nicht immer neu zu
erstellen, sondern sie wirklich einfach zu klonen.
Weil das steckt halt hinter den Prototype Pattern und das würde
ich sehr gerne heute mit dir mal so n bisschen besprechen vor und
Nachteile nennen und vor allem Fabi und da freu ich mich drauf
wieder schöne Analogien finden dazu.
Es soll doch Analogien hageln. Weißt du was, zino ich, ich
möcht mal spoilern, dass das dieses Mal ja gar nicht so viel
um Essen geht, ne ich, ich glaube in den.
In unserer generell in unseren Podcasts, wenn es um Analogien
geht, geht es oft um Essen. Gerade glaub ich jetzt auch in
der in der Pattern Reihe hier, aber wir wollen heute mal
vielleicht warum sagst. Du das jetzt schalt ich 90%
schalten jetzt ab, wenn es nicht um essen.
Geht es geht um unseren. Ja, unsere Essensanalogien sind
doch mittlerweile legendär. Welche Leute erwarten das doch,
fabi, aber du hast recht, das ist bei dem Pattern wirklich
schwierig mit Essensanalogien. Ja, aber das genau.
Du meintest ja, es geht um dieses Pattern.
Wir haben das selber auch noch nicht so häufig verwendet und
das wird auf jeden Fall Analogien geben, definitiv was
ich n bisschen ich sag mal missleading finde, ist der der
Name so Prototype, also so weiß nicht als ich auch das erste Mal
dieses Pattern gehört hab, dachte ich mir auch so
Prototypen also wofür soll das jetzt im Endeffekt sein?
Weißt du weil es ist ja. Es steckt jetzt nicht wirklich
dahinter, dass du irgendwie n Prototyp von etwas erschaffst,
sondern wie du schon meintest, es geht ja viel ums Klonen und
da würde ich auch gerne schon mal vielleicht ne kleine
Analogie geben, damit man sich das im groben erstmal schon mal
so n bisschen vorstellen kann und zwar also angenommen du hast
jetzt irgendwas, was vielleicht n bisschen komplexer ist.
Ne, nimm vielleicht jetzt mal irgendwie so n so n so n.
Wenn so n Formular ne und ne Menge drin steht, da musst du
ganz viele Sachen reinschreiben ne und ich sag jetzt zum
Beispiel Tino, du musst ja noch mal n Formular ausfüllen, das
ist jetzt wichtig für unseren Podcast hier ne und dann musst
du da reinschreiben OK Name alter Beruf und ne es gibt ja
Formulare keine und nimm n Formular vom Finanzamt oder so
ne dann ist sowieso Feierabend ne und du.
Und du hast jetzt irgendwie so n so n so n Blatt Papier ne oder
mehrere Zettel, die ich dir dann gebe und das musst du alles
ausfüllen und jetzt kommt zum Beispiel noch jemand anders und
der muss das auch machen. Ja dann wär es ja eigentlich
viel sinnvoller ja zum Beispiel zu sagen, OK du nimmst diesen
dieses. Blatt Papier.
Diese dieses. Formular ja, wo halt alles
schon, sag ich jetzt mal. Drin steht wie zum Beispiel
keine Ahnung. Ne, also alles die ganzen
Attribute sind schon hingeschrieben.
Du musst jetzt nicht noch mal hingehen und sagen ich nehm
jetzt n Blatt Papier und schreib jetzt noch mal diesen ganzen
Vordruck da auf und dann geb ich das erst weiter so und du kannst
einfach n Kopierer jagen, kannst den Vordruck sozusagen einmal
durchkopieren und dann gibt es halt weiter ne also das ist so
im groben und ganzen, du hast etwas ja und musst es aber nicht
noch mal komplett von der Pike auf neu machen, sondern kannst
bestimmte Dinge die du halt schon hast halt eben kopieren
und wiederverwenden so ne. Ja, das ist n ganz gutes
Beispiel, so aus der Realität. Was glaub ich jeder sich
vorstellen kann oder schon mal die Erfahrung gemacht hat etwas
zu kopieren, gerade so Blätter ist ja genau der Sinn, dass du
es nicht jedes Mal neu schreiben möchtest, sondern halt einfach
ne exakte Kopie davon erstellen möchtest.
Ja im Prinzip und dann trotzdem Eigenschaften dieses Blattes,
weil du meintest Attribute, also die Felder die du ausfüllen
kannst. Unterschiedlich ausfüllen kannst
dann auch noch, das ist n ganz wichtiger Punkt dabei, du
kopierst quasi sozusagen diesen Rohling und das ist der Prototyp
dahinter. Ja, also du hast n Prototyp von
diesem Vordruck, den kannst du kopieren und du kannst aber die
Eigenschaften die Echten des Objektes also auf dem Blatt
natürlich noch variieren, das heißt da steht dann nicht immer
der gleiche Name schon eingetragen drauf, sondern du
kannst halt bei dir schreibst du den Fabi rauf und ich schreib da
Tino rauf, zum Beispiel ne. Dann hab ich ne Kopie erzeugt,
aber ich kann es das Blatt unterschiedlich ausfüllen.
Du kannst theoretisch. Aber auch wenn du es jetzt noch
n bisschen weiter spinnst, auch sagen, OK, wenn du das jetzt am
heutigen Tag machst und das ist immer für den heutigen Tag,
kannst du theoretisch trotzdem aber auch n Attribut schon
eintragen, ne und mit kopieren wie zum Beispiel das Datum ne,
dass halt solche Sachen halt auch eben schon voreingetragen
hast, ne? Genau.
Also das ist dann halt im Prinzip, denn sag ich mal
Implementierungssache am Ende, wie man das machen möchte.
Du kannst ja auch sag ich mal die Werte übernehmen und.
Und sie aber trotzdem im Nachhinein noch ändern können.
Das werden wir gleich im technischen Teil mal so n
bisschen erläutern, was man dafür braucht um sowas zu
ermöglichen. Ich hab auch noch ne andere
Analogie gefunden bei der Recherche und die fand ich halt
extrem witzig und zwar sollte man sich da eine Schaffarm
vorstellen oder das fand ich halt extrem cool, weil ich mir
sofort dachte, OK ich bin jetzt so auf einer Farm und das sind
so ganz ganz viele Schafe. Und da war halt geschrieben, ich
glaube, das war ein Medium Artikel, also kann man auch
gerne mal recherchieren, der war ganz cool.
Stell dir vor, du hast so ein perfektes Schaf, ne und ein
Schaf hat ja Eigenschaften, das hat eine gewisse Größe,
vielleicht so eine gewisse Flauschigkeit ja, aber vor allem
auch Namen so und das Name ist ja schon sehr unique, sag ich
mal. Das heißt, das ist zum Beispiel
so ein Attribut, was du nicht übernehmen möchtest, sondern
abändern möchtest. Und jetzt stell dir vor, du hast
so ein Prototyp scharf, so scharf.
Ali Sheep nennen wir das jetzt mal, und das hat so ganz, ganz
viele Eigenschaften. Ja, und die sind gut, also es
ist n gutes Schaf, es ist n super Prototypen und davon
möchtest du jetzt einfach mehrere Schafe ableiten.
Und warum möchtest du denn jetzt quasi jedes Mal wieder n neues
Schaf sozusagen erstellen, wenn du doch dieses Schaf, diesen
Prototypen einfach mehrfach haben möchtest?
Ja, und dann klonst du das ich mein so scharfe Klonen OK, in
den letzten Jahren war oft n Thema, aber wir wir machen das
jetzt mal ganz abstrakt, ja. Und dann hat das Halt n anderen
Namen. Ja, dann hast du halt keine
Ahnung noch Toby allen und weiß ich wie sie alle heißen dann da
hast du so ganz viele Schafe, die quasi voneinander geklont
sind, aber doch ihre eigenen Eigenschaften noch haben.
Am Ende zum Beispiel den Namen und das kannst du natürlich mit
allen Schafen machen ne, also du hast n großes Schaf was du
klonst. Du hast n graues Schaf, du hast
n Vampirschaf keine Ahnung was es auch immer für Schafe gibt,
ja. Und du kannst ja dann im Prinzip
von jedem Schaf Klone erzeugen, wenn du das möchtest.
Oder jetzt mal allgemeiner von der Analogie weg.
Du hast Formulare gesagt, Formulare ist n gutes Beispiel,
gehen wir. Noch mal in die Richtung UI,
wenn du Komponenten hast, kannst du auch Klone erzeugen, wenn du
sagst ich hab ne richtig coole UI Komponente und ich möchte die
genauso wieder haben und ich möchte nicht die grundlegend
noch mal neu aufbauen, dann kann ich das auch verwenden.
Das Pattern das ist n super Beispiel dafür oder?
N anderes Beispiel, wo es bei mir auch so Klick gemacht hat im
Sinne von weil ich meinte das werden wir in Twitch vielleicht
mal gebrauchen, weil wir entwickeln ja für unsere
Programmierwettbewerbe immer kleine Spiele.
Ja, also unsere Programmierwettbewerbe basieren
ja meistens auf Spiele, dass man n bot dafür schreibt und dieses
Pattern macht halt total Sinn, wenn du zum Beispiel n Spiel
hast, wo es ganz ganz viele Gegner gibt.
Du hast so Gegnertypen, ja, das ist so der Prototyp und davon
möchte ich aber jetzt ganz ganz viele erzeugen.
Da muss ich ja nicht jedes Mal neu definieren, wie genau dieser
Gegner aussieht. Ich mein, da muss man also ich
denk da zum Beispiel sofort so an Tower Defence Spiele.
Ja. Ist bestimmt n Begriff bei dem
ein oder anderen. Da hast du ja da kommen ja
irgendwann. Massen an Gegnern vom gleichen
Typ auf dich zu und da würde es Sinn machen, dass du sagst, komm
erzeug n Klon noch n Klon noch n Klon, noch n Klon und so weiter
und dann kommen halt die 5 Gegnertypen da von dem einen Typ
allein angerannt sag ich mal ja. Ich muss da also das.
Sind so Beispiele wo ich. Muss da mal relativ schnell
irgendwie oder was mir als erstes bei Gaming und dem
Prototype Pattern eingefallen ist.
Ich weiß nicht ob du das kennst. Bestimmt, wenn du jetzt
irgendwie so Gegnertypen hast und du machst jetzt zum Beispiel
ein Blatt davon. Ja, und manchmal gibt es ja so
in so spielen so Gegner, die sich dann so aufteilen.
Ne, also du machst quasi einen Gegner platt und dann kommt der
irgendwie, also der ist dann hinüber und dann kommen
sozusagen spawnen auf einmal aus diesem Gegner, den du platt
gemacht hast. Noch mal 3 von diesen Gegnern,
aber kleiner ne so und dann hast du ja im Endeffekt auch so ne
Art nutz könntest du ja hier an der Stelle auch so ne Art
prototypepad da benutzen, weil du sagst du der eine Gegner der
verschwindet sozusagen aber du. Klonst quasi noch mal 3 davon,
aber mit zum Beispiel dem Attribut.
Die Größe ist nur 0,5 davon und der Angriff von dem Gegner ist
aber jetzt auch nur noch n Drittel davon ne oder was auch
immer und so weiter dass du halt genau diesen Gegner noch mal
nimmst. Aber halt eben also du klonst
die Attribute. Nimmst das noch mal und
veränderst vielleicht n bisschen ne, also dass vielleicht die
Lebenspunkte sind n bisschen weniger.
Der Angriff ist n bisschen weniger und die Größe ist n
bisschen weniger, aber prinzipiell ist es immer noch
sozusagen n ursprungsklon ne von also oder n Klon von dem
ursprungsgegner sag ich genau. Du hast halt im Prinzip die
gleiche Ausgangsbasis, ne wie gesagt, also egal wieviel
Attribute das am Ende sind, die man da noch verändern kann oder
personalisieren kann, nenn ich es mal ja.
Wie zum Beispiel den Namen auch. Einfach jetzt bei dem
Schafbeispiel ne, das ist halt n ganz essentieller Punkt, dass du
diese Möglichkeit hast. Und ich find es gut, wenn wir
bei dem Thema sind, dann lass uns doch mal so technisch da
drauf gucken. Also ich glaube man kann sich
jetzt ganz gut vorstellen, was dieses Pattern bezweckt und was
der Vorteil dabei ist. Aber wie kann man das denn jetzt
als Designpattern, wie sieht das Designpattern dahinter aus, wie
kann man das technisch umsetzen? Und wieso?
Oft sind wir da wieder in der Objektorientierung unterwegs,
wie bei den bisherigen Pattern auch und im Prinzip startet
alles wieder damit, dass du sagst, OK, ich erzeuge mir
erstmal ein Interface Mhm oder eine Basisklasse, aber gehen wir
mal von dem Interface aus und dieses Interface muss im Prinzip
eine clone Methode beinhalten. Ja.
Ja, also du kannst auch natürlich noch mehr reinpacken,
wenn du jetzt zum Beispiel sagst, nee, aber über das
Interface möchte ich auch definieren, dass ich Attribute
ändern kann zum Beispiel, oder also, dass du das Fest
vorschreiben möchtest. Wie auch immer, das ist halt
nachher die die Implementierungsfreiheit was
will ich genau alles festschreiben, aber fangen wir
ganz simpel an und sagen, es gibt ne clone Methode, die muss
implementiert werden, wenn ich beispielsweise meine Klasse
scharf klonen möchte, dann. Muss ich sagen, diese klasse
Schaf implementiert dieses Interface und muss damit ja ne
clone Methode bereitstellen. Mhm, das ist ja der Sinn erstmal
dahinter, weil dann zwingst du quasi den Entwickler drüber sich
darüber Gedanken zu machen, wie muss denn ne clone Methode
aussehen um ein exakte Kopie des Schafes zu erstellen sozusagen?
Also du kannst ja rein theoretisch, kannst ja auch,
also jetzt muss ja nicht clone heißen, ne, aber es macht in dem
Fall natürlich Sinn. Ist so, dass es Clone heißt,
aber kann es natürlich auch anders benennen.
Ne, so wie du wie du es willst rein.
Theoretisch so n bisschen Best Practice, sag ich mal genau oder
so so standardmäßig vom Design Pattern.
Ja, aber prinzipiell ist es halt eigentlich nichts weiter als n
ganz normales Interface. Also wir hatten ja Interface
auch schon mal in einer Pattern Folge besprochen, was genau n
Interface ist. Im Endeffekt ist es jetzt nichts
anderes ne, also es ist sozusagen einfach n Konstrukt
wie man es baut, also so n Design pattern ne, aber du
kannst ja überall im Endeffekt wieder, also in vielen auch
Infekten. Repattern wird ja zum Beispiel
auch ein Interface verwendet und dann ist es halt im Endeffekt
nur die Frage, so wie genau implementierst du das, was sind
Best practices, dass es sozusagen diesen Prototype
Pattern von der Idee her matcht, ne, aber wenn du dir das so
vorstellst, hast du ja im Interface auch eigentlich nur am
Ende, wenn das Interface, ich nenn es jetzt mal Fahrzeug ist,
dann kann ja alles Mögliche rauskommen, also ein Fahrzeug
kann ja alles Mögliche sein, aber dieses Clone selber gibt am
Ende ja nur ein Fahrzeug zurück, beispielsweise was ja?
Dann am Ende in der konkreten Implementierung ja wiederum
wirklich NN Auto oder Motorrad oder sowas sein.
Kann ne mal als Beispiel. Das hat halt den Sinn und da ist
vielleicht jetzt der Punkt, wo man, gerade wenn man sich am,
also am Anfang befindet und sich mit solchen Pattern
auseinandersetzt, wo? Gerade bei mir auch früher sag
ich mal im Studium so n bisschen so n Knoten im Kopf entstanden
ist. Wichtig hierbei ist, warum macht
man das, weil es klingt jetzt vielleicht komisch, wir haben
gesagt, OK jetzt jetzt hab ich zum Beispiel geh ich ich nehm
noch mal das schafbeispiel ne ich hab jetzt n Schaf und das
implementiert jetzt mein Interface sozusagen dieses
Prototypen Interface ne sheep also einfach n sheep dann so ne
und ich hab jetzt mein Grey Sheep, mein graues Schaf
sozusagen und es ist natürlich komisch dann zu sagen ich ruf
Klon auf und Klon gibt natürlich.
Sheep dann zurück, so wie auch der das Interface ist.
Aber das hat den Grund, dass wenn ich es von außen verwende,
ja zum Beispiel auf meiner Sheep Farm möchte ich eigentlich gar
nicht wissen, was das genau für n Schaf ist.
Das ist für mich nur n Prototyp. Also es ist halt wirklich nur
ein Schaf was dieses Interface implementiert und mir ist zum
Beispiel nur wichtig, dass ich es klonen kann.
Ja, wenn man diese. Clone Funktion aufrufen kann.
Genau. Also nehmen wir mal an, du hast
jetzt zum Beispiel n Spiel und du bist auf einer Farm und hast
da so Schafe und du hattest ja von von einem Vampirschaf
geredet und wenn du jetzt zum Beispiel so als dein klassisch
klassisch als dein Character durch die Gegend läufst, ne und
du. Du sagst zum Beispiel, OK, du
haust. Kannst du mich auf n Schaf
hauen? Wie auch immer ne und so n
Vampirschaf beispielsweise das verdoppelt sich in der Nacht
oder keine Ahnung wird wird quasi wenn du es haust ne wenn
du es haust. Und wenn du aber jetzt zum
Beispiel am am Tag des Haust, dann verschwindet es, dann hast
du es wirklich sozusagen besiegt, aber wenn du es in der
Nacht machst verdoppelt es sich, dann willst du ja eigentlich
rein theoretisch gar nicht programmatisch sozusagen auf
programmierebene wissen, auf welches Schaf haust du da
gerade, sondern wenn du da. Drauf haust.
Dann soll es sich halt verdoppeln.
Ne so also geklont werden sozusagen ne, also da soll
sozusagen noch ein eine Instanz genau mit den gleichen
Attributen von diesem Schaf erstellt werden, ne und
demzufolge ist es halt was du meintest ne es es interessiert
dich nicht, ich fand das früher immer so schwierig zu sagen es
interessiert dich an der Stelle nicht was du da hast und Und
dann habe ich mich immer gefragt.
Ich verstehe, also weißt du so früher so im Studium, dachte ich
immer so, wieso sollte mich das nicht interessieren, ich weiß
doch aber eigentlich immer genau was ich habe, ne, aber wenn du
jetzt zum Beispiel wirklich zur Laufzeit bei so einem Spiel.
Irgendeinen Typen vor dir hast, dann weißt du das zwar als
Spieler selber, das siehst du natürlich, aber der Algorithmus
ja, also der der Code, der dann gerade da an dieser Stelle ist,
der weiß es ja nicht unbedingt, der denkt sich so k.
Ich hab hier ein Objekt und das ist irgendwie n Schaf und wenn
das passiert, dann muss ich halt n Copy aufrufen so ne und dann
muss das Halt funktionieren oder klonen in dem Fall sorry.
Ja, also es ist halt genau dieses Konzept der Entkopplung.
Ne, also dass du quasi die Aufrufe und die Logik davon
entkoppelst von der eigentlichen Erstellung und von dem Objekt
selbst. Und das ist am Anfang halt immer
so. N kleiner Knoten im Kopf muss
ich wirklich sagen, aber genau der Sinn steckt halt dahinter.
Ne, dass du das Entkoppelst, weil es dich nicht interessieren
muss. Ja, das ist halt wichtig.
Es musst, du musst nicht das wissen da drüber haben, um es
verwenden zu können. Ich fand deine Formularidee als
Beispiel ganz cool und noch so ne weitere Analogie, die glaub
ich auch jeder schon mal verwendet hat, so so gerade in
der Schulzeit so wenn du mit powerpoint so Vorträge gemacht
hast, ne und so n Slide kopieren ist am Ende, wie auch immer es
implementiert ist, aber vom Grundgedanken dahinter, ja es
ist auch nichts anderes, du hast so n Slide.
Zum Beispiel mit so einem fertigen Design, ne, also so n
keine Ahnung, so n Header n Footer sieht richtig schön aus,
hast dir so richtig Mühe gegeben und dann kopierst du das erstmal
und tauscht dann quasi den Content sozusagen aus und das
ist ja im Prinzip auch wieder so n Anwendungsfall am Ende um da
noch mal so n weiteres Beispiel zu geben, die Frage ist nur wann
macht es Sinn? Wir haben ja gesagt, zum
Beispiel bei dem Kopieren der Blätter.
Absolut sinnvoll, macht gar keinen Sinn, das immer neu zu
schreiben, ja, oder bei dem bei den Slides jetzt oder bei
unserer Schafsfarm ja, da kann man vielleicht noch
argumentieren, ah nee, ist vielleicht doch besser, jedes
Schaf individuell zu machen oder so oder bei den Gegnertypen ja,
aber wäre in Spielen halt auch n Anwendungsfall, wie könnte man
das mal so ganz allgemein runterbrechen, was sagst du aus
deiner Sicht? Wann ist dieses Pattern
geeignet? Ja, also ich würde schon sagen,
im Endeffekt, wenn du jetzt also grundprämisse würde ich sagen,
ist wenn du ein Objekt hast, was vielleicht unglaublich viele
Attribute hat, ne, also wenn du jetzt zum Beispiel sagst, die
Erzeugung von so einem Objekt ist relativ komplex, ist relativ
teuer in Anführungsstrichen. Weil im Endeffekt ist es ja so,
dass du, ich hatte mich zum Beispiel auch mal gefragt, OK,
du hast jetzt entweder n du machst n Copy ne beispielsweise
und in diesem Copy passiert ja an sich eigentlich under The
Hood auch nichts anderes, als dass du sagst, du Erzeugst mit
einem New irgendwie n konstruktor du, du nimmst
irgendwie dieses Objekt und machst damit irgendwas.
Könntest du zum Beispiel tun, ne, ist ja ne Möglichkeit, aber
was du halt. Also das wäre ja im Endeffekt
so. Kannst ja sagen, ja OK, machst n
Copy und n New oder du machst n New mit den Attributen und am
Ende ist es halt irgendwie das gleiche.
Also wie du jetzt dieses Copy ne und auf der einen Seite hatten
wir gesagt OK wir haben halt eben diese diese Art von von
diesem Interface was man dann halt eben ne wo man das gut
gekapselt hat am Ende und nicht wissen muss was es ist.
Aber und jetzt find ich das das kommt noch n top wenn du jetzt
zum Beispiel weil ich ja auch gesagt hab teuer ne.
Wenn du jetzt zum Beispiel n Konstruktor hast oder so ne und
und da passieren viele Initialisierungsdinge ne, also
sagen wir mal du willst n bestimmtes Attribut erstellen,
musst aber erstmal n paar Berechnungen anstellen um halt
eben wirklich den richtigen Wert für dieses Attribut zu bekommen,
dann musst du diese ganzen Berechnungen, die du für dieses
entsprechende Attribut brauchst, halt nicht mehr unbedingt
berechnen, weil du zum Beispiel weißt, OK, dieses Attribut
übernehme ich einfach von. Dem Prototypen ne, also von dem
was ich vorher schon hatte und kann es einfach klonen dann und
muss halt nicht extra noch diesen ganzen Overhead sozusagen
machen. Ne und das ist dann finde ich
meiner Meinung nach n großer Punkt der einem sagt da macht es
irgendwie Sinn weißt. Du ja.
Und im Umkehrschluss ist das genau, wenn genau das Gegenteil
der Fall ist, auch schon der Grund, wann es ungeeignet ist.
Wenn ich jetzt zum Beispiel sehr simple Objekte hab, ne mit einem
Parameter zum Beispiel die wirklich.
Sich kaum unterscheiden, außer auf abgesehen von einem Attribut
zum Beispiel. Ja dann habe ich halt nicht
wirklich einen Vorteil gegenüber der Instanziierung durch New
beispielsweise, ja weißt. Du, das ist ein wichtig.
Neues Objekt anlegen? Was denn?
Ich finde es immer schwierig, dass meistens ja genau solche
bei. Also wenn du jetzt ein Beispiel
hast, ne und jemand erklärt das daran, dann finde ich macht es
total Sinn das einem kleinen Beispiel zu erklären und zu
sagen Na ja guck mal, aber so sieht es ungefähr aus.
Und dann hast du n kleines Beispiel, was übersichtlich ist,
woran du verstehst. Und.
Dann kommt aber auf der anderen Seite wieder so.
Ja, aber mach das nicht bei kleinen Sachen, mach das nicht,
wenn der Konstruktor einfach ist und dann.
Also für mich war das auch manchmal so früher als ich mir
dachte, so Alter hä, warum nimmst du denn dieses Beispiel
dafür? Ne, wenn es doch sogar nicht
dafür geeignet ist? Ne, aber es ist halt.
Aber da ist halt wie gesagt, das was hast du gesagt Finanzamt
Formular n gutes Beispiel weil das willst du halt nicht jedes
Mal neu schreiben, richtig ja aber genau das ist halt der
Grund der wenn es ungeeignet ist wenn es halt einfach zu simpel
ist oder es kann komplex sein aber es gibt einfach keine
einheitliche Modellierung die dahinter steckt also.
Es. Gibt quasi nicht keine klare
Struktur, die ich ableiten und wiederverwenden möchte
sozusagen. Also es macht einfach keinen
Sinn, einen Klon zu erzeugen. Ja, also wenn ich sehr, sehr
dynamische Objekte hab, wo keine Grundmodellierung dahinter
steckt, wie beispielsweise wir ja gesagt haben, Gegnertypen,
wenn ich mehrere davon haben möchte, macht das absolut Sinn
die zu klonen. Wenn ich aber jetzt keine
Ahnung, jeder ist total dynamisch, ja, also irgendwie.
Weiß ich nicht. Also in den Grundeigenschaften
völlig verschieden, dann brauch ich da nichts klonen, wenn ich
danach eh wieder alles ummodelliere sozusagen.
Das macht dann halt gar keinen Sinn, ja.
Richtig. Und ja, das sind eigentlich
wirklich die Kernpunkte, wo man entscheiden muss.
Macht dieses Pattern für mich jetzt Sinn oder nicht genau das
daran quasi festzumachen, eine Sache, die ich aber mit dir
besprechen möchte, weil das ist n Stolperstein.
Der hat es in sich und da wird jeder mal drüber stolpern.
Weil aber auch so im Sinne von, du findest dann irgendwann den
Fehler und denkst dir, ah ja klar, verdammt ist mir schon so
oft passiert und zwar möchte ich über diese Copy falle über das
Problem mit dir sprechen und zwar den Unterschied zwischen
einem Cello und einem deep Copy Entschuldigung Copy ja also
Cello oder deep Copy so. Ja, wir hatten ja auch bei der
Reihe auch gesagt, dass wir ja auch immer gucken wollen, wann
lohnt es sich und wann lohnt es sich nicht oder vielleicht auch
was für Gemeinheiten. Gibt es da vielleicht ne oder
was für Begrenzungen oder wo man halt drauf achten muss und das
ist auf jeden Fall n guter n guter Punkt, was ist denn jetzt
n? Also weil du jetzt gesagt hast
Shadow und deep Copy ne, was ist denn das erstmal grob, dass wir
einmal auf n ja. Also im Prinzip kann man das.
Also ich stell mir das so vor beziehungsweise wenn ich jetzt
Anwender bin ne. Also ich hab jetzt quasi
beziehungsweise der Entwickler hat das Prototype Pattern
verwendet und ich habe jetzt Prototypen die ich kopieren kann
ne und ich rufe jetzt einfach die copy Funktion auf und ich
denk mir so er ist ja sicher das ist ja ne copy Funktion ich
krieg jetzt ne komplette Kopie von dem Objekt ich arbeite mit
dem beiden Ich rufe Funktionen auf auf dem einen Mal auf dem
anderen und hab auf einmal so komische Side Effects wo ich mir
denke hä? Warte, warte mal, warte mal.
Ich hab ich hab jetzt irgendwie scharf 1 hab ich jetzt irgendwie
n Halstuch vor fascal ich denk mir jetzt gerade irgendwas aus
und scharf zum Ei hat auf einmal auch n Halstuch um was ist da
los? Beides schon das scharf.
Ja, so weißt du und du denkst dir so hä, ich hab ne Änderung
an scharf 1 gemacht. Und scharf 2 ist auch davon
betroffen. Das will ich doch gar nicht.
Es sind doch Kopien. Ja, es ist eine Kopie von scharf
1, aber sie sind doch danach völlig unabhängig voneinander
und genau das ist der Knackpunkt, das zu erreichen ist
halt nicht so trivial. Und da kommt jetzt das Problem,
der Unterschied Cello und deep Copy und zwar wenn ich eine
Kopie mache ja und standardmäßig ist das immer ein Cello Copy,
das heißt ich kopiere einfach mein Objekt scharf.
Und das Schaf hat aber Attribute, die wiederum Objekte
sind ja, wie beispielsweise Listen, ja ja, Listen sind gute
Beispiele. So, dann kopiere ich zwar das
Schaf auch mit der Liste, aber nur die Referenz auf die Liste,
das heißt unter der Haube. Da hab ich jetzt 2 Schafe, die
auf die gleiche Liste verweisen und das ist n Stolperstein.
Da muss man das auch von Sprache zu Sprache muss man halt gucken,
ja wie das zu implementieren ist.
Aber das verbirgt sich halt hinter einem Cello, also
wirklich so n so n oberflächlicher Copy ne ganz
gute Analogie um das mal zu verstehen, ich hab n Notizbuch.
Ja, und ich guck mir das Notizbuch an, wenn es
geschlossen ist. Da sind jetzt die Seiten drin
beschrieben. Ich hab draußen quasi mein mein
mein Umschlag, sag ich mal so, ja, und ich kopiere das, dann
hab ich jetzt zweimal dieses Notizbuch, aber eigentlich hab
ich es nur oberflächlich kopiert, das heißt die Seiten da
drin sind gleich, es sind die gleichen Seiten sozusagen.
Ja, und wenn ich jetzt auf der ersten Seite ne Zeile
durchstreiche, verweist das zweite Notizbuch genauso auf
diese Zeile und es wird automatisch damit
durchgestrichen. Das sind so Zaubernotizbücher
weißt du, ganz klar. Und das muss man sich halt so,
so physisch dahinter vorstellen, dass ich halt die Seiten sind,
die gleichen. Ich habe nur n Notizbuch
erzeugt, wo quasi die gleichen Seiten drin abgebildet sind,
aber eigentlich hab ich nur von außen ne wirkliche Kopie erzeugt
und jetzt das ist deep Copy, ja musst du dir vorstellen, dass
ich jetzt sage, diese Liste die ich hab da drin zum Beispiel die
Seiten, die kopier ich jetzt wirklich, also ich erzeuge ne
neue Liste. Die ich in meine Kopie gebe,
gerne mit dem Inhalt der Seiten. Ich soll ja nicht leer sein, ich
möchte ja auch den Inhalt haben. Ja, also ich nehme quasi die
erste Liste und erzeugt daraus ne komplett neue mit dem
gleichen Inhalt und dann habe ich wirklich 2 Notizbücher und
wenn ich jetzt bei dem ersten was ändere ist das zweite
Unbetroffen, weil die sich keine nicht mehr die gleichen Seiten
teilen sozusagen. Ja, ja, wenn du das jetzt so n
bisschen auf auch das ganze Computerspiel Gaming münzt.
Wo wir auch meinten, dass das auch sehr sinnvoll zum Beispiel
ist, auch als Anwendung. Und du hast jetzt beispielsweise
NN Gegnertypen, den du kopierst und dieser Gegnertyp hat
wiederum ne, um das jetzt noch mal n bisschen abzuwandeln, hat
zum Beispiel n Objekt wo irgend so n Status drin ist.
Ne wie zum Beispiel irgendwie das Leben, der Zustand, ob er
gerade irgendwie weiß, nicht sitzt oder kämpft oder was auch
immer und du kopierst es und du erzeugst ganz viele Gegner
davon. Und dann haust du zum Beispiel
einen Gegner an und dadurch, dass es ja sozusagen dieser
Status mit dem Leben da drin beispielsweise ne nur ne flache
Kopie, also ne Shadow Kopie ist, würden ja alle Gegner sozusagen
leben verlieren. Ne, so als Beispiel jetzt
gemünzt auf. Also ich find im Gaming ist das
halt auch ganz gut. Man kann sich das so vorstellen.
Ich hab zwar ganz ganz viele Kopien erzeugt, aber wenn es n
Cello Copy war, dann haben die quasi alle das gleiche
Gedächtnis, sozusagen ja also es es ist kein wirkliche, kein
wirkliches Individuum, was sozusagen seine eigenen
Erfahrungen, seine eigene Lebensanzeige oder irgendwas
hat, sondern unter der Haube sind sie alle miteinander
verbunden sozusagen. Das ist eigentlich auch n ganz
cooles Beispiel und ich glaube jedem, der jetzt das hört und
drüber nachdenkt, ist klar was für n Bugpotenzial das Ganze hat
und wie versteckt das vor allem auch sein kann.
Ja und deswegen da Leute wenn ihr sowas verwendet also das
Prototype Pattern liebe Zuhörer liebe Zuhörer immer drauf achten
wie diese copy Methode implementiert ist, ob es sich
wirklich um ein ne saubere Kopie handelt oder ob ich mir da
Probleme mit einhandel. Ja, also da kann man auf jeden
Fall bei dem. Problem mit diesem, mit dieser
Copyfalle was du meintest kann man ja auf jeden Fall direkt,
wenn man dieses Pattern nutzt oder wenn sowas auftritt.
Da muss man eigentlich direkt dran denken, Oh das ist jetzt
zum Beispiel wirklich ne echte Kopie oder nur ne Referenz ne
also ja das hatten wir beispielsweise auch beim beim
Flappy Buddy ne, da hatten ja zum Beispiel Gegnertypen so ne
bestimmte. So bestimmte Arten, wie Sie
geflogen sind, ne zum Beispiel der Rabe hatte so ne Sinuskurve
und am Anfang als wir es implementiert haben, war es
beispielsweise auch erstmal so, dass die Kurve, die der Rabe
geflogen ist, alle Raben sind synchron geflogen, ne bevor es
dann quasi und. Und das ist ja olympisch.
Also das ist ja nichts Neues. Ja, synchron fliegen von Raben.
Richtig, aber das ist halt so das Ding, dass man da eigentlich
dann noch relativ schnell drauf kommt und sagt, OK, hier muss
ich irgendwo ne Referenz übergeben haben, ne und das war
dann im Endeffekt die. Sag ich mal das die wie diese
Bewegung ist. Ne und die war dann halt überall
gleich und hat immer den gleichen Wert für alle Raben
gesetzt und dann musste man halt da kommt man halt eigentlich
relativ schnell drauf, dass man sagt, OK irgendwo müssen wir
wahrscheinlich ne echte Kopie erzeugen und nicht einfach nur
ne Referenz übergeben ne so. Genau.
Ja, das ist eigentlich auch im Großen und Ganzen das Pattern.
Es ist nicht so komplex, hat aber sag ich mal seine Tücken,
wie gerade. Angesprochen und vor allem aber
auch seine Daseinsberechtigung. Und ich denke Fabi im nächsten
Game könnte ich mir vorstellen, dass wir sowas mal gebrauchen
könnten. Ja, je nachdem wie das Game dann
aussieht und dann werden wir da auch noch mal explizit drauf
eingehen, das mal wirklich so umsetzen und mal den Mehrwert
draus ziehen, aber Mehrwert ist n gutes Stichwort, lass uns noch
mal jetzt als Fazit am Ende der Folge so als Take Home Message
noch mal kurz vor und Nachteile des gesamten Patterns
zusammenfassen. Ich fang mal an, ich hau mal so
n erstes Ding rein was natürlich, und das ist ganz oft
bei Pattern, das haben wir anfangs gesagt, immer n Vorteil
ist, dass ich halt kein Wissen mehr über die konkrete Klasse
brauche ne ich entkoppel das halt die Anwendung von der
eigentlichen Implementierung, das heißt ich definiere nur über
das Interface wie das ganze aussehen soll.
Ich hab ne Klonmethode dann zum Beispiel und dann kann ich halt
einfach von irgendeinem Objekt was das anbietet oder
implementiert Klone erzeugen. Ja, und es interessiert mich
nicht, wie das passiert, sondern ich will einfach nur, dass es
passiert, sozusagen. Und das ist natürlich, Stichwort
Wiederverwendbarkeit, ja saubere Entkopplung, das ist halt n sehr
flexibles Konzept, was wirklich seine Vorteile mit sich bringt.
Ja, was natürlich Nachteile sind, das hatten wir ja gerade
schon beschrieben, das ist ja die Cellocopy und du hast
natürlich logischerweise auch mehr.
Ich nenn es jetzt mal boilerplate Code.
Gerade wenn du jetzt zum Beispiel wenig komplexe Klassen
hast, weil du ja im Endeffekt anstatt einfach nur n
konstruktor zu haben, wo du irgendwas übergibst, hast du ja
noch n Interface noch mit dazu. Mindestens und ja.
Wie gesagt, es kann halt manchmal auch tricky sein, dann
eben diese deep Copy selbst zu bauen beziehungsweise dann auch
wirklich darauf zu achten, dass sie halt eben wirklich ne deep
Copy ist. Wenn man dann ne deep copy
braucht, ne. Ja.
Also man kann sich das mal vorstellen.
Nur mal so als Gedankenexperiment, wenn ich
jetzt Objekte hab, ja die wiederum als member variablen
Objekte haben die Member variablen Objekte haben wiederum
Referenzen und so weiter das kann halt wirklich deswegen auch
deep Copy sich richtig tief verschachteln und dann auf
oberster Ebene ne echte Deep Copy zu erzeugen kann richtig
richtig. Komplex wären, um es nett
auszudrücken. Und deswegen ist das wirklich
nachteilig. Ich find es gut, dass du es auch
noch mal gesagt hast, weil das ist wirklich dann der Painpoint,
der entstehen kann, ganz klar. Ja, was ich noch mit also so ein
bisschen zusammenfassend auch noch mal sagen würdest.
Wir hatten ja jetzt zum Beispiel auch über in in den vorherigen
Folgen sowas wie über Bilder Pattern geredeten Factory
Pattern, das sind ja auch alles Pattern, die man auch zum
Beispiel super einsetzen kann, rein theoretisch auch in im im
Gaming Bereich ne, also wenn man das jetzt noch mal nehmen und
wenn du jetzt zum Beispiel sagst Fabian, aber jetzt mal ohne
Scheiß, warum ist es denn zum Beispiel, warum macht man das
Ganze denn nicht jetzt einfach mit einem Factory Pattern?
Ne so kann man sich hinstellen und sagen ja klar du wirst es
auch hinkriegen mit anderen Pattern ungefähr das gleiche.
Hinzukriegen ne, du kannst theoretisch ja auch mehrere
Pattern sag ich mal mischen und irgendwie ne Art Bilder mit in
dieses Copy mit reinbauen, wenn man da irgendwie Bock drauf hat
kriegt man irgendwie hin. Aber es hat natürlich alles noch
mal um das vielleicht noch mal kurz zu differenzieren, einfach
unterschiedliche Anwendungsfälle.
Ne ne Factory ist im Endeffekt dafür da, dass du sagst ich weiß
nicht genau was ich bauen muss, das entscheide ich aber dann,
wenn es soweit ist. So nach dem Motto dafür wäre
dann ne Factory da. Bei einem Builder ist es so, ich
weiß zwar was ich bauen will ne, aber es ist relativ kompliziert
und man muss es irgendwie konfigurieren.
Und beim Prototype ist es halt eher so, dass man sagt, OK, ich
hab schon n ziemlich gutes Beispiel davon und ich brauch es
einfach nur kopieren, so salopp gesagt ne und an der Stelle
würde ich einfach noch mal sagen, Liebe zürer lieber zürer,
wenn du jetzt zum Beispiel sagst, Ey wart mal Factory
Bildern, hab ich noch gar nicht gehört, will ich mehr drüber
erfahren, haben wir schon 2 folgen drüber gemacht, also
einfach mal da reinhören wenn es interessiert.
Ist auch n guter Punkt, weil. Gerade dieses mehr, also Design
Pattern ist ja nicht so pro pro Software Projekt.
Ein Design Pattern, mehr nicht, sondern es ist ja wirklich
Anwendungsfall abhängig. Ich finde es ja auch gut zu
sagen, also dass du es gerade noch mal zusammengefasst hast,
weil wenn du jetzt wirklich einen sehr komplexen Prototyp
hast, warum soll da nicht ein Bilder Pattern dahinter stecken,
dass du das aufbauen kannst? Beispielsweise und wenn du es
aufgebaut hast, kannst du dann das Prototype Pattern verwenden
um wieder Kopien davon zu erzeugen?
Das ist dir ja völlig freigestellt, wichtig ist mit
einem gesunden Verstand und. Das bringt auch irgendwann, sag
ich mal, die Erfahrung, weil wir hatten es glaub ich schon oft
gesagt, gerade am Anfang im Studium hast du n Pattern
gelernt und hast es erst mal überall verwendet, weil du bist
ja jetzt in der Lage dieses Pattern zu bauen und bist.
Hammer, jetzt ja, du hast es drauf jetzt und deswegen ich hab
keine Ahnung wie oft ich anfangs auch selbst singelten oder so.
Ja wo ich das gelernt hab wie du meintest ey ich kann das global
machen, dann nimmst du das halt erstmal und die Erfahrung muss
man sammeln um auch die Nachteile da drin zu sehen und
genauso wie jedes Pattern seinen Nachteil hat wird man diese dann
auch erfahren, beispielsweise hier das Deep Kopie Problem ja
ne. Und deswegen einfach
ausprobieren und das ganze Mal durchspielen.
Ja, also den Aufruf machen wir glaub ich immer am Ende der
Folge zu sagen Codet das doch mal runter codet doch zum
Beispiel mal die kleine Schäfchenfarm lasst sie uns
zukommen, wir würden Sie gerne sehen, ich find das Beispiel
ziemlich witzig ansonsten ja kann man sagen Copy Paste 2.0
haben wir durchgesprochen heute nur das ganze Halt mit wie
gesagt Verantwortung tragen, es gibt halt Sachen zu beachten.
Und ansonsten interessiert uns liebe, zuhören, liebe Zuhörer,
natürlich hast du das Pattern schon mal verwendet oder war es
dir komplett neu? Wie sind deine Erfahrungen
damit? Kennst du Anwendungsfälle, wo
das einfach absolut genial ist, sodass wir das Ganze auch mal
mit der Community teilen können? Schreib uns gerne die Mail, wie
immer in den Shownotes wir freuen uns über jede Nachricht,
vielen Dank dafür schon mal. Ansonsten findet ihr auch n
kleinen Spendenling. Wenn ihr sagt, Ey Mensch Leute,
der Podcast auch gerade die Reihe, die hat mir echt
geholfen. Ich würde euch gerne
unterstützen dann vielen vielen Dank für den Support der Link
wie gesagt in den Shownotes auch zu allen anderen Plattformen und
da bleibt mir jetzt nichts weiter zu sagen außer wir hören
uns alle beim nächsten Mal wieder ich wünsche euch ne
schöne Zeit bis dahin macht es gut eure Coding Buddies.
Gemeinsam besser.