Transkript: Python 3.9 und Design Patterns (Teil 1)
Vollständiges Transkript der Episode. Zeitstempel beziehen sich auf die Audiowiedergabe.
Ja, hallo liebe Hörerinnen und Hörer, willkommen beim Python Podcast, 25.
Episode.
Heute geht es um Patterns, Software-Patterns, Design-Patterns, Architektur-Patterns.
Und wir haben einen Gast dabei, der Antony.
Hallo.
Hallo mal wieder.
Hallo, ich bin der Dominik, Jochen ist auch da.
Hoi ho!
Wir sind im Wintergarten bzw.
Remote, wie es halt sich für die Pandemie so gehört.
Wir wollten noch sagen, wenn wir aufnehmen.
Heute ist der 20.
Oktober.
2020.
20, 20, 20.
Immer noch 2020.
Ja.
Es zieht sich ein bisschen, finde ich, in letzter Zeit.
Ich erinnere den XKCD, wo ein Zeitreiser nach 2020 kommt und fragt, welches Jahr es ist, und er sagt 2020.
Ja, aber das wie Fielte.
Ja.
Das wissen wir auch nicht so ganz genau.
Ja.
Ja.
Ja, vielleicht noch ein paar News aus der Szene vorweg.
Genau, ja, was haben wir denn an News so?
Am 5.
Oktober kam Python 390.
Oder war das am 6.?
Ich weiß gar nicht mehr genau.
Ich glaube an dem Montag irgendwie.
Ja.
Was released on Oktober 5th, okay.
Habt ihr alles schon geupdatet?
Nein.
Ich habe mich diesmal nicht getraut, weil letztes Mal mir bei 380 so ein paar Sachen wie Jupiter auseinandergeflogen sind.
Und ich diesmal darauf keine Lust hatte.
Ich glaube, ich habe es auch noch nicht bei uns in die Auswahl mit reingenommen, aber wir haben eh immer sozusagen das komplette Portfolio von allem verfügbar.
Ja, ich habe mir überlegt, wir machen das bei 1 dann, 391.
Ich bin tatsächlich schon quasi zumindest mit den privaten Sachen umgestiegen, aber ja, so, das wird natürlich noch ein bisschen brauchen, bis sich das komplett durchgesetzt hat, sodass man es halt auch verwenden kann.
Zum Beispiel Pandas gibt es halt noch keine Binaries und da ist das natürlich also ein bisschen hässlich, wenn man das irgendwie dann selber kompilieren muss.
Das heißt doch, im Bateau habe ich tatsächlich das in die in die Travis-Liste schon mit aufgenommen.
Da kam auch da kam auch jemand vorbei, der sich gleich irgendwie sofort beschwert hatte, dass es unter 3.9 nicht ging.
Weil irgendwas ist rausgeflogen.
Achso, die haben im Async irgendeine API, die deprecated war, jetzt tatsächlich gestrichen gehabt.
Ich glaube, die in 3.7 hatten sie irgendeine neue API, um alle Pending-Tasks abzufragen, eingeführt.
Und die, glaube ich, in irgendein Untermodul verschoben oder so, statt im direkten Async-Modul.
Das war was, da musste ich dann irgendwie daher.
Und in 3.9 war dann irgendwie die Abwärtskompatibilität von der API jetzt weg.
Da flog es dann auseinander.
Insofern?
Ja, ich hab's schon mal in der Hand gehabt, weil ich was.
Was gibt's denn Neues?
Ganz viele spannende Sachen.
Union Operators?
Was ist das?
Was macht man damit?
Ja, zum Beispiel Dictionaries zusammenschübbeln.
Ja, ja, ich glaube also wirklich mehr als das, was man vorher auch schon mit Tupple Unpacking machen konnte.
Also man schreibt halt irgendwie neuer Key, also neuer Value und dann sagt dann hinten der Sternstern irgendwie das andere dickt, was man merken will.
So, ich glaube, wenn man jetzt den Pipe-Operator verwendet, macht es so mehr oder weniger genau das gleiche.
Ja, aber warum passt das?
Also ich habe es nicht genau verstanden.
Ich finde es irgendwie, weiß nicht, das erste, was ich Python so richtig hässlich fand.
Naja, was fandst du hässlich?
Ja, diesen Operator, diesen Pipe-Operator da stehen zu haben auf einmal für so eine Operation.
Och, ich weiß nicht.
Ich meine, das halt wäre halt Mengenoperationsoperator an der Stelle.
Das ist halt ein Oder.
Das passt schon.
Das passt schon.
Das war halt vorher schon immer das Oder und wenn ich halt über die mengentheoretische Definition nachdenke, dann ist das halt genau das, was passiert, wenn ich halt die Oder-Verknüpfung von zwei Mengen irgendwie definieren möchte.
Oder gleich dieses Assignment irgendwie ist das komisch.
Naja, das ist halt so wie plusgleich oder mal gleich.
Das habe ich tatsächlich in Bateau benutzt oder gleich tatsächlich auch.
Bateau hat ja so eine komische Syntax, wo wir plusgleich benutzen.
Wo du irgendwie so einen Baum aufbaust mit Self plus gleich und dann den Kindknoten.
Und da gibt es nochmal ein Overloading für die Pipe, wo man dann sozusagen eine spezielle Form von Verkettung hat.
Insofern finde ich das ganz cool, dass die jetzt auch die Pipe genommen haben.
Da fühle ich mich in meiner Wahl von vor sechs Jahren bestätigt.
Ja.
Ja, also ich glaube, also so, was, es ist halt, es sieht halt, ich finde es schon besser aus, als wenn man jetzt immer mit den Sternen und Sternsteinen, da muss man mal so ein bisschen nachdenken, was denn jetzt, was man halt jetzt eigentlich genau machen wollte.
Das ist ein bisschen hübscher, aber ist jetzt keine so weltbewegende Änderung.
Ja, das ist echt hübscher.
Und es ist vor allem, es erzeugt halt ja ein neues Dikt.
Also ganz klassisch war ja immer das Thema, dass du Dikt-Update sagst.
Ja, und dann macht das was anderes, als man denkt.
Das modifiziert dein Original-Dikt und genau.
Ja.
Insofern ist es vielleicht ein bisschen eindeutiger, was es macht, ja.
Ja, also mein Lieblingsfeature tatsächlich, oder die Lieblingsneuerung, meine Lieblingsneuerung ist der Pack-Parser.
So ehrlich gesagt bin ich jetzt kein Experte für so Parser-Geschichten, aber ich fand das schon eigentlich ganz nett, was man damit dann eventuell alles dann zusätzlich so machen kann.
Also es hieß irgendwie so, ja, das macht dann irgendwie neue Sprachfeatures einfacher oder so.
Das stimmt nicht so ganz.
Also so wirklich viel einfacher wird dadurch nicht, aber es macht halt so ein paar Sachen, die bisher sehr hässlich waren.
Du musst uns dann hören nochmal kurz erklären, was überhaupt ein Pack-Parser ist, bitte.
Oh nein, das wollte ich eigentlich vermeiden.
Das kann ich ehrlich gesagt nicht wirklich.
Also es gibt halt diese Standard-Parser für so Programmiersprachen.
Also die meisten Programmiersprachen sind halt, oh, oh je, jetzt kommen auch mal, jetzt muss man sich tief in die Informatik hinabsteigen.
Da gibt es halt so, so Programmiersprachen sind meistens die Grammatiken dafür sind so kontextfreie Sprachen.
Also, oje.
Ja, ja, genau.
Ja, du musst halt.
Und sogar in bestimmter Form davon, ne, so Lalle 1-Grammatiken oder so, das ist halt Lallere 1, LLR1.
Lallere häftig ist.
Ja, also in dieser Form ist auch zum Beispiel immer die Java-Sprachspezifikation.
Also das Erste, was ich in, sollte man sich im Studium, also als ich mal angefangen habe, irgendwie, sollte man sich das mal kaufen.
Habe ich dann gemacht.
Fand ich sehr langweilig, ehrlich gesagt.
Das war ein sehr dickes Buch, in dem stand halt die komplette Sprache und halt Grammatik drin.
Und da dachte ich schon, sowas ist eine komische Abkürzung und das ist halt genau die, die halt beschreibt, ja, wie die Grammatik für diese Sprache aussieht.
Und wenn man das sozusagen in dieser Form notiert hat, dann kann man das in einen Parser-Generator werfen.
Der liest die Sprache und weiß, was der machen muss.
Der gibt dann einen Parser, der genau diese Sprache akzeptiert.
Und das sind dann so Dinge wie, damit habe ich auch, das hat man in letzter Zeit da wenig mit zu tun gehabt.
Früher ganz mehr.
Sowas wie Jack zum Beispiel gibt es da.
Ist auch so ein rekursives Akronym, Justin Nazareth Compiler, Compiler.
Dem kann man sowas vorwerfen und der spuckt dann halt ein Parser aus und da was gab es dann damit noch Lex und Bison und ja, ich weiß gar nicht mehr so genau.
Und genau, damit kann man Parser generieren und die akzeptieren dann solche Sprachen und die meisten Programmiersprachen sind halt so irgendwie diese Geschmacksrichtung von kontextfreier Sprache.
Und Python-Parser war halt so auch sowas.
Aber das Problem ist, es gibt halt so ein paar Features, die passen da nicht so richtig rein.
Oder ein paar Dinge in der Sprache, die funktionieren damit halt nicht so richtig.
Und deswegen gab es da sowieso schon immer so Ausnahmen.
Und deswegen ist es halt bisher so ein bisschen hässlich gewesen.
Also es gibt dann zum Beispiel, es gibt halt, jetzt ich kriege das auch nicht alles auf die Reihe, aber es ist, es gibt halt den, der Parser macht, nimmt halt sozusagen den Text, also irgendwie ein Python-Programm und gibt dann halt ein Abstract-Syntax-Tree aus.
Und der wird dann von dem Compiler verwandelt in Bytecode oder so und da wird dann halt irgendwie interpretiert.
Und das gibt dann halt so diverse Teile.
Und das Problem ist irgendwie, dass manche Sachen halt verteilt sind auf unterschiedliche Teile.
Also dass es halt nicht so ist, dass es, also bis, oder der Parser bisher, da bestimmte Sachen halt nicht so einfach damit parsbar waren.
Und der ist auch handgeschrieben, also dass halt irgendwie, wenn man sich das angucken will, gibt es ein Modul, das nennt sich AST.c oder so in Python-Source-Code, dass der alte Parser ein paar tausend Zeilen handgeschriebenes C ziemlich fies.
Also, genau.
Und der ist halt nicht automatisch generiert, was halt schon mal nicht so schön ist, weil das halt dazu führt, dass er nicht so richtig konsistent ist und so und sich manchmal komisch verhält.
Und das Problem eigentlich dabei ist, wenn man jetzt sozusagen, teilweise sind halt Sachen, ah, ich kriege das nicht mehr richtig auf die Reihe, aber es war irgendwie sowas, wenn man zum Beispiel rechts neben dem Gleichheitszeichen, weil das Gleichheitszeichen ist irgendwie ein Problem.
Und wenn man da mehrere Sachen stehen hat, also mehrere Dinge, die addiert werden oder so, dann muss das hinterher nochmal im Compiler umsortiert werden, weil der Parser noch nicht irgendwie ordentlich gemacht hat irgendwie.
Und das heißt, wenn man jetzt irgendwie so ein Problem hat, auch ein Syntaxproblem, Funktion A plus Funktion B rechts von einem Gleichheitszeichen, dann ist halt komplett unklar, wenn jetzt da irgendwo ein Syntaxfehler ist, wo der eigentlich passiert.
Weil das ja dann schon einem erst im Compiler irgendwie um die Ohren fliegt oder so.
Sodass halt der einem, halt sozusagen der Pythoninterpreter auch gar nicht sagen kann, wo der Syntaxfehler ist, was halt eventuell ein Problem sein könnte.
So, wenn man nicht mehr weiß, wo der Fehler ist, dann ist es halt schwer, den zu fixen.
Und das sind halt so Hässlichkeiten, sodass man halt, da diese, diese, diese Überprüfung, ist das jetzt korrekter Python-Code oder nicht, halt nicht an einer Stelle passiert, sondern halt über ganz viele Teile verteilt ist, ist das halt, sind manche Sachen halt einfach total hässlich.
Und ich habe da so ein Podcast-Podcast-Init, da waren die beiden, die dieses, die im Pack-Baser hauptsächlich gebaut haben jetzt in Python 3.9 zu Gast und haben da halt so ein bisschen was überzählt, was sie da gemacht haben.
Einer von denen meinte so, also was eine User-Anfrage war halt so, ah, warum können wir das in WIS-Kontext-Managern, so mit diesem WIS-Statement nicht einfach so machen wie bei Imports oder halt mit bei Strings, dass wir da Klammern drumrum machen und dann haben wir mehrzeilige Dinger, weil mehrzeilige WIS-Stats geht halt einfach nicht.
Und das hat er dann versucht umzusetzen im alten Parser und das ging halt überhaupt gar nicht.
Also er hat da irgendwie wohl eine Menge Sachen probiert und es ging einfach nicht.
Und er meinte so, ja, yes, jetzt geht es endlich.
Jetzt kann man das auch mit Klammern machen, das ist viel besser.
Voll gut.
Obwohl das wahrscheinlich nie irgendjemand verwenden will, wird wahrscheinlich, ne?
Aber ja.
Also, aber das, äh, ähm, was jetzt oft erzählt wird, ist es halt irgendwie, dass man damit besser neue Sprachfeatures umsetzen kann oder so.
Das ist eigentlich nicht unbedingt der Fall.
Es ist halt nur so, dass es jetzt konsistenter ist, dass der Faser automatisch generiert wird und ja, schneller?
Ja, nee, also ähnlich.
Er braucht sogar mehr RAM.
Ja, genau.
Also das war der Grund, warum man das früher nicht gemacht hat, weil man muss jetzt alle Tokens im Hauptsprecher halten und das war halt früher ein Problem.
Heute nicht mehr so, also genau, er braucht einfach mehr RAM.
Irgendwer hatte auch was erzählt von, dass sie jetzt per Default sagen, also mehr als eine Million Zeilen in einer Python-Datei wollen sie jetzt bitte nicht mehr sehen.
Ja.
Oh Mist, was mache ich denn jetzt?
Ja, genau.
Da habe ich die ganze Firma drauf aufgebaut.
Ja, also von der Performance her ist kein großer Unterschied, wohl von der Laufzeit und Hauptsprecher braucht es ein bisschen mehr.
Aber, ah, genau, das tolle Ding, was man eventuell jetzt damit machen kann, was sonst sehr schwer geworden wäre, ist, da gibt es auch ein Pap jetzt, weiß ich nicht welche Nummer, Pattern Matching.
Bin mal gespannt, ob das angenommen wird für Python 13, dass man halt so Lisp-Style-Makros hat, beziehungsweise halt in funktionalen Programmiersprachen ist das schon länger, oder das ist halt ja so eines der grundlegenden Geschichten.
Und ja, in Python ging das halt auch vor allen Dingen wegen dem Parser bisher nicht.
Und das geht dann eventuell.
Und wenn man das darin hat, ist es natürlich schon netter.
Also eines der zentralen Features von funktionalen Programmiersprachen auch mit drin.
Was sind denn Live-Like-Makro-Sprachen?
Ja, das müssen wir mal irgendwann machen, wenn wir irgendwie auch so ein bisschen so, ja, nochmal funktionale Programmiersprachen und was ist Pattern Matching und was sind Makros, da kann man das nochmal, aber ich glaube, das ist einfach so eine Produkte.
Okay, das verstehen wir jetzt eine folgende Folge.
Für die Leute, die gucken wollen, wer ist PEP 634.
Ah, 634, ah ja,
das ist ja auch eins, wo Guido jetzt selber wieder.
Guido hat ja mit beim Parser natürlich mit drin gesteckt.
Und das ist jetzt auch anscheinend eins einer Themen, wo er dran steckt.
Ja, also auf jeden Fall, das klingt irgendwie sehr vielversprechend.
Bin mal gespannt, was dabei so rauskommt.
Ja, ein Bug ist auch schon aufgefallen wohl.
Achso Match war, Match war, achso, ja vielleicht tatsächlich, das ist eine bessere Variante dessen, was sonst in anderen Sprachen das Case gewesen wäre.
Nur mal so als zur groben Einordnung.
Also mit dem Match geht es dann am Ende tatsächlich darum, die, wenn man sehr komplexe If-else-Zweige hat, dann kann man die damit ein bisschen hübscher abbilden.
Also substanziell hübscher.
Warum hatten wir das nicht Case genannt?
Das müsste ich jetzt nachlesen.
Also es macht schon, glaube ich, noch ein bisschen mehr.
Also ich meine, ja, naja.
Ach, keine Ahnung.
Genau, ein Bug gab es auch schon.
Da wird jetzt dann wahrscheinlich in 391 gefixt.
Und zwar, was der alte Parser konnte und was jetzt halt mit dem neuen nicht mehr geht, ist, wenn man Tuppel-Unpacking halt auch so Sternen irgendwas in with so Kontextmanagern verwendet, dann funktioniert das nicht.
Tja, aber es ist halt bisher niemandem aufgefallen, also so häufig scheint es nichts verwendet zu werden, aber das klappt schon irgendwie nicht.
Achso, das ist auch vielleicht ganz interessant.
Also das ist in den 3.9 sind beide Parser drin.
Man kann auch irgendwie per Kommandozeilen-Option sagen, minus X irgendwas, Old Parser oder so, verwende doch bitte den alten, wenn man irgendwie mit dem neuen Probleme hat.
Der neue ist defaultmäßig aktiv.
Und der alte ist aber halt noch drin.
Und ja, mit Python 3.10 wird es dann halt so sein, dann wird der alte Parser komplett rausfliegen und nur noch der neue drin sein.
Okay.
Was mit Tappel-Uppacking in Kontextmanagern?
Das habe ich jetzt nicht so ganz verstanden.
Warum geht das nicht?
Oder ging das vorher auch nicht?
Doch, das ging vorher schon.
Das hat bloß keiner gemacht.
Warum auch?
Aber ja, jetzt geht's nicht mehr.
Also warum will er das denn nicht machen?
Also ich meine, man, äh, hä?
Naja, also warum, also das ist halt, niemand versteht dann, was du tun willst, wahrscheinlich.
Ich überlege gerade, wie die genaue Syntax ist, was da kaputt geht.
Hast du den Bug irgendwo da?
Nee, momentan müsste ich auch gerade suchen.
Ich versuche so leise wie möglich zu tippen.
Warum nicht im Contact Manager einfach irgendein Tupel anpacken, was das doch durchaus okay?
Nee, nee, die Frage ist, ich meinst wahrscheinlich oben in der With-Expression-Angekehrung.
Ja, ja, in der Expression selber.
Also With und dann irgendwas mit Tuple-Unpacking machen.
Also ich sehe da echt keinen Anwendungsfall für.
Und es ist, glaube ich, also die haben da ja die komplette Standardbibliothek durchgejagt und noch viele PyPI-Pakete.
Und sie haben es nicht, also sowas, das ist nie aufgetreten.
Also das ist nicht so, dass das irgendwie dauernd gemacht wurde, sondern das hat bisher wohl noch nie jemand gemacht.
Quasi.
Also jedenfalls nicht in Code, der irgendwie häufiger verwendet worden wäre.
Also, ja.
Es war nur, das ist halt schon mal aufgefallen, dass es da einen Unterschied zwischen den beiden Parsern gab.
Ja.
Tja, was haben wir denn noch so?
Oh, hier.
Also was ich wirklich hübsch fand, war jetzt irgendwie nochmal explizit die String, Prefix, Suffix Removals.
Weil das ist einfach, das war seit langen Jahren einen L-Strip und einen A-Strip und da fallen Leute ja gern drauf rein.
Dass Leute gerne irgendwie sagen L-Strip oder Strip und dann irgendwie eine Zeichenkette.
Und sie denken, damit wird irgendwie, also wenn ich sage, Strip, A, B, C, also möchte ich immer, wenn ABC ganz links steht, das weggestrichen haben.
Aber das macht es ja nicht, sondern das macht ja Streich von links so lange alles weg, wie das, was links ein A, ein B oder ein C ist.
Das heißt, da kommen ganz lustige Dinge dann manchmal raus.
Und jetzt gibt es halt ein explizites Remove Prefix, Remove, Suffix und dann wäre das auch geklärt.
Ja, das ist schon hilfreich.
Ja, ansonsten Zeitzonen-Handling ist jetzt irgendwie mit drin.
Das habe ich noch nicht angeguckt, weil ich habe ich bin seit irgendwie 15 Jahren mit PyTZ unterwegs.
Und PyTZ hat halt den Vorteil, dass es unabhängig ist, ist es halt so ein Ding, die Zeitzonendatenbanken werden halt ständig aktualisiert und geändert und ich bin mir gerade nicht sicher, haben die da irgendwie die Datenbanken mit dabei oder ist
das eine API?
Genau, das ist halt auch der Grund, warum, also im Daytime-Standard, äh, im Modul der Standardbibliothek war das auch nie, waren diese Zeitzondatenbanken auch nie drin, obwohl aber eine API dafür, wie man da seine eigene Datenbank oder sein eigenes Objekt, das halt implementiert, Zeitzonenobjekt irgendwie reintun kann, weil sich die Leute gesagt haben, ah, Python-Release-Zyklus viel zu lang für diese Updates und dann wollen die Leute das mal selber machen.
Und dann haben es die Leute natürlich nicht selber gemacht, weil keiner Bock hatte, das zu machen.
Und ja, nee, wie es jetzt wohl ist, ist, dass
die System Time so im API dafür, um das reinzuziehen.
Und genau, auf Windows gibt es noch eine komische Geschichte.
Da gibt es dann ein First-Party-Package, was man dann noch installieren muss, TZ-Data oder sowas.
CZ-Data, ja.
Dann geht das da wohl irgendwie auch.
Aber genau, so ist das dann.
Ja, das ist so als Fallback gedacht, für wenn das andere nicht da ist.
Und die intern funktioniert das wohl mehr oder weniger genauso wie Date Util oder sagen wir so, das ist auch, also wie Date Util das macht, also ich glaube, das ist auch von dem Autor von Date Util irgendwie, meine ich jedenfalls gehört zu haben, dass der das, das von dem.
das ist.
Und es ist, es implementiert halt so die Kerngeschichten, aber viele von den Fancy Features von Date Util sind halt nicht drin, aber so die Kerndinge.
Ja.
Ja.
Noch was?
Noch irgendwas?
Naja gut, da gab es noch irgendwas mit Dekoraturen und Syntax, dass man, da konnte man früher immer nur, bis jetzt halt immer nur Funktionen verwenden und jetzt kann man halt auch irgendwie ein Dikt nehmen und dann eckige Klammern oder so.
Das ging vorher auch nicht so richtig.
Und das geht jetzt.
Ah, das wird wahrscheinlich auch kaum jemand machen, insofern.
Jawohl, da kann ich mir jetzt gab eher vorstellen noch.
Ja, dass man halt, man könnte sich vorstellen, man hatte irgendwie einen Dikt von Dekoratoren oder so, wo die Values halt irgendwie Funktionen sind und dann wählt man halt das Ding aus, was man halt und da hätte man halt bisher immer irgendwie eine extra Funktion haben müssen, die dann halt die richtige Funktion, innere Funktion auswählt und jetzt geht es halt direkt.
Ja, auch nicht so schlecht.
Es ist ja eine Frage von in solchen Momenten immer bei diesen syntaktischen Kleinheiten, dann kann man ja immer dieses berühmte Dokument des PHP A Fractal of Bad Design herausholen, dass du dich halt irgendwie darauf verlassen können möchtest, wenn gesagt wird, okay, hier hinter dem Ad kommt halt eine Expression, dann kann ich hier auch bitte alles machen, was eine Expression halt kann.
Und wenn das halt nicht geht, dann steht man immer traurig da und fragt sich, was soll denn der Quatsch eigentlich?
Insofern, ich finde das einfach, das ist halt so das Thema, wenn das auch gerade was ist, was der neue Parser vielleicht besser unterstützt, dann all for it.
Was ist PRP Affect of Bad Design?
Also, um nicht auf anderen Sprachen rumzuhauen, gibt es aber ein wirklich berühmtes Dokument zum Thema, warum PHP so ein massives Problem im Sprachdesign hat.
Und da gibt es in dieser Blogpost, der ist jetzt auch bestimmt schon zehn Jahre alt oder so.
2012.
Acht Jahre.
Und da geht es sozusagen darum, dass diese Herangehensweise des Sprachdesigns, und da ist Python ja schon lange ein Vorreiter gewesen, dass es halt eine explizite Sprachdefinition gibt, aus der dann halt das C-Python nur in Anführungszeichen die eine Implementation ist und es ist klar, es kann auch andere Implementationen geben.
Und hier nehme ich an mindestens ein Thema, wo allein von dieser syntaktischen Genauigkeit tatsächlich irgendwie, ich glaube, war das das Type of Äquivalent bei PHP oder so, war so im Parser integriert, dass tatsächlich die Aussage war, diese eine Funktion kann immer nur exakt mit einem Variablen-Namen aufgerufen werden, aber niemals jemals mit einer Expression, wo du dann von dem Ergebnis den Typen haben
möchtest.
Weil halt jemand das in den Parser so reingestrickt hat.
Und dieser Artikel geht da sozusagen in arg detaillierter Form durch und nimmt da irgendwie tausend von den Sachen auseinander und sagt halt hier, was willst du jetzt noch sagen, wenn du irgendwie nur noch von einem zum anderen Stolpost dabei?
Ja.
Der ist mal ganz interessant zu lesen, wer zum Thema irgendwie ein bisschen analytisch auseinandergenommen, was das liebe PHP da so ein bisschen auf die schiefe Bahn geraten lässt.
Ja, müssen wir mal in die Shownotes packen.
Ja, ja, mit den III.I oder sowas.
Ja, aber ich glaube, das war es dann auch schon mehr oder weniger, ne?
Nee, ich glaube, sonst war da eigentlich nichts zu.
Ja, ich glaube irgendwie noch was zu Type-Ins oder sowas, aber.
Oh ja, stimmt, man kann jetzt irgendwie List, man muss nicht mehr diese List mit Großbuchstaben vom Typing importieren.
Wahrscheinlich war das halt auch so gedacht, wer weiß, wie lange, ob die Leute das gut finden mit dem Type-Ins und so.
Nehmen wir mal nicht, irgendwie machen wir nicht den Aufwand, das direkt so zu ändern.
Und jetzt muss man das halt nicht mehr aus Typing irgendwie List mit großem L importieren, sondern kann halt die Build-Ins verwenden.
Und das funktioniert dann halt auch in den Type-Ins.
Genau, das wäre ganz nett.
Das macht es ein bisschen einfacher, das zu schreiben und muss nicht mal nachgucken, welche Imports das jetzt waren.
Ja, was steht an Veranstaltungen an?
Gabt ihr irgendwelche?
Oh, habe ich jetzt dummerweise gar nicht so richtig nachgeschaut.
Die DjangoCon ist gerade vorbei.
Ja, gab
es da jetzt PyCon auf jetzt um wieder zu warten.
War die PyCon dieses Jahr virtuell?
Ich weiß gar nicht.
Welche meinst du, die deutsche oder die?
Nee, die haben wir tatsächlich verschoben.
Also wir hatten relativ zeitig im Jahr mit den, also es wäre jetzt wieder in Berlin gewesen.
Genau, letzte Woche wäre es gewesen eigentlich, ja.
Genau.
Und wir haben aber relativ frühzeitig mit den Veranstaltungsort, wir wären gewesen im Nicht-Haus des Lehrers hier daneben.
Ja, in Berlin, genau, ach, wie heißt denn das doch?
Da wo immer der CCC-Kongress war,
da wo immer der Kongress war, genau.
Dieses UFO.
Ja, da wären wir gewesen eigentlich und haben mit denen dann halt, das war halt so ein bisschen schwierig, weil im Januar ja wirklich, im Februar, März war das, März, März, nicht klar war, wie wird denn das jetzt sich über das ja eigentlich entwickeln und tatsächlich jetzt sehen wir ja gerade auch, dass die Zahlen schon wieder schwierig sind und Massenveranstaltungen sind ja eh abgesagt bis mindestens Ende 2020 und wir hätten gerechnet, also bei einem regulären Jahr wäre unsere Hochrechnung, glaube ich, bei knapp 2000 Leuten
gewesen.
Und das kannst du halt gerade knicken, das geht gar nicht.
Und gleichzeitig war halt auch schon eine Anzahlung geleistet gewesen.
Deswegen musste man mit denen entsprechend verhandeln.
Und jetzt ist die Aussage, wir probieren es 2021 und 222, also wir haben uns committed, 21 und 22 nochmal in Berlin zu machen.
Und da haben wir gesagt, na gut, um dann halt sozusagen die Anzahlung zu retten.
Dadurch dürfen wir die fürs nächste Jahr mit verrechnen.
Und haben jetzt auch schon garantierte Preise für 21 und 22 schon rausgehandelt.
Ja, die haben ja auch das Problem.
Auf der einen Seite müssen sie irgendwie sehen, wo sie bleiben und auf der anderen Seite wollen sich natürlich auch nicht alle Leute verbrennen, die eigentlich jetzt regelmäßig Veranstaltungen mit ihnen machen.
Ich bin ein bisschen froh, dass wir halt jetzt irgendwie planmäßig schon für Berlin geplant hatten und nicht für Hinterpose Muckel, um dann sagen zu müssen, so auf die nächsten X-Jahre müssen wir nach Hinterpose-Muckel, ansonsten sind wir pleite, wären wir nicht pleite, aber ansonsten müssten wir da irgendwie Dutzende, 10.000 Euro vergraben.
Ja.
Nee, genau, das wäre es gewesen und das haben wir verschoben.
Was tatsächlich im November noch ist, vielleicht für alle, die auch im Python-Verband schon Mitglied sind, ist Mitgliederversammlung tatsächlich.
Das hat man auch ursprünglich geplant, die jetzt, weil es ja eigentlich ganz gut aussah, im Oktober mit vor Ort hier in Halle zu machen.
Aber sind gerade dabei, ich glaube morgen wird es beschlossen, und dann wird es wahrscheinlich auch eine digitale Veranstaltung werden.
Im November.
Da gehen demnächst noch Einladungen raus, wer beim Python-Verband Mitglied werden
will, kann
das nochmal noch machen.
Ja, dafür muss er tatsächlich nochmal kurz selber machen.
Die Webseite kurz nennen.
Genau, das wäre der Python-Verband.org, der Python Softwareverband als die deutsche Interessenvertretung.
Und eine unserer Hauptaktionen, und das war dies ja jetzt leider dann auch ein bisschen wenig durch Corona, ist, dass wir alle möglichen Community-Aktionen fördern.
Sowohl organisatorisch als auch mit Geld.
Das heißt, wir verstehen uns da ein bisschen als eine Drehscheibe.
Python selber ist ja gut bekannt, aber was wir stark unterstützen wollen, ist halt, Python noch in Communities zu tragen, die es vielleicht nicht so kennen und aber auch Veranstaltungen zu fördern.
Das heißt, man kann da auf der Webseite unser Förderprogramm nachschlagen und dann kann man sich relativ unkompliziert Geld für Ideen abholen, die man mal mit, wie man Python an andere Leute ranbringen will, mal was coden möchte, etc.
Genau.
Okay, interessant.
Und im Corona-Jahr war es jetzt auch so, dass wir tatsächlich ein, zwei schon länger bekannte Partner, da gibt es die Tech Kids zum Beispiel im Schwäbischen, die haben jetzt auch ganz schön drunter gelitten, weil denen die ganzen Veranstaltungen weggebrochen sind, mit denen sie normalerweise dann ja auch wieder so Teilnahmegebühren reinholen.
Und haben da jetzt dieses Jahr im Fördertopf tatsächlich dann auch eher mal großzügig gesagt, okay, wir sponsern euch jetzt auch mal, wenn gerade nichts los ist, damit das jetzt hier über die Corona-Zeit nicht alles zerbricht, einfach, was die Leute aufgebaut haben.
Ja, das ist tatsächlich vielerorts ein größeres Problem, ja.
Ja, ja.
Also das ist dann demnächst Weihnachten.
Ich habe heute die erste Weihnachtswerbung gekriegt.
Ja, Weihnachtswünsche.
Ja, sicher,
das Jahr geht schnell vorbei mit so einer Pandemie, ja.
So oder so?
Ja, ne, also genau, ich weiß nur, EuroPython war jetzt auch vor kurz.
Die Vorträge sind irgendwie da und die und DjangoCon da, das wollte ich mir auf jeden Fall angucken, aber habe ich es auch noch bisher nicht geschafft.
Gibt es auch die ganzen Vorträge online.
Und was jetzt in Zukunft kommt, weiß ich gar nicht.
Weil ich es nicht nachgeguckt habe.
Ja, wir verpassen übrigens gerade wie das Django mit Up Koloni.
Ja, ich weiß, aber das ist halt ein blöd.
Die Frostcon war auch noch, das ist jetzt auch so fünf, sechs Wochen her, glaube ich.
Da hat es ein bisschen gedauert, die haben jetzt auch erst vor, glaube ich, zwei, drei Wochen dann die Videos online gehabt.
Es kriegt glaube ich noch wieder so eine neue Anmeldung für das nächste Jahr, die 21, die auch online statt sein wird.
Äh, Forstem diesmal, ja.
Forstem, also das ist ja im Februar, Januar, Februar, irgendwie die Forst Dem, genau.
Nee, ich meinte die Frostcon.
Genau, die ist normalerweise St.
Augustin.
Genau, ja, da machen wir das Ja.
Ja, ansonsten, was mir noch so eingefallen ist, was jetzt geht, was früher nicht ging.
ISOT und Black sind kompatibel.
Ja, das ist auch nett.
Wie kam es?
Ich weiß es nicht genau.
Also mit irgendeinem Update von Icehort ist das jetzt sozusagen erledigt dann irgendwie gewesen.
Also Icehort hat was gemacht, damit Black nicht mehr der Zwischenpunkt.
Ja, irgendwie so, genau.
Und ja, jetzt geht es halt, man kann es halt parallel, also man kann halt beides verwenden und hat dann da kein, nicht mehr so, dass das eine mal die Sachen vom anderen umsortiert, was halt irgendwie ein bisschen doof ist.
Jetzt müssen wir das nur noch in PyProject Hummel konfigurierbar machen, genau wie PyTest und Blake 8 und dann.
PyTest ist das?
Ist das schon?
Ja, aber mit so einem komischen Text.
Ja gut, der Key ist so ein bisschen komisch.
Genau, PyTest, Iny-Options oder so ein Quatsch.
Wobei ich sagen muss, also wir haben jetzt tatsächlich Black ein paar Stellen wieder zurückgebaut.
Und ich breche noch eine Lanze für alle Leute, die sozusagen neben Schwarz noch ein bisschen grau haben wollen.
Ja.
Und empfehle mal noch ins Jap reinzuschauen.
Okay.
Ja, Black wird auch ein Problem kriegen.
Black verwendet auch den alten Parser.
Und spätestens ab Python 310 wird es dann halt sich was einfallen lassen, weil das geht dann nicht mehr.
Naja.
Kannst du kurz was zu Japf noch sagen?
Ja, Japf ist so ein, wie auch, wir waren ja vorhin schon beim Jack, der Yet Another Compiler Compiler und Japf ist der Yet Another Python Formatter.
Und die haben sich tatsächlich eher auf die Fahnen geschrieben, dass das Ding ein bisschen konfigurierbarer ist.
Oh, mit einer Japan Ignore, ich hab's gerade gesehen.
Und der erzeugt für mich, finde ich, deutlich lesbareren Code.
Also das ist die, ich komme persönlich mit der Black Formatterie an vielen Stellen so richtig gar nicht klar.
Und finde sie einfach urpott hässlich.
Ich fand sie auch sehr agli, aber Jochen hat es mir immer aufgezogen.
Ja, sorry.
Also ich unterstütze volle Kanne, das Thema einen Autoformatter einzusetzen.
Aber ich finde, Black ist halt nicht der weiße letzter Schluss.
Ja, also ich verstehe das durchaus.
Ich finde auch, ich habe so ein bisschen Schwierigkeiten mit den Anführungszeichen.
Ich habe auch vorher immer Single-Codes verwendet und dann so, ah, das ist schon so ein bisschen.
Auf der anderen Seite würde ich sagen, naja gut, also selbst wenn man es nicht so hübsch empfindet, wenn alle den gleichen Autoformatter verwenden, ist das ein so viel größerer Gewinn, als dass ich dann sage, na gut, dann gebe ich dafür die persönlichen Präferenzen auf.
Aber ja, ich kann auch verstehen, dass man das, ja.
Weil mein Streit sozusagen schon über das, was ich als persönliche Präferenz empfinde, rausgeht, weil es verletzt mein ästhetisches Gefühl so, dass ich wirklich daneben stehe und sage, nee, das ist volle Kanne gegen die Designziele von Python als Sprache.
Also das ganze Thema, dass die Indentation mir Dinge sagt, und dann irgendwie über X Dutzend Zeilen hinweg wieder schließende Klammer-Orgien zu sehen, dafür brauche ich kein Python.
Also dann brauche ich kein Python, dann kann ich JavaScript schreiben.
Ja.
Und sie wollen, also ich verstehe ja, warum das passiert.
Sie versuchen ja eine Formatierung zu machen, die möglichst wenig TIF erzeugt.
Wobei ich das bisher auch nicht gesehen habe, dass das wirklich, also da hätte ich gerne mal tatsächlich noch eine Metrik gesehen.
Und ich muss aber sagen, das verletzt dann so ganz klassische Clean-Code-Aspekte auch von Clean Code, optisch ist zum Lesen für Menschen da.
Und wenn das Ding halt tatsächlich erfordert, dass meine Kognition massiv mehr Aufwand leisten muss, um es zu lesen und alle Leute dann mehr oder weniger mit einem Stockholm-Syndrom ankommen und sagen, ja, ich habe mich daran gewöhnt, dann erinnert mich das so ein bisschen eher wie an die alten Leute, die ich hatte, als ich ein Haus gekauft habt und die Flugzeuge drüber fliegen und die sagen, ich höre die schon alle nicht mehr.
So fühlt sich das für mich jetzt halt an und wir haben jetzt tatsächlich in einem Projekt, in einem größeren Projekt, das eben nochmal umgestellt von Black auf einen anderen Formatter.
Auf Japf?
Auf Japf halt mit entsprechenden anderen Optionen und siehe da plötzlich hat man wieder so ein, ah stimmt, so muss das aussehen.
Danke, das ist Python.
Kannst du dafür mal die Config irgendwie teilen mit uns in den Shownotes?
Na klar.
Das wäre super, weil das finde ich sehr spannend.
Weil ich finde Black auch mega ultra hässlich und genau das, was du sagtest, also so ein paar Sachen, wo ich dachte, wieso macht das so?
Das ist auch eklig.
Ja.
Ja, naja, gut.
Dazu fällt mir gerade noch ein, ich habe letztens einen Podcast gehört, also ich höre den ab und zu, gefällt mir eigentlich, also mir gefallen ja auch so Formate, die so ultra lang sind und das ist halt auch so immer schön lang.
Der heißt irgendwie Lex Friedman und der spricht so mit allen möglichen Leuten und halt darunter sind halt auch viele der so Koryphäen.
Zum Beispiel hatte er letztens ein Interview mit James Gosling, zu dem quasi Entwickler von Java.
Und das fand ich ganz interessant.
Und der erzählte dann halt auch so, ja, also was ihn dann dazu gebracht hat, Java sich auszudenken, war halt seine lange Erfahrung mit C.
Auch sowas, was ich nicht wusste, der hat E-Macs irgendwie geschrieben in C oder die erste ordentliche Version von E-Macs.
Und stand dann irgendwann vor der Entscheidung, okay, ich mache jetzt entweder den Rest meines Lebens E-Macs oder halt nochmal was anderes und dann dachte so, naja, E-Max, so geil ist es dann, also weiß nicht, muss auch nicht sein.
Er hat immer was anderes gemacht und das abgegeben, irgendwie.
Also E-Max und Java sind eng verwandt, interessant.
Naja, also ja, ja, und aber er hat halt auf jeden Fall sehr, sehr viel C geschrieben.
Die ungleichen Zillinge.
Und dann auch größeren Projekten und dann sind ihm halt also Dinge aufgefallen, die immer wieder schief gehen in C und dann Java war halt sozusagen der Ansatz.
Also mit diesen großen Fehlerklassen, die halt C immer wieder ganz böse Probleme machen, halt aufzuräumen und das ist ja auch dann irgendwie gelungen.
Aber der sagte dann etwas, als es darum ging, irgendwie, wie das dann so ästhetisch aussieht, daher die Anknüpfung sozusagen, so, ja, also wenn ich irgendwie Code lese, es gibt ja mal so Leute, die sagen dann so, oh, ich finde das Ästhetisch ist aber nicht so, hm, gefällt mir nicht so richtig.
Und er hat so, mir war das immer alles total egal.
Ich habe da nie den Code gesehen.
Wenn ich irgendwie so eine Funktion angucke, dann sehe ich immer nur so, dann habe ich da so eine visuelle, so eine Bildvorstellung von, so wie so Zahnräder von der Maschine, und dann sehe ich, ob das das Richtige tut oder nicht.
Und wie die Syntax von der Sprache ist und wie die Sprache aussieht, das sehe ich gar nicht.
Und das ist mir auch total egal.
Jetzt wissen wir, was so ein Da waren.
Und dann dachte ich so, okay, ja, das erklärt natürlich einiges.
Aber das ist aber halt, da ist er in halt einer auch schwierigen Position, weil er hat den Quatsch halt erfunden.
Und mir geht es halt auch so, wenn ich irgendwelche Tools baue und erfinde, dann sehe ich da, wenn jemand die Tools verwendet, halt auch mit einem Schlag die Zahnräder.
Das ist aber halt kognitiv ein völlig anderer Prozess, als wenn ich das halt nicht erfunden habe und ich das verarbeiten muss, was da steht.
Und das ist sozusagen, und da gibt es, jetzt habe ich halt im Studium auch Linguistik gemacht und deswegen bin ich an der Stelle auch immer ein bisschen mit dran zu gucken, wie hängt das zusammen und unser Gehirn.
Kognitive Last ist halt was, das zwingt uns irgendwann halt dann nicht mehr über die Sache nachzudenken, sondern das Gehirn ist dann halt nur noch damit beschäftigt, dieses komplizierte Zeug zu lesen.
Deswegen hast du halt sowas wie Brainfuck, da bleibt dann halt nicht mehr viel über für, was macht der Code eigentlich.
Buchstaben.
Das ist halt schon eine echte Balance.
Ja, oder vielleicht sind unterschiedliche Leute da halt auch einfach unterschiedlich.
Vielleicht gibt es Leute, bei denen ist das halt egal, die sehen halt, wie die Mechanik dahinter direkt aussieht und können sozusagen an dem Code vorbeigucken, aber mir geht das auch nicht so.
Also wenn ich, ich bin sehr an dem Ästhetik.
Wenn man die ästhetischen Patterns direkt sehen kann und die einem klar ins Auge springen.
Ja.
Du willst ein anderes Thema einleiten.
Ich habe gerade versucht, einen kleinen Urgang zu finden.
Ich weiß nicht, ob es mir geglückt ist.
Wie geschimpft.
Ja, aber es ist doch wirklich so, ja.
Wenn man das sehen kann, dann kann man doch auch diese Patterns auch mit einer gewissen Ästhetik betrachten.
Und deswegen ist vielleicht diese Ästhetik der Sprache für manche wichtiger, vielleicht für einige unwichtiger.
Aber ich finde, das ist ein sehr essentieller Teil.
Also gerade weil auch die Hürde dadurch deutlich gesenkt wird.
Selbst wenn es jetzt ein sehr hochentwickeltes Feature ist, ermöglicht es halt auch einen deutlich einfacheren Einstieg, weil durch diese ästhetische Klarheit man das Konzept auch deutlich einfacher verstehen kann.
Man kann ja auch tatsächlich Ästhetik mal zur Seite legen und an der Stelle einfach, also es gibt ja mehrere andere Kriterien, die man ansetzen könnte, eben zum Thema Lesbarkeit, Menge der Zeichen auf dem Bildschirm, Menge an Noise, an syntaktischem Drumrum und so.
Und es gibt auch bestimmte Sprachen, bei denen ich halt sage, da ist es mir wieder zu wenig.
Also Python ist halt tatsächlich für mich so die Sweetspot-Sprache, da ist mein Gehirn super drauf angesprungen damals und extrem gut drin.
Mit Ruby tue ich mich zum Beispiel extrem schwer.
Ruby hat halt dieses Thema, dass wir sehr viel metasyntaktisch arbeiten.
Und das heißt aber, du musst teilweise schon überlegen, warum bedeutet, meint hier ist ein Leerzeichen, deswegen bedeutet jetzt gerade, hm, und wenn das dahinter eine Funktion ist, dann da musst du schon auch in diesen Mustern ganz schön arg drin stecken, um das halt wirklich lesen zu können.
Und ich habe bei Python halt immer das Gefühl, egal wie es geschrieben ist, irgendwie kriege ich es dann schon auch wieder relativ schnell auseinander geklamüsert.
Aber ich merke auch, oh, jetzt ist es auf eine Art geschrieben, die ist irgendwie durch die Brüste ins Auge und war irgendwie nicht zum Lesen gedacht.
Ja, man muss ja schon irgendwie eine Methode relativ schnell begreifen können, irgendwie, ne?
Zumindest ein Ziel, wenn man das so vernünftig machen möchte.
Naja, es ist halt so, ich glaube auch da wieder, dass halt für unterschiedliche Leute vielleicht da unterschiedliche Trade-offs besser funktionieren oder schlechter und irgendwie so die, wie sieht das aus oder wie kann man, wie schreibt man Dinge dran, ist halt irgendwie so das User-Interface der Sprache.
Was ich auch letztens noch gehört, was ich ganz interessanten Ansatz fand, dass er, wo habe ich das denn gehört, genau, dass es ja auch noch andere Aspekte gibt.
Also, ja genau, das war auch in einem Interview-Podcast mit, glaube ich, Chris Lettner, der Swift und Clang und so gebaut hat.
Und das hatte ich vorher noch nicht so richtig auf dem Schirm, weil ich dachte immer so, ja gut, was halt dann an Code dasteht, ist halt das Entscheidende.
Und der meinte dann halt auch so, ja, also User Interface der Sprache sehr wichtig und Python voll gut.
Wusste ich auch gar nicht, dass er da so weiter, das ist total super.
Das Problem ist nur, es gibt halt auch noch andere Dinge, die halt auch eventuell wichtig sind, wie zum Beispiel so etwas wie, wie gut ist das denn jetzt nicht, wenn ich da drin irgendwas programmieren will, was dann irgendwie mein Problem löst, sondern wie ist das eigentlich, wenn ich jetzt ein Framework darin entwickeln will oder irgendeine Library, ist das denn dann immer noch gut, weil bei Python hat man dann zum Beispiel das Problem, okay, wenn das jetzt irgendwas ist, was CPU-Bound ist sozusagen, dann hat man wahrscheinlich, wenn man
jetzt irgendwie so eine Basis-Zumpiel sowas wie ein Machine Learning-Framework oder so bastelt, dann kommt man da nicht aus ohne relativ große Anteile C, C<unk>, irgendwie sowas.
Und dann wiederum hat man das Problem, dass das User-Interface sozusagen von dem Use Case aus gesehen halt nicht mehr so schön ist, weil jetzt kann man nicht mehr richtig debuggen.
Weil man hat halt einen Teil in C und einen Teil in Python und ja, was macht man jetzt, wenn irgendwie und wenn da irgendwo Fehler auftreten, gibt es keine konsistente Art mehr, das so richtig zu debuggen.
Und das ist natürlich schon so ein Punkt.
Oder was er auch macht, ist dann halt sowas wie, ja, also was ist eigentlich, kann nicht sowas wie ein Int-Typ überhaupt irgendwie selber basteln?
Das geht ja jetzt in Python nicht, geht auch in Java nicht.
Aber in Swift ging das, ne, natürlich, deswegen.
Swift voll gut.
Da könnte man halt, kann man solche Typen halt tatsächlich bis ganz runter selber sozusagen als Library-Autor halt auch haben und selber definieren.
Ja.
Und natürlich, also in gewisser Weise, da ist schon so ein, das auch ein Punkt dabei.
Und das ist natürlich in Python vielleicht jetzt nicht so einfach wie in anderen Sprachen.
Also ja, das, ja.
Aber so zum Lösen von Problemen finde ich das auch halt irgendwie schon sehr, sehr angenehm im Vergleich zu allem anderen.
Aber kann auch sein, dass ich da einfach nur komisch bin und das halt für mich funktioniert.
Die Interviewreihe, die du da gerade aufgemacht hast, die kann ich auch allgemein empfehlen.
Da hatte ich letztens nämlich jemanden, wie hieß er nochmal, wie hieß der Interviewer?
Lex Friedman.
Lex Friedman, genau.
Und da hatten wir diesen einen Chip-Designer.
Der ist auch extrem spannend, den sich anzuschauen.
Das ist gerade so ein querthematischer Querschlag.
Aber ich glaube, die muss sich einfach mal loswerden, weil der hat mich dermaßen begeistert.
Wie hieß er denn?
Lex Friedman mit zu viele Sachen gemacht.
Ja, ja.
Er macht eine ganze Menge, ja.
Ah, genau.
Wo ist er, wo ist er, wo ist er?
Chip Designer, Chip Designer, Chip Designer.
Namen sind Schall und Rauch.
Ja, manchmal macht er auch so ein bisschen komisch, also manchmal ist man das auch, ich weiß nicht, es gibt ja so eine, also ich würde das mal, also wenn man das so, hm, wenn man versteht, also es ist halt auch sehr amerikanisch, muss man sagen.
Und manchmal macht er auch einfach so etwas seltsame Dinge, irgendwie so, sagt dann da, dass er jetzt nur noch Fleisch isst oder keine Ahnung oder irgend macht ganz viel mit Cryptocurrency-Zeugs, was ja auch irgendwie so ein bisschen ist, aber ja, aber es sind auch auf jeden Fall super interessante Sachen dabei.
Genau, also hier Lex Friedman Nummer 70, Jim Keller.
Ah, okay, gut.
Jim Keller ist tatsächlich einer der, also ich habe da gleich nach 10 Minuten so ein bisschen so ein Man-Crush entwickelt.
Der ist so intens, wie der da sitzt und denkt und redet und sein Mienenspiel eigentlich gar nicht so richtig präsent ist, so richtig.
Und dann doch so ganz kleine Nuancen und haut da Sachen raus zum Thema Chip Design und der ist halt sozusagen in den, ich glaube in den 80ern ist er ins Chipdesign eingestiegen und hat so alles mitgemacht.
Der hat halt bei AMD und bei Apple und bei Tesla und bei Intel gearbeitet und ich habe jetzt so ein bisschen so persönlich so dieses Gefühl von, ah, dieser Kampf zwischen AMD und Intel, der wird eigentlich nicht irgendwie da weit oben ausgetragen, sondern die Frage ist nur, ob Jim gerade bei AMD oder bei Intel ist.
Die Folge hat schon wie es Moore's Law, dass ich so was sagen würde.
Ja, genau.
Also der war, der ist schon krass.
Der ist schon, der war richtig gut.
Ja, dann, ne?
Der Podcast kann man tatsächlich empfehlen.
Es kommen auch andere tolle Folgen, die man hören kann, mit Donald Knus oder Paul Krugmann sogar mal dabei gewesen
und und und.
Es lohnt sich, die auch auf YouTube zu gucken, denn es gibt Videos davon mit den Interviews nicht nur als Podcast.
Und da ist, ja, die Mimik ist.
Peter Norweg.
Ja, ja.
Wenn man mal so durchscrollt.
Ja, genau.
Wo waren wir denn jetzt?
Wir wollten eigentlich folgendes.
Ja, genau.
Ja, und irgendwie gewisserweise, da, genau, da, da, äh, auch zu Patterns hatte Christlett noch was zu sagen und sagen, dann so, ja, also Patterns sind ja auch immer so, es wird halt gesagt, wenn man Patterns braucht, dann hat die Sprache eventuell einfach nicht genug, also hat es eigentlich ein Zeichen dafür, dass die Sprache halt etwas nicht kann, was sie vielleicht können sollte, ne?
Und deswegen muss man halt einen Pattern machen.
Und das kenne ich auch schon lange und er fügte halt dann noch was hinzu, was mir dann, wo ich dachte so, oh ja, das stimmt, das ist ja auch eigentlich so ein Punkt, der warte, das ist nicht nur bei Pattern so, sondern halt auch bei sowas wie, gibt es eigentlich sowas wie eine Standardbibliothek.
Und das ist halt immer, das ist ein ähnlicher Trade-off.
Also wenn du jetzt irgendwie bei Python eine relativ große Standardbibliothek hast, dann hat das natürlich eventuell den Vorteil, dass du dir so etwas ersparst wie JavaScript, ja, die haben das da halt nicht.
Und dann kriegst du halt NPM.
Und das ist halt sozusagen ein Pattern, um halt diese fehlende Standardbibliothek irgendwie dann aufzufangen, sozusagen außerhalb von dem, was die Sprache tatsächlich macht.
Und das hat halt, ist halt so ein bisschen fies dann unter Umständen.
Auf der anderen Seite ist es natürlich auch so, dass es wieder ein Vorteil sein kann, weil wenn man sich jetzt irgendwie sich TypeScript anguckt oder so, dann, wenn sich so ein Type-System halt außerhalb der Sprache entwickeln kann, kann es das natürlich deutlich schneller tun, als wenn das immer nur alle 18 Monate oder jetzt alle zwölf Monate updatebar ist, mit dem Release-Zyklus der Sprache.
Also es ist nicht so einfach.
Also, tja.
Und mit Patterns ist es halt irgendwie ähnlich.
Wenn eine Sprache halt sehr, sehr viel kann, dann braucht man eigentlich nicht so viele Patterns, weil dann hat man einfach diese Probleme nicht.
Und auf der anderen Seite, wenn, ja, gibt es einen Nachteil, wenn eine Sprache zu viele Features hat, naja gut, dann ist man halt auch an die Sprache sehr gebunden und ja, eigentlich hat das keine Nachteil.
Ich glaube, Patterns ist sozusagen.
Das war gerade aufgekommen, da war ich glaube ich im Studium.
Ich weiß nicht, wann das Buch rauskam.
Ich glaube, das ist 94.
Was?
Dann war ich da nicht im Studium.
Oh, Tatsache.
94.
Nee, da war ich bei weitem noch nicht im Studium.
Ja, Tatsache, 94.
Und wir hatten ja vorhin schon mal kurz angerissen, dass das in C<unk>
Ja, also du wolltest über das Buch reden, Gang of Four Design Patterns.
Gang of For Design Patterns, genau.
Das ist sozusagen, wenn man diesen Begriff Patterns in die Hand nimmt, ist das eine IT sozusagen das, wo es alles mit angefangen hatte.
Und vielleicht kann man da noch kurz den einen Umweg gehen zu Name, wie hieß er?
Steve Alexander?
Nee.
Alexander war Alexander.
Christopher Alexander.
Christopher Alexander war das, genau, war ein Architekt.
Und der hatte dieses Thema Patternsprachen halt mal aufgegriffen und beziehungsweise entwickelt, um sich städtebaulich so einem Gesamtkunstwerk anzunähern.
Um halt auf der einen Seite zu sagen, okay, Patterns sind Dinge, die immer wieder auftauchen, die halt in leichten Variationen anwendbar sein müssen.
Und es ging ja nicht darum, dass Patterns, es sind ja Patterns und nicht Templates.
Also was ist das denn?
Ist das sowas wie ein Mosaikbausteinding, das man irgendwo reinstecken kann und dann in alle Richtungen funktioniert?
Nee, eigentlich nicht.
Eigentlich ist es halt tatsächlich ein Entwurfsmuster, wo du mehrere Dinge genannt bekommst drumherum.
Also die haben da ein so ein gewisses formales Schema aufgebaut.
Es ist ein Name und Klassifikation und Zweck und Synonyme und Motivation.
Und aber was eben tatsächlich interessant ist, sind halt dann immer Hinweise zur Anwendbarkeit, Hinweise zu einer allgemeinen, ja, sozusagen Oberflächenstruktur, Klassen, die da auch dran, also musst Akteure, das ist jetzt eher C<unk> na dann schon so Klassen, die daran beteiligt sind, aber auch das Zusammenspiel davon und eine Abwägung von Konsequenzen mit Vor- und Nachteilen, Implementierungen und Beispielcode häufig.
Und da geht es halt darum, dass man für einen bestimmten Fall, wenn man merkt, ich schreibe jetzt hier Code, der hat so einen ähnlichen Einsatz wie von diesem Muster und dann liefert dir das Muster zumindest schon mal einen Design-Input von.
Also wenn du jetzt sowas in dieser Art machst, dann solltest du auf X, Y, Z achten und dann hängt da noch das und das und das dran.
Und es ging nicht darum, sozusagen ein fertiges Stück Code, was man nur noch copy-pastet, irgendwo reinzusetzen, sondern zu sagen, na guck mal, es gibt zum Beispiel, wenn du das Problem hast, dass du Code dynamisiert auswählen können möchtest, dann ist zum Beispiel das Strategy Pattern eine mögliche Variante, das zu tun.
Das sieht dann so und so und so aus und da muss man auf das und das und das aufpassen und den Rest baust du dir jetzt selber zusammen.
Ja, das ist ein bisschen wie wenn ich sage, ich setze mich hin und schneide mir ein Kleid, dann habe ich da ein Entwurfsmuster.
Aber ich muss natürlich trotzdem noch messen, ob mein Bauch ein bisschen dicker ist, meine Beine ein bisschen länger und muss das dann halt anpassen.
Und da ging es tatsächlich dann darum, und das ist auch das, was der Christopher Alexander an der Stelle wollte, er wollte ja damit Leuten eine Auswahl von Mustern an die Hand geben, wo die Muster auch ineinandergreifen und zusammenspielen.
Also das ist ja auch ein Thema, dass das nicht irgendwie eine wahllose Menge von Patterns ist, wo man sagt, die lerne ich jetzt auswendig und dann nehme ich einmal das und einmal das und einmal das, sondern das soll eine Sprache ergeben, wo man dann anhand von diesem Zusammenspiel, von den Verknüpfungen zwischen den Teilen dann immer weiß, ah, wenn ich hier drüben das mache und das mache, dann sollte ich wahrscheinlich hier drüben gleich mal aufpassen, dass ich nicht noch XYZ versauere.
Und diese Sprache, da geht es ein bisschen um Kräfteverhältnisse zwischen den Dingen, aber eben auch immer dieses, man muss es sich selber zurechtschneiden für den eigenen Anwendungsfall.
Ansonsten hätte man das ja auch in eine Library kippen können.
Das hätte man sagen können, das ist jetzt der einmal fertige Code.
Und der Trick ist aber, das muss da auf eine Ebene greifen, wo ich nicht vorher sagen kann, ah, da braucht man eine Funktion für oder da braucht man dieses Ding oder eine Klasse oder sowas, sondern es ist häufig auch ein, ja, wenn du folgende sieben Zeilen dreimal geschrieben hast, dann solltest du mal darüber nachdenken, ob du das vielleicht anders anordnen möchtest.
Aber das ist jetzt ja vielleicht nochmal interessant für alle unsere Hörer, wir haben jetzt ja ja abstrakt vielleicht irgendwie da mit angefangen, was so Patterns vielleicht so konzeptuell sein sollten und vielleicht gehen wir dann so ein bisschen in die konkretere Implementierung.
Was es denn so gibt an Sprachpatterns überhaupt und dass wir vielleicht die mal erklären und ein bisschen versuchen, wie man das in Python vielleicht macht.
Wenn man das macht, wenn man die überhaupt braucht.
Also ja genau, also ich meine, die Muster, die sind ja sozusagen allgemeingültig.
Das sind ja tatsächlich sehr abstrakte Ideen, die da existieren.
Vielleicht mal mit Alpha Hand, was eben irgendwie Strategie gesagt?
Ja, ich würde woanders anfangen, ich würde beim Singleton anfangen.
Ja, okay, fangen wir mal beim Singleton an.
Was ist ein Singleton?
Die mäßige schöne Übersetzung ist das Einzelstück.
Ich mag es einfach nicht, wenn.
Und also da gibt es, es gibt ja so ein paar Kategorien.
Also der Singleton gehört zu den Mustern aus dem Bereich Creational Patterns.
Also wie werden in einer objektorientierten Sprache Objekte erzeugt?
So, da gibt es so verschiedene Muster.
Es gibt manchmal den Effekt, und gerade in Java ist das halt noch ein stärkerer Fall, dass ja alles als alles muss eine Klasse sein.
Und manchmal brauchst du aber Code, wo das Objekt nur ein einziges, wo es nur ein einziges Objekt zugeben darf.
Und dieses Objekt soll aber auch gut zugänglich sein.
Und das kann zum Beispiel sowas sein wie das Objekt.
In Python gibt ein Python-Analogum dazu tatsächlich sogar.
Das ist nämlich das Objekt, was den Logger in dieser Anwendung zum Beispiel repräsentiert.
Davon willst du nicht, willst du fünf Logger haben nachher, sondern du willst halt irgendwie, wo ist denn hier die Log-Konfiguration, mit dem Ding möchte ich jetzt reden, da soll jetzt bitte Log-Output rausgehen.
Und da gibt es dann halt entsprechende Muster, wo man sagen kann, okay, wenn irgendwer die Klasse in die Hand kriegt und die nochmal neu instanziiert, dann dreht die sich um und gibt einfach statt ein neues Objekt zu machen, dir das eine erzeugte Objekt schon wieder zurück.
Und dieses konkrete Singleton lässt sich aus Java so auf Python, du kannst es glaube ich, glaube ich, codemäßig sogar so bauen.
Das hat aber nicht die gleichen Eigenschaften, weil die Sprache ja eine andere ist.
Und in Python gibt es dafür halt andere Möglichkeiten, sowas zu machen, dass du zum Beispiel sagst, du hast einen Namespace, bei dir in deiner Anwendung ein Modul, das heißt dann Log.
Tipp, man sollte es nicht Logg nennen, das geht gerne schief, wenn man die Standardbibliothek schattiert.
Das heißt vielleicht Log.
Und da drin gibt es eine Klasse, das ist dann dein Logger und nach der Definition der Klasse würdest du gleich dieses Objekt instanzieren.
Und wenn du willst, löschst du danach diese Klasse einfach aus dem Namespace von dem Modul wieder raus.
Dann kann auch keiner aus Versehen so eine zweite Instanz machen.
Und dann muss man wieder dazu sagen, naja, Python als Sprache für Erwachsene, das stimmt halt so auch nicht, weil wenn du die Klasse aus dem Modul dann löschst, dann ist der Name zwar nicht mal ansprechbar, aber du kannst natürlich auf diesem singleton Objekt wieder nach Under Underclass fragen, dann hast du das Klassenobjekt, dann kannst du da wieder eine neue Instanz von machen.
So, jetzt kannst du halt hergehen und kannst, wenn du willst, in Python sagen, also der, jetzt muss ich selber überlegen, welche Doppel-Under- underscore-Methode da die richtige war.
Nicht init, sondern was Create?
New, genau.
Ich habe es zu lange nicht mehr in der Hand gehabt.
Ich merke, ich mache in letzter Zeit zu wenig Metaprogrammierung in Python.
Du könntest aber Under UnderNew nehmen und könntest dort sowas machen wie, wenn es auf dem Klassenobjekt schon ein bestimmtes Attribut gibt, nämlich die Instanz selber von dem Objekt, was du mit der Klasse erzeugt hast, dann liefere einfach das zurück und ansonsten mach einmal ein neues und ansonsten nie wieder.
Solche Meta-Aktionen kann man damit machen.
Die Frage ist nur immer, wie gesagt, was hat das Pattern für einen Kontext.
Und es gab eine ganze Zeit lang, und das wurde so ein bisschen diesen Java-Programmiererschmieden, die halt so viele Leute wie möglich die Java programmieren können sollten, rausgespuckt hatten, so Ende der 90er und Anfang der Nullerjahre.
Die sind immer rausgekommen mit, ich kann die Patterns, ich muss alles in Patterns denken.
Und das ist aber in der Informatikausbildung, einen selber ein Pattern, was immer wieder kommt, dass die Leute irgendwie Werkzeuge in die Hand gedrückt kriegen und dann denken, ich muss alles mit diesen Werkzeugen ausdrücken.
Und eigentlich ist es aber umgekehrt, eigentlich ist es halt, du schreibst halt Code und wenn du die Patterns kennst, dann merkst du vor deinem Auge plötzlich, ich baue hier etwas auf, das riecht wie so ein Singleton.
Dann sollte ich mir jetzt nochmal kurz Gedanken machen, was wir alles wissen über diese Form von Pattern und ob ich jetzt bestimmte Dinge von Fehlerbehandlung, von bestimmten Edge Cases etc., nicht einfach alle gleich glatt ziehe, weil ich weiß, wenn ich das jetzt so und so mache, dann habe ich das hier alles handwerklich ordentlich gemacht.
Und das ist aber ein Bottom-Up-Approach und gelehrt wird das Ganze häufig halt als Top-Down-Approach.
Im Sinne von, du baust deine Anwendung nur noch aus Dingen zusammen, die diese Patterns sind.
Und das ist halt Quatsch.
Du baust halt die Anwendung erstmal, wie du sie willst, und wenn du feststellst, ah, du hast hier ständig irgendwie Dinge, die eigentlich nach diesen Patterns riechen und dafür ist es dann wichtig, dafür muss man sie erkennen, dann kannst du es damit leichter und schneller strukturieren und musst das Rad nicht jedes Mal neu erfinden.
Ja.
Ja, genau.
Ja, und ich würde auch sagen, eben genau diese Creational Patterns, das ist halt so ein, es gibt irgendwie drei Teile, Creational, Structural und Behavioral oder sowas, glaube ich.
Da würde ich sagen, ist auch also schon eine der Hauptpunkte, dass es halt so irgendwie fehlende Sprachfeatures so ein bisschen relevant, weil tatsächlich braucht man diese Patterns vor allen Dingen in Sprachen, wo halt das syntaktischen Unterschied macht.
Also wenn ich halt zum Beispiel in C<unk> oder auch in Java oder selbst in JavaScript, wenn ich dann New sage, um ein neues Objekt irgendwie zu erzeugen, dann habe ich halt das Problem, dass das, also in Python ist es halt, ist ja sozusagen ein neues Objekt erzeugen, gar nicht syntaktisch zu unterscheiden von einem Funktionsaufruf.
Das sieht halt einfach genauso auf.
Und ich kann ja irgendwas zurückgeben.
Also ich muss ja jetzt, wenn ich ein neues Objekt erzeuge, nicht irgendwie irgendwas New sagen, sondern ich rufe halt eine Funktion auf und dann habe ich halt ein neues Objekt.
Aber die könnte da halt auch was ganz anderes machen.
Auch ein Objekt von einer anderen Klasse zurückgeben oder so.
Das geht halt in C<unk> nicht.
Wenn ich da sage, New irgendwie diese Klasse, dann kriege ich halt ein Objekt von dieser Klasse.
Also muss ich mir, wenn dann was anderes aber rauskommen soll, halt überlegen, wie gehe ich denn jetzt damit um.
Und dann wird es halt, kriege ich halt irgendwie if-else-Kaskaden in irgendwie Konstruktoren und dann irgendwann denke ich mir so, hm, das sieht aber hässlich aus, was mache ich denn jetzt?
Und dann brauche ich halt Pattern.
Ich habe einen Pilot um die Ohren.
Und das hat man in Python so, eigentlich würde ich sagen, so viele der braucht man so nicht.
Also es gibt vielleicht die Ausnahmen, ich würde sagen, Ausnahme ist vielleicht das Builder-Pattern, das man halt auch in Python vielleicht ganz gut verwenden kann.
Dann bitte noch erklären, was das ist.
Also das Builder-Pattern ist halt so, wenn man jetzt nicht nur ein Objekt bauen möchte, sondern halt eine ganze Menge von Objekten, dann wird das halt unter Umständen unübersichtlich, wenn nicht das jetzt irgendwie, weil da muss ich halt einen Konstruktor machen, der irgendwie riesig wird und ganz viele Argumente übergeben oder so, das ist halt eventuell nicht so schön.
Gutes Beispiel dafür ist halt LXML hat da so ein Ding, wie man sozusagen XML-Dokumente zusammenbauen kann.
Das ist halt quasi Bilder-Pattern, kann man sagen, also wenn man sich das mal angucken will, und da gibt es dann halt für jedes Tag ein Objekt und dann kann man das halt ineinander schachteln und dann hat man quasi, sieht das syntaktisch so ein bisschen aus, als würde man XML zusammenbauen und hat dann aber tatsächlich eigentlich quasi halt eine Reihe von Objekten zusammengebastelt.
Meistens reicht es aber, also das, wofür dann das Bilder-Pattern verwendet wird in anderen Sprachen, in Python reicht es dann meistens, irgendwie einfach eine neue Klassenmethode an Objekt dran zu machen, die halt dann irgendwie Sachen zusammenbaut.
Das geht halt.
Anderswo geht das halt nicht so gut, dann muss man halt sich, dann muss man halt das ein bisschen komplizierter machen.
Aber es gibt auch in Python-Fälle, wo man das Pattern tatsächlich braucht.
Und es ist halt schön, das Pattern zu kennen, auch wenn es halt nicht primär um komplizierte Syntax geht.
Hat das was mit Factory zu tun, weil das Builder-Pattern heißt?
Ja, also Factory-Pattern würde ich sagen, braucht man fast nicht.
Das ist genau so etwas, das ist, da das irgendwie da Funktionen First-Class-Dinger sind in Python, gibt es eigentlich gar keine Sache.
Fangen wir auch wieder so an, wir wollen ja auch ein bisschen erklären.
Ich weiß gar nicht, ob ich das genau erklärt kriege.
Guckt irgendwas aus, wird irgendwas fabriziert auf eine ähnliche Art und Weise.
Irgendwas generiert, was ähnliche Eigenschaften besitzt, ich weiß nicht.
Nee, es geht eigentlich eher darum, dass du deine Objektkonstruktion konfigurierbar machen möchtest.
Dass du nicht sagen möchtest, also du hast halt nicht irgendwie einen Hammer und ich hätte irgendwie New Hammer, sondern du hättest gern jetzt einen sehr speziellen Hammer mit allem möglichen, keine Ahnung, so einer Stil, der so und so lang ist und keine Ahnung, der soll so und so schwer sein und weiß ich nicht.
Und ja, jetzt ist halt die Frage, wie konfiguriertest du dieses Ding halt und wo man in Python halt eine Funktion verwenden würde, musst du halt in anderen Sprachen jetzt anfangen, sozusagen da Objekte ineinander zu stapseln.
Und ich krieg's jetzt auch, weiß ich nicht genau, wo ich das so super glatt kriege.
Ich habe mir das auch schon lange nicht
mehr angeguckt, aber bitte.
Ja, man muss an der Stelle halt auch.
Es geht wieder um Syntax halt auch an der Stelle.
Das eine ist, du benutzt halt plötzlich keinen New Operator mehr an der Stelle.
Das geht weg, sondern du änderst halt den Aufruf eines traditionellen Konstruktors in halt eine ganz normale Funktion oder Methode und kannst halt tatsächlich auch unterschiedliche Semantiken haben.
Also hier wird zum Beispiel gerade ein Beispiel aufgeführt von, hab eine Farbklasse, ja, und du willst jetzt eine neue Farbinstanz haben und sagst einmal Create vom RGB oder Create vom HSV oder solche Sachen.
Das kannst du damit ein bisschen expliziter machen.
Speziell, wenn du dann halt wirklich unterschiedliche Semantiken haben willst oder das Ding noch 13 andere Dinge tun soll oder eben gar kein New aufruft, sondern das Ding von woanders ranzerrt.
Da sind Konstruktoren halt häufig einfach extrem begrenzt, was die Flexibilität angeht.
Und das ist tatsächlich in Python halt ein, naja, Init und New sind halt auch nur ganz normale Funktionen, die kannst du parametrisieren, benutzen, wie du willst.
Da ist Python halt einfach eine Ecke voraus gewesen.
Nichtsdestotrotz kann man halt noch was draus lernen.
Ich mache das auch gerne manchmal, dass ich Konstruktoren habe oder solche Factories habe, die eben dieses aus unterschiedlichen Kontexten raus initialisieren.
Es ist in der Python-Bibliothek selber auch drin, wenn man sich Date Time zum Beispiel anguckt, dann gibt es da mehrere, so das sind dann entweder Klassen- oder statische Methoden, die heißen dann irgendwie from Timestamp oder From was auch immer, um dann halt ein Objekt dieser Klasse zu erzeugen, aber eben mit völlig anderen Ansätzen und der Code ist natürlich leichter zu strukturieren, als wenn du nur einen Konstruktor hättest, wo 23 Parameter drin sind, die sich alle nicht um den Füßen rumtreten dürfen.
Ja.
Okay, ja.
Ja, dann machen wir noch weiter mit was für, würde ich dir als nächstes nehmen.
Eigentlich hatten wir ja mit dem Singleton angefangen und mit den verschiedenen Arten.
Achso, ja, ja, genau.
Auch zu Singleton wollte ich auch noch kurz, genau, was ich meistens verwende, oder was für meine Anwendungshalle, wo ich sowas habe wie den Singleton meistens reicht, ist tatsächlich irgendwie eine Variable in einem Modul.
Weil das ist ja irgendwo, das Modul ist schon ein Singleton irgendwie und wenn ich da halt irgendwas dran packe, dann ist das halt überall gleich.
Wenn ich das irgendwo importiere.
Es gibt da so ein Pattern von Alex Martley, wenn man tatsächlich sowas braucht wie Shared State, über, dann, aber man, manchmal braucht man nicht unbedingt immer die gleiche Instanz, sondern nur, dass sich alles immer gleich irgendwie verhält und den gleichen State hält.
Da kann man das Borg-Pattern verwenden.
Das ist so ein bisschen ähnlich wie ein Singleton.
Das ist kein originales Gang of Four.
Nein, aber das ist halt sozusagen irgendwie eine etwas pythonischere Variante.
Ja, und es gibt dann natürlich auch noch die, also man kann tatsächlich auch so machen, dass es halt so ist wie Singleton in anderen Sprachen.
Meistens irgendwie muss man dann so mit der Programmierung mit New und keine Ahnung.
Ist aber dann schon nicht mehr so richtig einfach und meistens, wie gesagt, also meiner Erfahrung nach braucht man es eigentlich nicht.
Ja.
Okay.
Also was für Pattern haben wir denn noch?
Also ich kann jetzt natürlich die Liste hernehmen, aber wir haben ja Singleton gehabt, ich habe einen Kurz Factory, wo ich mir.
Es gibt noch zwei, die jetzt aus meinem, äh, sozusagen aus meiner Historie immer relevant waren.
Das waren Proxys und Adapter.
Ja, und Interface und
da muss ich mal die ganz ollen Gamellen rausholen.
Also Soap 3 war damals tatsächlich, also Soap 2 und der Nachfolger Soap 4 und Soap 5.
Da gab es auch einen.
Bitte?
Soap, genau.
Der Open Source Urgroßvater der Applikationsserver.
Z-O-P-E-SOAP.
Achso, Soap.
Ja, okay.
Ja, genau.
Und das war ursprünglich ja so ein Through the Web Entwicklungsumgebungstool, wo man halt nur durch einen Browser mit Python und so ein paar HTML-Template-Sprachen sich extrem schnell Web-Anwendungen zusammenbauen konnte.
Das war Original 1996 entstanden, glaube ich.
Und 2001 rum gab es da einen Aufschlag zu sagen, so bauen wir alles nochmal neu mit besserem Engineering.
Und da kam dann so ein Soap 3-Projekt raus und da gab es schon mal so eine 2 nach 3-Transition, die nicht so smooth war.
Für Soap war es tatsächlich, glaube ich, so ein bisschen auch dann der Untergang im Sinne von, das war sowas anderes, man hätte es nie Soap 3 nennen dürfen.
Es hat einfach nichts, so richtig gar nichts mehr mit dem vorherigen Ding zu tun gehabt.
Da war die, da war halt eine der Grundideen, dass es möglich sein sollte, Libraries und Anwendungen oder Anwendungskomponenten, das nannte sich dann auch Komponentenarchitektur, so miteinander zu verheiraten, dass es eine zentrale Registry gibt, in der aufgezeichnet wird, wie man Dinge miteinander verbinden kann.
Also das war dann sehr stark interface-basiert.
Das ist jetzt auch was, was in anderen Sprachen stärker verankert ist als in Python.
Und da hatten wir extra eine Interface-Typ für entwickelt, mit dem du dann deklarieren konntest, okay, das hier ist ein formales Interface, es muss folgende Methoden haben, die Methoden müssen folgende Parameter haben.
Interface ist ja ein anderes Design-Pattern.
Nee, Interface ist noch nicht mal so richtig ein Design-Pattern.
Interface kommt eher aus dem Bereich der Typsysteme und ist in einigen Sprachen sozusagen eine Möglichkeit, Schnittstellen zwischen Code halt zu explizieren.
Also in Java ist es ja sehr explizit und in C<unk> auch.
Ich glaube, Modular 3, damit hatte ich gelernt, ist es auch so ein Ding, Dinge, die du nicht deklarierst, kannst du nicht ansprechen, sozusagen.
Ja, du musst halt sozusagen immer, wenn du eine Funktion aufrufst oder eine Methode aufrufst, irgendwie, wenn du dir irgendwas übergibst, musst du dir halt sagen, was das denn ist.
Kannst du ja nicht einfach irgendwas übergeben.
Und wenn du jetzt Objekte unterschiedlicher Art da reintun willst, dann müssen die zumindest quasi vom gleichen Interface erben, sonst geht das halt einfach nicht.
Du könntest zum Beispiel sagen, okay, ich habe hier irgendwie eine Methode, die schreibt irgendwie zum Beispiel, die logte irgendwas weg oder so.
Und ich gebe da jetzt irgendwas rein, aber du, was du jetzt reingeben möchtest, ist einmal vielleicht irgendein Log-File, in das reingeschrieben wird, aber du möchtest vielleicht auch, dass das irgendwie übers Netz in irgendein Socket geschrieben wird.
Und dann kannst du sagen, okay, Socket und mein File haben beide ein File-like-Interface sozusagen, das sie implementieren, oder dann halt auch explizit davon erben, wenn du das halt irgendwie so machen willst und dann kannst du das halt dann sozusagen, sagst du, in der Methode, also ich habe hier, hätte ich gern ein Ding, das das File-Interface sozusagen implementiert und kannst dann sozusagen darauf dann irgendwie Write aufrufen oder so.
Und die Menge der Methoden sozusagen, die man da aufrufen kann, das ist halt das Interface.
Also die Idee ist, der wichtige Unterschied ist, dass du mit Interfaces halt Implementation und Spezifikation voneinander halt trennst.
Das heißt, ich habe eine Art abstrakte Vordefinition.
Ja, also wir hatten es damals so gemacht, es gab einen speziellen Klassentyp, also eine Basisklasse-Interface, die konnte auch keinen richtigen Code haben.
Da wurde also, da hattest du immer nur Rümpfe von Methoden gehabt.
Und dann konntest du halt deklarieren, dass eine bestimmte Klasse dieses Interface implementiert.
Und wichtig ist eben, dass die Implementationen nicht voneinander geerbt haben.
Es gab nicht irgendwie eine Basisimplementation oder du könntest das Interface gegebenenfalls sozusagen sowas wie eine abstrakte Basisklasse nennen.
Aber das ist expliziter noch viel weiter voneinander entkoppelt worden.
Und Python normalerweise da gibt es ja das sogenannte Duck-Typing.
Das heißt, solange es sich so verhält, wie es soll, ist mir als Laufzeitumgebung völlig egal, was du rein stopfst.
Das ist ja dann jetzt mit den Type-Annotations, kannst du da jetzt Laufzeitumgebungen nehmen, die das halt ein bisschen strenger behandeln und auch mit statischer Analyse schon mal versehen.
Aber da ging es uns tatsächlich mehr darum, wenn man solche Annotationen hat, dass man daraus dann auch den Vorteil zieht, dass ich sage, okay, ich definiere ein Interface für etwas.
Und wenn ein Objekt ein Parameter eines bestimmten Typs erwartet oder ein Objekt erwartet, das ein bestimmtes Interface erfüllt, dann wird nicht einfach gesagt, nee, du bist kein Objekt, also du implementierst dieses Interface nicht, sondern was dann passiert ist, dann wurde ein Adapteraufruf gemacht.
Man hat also das Ursprungsobjekt genommen, was jetzt als Parameter in die Funktion reingereicht wurde, und hat dann geguckt, welches Interface soll es denn erfüllen, hat einen Adapteraufruf gemacht und hat gesagt, so, liebe Laufzeitumgebung, ich habe hier ein Objekt gekriegt, mach bitte, dass es ein iLogger ist.
Und dann konntest du in der Laufzeitumgebung vorher registrieren und sagen, ah, also, wenn jemand einen iLogger braucht und einen String bekommen hat, dann mach bitte folgendes.
Und dann kommt da dieses Objekt raus.
Oder wenn eine Methode einen iLogger braucht und da kommt ein Socket raus, dann mach, da wurde ein Socket übergeben, dann mach bitte das und geh dann weiter.
Und da kannst du sozusagen immer wieder beliebige Typtransformationen mitten reinsetzen und hast dich dadurch flexibilisiert, dass jemand anderes plötzlich anfängt, okay, ich gebe dir, liebes Programm, jetzt plötzlich Objekte anderen Typs rein und deklariere an der dritten Stelle, wie diese Typt-Transformationen zu laufen haben.
Und dann kann ich plötzlich halt Anwendungen auf Arten benutzen, die nie so vorgesehen waren.
Hört sich nach großer Magie an.
Das war ein Haufen Magie, da war ein Haufen Engineering drin, um das auch schnell zu kriegen.
Also das war wirklich so, wenn man bei Soap nachher in einer ernsthaften Anwendung mal eine Seite aufgerufen hatte, dann waren in einem Call bestimmt eine halbe Million Adapter-Calls drin.
Und die waren aber auf C-Ebene halt so optimiert, das waren halt nur ein paar Millisekunden, die dafür drauf gingen.
Das war alles extrem schnell.
Da wurde extrem viel Arbeit reingesteckt.
Und da gibt es wirklich, also da gibt es Architekturen, die wir in Anwendung hatten, die waren extrem interessant.
Problem ist aber, die sind halt auch extrem aufwendig zu pflegen.
Also da spielst du dann halt Informatik wieder mit in der Klasse von, wir ziehen es jetzt alle den Laborkittel an und designen das jetzt hier ordentlich durch, ansonsten fliegt uns das alles um die Ohren.
Da ist so ein iteratives Vorgehen hat nur so begrenzt getragen, weil du halt häufiger recht große, starre Refactorings hattest, die du dann halt nehmen musstest.
Aber dieses Adapter-Pattern hat es extrem flexibel gemacht.
Also das war schon richtig gut.
Und das zweite, wo ich mich hier in Fanatismus und Rage vor euren Augen im Video begeben hatte, war dann, was da auch eine Rolle gespielt hat, waren sogenannte Proxy-Patterns, dass also ein Objekt anstelle eines anderen irgendwo reingereicht wird und er emuliert alle Attributzugriffe und alle Funktionsaufrufe, macht irgendwas und reicht den Originalaufruf dann an das Originalobjekt halt weiter.
Damit kannst du zum Beispiel sowas machen wie ein Logging-Proxy.
Und das geht in Python tatsächlich total super.
Du kannst ein Objekt bauen, der alle Attribut- und Methodenzugriffe halt an ein anderes übergibt und währenddessen zum Beispiel mitschreibt, ja, hier wurde gerade folgende Methode mit folgendem Parameter aufgerufen.
Und der Code, der das Objekt reingereicht kriegt, der muss aber davon nichts wissen.
Der denkt einfach nur, hier kommt ein Objekt, was halt irgendwie, keine Ahnung, eine Datei ist.
Und dann hast du gleich.
Genau, und sowas wie eine Middleware, nur genau umgedreht im Prinzip.
Du injectest das Ding in was anderes rein.
Eine Mittelware ist ja typischerweise was, was in der Pipeline irgendwo drin sitzt.
Und du kannst aber halt bei beliebigem anderen Code das Ding einfach unterjubeln.
Und das läuft dann durch diesen Code mit durch.
Und wie mache ich das?
Das ist relativ easy.
Also die Frage ist immer, wann du bei Python mit irgendwelchen Meta-Funktionen auf die Schnauze fliegen möchtest.
Also die ernsthaften Proxies, die wir hatten, waren dann Security-Proxies.
Die waren in der Lage, anhand von Access Controls, einer relativ aufwendigen Architektur, tatsächlich für jeden einzelnen Funktionsaufruf zu sagen, ob der zulässig ist oder nicht.
Ob dieser User mit den Rechten auf dem Objekt, das da aus der Datenbank kam, wenn das Objekt dann auch noch zu dem Kunden gehört, da so, darf der jetzt diese Funktion aufrufen, ja oder nein.
Das war halt eine sogenannte Subject-Oriented Security.
Und das ist so ein Unterschied, heutzutage, viele Systeme haben nur View-Oriented Security, dass du halt sagst, okay, darf ich jetzt diesen View anschauen oder nicht.
Und da war es aber tatsächlich so, dass wir über diese, dass wir praktisch alle Objekte, die aus der originalen Factory mal rausgefallen sind von, okay, hier ist deine Datenbank-Connection oder sowas.
Die wurden in solche Security-Proxies eingepackt und dann konntest du nachher wirklich für jeden einzelnen Attributzugriff aussteuern, ob da jetzt Security eingreifen soll und sagen soll, nee, User mit den Permissions dürfen halt auf die Passwortfelder nicht zugreifen.
Und wenn du das in deinem Template-Code aber gemacht hast, dann ist aber der ganze Request abgewirkt worden mit das Jetso nicht.
Da musst du halt dann noch einen Check gegenbauen und sagen, ah, der darf das nicht, dann wird das Template ordentlich gerendert.
Ansonsten hast du aber immer den Safety-Belt, dass dein Framework, selbst wenn du Blödsinn im Code schreibst, du musst da nicht drüber nachdenken, darf ich jetzt hier das Passwort rausrendern oder nicht, das geht nicht raus.
Im schlimmsten Fall wird die Seite halt abgebrochen und sagt so, hier ist nichts.
Und die mussten wir aber tatsächlich auf C-Ebene schreiben, um wirklich alles komplett unterbinden zu können an Protokollen, die Python so kann, mit den Doppel-Underscore-Methoden.
Einen einfachen Proxy kannst du in Python schreiben, indem du einfach nur sagst, es ist eine Klasse, die hat ein Init.
Da übergibst du das Objekt, was geproxied werden soll, also was eingepackt werden soll.
Und dann kannst du über die GetAttre bzw.
getAttribute Protokolle dann halt sagen, okay, aha, hier versucht jemand gerade zuzugreifen auf folgendes Attribut.
Und jetzt kannst du ein bisschen Log-Output erzeugen und danach halt das Originalobjekt mit genau diesem Objekt wieder aufrufen.
Und das ist der Vorteil bei Python, was diese Patterns angeht, mit Python als protokollorientierter Sprache, du hast immer irgendwas, was keine spezielle Syntax braucht, sondern du kannst in der Metaprogrammierung immer diese Doppel-Unders underscore-Methoden benutzen, um dann wieder über das System selber zu reden.
Also dann dann Magic quasi direkt auf den Objekten, während die gebaut werden.
Jetzt müssten wir im Podcast sozusagen ein bisschen Live-Coding machen, um da.
Ja, ich kann mir nicht ganz genau vorstellen, an welcher Stelle du das injiziert werden, weil wenn du jetzt sagst, dass das schon gebaut wird, jetzt weißt du, die Init ist dann quasi schon durch.
Also der Konstruktor ist quasi geschiren und dann habe ich ein fertiges Objekt.
Genau, das ist aber das Proxy-Objekt.
Also es hat aber doch erst ein Proxy-Objekt gebaut und das dann quasi die anderen Init-Methoden erst aufruft und währenddem.
Nee, nee, nee.
Du hast ein Proxy-Objekt, das kriegt das Objekt, was du sozusagen, was du hinter dem Proxy haben möchtest, oder das reichst du dem rein.
Also, ich versuch's ein bisschen bildlicher zu machen.
Du hast ein Objekt aus deiner Anwendung, zum Beispiel den Datensatz von einer Person aus der Datenbank als Objekt.
Class Person und die Instanz davon, die aus der Datenbank kam und jetzt mit den Daten gefüllt wurde, die hast du vor dir.
Person A.
Person A.
So.
Und jetzt würdest du sagen, ich habe einen Proxy, der loggt alle Zugriffe auf Attribute von Objekten mit.
Das Ding weiß nichts von Personenklassen oder irgendwas.
Aber ich instantiere jetzt quasi den Proxy.
Jetzt instanzierst du ein Proxy mit dem Objekt Person A.
Mit dem Objekt Person A als Parameter.
Bei dem Proxy heißt dieses Objekt intern nur Kontext zum Beispiel.
Das speichert er bei sich auf Under Kontext zum Beispiel.
Genau.
Wichtig das Under, also auch hinten, damit es in Private Namespace kommt und so.
Und wenn jetzt implementiert der Proxy, noch eine zweite Methode.
Wenn du es ganz einfach machst, nimmst du UndergetAdre Under.
Die wird ja immer dann getriggert, wenn jemand auf ein Attribut zugreift, was nicht definiert ist.
Da der Proxy selber keine Attribute hat, wird es immer getriggert.
In dem Moment würde er dann zum Beispiel ein Print machen von, ja, hier wurde jetzt auf folgendes Attribut zugegriffen und ruft dann self.underunder context, an der Under, getAtter, dieses Objekt auf.
Diese Attributname auf.
Erreicht sozusagen den Methodenaufruf 1 zu 1 weiter und gibt es auch wieder zurück.
Damit sieht, und dieses Objekt kannst du jetzt jedem anderen, der von Logging keine Ahnung hat, einfach in die Hand drücken.
Und könntest damit zum Beispiel tracen, wer ruft denn hier auf diesem Objekt jetzt, wenn ich jetzt folgenden Kleinen-Code habe, eigentlich was auf.
Was hat er gemacht?
Und da kann man auch einen Debugger bauen oder sowas quasi.
Kannst du dir einen Debugger mitbauen, Flow Debugger.
Genau.
Oder kannst du halt auch sozusagen, ja genau, ein Debugger.
Kannst du zum Beispiel auch was machen mit, aha, den Code da hinten kann ich nicht ändern, weil der ist so irgendwie, keine Ahnung wie, komme ich nicht ran.
Aber jetzt mache ich so ein Proxy-Objekt und wenn jemand auf dem Proxy-Objekt die Methode A aufruft, dann starte ich ein PDB.
So, und das ist dann ein Proxy, du wickelst etwas ein und gibst das eingedwickelte Ding weiter mit dem anderen, mit dem Original drin.
Da kann ich quasi alles mitlesen, was der da an Datenboss irgendwo aus der Datenbank sieht, wenn ich den Probe.
Genau, also in Python kannst du, wie gesagt, es ist immer die Frage, diese Double Under-Methoden, wenn du wenn du sagst, der andere kann alles an Python schreiben, was gibt und du hast den Client-Code, der ist völlig unbekannt, dann musst du den auf C-Ebene schreiben, um wirklich sicher zu sein.
Wenn du aber weißt, was der andere Code macht, dann kannst du es halt, dann kannst du Proxys auch rein in Python schreiben.
Es ist nur in Python, wenn jemand gegen dich arbeitet mit deiner Metaprogrammierung, dann kommst du gegen das Gegenarbeiten auch erst wieder an, wenn du weißt, wie er gegen dich arbeitet.
Ja, das ist, damit kannst du keine Security bauen, aber du kannst halt, du kannst hilfreiche Dinge bauen.
Oder du kannst zum Beispiel eine Proxy bauen, der alle Methodenaufrufe cached.
Und das Schöne ist, du kannst das dann halt machen für Objekte, die du selber nicht unter Kontrolle hast.
Also das ist ja sozusagen, du hast einmal, die Objekte kommen von irgendwo, wo du den Code nicht ändern kannst.
Und du steckst in irgendwas rein, wo du auch nicht ändern kannst, was da passiert.
Und ein Proxy kann da an der Stelle halt dann plötzlich neue Fertigkeiten einführen, die mit beiden Codebasen im Prinzip nichts zu tun hatten.
Ja, da versteht ihr ja Magie mit dem Flow irgendwie was.
Genau.
Okay, also das war der Pattern Patrick.
Das Proxy ist ein ganz interessante Pattern.
Ja, genau.
So eine Strategy ist halt auch was ganz Interessantes noch.
Vielleicht, das wäre so eins, was ich reinbringen würde.
Aber magst du, Jochen, magst du vielleicht noch eins?
Ja, also ich zum Beispiel Fassade.
Das ist halt sozusagen wie baut man eine API, sozusagen, wenn man eine komplizierte Geschichte hat mit vielen Objekten oder so, dann baut man davor halt eine API, die jetzt irgendwie einfacher zu bedienen ist.
Das ist auch etwas, was man häufig hat.
Und würde ich jetzt sagen, so in Python, was man da ganz oft macht, eben ist ja eben nicht das Pattern zu verwenden, sondern das halt irgendwie in dann da init PY zu schreiben, sozusagen, was halt exportiert werden soll und quasi alles so umzuorganisieren, dass es dann halt von außen gut aussieht.
Ja, genau.
Ja.
Decorator sind in Python Sprachfeature inzwischen.
Das war auch mal ein separates Muster.
Aber ich meine, Decorator-Pattern ist das nicht das, wo man so etwas machen kann, wie wenn man aus einem Pfeil liest, dann die Leerzeilen wegschmeißen oder sowas.
Man rappt den Funktionsabrufen irgendwie und Input und Output kann man dann immer modifizieren.
Nee, das ist ein Python Decorator, also das mit dem Ad irgendwas drüber.
Ich meine, das Decorator-Pattern wäre ein bisschen anders.
Aber vielleicht tausche ich mich auch, weiß nicht mehr genau.
Ich meinte, das wäre halt irgendwie sowas, dass du halt sozusagen einem eben, du tust halt so, als wäre das ein normales Pfeil, aber in Wirklichkeit schmeißt das Objekt, was du halt mit dem Decorator-Pattern gebaut hast, halt intern, weiß ich nicht, sowas wie Leerzeilen weg oder Dinge, die nicht gepasst werden können oder so.
Tatsächlich ist es gerade auch so ein bisschen ähnlich zu dem Proxy, wie wir es beschrieben haben.
Da ist in Python der Unterschied nicht so groß.
Ja, ja.
Hier wird nochmal, also ich gucke gerade immer so ein bisschen nochmal die Wiki-Seiten nebenbei nach.
Beim Dekorierer, beim Decorator wird nochmal explizit darauf hingewiesen, dass man hier halt chainen kann.
Das kannst du mit dem Proxy aber auch machen.
Dass du da mehrere hintereinander schaltest.
Ja.
Ja.
Ansonsten, was mir noch letztens ist mir das aufgefallen, Mysterium, ich weiß nicht, in welcher Episode wir das hatten, habe ich mich irgendwann mal gewundert.
Da dachte ich zuerst, es muss irgendwann letztes Jahr gewesen sein, ob das irgendwie eine Python 3.8 Neuerung gewesen wäre oder so.
Ich weiß es nicht.
Ich hatte mit Listen von irgendwelchen Dingen zu tun, mit Listen von Integers.
Und das war deutlich kleiner, als ich das gedacht hätte.
Ich dachte so, hä, komisch, warum, also es braucht tatsächlich nur irgendwie 8 Byte irgendwie pro Integer.
Dann dachte ich, eigentlich hätte ich jetzt mit deutlich mehr gerechnet, irgendwie, weiß ich nicht, eher so 23 oder als ich irgendwas zu einem Dreh.
Warum ist denn das so viel kleiner?
Und die Antwort darauf habe ich jetzt gefunden und das ist eigentlich blöd, aber ich weiß nicht, wisst ihr das zufällig?
Oder hättet ihr eine Ahnung gehabt, was das hätte sein können?
Also ich habe halt eine Liste gemacht mit irgendwie, weiß ich nicht, 100 Millionen Integers und das war halt dann bloß 800 MB im Hauptspeicher und ich hätte aber eigentlich erwartet, dass es hätte dort nicht mehr sein müssen.
Okay, Renundanzen weggelassen, ne?
Ja.
Nee, das, was da tatsächlich passiert ist, ist halt internen Benutzer-Python-Interpreter auch ein Pattern, um halt Integers und zwar nur kleine Integers sozusagen da Hauptspeicher zu sparen.
Das Pattern nennt man Flyweight.
Und die Integer von 0 bis 255, glaube ich, sind halt irgendwie immer die gleichen.
Also man kriegt immer das gleiche Integer sozusagen zu sehen und deswegen ist das halt im Hauptspeicher deutlich kleiner.
Das heißt, also es gibt halt sozusagen nur
eine Form von Singleton.
Es hat auch, es ist nicht zu Singleton, genau.
Also eigentlich ist das halt irgendwie für solche Dinge gedacht, wie du hast halt, wenn du jetzt einen, weiß ich nicht, einen Textprozessor hast, irgendwie so ein Programm, was irgendwie so was wie Word oder so.
Und wenn das jetzt irgendwie Buchstaben rendert, dann willst du halt nicht immer quasi alles, was halt in, der Buchstabe ist halt ein Objekt, dann willst du nicht immer alles für jeden Buchstaben, was da dran hängt, nochmal haben, sondern du willst es halt nur den Teil in dem Buchstaben austauschen, der halt ausgetauscht werden soll und der ganze Rest bleibt einfach immer gleich.
Und genau, für sowas ist es eigentlich gedacht und in Python wird es halt auch für Integers verwendet.
Und deswegen ist halt, wenn man jetzt sagt, Liste von 100 Millionen Integers, also vor i in Range, weiß ich nicht, 100 Millionen, aber dann sagt man halt irgendwie sowas wie 0 oder 5 oder so, dann ist das halt sehr klein.
Aber wenn man sagt, nicht also nicht 0, sondern irgendwie i, dann wird es plötzlich sehr groß.
Also dann hat man den Vorteil nicht mehr.
Aber genau, da hatte ich mich irgendwann mal drüber gewundert und jetzt habe ich, habe ich irgendwann zufällig gesehen, woran das lag.
Das hat, also in Python gibt es ja noch den Begriff Interning für.
Das ist sozusagen, da wird, äh, das kann man dann auch ganz gut sehen, wenn man halt die Objekte dann mit einem Identitätsvergleich halt anguckt.
Dann sind es halt tatsächlich wirklich immer, dass das Is das gleiche ist.
Und das gibt es bei Strings halt auch.
Da gibt es auch im bestimmten Bereich irgendwas mit Strings, die kürzer sind als so und so lang und kein Leerzeichen enthalten.
Und du machst ihn zweimal, also du jagst ihn auch zweimal durch den Literal durch, sind am Ende die gleichen Strings.
Das ist so ähnlich wie bei den Integern.
Okay.
Und also das, was ich halt sonst immer noch ganz gerne mag, ist dieses Strategy-Ding.
Und das ist im Prinzip halt das Thema von, wie du halt Code flexibilisieren möchtest.
Und zwar gegebenenfalls auch noch auf eine Pluggable Art.
Du könntest halt normalerweise, wenn du ein komplexes If-else hast, oder if-if-else, if else, if else, else, elf und du willst es flexibilisieren, weil da kommt noch ein Fall dazu, noch ein Fall dazu, noch ein Fall dazu.
Zum Beispiel sowas wie, aha, du möchtest unterschiedlichen Code ausführen, je nach Sprache, die wir unterstützen.
Dann kannst du halt das lange L if so refakturieren, dass du jeden Teil davon in eine eigene Funktion packst und entweder legst du die alle nach einem bestimmten Schema benannt in eine Klasse, sagst also sozusagen class country format Country Address Format und die Methoden darauf sind dann entsprechend zum Beispiel die I
SO-Codes von den Ländern.
Und wenn du dann für eine Adresse, die du hast, dann sowas formatieren möchtest, dann kannst du sagen, so, dann schnappen wir uns die Klasse, lesen von dem Objekt runter den ISO-Code von dem Land und rufen dann die Methode auf, deren Namen dem ISO-Code entspricht.
Und dann kannst du natürlich dir auch überlegen, das muss ich ja nicht unbedingt auf einer Klasse machen.
Ich kann dir auch einfach ein Dictionary irgendwo hinlegen, wo diese ISO-Codes drin stehen und lade damit sozusagen andere Drittanbieter-Packages ein, in dieses Dikt hinein andere Arten von, noch andere ISO-Codes reinzuschreiben, die ich halt noch nicht kannte und mein Code ist dann in der Lage, halt jede beliebige Art der Formatierung aufzurufen.
Oder jemand anders kann auch hergehen und kann sagen, hey, ich definiere diese dein Format für italienische Adressen, gefällt mir nicht, also überschreibe ich jetzt diesen Dikt-Eintrag von IT mit meiner eigenen Methode und der Code, der aber jetzt aufruft, der das aufruft, der hat halt jetzt keine hartkodierten LFL-Zweige mehr, sondern der macht immer bloß noch dieses Dictionary-Lookup von, ja, mit welcher Methode soll ich es denn formatieren?
Und das ist dann halt eine sogenannte Strategy im Prinzip.
Was ist ein Observer?
Ich weiß nicht nach.
Muss ich hier auch nachgucken.
Also ich glaube, das ist, ah doch, warte mal, das ist halt, wenn du benachrichtigt werden möchtest über irgendwie, wenn sich irgendwo was geändert hat.
Also, die dir Bescheid sagt.
Naja, du registrierst, also die registrieren sich halt irgendwo quasi.
Also alle, die benachrichtigt werden möchten, registrieren sich irgendwie und dann rufst du da einmal halt das auf und dann werden halt alle benachrichtigt.
Ach Gott, ja, es ist lange her, dass ich mich damit beschäftigt habe.
Ja.
Das hat man im SOB auch, das war tatsächlich auch eine ganz, das war das Event-Handling-System tatsächlich.
Das ist halt ein, du hast zwei Enden, die da mitspielen müssen.
Das eine ist, du möchtest halt, dass zu bestimmten Ereignissen in deiner Anwendung andere Leute flexibel definieren können, was da alles noch passieren soll.
Das heißt, du hast sowas wie, okay, ich habe hier eine Methode, ein Datensatz wird geändert, dann änderst du den Datensatz und am Ende von der Methode schreibst du einmal sowas rein wie Eventsystem.event oder Trigger und dann kannst du zum Beispiel übernehmen, übergeben den Namen eines Events, a la changed record.
Kannst auch, kannst du alle möglichen Sachen machen, um das zu identifizieren.
Du kannst auch singleton Objekte machen, um Events zu registrieren oder Interfaces oder was immer, aber so im einfachsten Fall sagst du sowas wie Event Trigger, Eventname und danach übergibst du zum Beispiel irgendeinen eventspezifischen Payload.
Das ist in Python ja auch schön zu machen, weil du ja auch mit Stern-Args, Stern-Stern-KW-Args arbeiten kannst.
Aber du würdest halt sagen, so Record Change als Event und hier ist das Objekt, was sich geändert hat.
Und jemand anders kann zu dem Event-System als unparteischen Dritten hingehen und sagen, so hier ist eine Funktion, die übergebe ich dir jetzt, die rufst du bitte immer dann auf, wenn ein Record-Change-Event kommt.
Das ist so, wie man es im JavaScript ja auch kennt, dass man sagt, ich möchte bei einem Mausklick benachrichtigt werden, ich möchte bei einem Tastaturanschlag benachrichtigt werden, so kann man das natürlich auch einfach für beliebige Dinge kodieren.
Und wichtig dabei ist halt, das ist ja, daraus baut man sich sein eigenes Framework.
In JavaScript ist über das DOM ja definiert, welche Events da gibt.
Und das ist eine Art, wie man sich selber solche Events halt bauen kann.
Dass man sagt, so, okay, wenn auf einem Record-Objekt das Safe aufgerufen wird, dann triggert der gleichzeitig noch, wenn sich tatsächlich was geändert hat, diesen Event.
Und dann kannst du zum Beispiel solche Dinge tun wie wieder loggen oder nochmal ein anderes Event mitschreiben oder keine Ahnung.
Kann man Signale abfangen, genau.
Und wichtig ist halt an der Stelle, das ist in Python dann typischerweise eine synchrone Aktion, weil ja im Prinzip, du rufst die eine Funktion auf, die ruft dann, die macht ein sogenanntes, nennt sich auch Method Dispatch, die ruft dann auf, die guckt danach, da kann man auch überlegen, darf es mehrere Händler geben oder nur einen, in welcher Reihenfolge werden die aufgeführt?
Das sind dann so wirklich so differenzierte Betrachtungen von dem konkreten Eventsystem, was man sich baut.
Oder gibt es nur ein Best-Match von, je nachdem, dass ich auch noch auf Typen von den Parametern matche, sowas wie, ich will aufgerufen werden beim Record-Change, aber nur wenn der Rekord vom Typ Person war und solche Sachen.
Und dann kannst du halt solche Dinge machen wie der erste, ein User setzt eine Bestellung ab und anderer Code von dir, ein anderes Modul, ist zum Beispiel dafür da, eine E-Mail rauszuschicken, wenn der User seine allererste Bestellung abschickt.
Ja, dann kannst du das halt als völlig kommen.
Da geht es immer, also häufig geht es bei diesen Sachen darum, wie kann ich Code so geschickt modularisieren, dass ich halt später, wenn ich die Anwendung umbaue, möglichst wenig umstricken muss und mir selber auf den Füßen stehe.
Idealerweise kannst du halt dann auch so mit sowas wie Feature Flex ganze Module stilllegen und das ergibt aber trotzdem noch eine konsistente Anwendung und nicht, ah, da musst du in der Klasse die drei Zeilen da wegschmeißen, in der Klasse die drei Zeilen, in der Klasse die drei Zeilen, sondern daraus kriegst du halt so eine komponierbare Anwendungsarchitektur im Prinzip nachher.
Und auch da wichtig, Patterns sind etwas, die entstehen erst, wenn man etwas macht.
Deswegen ist das ja ein sehr handwerkliches Buch, ein handwerkliches Konzept, im Sinne von, die haben halt, das ist nichts, was man sich hinsetzt und sagt, so wir designen jetzt hier nochmal ein paar Patterns, sondern das ist halt ein so, wir haben jetzt hier so ein 120 Anwendungen geschrieben und das da sehe ich ständig in Variationen.
Was ist denn jetzt die Essenz von diesem Ding in Variation?
Ah, okay, this is a published Subscribe, das ist ein Observer.
Okay, alles klar, da hat man also dieses Ende und jenes Ende und das Ende und hier jetzt geht der Blumenstrauß auf, von wie könnte man das eigentlich alles bauen.
Und das heißt aber nicht, dass man das halt jedes Mal ständig in der Vollausprägung baut.
Ich weiß, ich sage das jetzt zum dritten Mal, aber ich habe auch gelernt, wenn man Dinge zum siebten Mal sagt, dann hat die Hälfte der Leute zum ersten Mal gehört.
Ich habe heute gelernt, weil du gerade vom Blumenstrauß am Methoden sprachst, es gibt auch welke Blumen in Blumenstraußen.
Ja, genau, es gibt auch welke Blumen.
Möchtest du welke, möchtest du unter den Patterns welke Blumen suchen?
Ja, tatsächlich, du weißt ja nicht genau irgendwie, was da stimmt, wenn du jetzt davon noch keine Ahnung hattest und die eben nicht durch Patagition von vornherein verstehst, oh ja, das ist das, dies und jedes, sondern du versuchst halt dich irgendwie an eine, ich sag mal, clevere Architektur zu halten oder seine, die du für clever hältst, vielleicht weil du es noch nicht verstehst oder denkst, du möchtest halt in die Richtung entwickeln, um möglicherweise flexibel oder modular zu bleiben oder so.
Oder halt verschiedene Schnittstellen aufmachen zu können, wenn du sie brauchst, dann könnte sowas ja passieren, dass man eine welke Blume baut, weil man da irgendwelchen Unsinn gebaut hat.
Also speziell halt, das kommt dann eher aus dem Agilen, das You Ain't Gonna Needed.
Also ich finde halt, man sollte sich bei der Anwendungsmittlung extrem stark auf den, erst erstmal auf den Inhalt der Anwendung konzentrieren.
Und erst wenn man eine gewisse Menge und Masse beisammen hat und überhaupt weiß, worum es eigentlich geht und was man tut, dann kann man irgendwie ans Gärtnern gehen und kann gucken, okay, jetzt räumen wir hier mal auf.
Also da ist Python als Sprache natürlich auch wieder extrem gut positioniert, weil, also ich habe jetzt in den letzten Jahren häufig Projekte angefangen mit so, ich fange mit einer einzigen Datei an, ich baue bei keinem Package, kein Nichts, eine einzige Datei, keine Dependencies, erstmal nur die Standardlibry und mal gucken, wie weit ich komme, um das eigentliche Problem mal so 80% zu lösen, was ich eigentlich gerade habe.
Und wenn ich dann weiß, worum es hier eigentlich geht, weil ich bin ständig dabei, dann alle Steine wieder auseinander und zusammen und auseinander und zusammen und vorwärts und rückwärts, wenn du da schon zu viel Code angehäuft hast in so einem Moment, dann macht sich das halt langsamer.
Und das ist ab einem gewissen Punkt dann auch halt legitim, wenn du feststellst, so, jetzt brauchen wir hier irgendwie ein Plugin für NFS und für Ceph und für einen S3 und für so, jetzt müssen wir anfangen, diesen ganzen Code zu restrukturieren.
Dann ist es halt schön, wenn man in der Hinterhand hat, von was gibt es denn da für Patterns, wenn man sowas umstrukturiert, also bauen wir da jetzt ja, okay, guck mal, hier passt jetzt irgendwie eine Strategy und da passt noch ein Event-Handling-System und dann haben wir den ganzen Code irgendwie reduziert, dann ist es jetzt, jetzt gefällt es mir.
Aber für mich ist das immer eine Sache, das geht erst am konkreten Objekt.
Ich kann mich nicht vorher hinsetzen und sagen, so, wir bauen jetzt ein neues Backup-System.
Wir brauchen einen Observer.
Okay.
Und ich glaube, was eben ganz wichtig ist, was bei den Patterns auch.
Also Jagny
ist auch ein Pattern.
Nee, JacNI ist eine Methode, die aus dem originalen Extreme Programming kam.
Das ist immer, wenn jemand sagt, ah, vielleicht könnten wir nein.
Aber irgendwann im Zug, nein.
Aber wenn dann in zwei Jahren, nein.
Wichtig gegenüber Jagni ist halt, wenn man auf der Ebene bleiben, ist immer noch persistence.
Persistency means having to say I'm sorry.
Also dieses You ain't gonna need it wird ein bisschen, kriegt ein Gegengewicht durch, ja, aber alles, was du als persistente Daten wegschreibst, wird dir halt auf Gedeihenverderb im Nacken hängen.
Ja, Code ist flexibel.
Code ist total easy.
Kannst du umbauen, kannst drehen, kannst du wenden, solange das Interface das gleiche bleibt, alles super.
Aber wenn du es einmal auf Platte geschrieben hast, dann kannst du aber wissen, dass es dich in zehn Jahren noch verfolgt.
Ja, und wenn man das richtig gemacht hat, dann hat man halt sozusagen auch später noch großen Nutzen.
Also der schöne Spruch da an der Stelle ist ja immer irgendwie Daten, also gute Daten altern wie Wein.
Das ist halt schön, wenn man irgendwie mehr gute Daten hat.
Schlechte wie Milch.
Ja, Applikationscode, wenn man gesagt hat, Applikationscode altert wie Fisch.
Das ist halt
wer hat das geschrieben?
Oh, das war ich.
Ah, ja.
Der hat nicht mehr so ein paar dahinter.
Ich habe letztens einen Anschluss gekriegt von Jochen.
Unmöglich, also du kannst das nicht machen, Alter.
Furchtbar, dass ich das denn auch.
Nee, das geht aber gar nicht.
Jochen, das von dir.
Oh.
Ah, das passiert.
Ja, gar nicht so schlecht, ja.
Ja.
Naja, das
passiert auch denn jetzt.
Das passiert durchaus ab und zu.
Ich glaube an der Stelle auch, das ist halt der handwerkliche Teil wieder.
Und jetzt mache ich mal die Schleife, wo ich halt eben hinwollte, die Gang of Four-Leute, die haben alle ein extrem gutes Sprachverständnis selber gehabt von der Sprache, um die es eigentlich geht.
Mit warum ist das hier ein Problem?
Und welche Mechanik der Sprache steht mir eigentlich im Weg und wie kann ich die halt countern.
So was wie, welchen Konstruktor habe, dann bin ich halt auf den Typen festgelegt und kann ich das nicht machen, kann ich sagen, nee, deswegen muss man Beispiel ist halt bei Java das Getter Setup Pattern.
Wenn du Leute Java Code, ernsthaft Java Code schreiben siehst, dann bauen die halt für jedes Attribut immer ein, keine Ahnung, Klasse Person, Geburtsdatum als Attribut und dann ein Set-Geburtsdatum, Get-Geburtsdatum.
So.
Warum?
Weil es in Java später, wenn du dich mal, wenn du mal irgendwie meinst, du musst hier was ändern, dann hast du keine Chance mehr, wenn irgendwelcher Client-Code auf Attribute zugreift, jemals noch irgendwie dich dazwischen zu hangeln.
Das ist ein reiner Future-Proofing Aspekt.
Und ich sehe immer wieder Leute, die aus der Java kommen, die in Python Code schreiben und dann für jedes Attribut eine Getter Setter Methode schreiben.
Und du siehst sofort, das ist Java und wenn man immer erzählt, nein, es gibt, du kannst im Nachhinein eine Property draus machen, das kannst du machen, was du willst, dann ist alles schick.
Ja, aber.
Nee.
Nee.
Das ist halt, und da merkt man halt, es ist extrem wichtig zu verstehen, wie die Sprache selber mechanisch funktioniert.
Weil nur dann diese ganzen Patterns tatsächlich irgendwie Sinn haben oder keinen Sinn haben.
Und das ist, glaube ich, was, was ich halt an der Stelle wieder diesem Handwerklichen und sich selber weiterentwickeln mitgeben würde, ist, wenn man halt so Patterns gerade aus anderen Sprachen halt nach Python transportiert, muss man schon immer nochmal extrem gut auf die Suche gehen von hat's hier nicht irgendeine andere Mechanik in Python, die das schon überflüssig macht.
Wir haben die Dekoratoren, wir haben die Konstruktoren, wir haben New, wir haben Getter Setter, also wir haben Properties, die ganzen Sachen und die erschlagen viele von diesen anderen Sachen halt.
Ja.
Also die Gang of Four Patterns habt ihr so einigermaßen einmal kurz eingekringelt und erwischt.
Würde ich sagen.
Gibt es noch welche, über die ihr unbedingt reden möchtet?
Naja, es gibt dann auch so ein paar, die halt später dazugekommen sind, beziehungsweise Sachen, wo man nicht so klar sagen kann, ist das jetzt eigentlich ein Design-Pattern oder sowas wie MVC, weiß ich jetzt nicht.
Ist das ein Design-Pattern?
Eher nicht, ein bisschen größer, keine Ahnung.
Model View Controller.
Ja, genau, genau.
Schwer zu sagen.
Oder sowas wie.
Na, Model View Controller ist älter.
Das war nicht, also Model View ist selber, das ist eine, das ist eine Anwendungsarchitektur.
Die kam aber 82, 83 irgendwann.
Also die war halt schon auch, bevor man sich mit dem Begriff Patterns auseinandergesetzt hatte an der Stelle.
Ja, kann gut sein.
Ja, oder halt so etwas wie, ich glaube, wie kam aber dann tatsächlich später Datenbank, so ORM, wie baue ich eigentlich ein ORM?
Also sowas eben Active Record oder halt Datamapper Pattern, das sind halt auch so, tja, hm, keine Ahnung, ob das Pattern sind oder was ist denn das jetzt schon wieder?
Ja, das ist halt die Frage, wie man sozusagen die Übersetzung macht zwischen Sachen, die jetzt in der Datenbank, vor allem in relationalen Datenbanken liegen, und halt Objekten in Python beispielsweise.
Und das sind halt diese beiden unterschiedlichen Dinge.
Also Active Record ist halt das, was Django macht, oder halt auch Ruby und Rails.
Und Datamapper ist halt das, was SQL Alchemy macht und hat so.
Und wo ist der Unterschied?
Naja, also du hast es, du kennst du dich mit SQL Alchemy gut aus?
Ja, ich kenne mich halt mit SQL Alchemy aus, ich kenne mich wiederum mit Active Record nicht anjochen.
Super gut, dann mache ich.
Ich lese jetzt gerade mal schnell mal wieder.
Dann fangst du noch mit Active Record an, Jochen und dann gemäner.
Ja, also da ist es halt so, dass quasi jedes Objekt repräsentiert halt eine Zeile in der Datenbank und die Attribute sind halt die Spalten.
Und genau wenn man halt halt irgendwie Dinge aus der Datenbank holt, dann hat man halt eine Liste von diesen Objekten und wenn man da Attribute ändert, dann speichert das halt die, ja, kann man halt sagen, auf dem Objekt, auf der Zeile halt, speichert das und dann geht das Teil zurück in die Datenbank und ja.
Genau, so sieht das halt ungefähr aus.
Und normalerweise hat man halt eine Klasse, die, jedenfalls, ich sage jetzt mal so, wie es in Django ist, hast du halt eine Klasse, die definiert, welche Spalten oder es halt in dieser Tabelle gibt.
Also du hast pro Tabelle eine Klasse und die Spalten sind halt Attribute auf dieser Klasse, die halt so ein bisschen, dass diese Diskriptorengeschichte ein bisschen eigenartig definiert sind.
Und dann kann man halt auch aus diesen Klassen die Tabellen direkt erzeugen.
Auch die sozusagen Relationen zwischen den Tabellen sind halt in den Attributen enthalten.
Das heißt, ich kann halt, wenn ich mir so diese Tabellen hin definiert habe, halt auch komplett mein Datenbankschema halt aus den Dingern erzeugen.
Und ja, immer wenn einzelne Sachen passieren sollen auf einer Zeile, dann sind das halt Dinge, Methoden auf dieser Klasse.
Eine einzelne Instanz ist eben eine konkrete Zeile.
Und wenn etwas alle Sachen betreffen soll oder viele Zeilen, dann sind das halt sogenannte, also Django heißen die Model Manager, die dann halt irgendwie eine ganze Reihe von Sachen updaten oder halt irgendwie Reihe von Zeilen löschen.
Und so kann man das dann halt aufteilen.
Alle Methoden, die irgendwie auf einem auf einer einzelnen Zeile was machen sollen, gehen halt in die Klasse und alle Methoden, die halt auf vielen Sachen was machen, gehen halt in den Manager auch, die jetzt irgendwas filtern oder so.
Und dann, ja.
Genau, so funktioniert es ungefähr.
Und jetzt kommt sie gleichen.
Ja, Data Mapper.
Ich habe selber erstmal noch die Active Record Sachen angeguckt.
Das Interessante bei Active Record ist ja, dass du relativ klar Tabelle und Klasse aufeinander mappst.
Und beim Datamapper ist es tatsächlich so, du entkoppelst es komplett.
Und die Objekte müssen halt, also beim Active Record hat zum Beispiel die Klasse gerne irgendwie eine Save-Methode.
Wo du sagen könntest, ich ändere ein paar Attribute und dann kannst du irgendwie Save aufrufen und dann ist die irgendwie in der Datenbank.
Das ist zumindest das klassische Pattern dafür, wie es bei Django jetzt gerade aussieht, weiß ich nicht.
Ja, ja,
doch, ist es genauso.
So, genau, und bei Signal Icon ist es so, dass im Prinzip deine Klassen von der Datenbank überhaupt nichts wissen.
Es gibt einen deklarativen Stil, bei dem du tatsächlich dann wieder innerhalb, da kannst du wieder sagen, doch, die Klasse weiß was davon, weil du es halt eng aneinander koppeln möchtest, um solche Effekte zu haben, wie dass du deine Datenbank anhand deiner Klassendefinition halt ableiten kannst.
Aber im Prinzip gibt es dann zwei getrennte Schichten von einmal, okay, ich beschreibe hier Tabellen und ich beschreibe Klassen und jetzt beschreibe ich, wie diese Tabellen auf Klassen gemappt werden.
Und da kann halt auch alles möglich reinspielen, dass irgendwelche Attribute über komplexere Querys erst zustande kommen und dass da irgendwelche komplexen Relationen zu sind und etc.
Und SQL Alchemy bricht das auch extrem abstrakt runter, dass du halt mit den Objekten nativ arbeitest, ohne irgendwie über die Datenbank nachzudenken.
Und dann baut der sich und du brauchst kein separates, wenn du viele Aktionen machst, kannst du auch einfach auf 100 Objekten rumrechnen.
Und er fasst das nach hinten automatisch in die optimierten SQL-Statements zum Beispiel zusammen, dass er weiß, okay, jetzt hat der hier, der Herr hat hier 100 Objekte angefasst, jetzt machen wir ein großes Update-Statement, was irgendwie einmal sinnvoll aussieht.
Bumm.
Anstatt halt dann die eher naiveren Varianten von, okay, jedes Mal Safe drücken ist, jedes Mal irgendwie einmal zur Datenbank laufen und speichern drücken oder so.
Und da ist es halt einfach viel, viel flexibler, wenn du das Datenbankmodell entkoppeln möchtest.
Das ist zum Beispiel auch dann, wenn du konfrontiert wirst mit, ich habe hier eine fertige Datenbank, die besteht seit 20 Jahren, die muss jetzt hier irgendwie mal rein.
Und dann kannst du mit dem Data Map Map.
Bla, es ist Zeit fürs Bett.
Dann kannst du mit einem Data Mapper Pattern nämlich beliebige Transformationen machen, um zu sagen, okay, die Datenbank sieht aus wie Kraut und Rüben, aber ich habe vorne ein ordentliches Object-Model dran.
So, und bei SQL Alchemy ist das Ganze sozusagen, wie heißt es in der so schön, auf 11 gedreht.
Da ist es so richtig laut, da sind die Abstraktionen so gut gemacht und die haben sich so viel Mühe gegeben, was Performance angeht, dass so ein Zeug von, du machst komplexere Abfragen und er weiß irgendwie, okay, wenn ich das jetzt mache, dann lade ich schon mal irgendwie die nächsten Relations mit und falte irgendwie die Relation-Objekte schon mal in die originale Set Query mit rein, damit ich nur einmal einen großen Bike-Transfer am Anfang habe, anstatt nachher bei jedem Attributzugriff nochmal zur Datenbank zu laufen oder so.
Und das kannst du da extrem genau aussteuern.
Django deine Manager, oder?
Bitte?
Ja, in Django ist das, aber da gibt es das auch, da gibt es das werden halt die Sachen, also das, was man halt nicht will, das droht bei Active Record natürlich, ist, dass wenn du jetzt zum Beispiel irgendwie ein Objekt hast und das hat halt irgendwie ein Foreign Key, ist halt mit einem anderen Objekt verknüpft und dann greifst du auf ein Attribut von dem verknüpften Objekt zu und das am besten in einer Liste irgendwie von Dingen, auf so einer Webseite, wo du halt eine Listenansicht hast und dann hast du halt irgendwie, zeigst du halt eine Tabelle zum Beispiel an oder halt
eine Liste von Dingen und nimmst dann halt das Attribut von einer verknüpften anderen Geschichte, zum Beispiel einen User-Name oder so, der halt an einem von diesen Listenobjekten dranhängt, dann kann es halt sein, dass du halt, wenn du das naiv machst, kriegst du halt N plus eins Queries gegen die Datenbank.
Und das ist natürlich extrem fies und ein Haufen Performance-Problemen kommen, genau deswegen.
Aber also in Django sagt man dann halt Select-Related.
Genau.
Und dann zieht sie oder Prefetch-Related für N-2M-Relationen und so.
Also das geht auch alles.
Man muss halt ein bisschen.
Machst du das am Model oder musst du das irgendwo in der Query machen?
Das machst du an der Query.
Genau, und bei SQL IME kannst du das im Prinzip modellieren.
Da kannst du halt diese ganzen Relationen alle ausdefinieren.
So mit diesem, auch so richtig mit Vor- und Rückreferenzen will ich die irgendwie als Listen oder Dicts kriegen oder als Attribute oder so ein Zeug und kannst dann halt sagen, so, und irgendwie die Richtung, die machst du bitte als Eagerload und die bitte nicht und folgende zehn Attribute bitte im Eagle Load wieder rauslassen und das kannst du halt so alles zurecht tunen, damit du halt dann möglichst dummen, konkreten Query-Code schreiben kannst, der über so ein Zeug nicht mehr nachdenkt.
Ja, interessant, genau.
Und du kannst bei SQL Alchemy auch sehr dynamisch, dann, die haben halt auch eine vollgetrennte Schicht zwischen, ich habe erstmal dieses Object Mapping-Ding und dann hat der nochmal eine komplette Abstraktion über SQL drüber.
Das heißt, der kann dann halt die ganzen SQL-Dialekte halt auch noch nach unten.
Der hat im Prinzip einmal SQL in Form von diesem Builder Pattern.
Ja, du kannst auch sagen, ich hätte gerne eine Query, also Query, Klammer auf, von folgendem gemappten Objekt.
Und dann Punkt Filter Punkt Join.
Hast du nicht gesehen?
Immer so Funktionschains hinten dran.
Und er baut dir dann nachher tatsächlich einen für die Datenbank, die du eigentlich hast, also Postgres oder MySQL, ein syntaktisch korrektes und optimiertes Query halt auf.
Unter Berücksichtigung von allem, was er über diese Mapper weiß, was er gleich noch als irgendwie Eagerload oder nicht machen soll.
Und du kannst halt mittendrin immer wieder die Ebenen wechseln.
Du kannst irgendwie im Object-Mapping-Teil sein, drei Zeichen dann von diesem generativen, also dann irgendeine Query mit dem generativen SQL machen, da dann aber wieder gemappte Objekte reinstecken und der kriegt das immer so vor und zurück und vor und zurück.
Hat halt das Problem, wenn es, also es tut sehr selten nicht, aber man muss sich halt dann schon relativ viel mit schon gut mit dem relationalen Datenmodell auskennen, um mit dieser Komplexität dann auch umgehen zu können.
Weil wenn es dir dann mal um die Ohren fliegt, dann kommen da halt auch Fehler raus mit so, was will der jetzt von mir?
Ja.
Aber wir haben das in Projekten eingesetzt, wo es halt teilweise um richtig, richtig große Datenmengen ging.
Und da dann halt wirklich an diesen Stellen alle Stellschrauben zu haben, um das gerade zu ziehen, das ist halt dann in dem Moment extrem viel wert.
Und umgekehrtes Active Record wiederum, du fängst halt an und hast sofort was, was du präsentieren kannst.
Das entwickelt sich halt sehr schnell.
Das ist halt super.
Ja, und dann, ich meine, das geht bei SQL ja auch, ich meine, man kann ja auch immer noch dann einfach auf großes SQL zurückfallen, wenn halt irgendwas, wenn man schon Spezielles macht.
Ja, Single schreiben muss, ja.
Haben wir alle Patterns durch, tatsächlich.
Also, du wolltest noch irgendwas zu Datenbanken sagen.
Ich glaube, da gibt es noch so ein Solid-Modell oder sowas.
Ja, achso, nee, das ist dann nicht Datenbanken, aber das ist auch so genauer, ja, ich weiß nicht, ob das Patterns sind, das ist eher so, was sollte man, wenn man Dinge macht, sowieso beachten vielleicht.
Das ist halt auch so eine ganz bekannte Geschichte.
Ich weiß gar nicht, ob man es unter Pattern Designprinzipien.
Ja, ja.
Was ist das denn mit der Kundin?
Ja, das ist auch etwas, was es gibt ja dieses Buch Clean Code von Robert Martin, Ankel Bob.
Gibt es was auch in Python?
Das ist, nee, das ist auch.
Dieses ganze, das ist übrigens, ich meine, ehrlich gesagt, ich bin ja ein bisschen peinlich berührt, wenn ich dann irgendwie so, ob Java-Pattern, keine Ahnung, habe ich schon mal gehört oder so.
Also bei den meisten Patterns ist es so, ich habe die schon mal gesehen, vielleicht irgendwann mal oder auch mal, aber so wirklich viel zu tun habe ich mit denen ja eigentlich nicht.
Also dieses ganze Thema kommt eigentlich eher aus so ein bisschen anderen Ecke der Softwareentwicklung.
Und während das jetzt bei so Java-Geschichten oder so halt so ist, eben.
Das ist also für Junior-Stellen irgendwie, wenn man sich da, wenn man da ein Vorstellungsgespräch ist, dann wird halt erwartet, dass man die alle kennt.
Und ja, das wäre dann schon sehr peinlich, wenn man sagt, ich habe keine Ahnung, was das eigentlich ist.
Aber ja, zum Glück mache ich ja kein Java.
Ja, das Interessante ist auch, man kann das Zeug ja im Alltag eben nicht so benutzen, wie bei jeder Zeile Code, die ich schreibe, gehe ich nochmal alle mir bekannten Patterns im Prinzip hier durch, ob ich die jetzt ja nicht verletze.
So funktioniert es halt nicht.
Du willst ja, und deswegen ist Pattern, glaube ich, auch für unsere Kognition eigentlich ganz interessant.
Du willst aber, dass dein Gehirn eine ausreichende Menge von so einem Zeug so dran trainiert hat, dass wenn da irgendwie die roten Warnlämmchen angehen, du halt weißt, Moment, jetzt müssen wir nochmal nachdenken, warum geht das hier schief?
Damit du dann halt wenigstens weißt, wo du googeln musst.
Ja, immerhin.
Über Solid jetzt auch, ich habe über Solid jetzt gerade nochmal schnell drüber geguckt, neher, oh, das ist aber schon ganz schön alte Schule teilweise.
Also wenn ich halt Lisk of Substitution höre, der so, oh ja, das Akademikerherz.
Das ist das L in Solid, ja, das Liskov-Substitution.
Ja, also es ist halt auch alles relativ alte Geschichte und das macht halt in diesem Kontext von so statisch typisierten Programmiersprachen, macht das auch alles irgendwie gewisserweise schon Sinn, also durchaus mehr Sinn als bei Python, weil da viele Dinge einfach automatisch erfüllt sind.
Also eben, ich würde sagen, ja, ich würde...
Lischkoffs Substitution Principle.
Nee, das ist ein Design-Thema, das musst du selber als Programmierer richtig umsetzen.
Das ist Typtheorie und das ist die Aussage, dass Objekte in einem Programm, also aller Programmcode, der Objekte verwendet, also mit Objekten arbeitet, sollte immer in der Lage sein, alle Subtypen dieser Objekte zu akzeptieren, ohne die Korrektheit des Programms zu verletzen.
Genau, also ich würde jetzt mal so als konkretes Beispiel wäre jetzt für mich sowas wie, man macht eine Vorschleife über Mitarbeiter und wenn man, wenn jetzt man in der Vorschleife so Faltunterscheidungen macht, also und nehmen wir an, man hat einen Typ Hierarchie, es gibt halt irgendwie eine Oberklasse Mitarbeiter und dann gibt es halt konkretere, die halt irgendwie davon erben, also weiß ich nicht, irgendwie, keine Ahnung, CEO oder irgendwie Senior Vice President Facility Management oder sowas.
Und wenn man jetzt aber in der Vorschleife, man iteriert über alle und weiß jetzt nicht genau, welchen konkreten Typen man hat, man weiß nur, es sind halt schon irgendwie Mitarbeiter und macht dann Fallunterscheidungen wie, also, wenn das jetzt irgendwie, keine Ahnung, der CEO ist, dann machen wir aber folgende Ausnahmegeschichten.
Und wenn jetzt zum Beispiel, wir wollen Gehaltauszahlen, wir rufen nicht einfach Gehaltauszahlenmethode auf, sondern wir sagen nochmal, okay, wir machen Speziallogik, je nachdem, was das denn für ein Typ ist.
Also du weißt schon, dass der Senior Vice President Facility Management nach der Mist stille Witz ist.
Wieso?
Das ist voll wichtig.
Also dann hätte man sozusagen, aus meiner Perspektive hätte man jetzt eben Lischkovs Substitution Principle verletzt, weil eben der Code nicht funktioniert, unabhängig davon, was das für ein Typ ist, sondern weil man da noch überprüft.
Ja, noch nicht so ganz.
Okay, also Spezialfälle zu erlauben, ist ja kein Problem.
Es muss bis die Korrektheit gewährleistet sein.
Aber Beispiel.
Wenn man zum Beispiel sagt, und Korrektheit ist tatsächlich auch immer eine spannende Frage von, das gehört, da gehört für mich auch dazu im Sinne von, erfüllt tatsächlich auch nachher für den User was Sinnvolles.
Und du sagst zum Beispiel, alle Mitarbeiter müssen eine private Telefonnummer haben.
Und bei den CEOs legt man dann fest, nee, da ist die immer null, weil die privaten Nummern der CEOs werden nicht rausgegeben.
Und das würde einem Subtyp entsprechen.
Dann hättest du halt in dem Moment das verletzt, im Sinne von, ja jetzt machen wir hier mal für Weihnachten die Liste aller, die Telefonliste der Mitarbeiter fertig und machen die Secret Centers für hier da und denen kannst du anrufen, um noch ein bisschen was abzufragen.
Und plötzlich kommen bei den CEOs halt da keine Telefonnummern raus.
Also, ja, nee, das war jetzt halt kaputt.
Und das ist eine Designanforderung nicht von dem Client-Code, der damit arbeitet, sondern es ist eine Designanforderung von Objekt, von Unterobjekten, von Unterklassen.
Von Subklassen.
Dass eine Subklasse den Raum der Möglichkeiten erweitern, aber nicht einschränken darf.
Okay, das ist L.
Jetzt haben wir noch S-O-I-D.
Das würde ich gerne verschieben.
Ich habe vorhin schon meinen Zungenbrecher gehabt.
Und wir haben heute etwas Zeit.
Wir haben jetzt relativ gut zeitig angefangen mit dem mit dem Nachteil, dass meine Technik heute ein wenig...
Ja, du hast inzwischen durch für dich alleine geredet.
Ja, ja, und auch bis wir zum Reden gekommen sind, dann, weil irgendwie hier alleine
gegen mich gearbeitet haben.
Wir machen das einfach zu selten.
Wir müssen das häufiger machen.
Das stimmt.
Sehr gerne.
Wie gesagt, von meiner Seite immer gerne.
Wir müssen einfach immer sofort den nächsten Termin ansetzen.
Ja, das machen wir.
Schön, dass ihr aber alle wieder eingeschaltet habt heute.
Ja, genau.
An der Stelle müssen wir uns eigentlich auch.
Wir haben letzten Monat irgendwie verbasselt, aber ich meine, es war viel zu tun und so.
Ja, es war viel zu tun und es war ein bisschen sehr gut.
Ja, eigentlich wollten wir noch zwei aufnehmen, dass wieder was ausgefallen und so.
Die Terminen, Findungs-Koordinationsschwierigkeiten kommen noch ihr
Übriges dazu.
Ja, aber wir geloben Besserung, das kriegen wir auch schon irgendwie hin.
Genau.
Genau, nee, dann am besten, ja, wir haben ja auch schon echt viel Zeug gemacht.
Dann verschieben wir das mal solid, das ist noch ein gutes Thema.
Ja, und halt auch noch diverse Architekturpatterns, halt so Repository Pattern, Unit of Work, weiß ich nicht.
Es gibt da ein schönes Buch, das wäre dann schon sozusagen Vorbereitung aufs nächste Mal.
CosmicPython.com.
Ich glaube, das heißt dann auch tatsächlich, wenn man es als Buch kauft, also kann man da online lesen.
Cosmic Python, ja.
Ja, ist halt auch Architectural Patterns for Python oder irgendwie sowas.
Ist von dem, na, wie heißt er noch?
Der auch Obeys the Testing Code geschrieben hat.
Und einem anderen.
Verdammt.
Okay.
Weiß nicht mehr genau.
Da kann ich eigentlich auch sofort gucken.
Percival.
Percival.
Ja.
Cosmos as the opposite of Chaos.
Und Gregory.
Bitte?
Aha, Cosmos ist the opposite of Chaos.
Genau, das ist auch einer der Gründe, warum ich dieses Pattern-Thema überhaupt irgendwie interessant fand, mal darüber zu sprechen, weil ich gerade momentan halt auch so zum ersten Mal irgendwie so ein bisschen eine größere Geschichte habe, wo man wo es einfach nicht reicht, einfach nur so Django-Modelle zu haben oder irgendwie so, sondern wo man das vielleicht trennen muss, irgendwie Business-Logik von
Ja, das kannte ich noch nicht und das sieht aber tatsächlich gut aus.
Das sind so tatsächlich die Patterns, die ich auch kenne, die in Python gerne kommen.
Unit of Work ist so ein SQL Alchemy-Ding auch, Event-Driven und Message Bus klingt gut, Commands klingt gut, Dependency Injection ist super.
Das klingt interessant.
Das klingt die Leseliste.
Super, dann haben wir auf jeden Fall auch noch eine Menge Stoff für den nächsten, für den zweiten Teil.
Okay.
Ja, wir haben einige zweite Teile noch offen übrigens.
Ja, ja, Async müssen wir auch unbedingt nochmal dran.
Ja.
Ja, vielen Dank, dass du wieder da warst, Christian.
Danke, dass ich dir beiseinen durfte.
Na klar.
Und ja, schön, dass ihr da reingeschaltet habt und gute Nacht, guten Morgen, guten Abend, gute und so weiter.
Bis zum nächsten Mal.
Bis dann.
Tschüss.
Ciao, ciao.