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.
Wir haben einen Gast dabei, der Herr Toini, hallo.
Hallo immer wieder.
Hallihallo.
Ich bin der Dominik, Jochen ist auch da.
Hoi ho.
Wir sind im Wintergarten, beziehungsweise 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, 20, 20.
Immer noch 2020.
Ja.
Es zieht sich ein bisschen, finde ich, in letzter Zeit.
Ich erinnere den XKACD, wo
ein Zeitreiser nach 2020 kommt
und fragt, welches Jahr
es ist und er sagt 2020.
Ja, aber das wievielte.
Das ist mir auch nicht so ganz genau.
Ja.
Vielleicht noch ein paar News aus der Szene vorweg.
Genau.
Am 5. Oktober kam Python 3.9
0. Oder war das am 6.?
Ich weiß gar nicht mehr genau.
Ich glaube an dem Montag irgendwie.
Ja.
Watch released on October 5th.
Oh, okay.
Habt ihr alles schon geupdatet?
Nein. Ich habe mich diesmal nicht getraut,
weil letztes Mal mir bei 3.8.0
so ein paar Sachen wie Jupiter auseinander
geflogen 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 würde gerne machen, dass bei 1 dann
3, 9, 1.
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
Binarys und da ist es natürlich
ein bisschen hässlich, wenn man das irgendwie dann
selber konfigurieren muss.
Das heißt doch, im Bateau habe ich tatsächlich das
in die Travels-Liste
schon mit aufgenommen.
Da kam auch
jemand vorbei, der sich gleich sofort beschwert hatte,
dass es unter 3.9 nicht ging,
weil irgendwas ist rausgeflogen.
Achso, die haben im Async
irgendeine
API, die deprecated war,
tatsächlich gestrichen gehabt.
Ich glaube, 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 hinterher und in 3.9 war dann
irgendwie die Abletzkompatibilität von der API
jetzt weg. Da
flog es dann auseinander.
Insofern, ja, ich habe es schon
in der Hand gehabt.
Was gibt es denn Neues?
Ganz viele spannende Sachen.
Union Operators.
Was ist das? Was macht man damit?
Ja, zum Beispiel ein Dictionary ist zusammen
schütteln. Ja, ich glaube also wirklich
mehr als
das, was man vorher auch schon mit
Tuple-Unpacking machen konnte. Also
man schreibt halt irgendwie
neuer Key, neuer Value
und dann sagt dann hinten der Sternstern
irgendwie das andere Dict, was man merchen will.
Ich glaube, wenn man jetzt
den Pipe-Operator verwendet, macht es so mehr oder weniger
genau das Gleiche. Ja, aber warum?
Also ich habe es nicht genau verstanden. Ich finde es irgendwie,
das Erste, was ich Python so richtig hässlich fand.
Naja, was fandst du hässlich?
Ja, diesen Operator, diesen Pipe-Operator,
stehen zu haben auf einmal für so eine Operatoren-Urgie?
Ich weiß nicht.
Es wäre halt Mengen-Operations-
Operator an der Stelle.
Es ist halt ein Oder.
Ja, das passt schon.
Das war ja 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 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 so einen Baum aufbaust
mit self plusgleich 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, okay.
Ja, also ich glaube also so, was es halt, es sieht halt, ich finde es sieht schon besser aus, als wenn man jetzt immer mit den Sternen, Sternsteinen, da muss man mal so ein bisschen nachdenken, was man jetzt eigentlich genau machen wollte, ist ein bisschen hübscher, aber ist jetzt keine so weltbewegende Änderung.
und es ist vor allem, es erzeugt halt ja ein neues Dict
also ganz klassisch
war ja immer das Thema, dass du
Dict Update sagst
ja und dann macht das was anderes
als man denkt, das modifiziert
dein Original Dict
ja
insofern ist vielleicht ein bisschen
eindeutiger, was es macht
ja also mein Lieblingsfeature
tatsächlich oder meine Lieblingsneuerung
Meine Lieblingsneuerung ist der Packparser.
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 dann den Hörer noch mal
kurz erklären, was überhaupt ein Packparser ist, bitte.
Oh nein! Das wollte ich
Das wollte ich eigentlich vermeiden. Das kann ich ehrlich gesagt nicht wirklich. Also es gibt halt diese Standard-Parser für so Programmiersprachen. Die meisten Programmiersprachen sind halt, oh je, jetzt muss ich tief in die Informatik hinabsteigen. Da gibt es halt so, Programmiersprachen sind meistens, die Grammatiken dafür sind so kontextfreie Sprachen. Also, oh je.
Ja, genau.
und sogar eine bestimmte
Form davon,
so LR1 Grammatiken oder so,
das ist halt
LR1
Grammatik zum Beispiel.
In dieser Form ist auch zum Beispiel
die Java Sprachspezifikation, das ist also das erste,
was ich, sollte man sich im Studium,
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 lasse ich schon so was
in komische Abkürzungen 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
und dann... Der liest die Sprache
und weiß, was der machen muss.
Der gibt einem dann einen Parser,
der genau diese Sprache akzeptiert.
Und das sind dann so Dinge wie...
In letzter Zeit habe ich da wenig mit zu tun gehabt.
Früher ganz mehr
sowas wie YAK zum Beispiel
gibt es da
auch so ein rekursives Akronym
Justiner sagt Compiler Compiler
dem kann man sowas vorwerfen
und der spuckt dann halt ein Parser aus
und das gab es dann noch mit Lex
und Bison und
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 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 zum Beispiel
es gibt halt, ich kriege das auch nicht alles auf die Reihe
aber es gibt halt
der Parser 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
oder der Parser bisher
bestimmte Sachen halt nicht so einfach damit parsbar waren
und der ist auch handgeschrieben, also das ist halt irgendwie,
wenn man sich das angucken will, gibt es
ein Modul, das nennt sich
ast.c oder so
in Python-Source-Code, das ist der
alte Parser,
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, ich kriege das nicht mehr richtig auf die Reihe,
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. 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 Python-Grafiker auch gar nicht
sagen kann, wo der Syntaxfehler ist, was
halt eventuell ein Problem sein könnte.
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 Ü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
den Pack-Baser hauptsächlich gebaut haben
jetzt in Python 3.9 zu Gast
und haben da halt so ein bisschen was erzählt, was sie da gemacht
haben.
Einer von denen meinte so, also
und
eine User-Anfrage war halt so,
warum können wir das in RIS
Context Manager mit diesem
RIS-Statement nicht einfach so machen
wie bei Imports oder halt mit
bei Strings, dass wir da
Klammern drumherum machen und dann haben wir mehrzeilige
Dinger, weil mehrzeilige RIS-Statements 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,
und Jochen unterhalten sich über die Programmiersprache Python
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 Hauptspeicher 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 eine Python-Datei wollen sie
jetzt bitte nicht mehr sehen.
Ja, okay, aus dem Kreise.
Oh Mist, was war ich denn jetzt?
Da habe ich eine 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
genau, das ist das tolle Ding, was man eventuell jetzt damit machen kann
Was sonst sehr schwer geworden wäre
ist, da gibt es
auch ein PEP jetzt, weiß ich nicht welche Nummer
Pattern Matching
Bin mal gespannt, ob das
angenommen wird für Python 3.10
dass man halt so
Lisp-Style-Makros hat, beziehungsweise
halt in funktionalen Programmiersprachen ist das schon länger
oder das ist halt ja so eins 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
natürlich schon nett, hat man so eines der zentralen Features
von funktionalen Programmiersprachen auch mit drin
Was sind denn Lisp-like-Makros?
Ja, das
müssen wir mal irgendwann machen, wenn wir irgendwie auch
so ein bisschen, so ja, noch mal funktionale Programmiersprache und und und und und und und und und und und und und und und und und und und und
Ja, ein Bug ist auch schon aufgefallen wohl.
Also 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
schon
Warum hat man das nicht Case genannt?
Das müsste ich jetzt nachlesen
Also es macht
schon glaube ich noch ein bisschen mehr
Ach, keine Ahnung
Genau, einen Bug gab es auch schon
da wird jetzt dann wahrscheinlich in 3.9.1
gefixt und zwar
was der alte
Parser konnte und was jetzt halt mit dem neuen
nicht mehr geht, ist,
wenn man
Tupple Unpacking, halt auch so Stern
irgendwas in, with
so Context Managern verwendet,
dann funktioniert das nicht.
Tja,
aber es ist halt bisher niemandem aufgefallen, also so häufig
scheint es nicht verwendet zu werden, aber
das klappt schon irgendwie nicht. Achso, das ist auch vielleicht ganz
interessant, also in 3.9
sind beide Parser drin, man kann auch
irgendwie per Kommandozeilenoptionen sagen
minus x irgendwas, Old Parser oder so,
verwendet doch bitte den alten, wenn man
irgendwie mit dem neuen ein Problem hat. Der neue ist
defaultmäßig aktiv
und der alte ist aber halt
noch drin und
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 Tablet Unpacking in Context Managern, 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
aber ja, jetzt geht es nicht mehr.
Also warum will er das denn nicht machen?
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?
Naja, momentan müsste ich auch gerade suchen.
Ich versuche so leise wie möglich zu tippen.
Also ich kann mir schon vorstellen,
warum nicht im Contact Manager einfach irgendeinen Tupel
anpacken, was das doch durchhört.
Nee, nee, die Frage meint
wahrscheinlich oben in der Riff-Expression.
Ja, in der Expression selber.
Und dann irgendwas mit Tupel-Unpacking machen.
Also ich sehe da echt keinen Anwendungsfall für.
Und es ist glaube ich, also die haben da ja die komplette
Standard-Bibliothek durchgejagt und noch viele
PyPI-Fakete und sie haben es 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 ein Code, der irgendwie häufiger verwendet worden wäre.
Also, ja.
Es war nur, das ist halt schon mal aufgefallen, dass da ein Unterschied zwischen den beiden Passern gab.
Ja.
Tja, was haben wir denn noch so?
und Jochen unterhalten sich über die Programmiersprache Python
Ja, das ist schon hilfreich
Ja, ansonsten
Zeitzonen-Handling
ist jetzt irgendwie mit drin
Das habe ich noch nicht angeguckt
weil ich bin seit irgendwie 15 Jahren
mit PyTZ unterwegs
und PyTZ hat halt den Vorteil
das ist unabhängig, das ist halt so ein Ding
die Zeitzonen-Datenbanken 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
im DateTime-Modul
in der Standardbibliothek
waren diese
Zeitzonen-Datenbanken auch nie drin, wohl aber
eine API dafür, wie man da seine eigene Datenbank
oder sein eigenes Objekt, das halt implementiert,
Zeitzonen-Objekt irgendwie
reintun kann, weil sich die Leute gesagt haben,
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
und ja, wie es jetzt wohl ist, ist, dass...
Ja, die nehmen die System Time so, weil sie haben eine API dafür, um das reinzuziehen.
Ja, 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.
TZ-Data, ja.
Dann geht das da wohl irgendwie auch, ja.
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
DateUtil oder sagen wir so, das ist auch
also wie
DateUtil das macht, also ich glaube
das ist auch von dem Autor von
von DateUtil irgendwie
meine ich jedenfalls gehört zu haben
dass der das von dem das ist und das
es implementiert halt so die Kerngeschichten
aber viele von den fancy Features von DateUtil
sind halt nicht drin, aber
so die Kerndinge, ja
Ja
Noch was?
Noch irgendwas
Naja gut, da gab es noch irgendwas mit Dekoratoren
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
das wird wahrscheinlich auch kaum jemand machen
in der Sperre.
Jawohl, da kann ich mir das KMR vorstellen.
Man könnte sich vorstellen, man hatte
irgendwie ein 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.
Auch nicht so schlecht.
Es ist ja eine Frage von, in solchen
Momenten immer bei diesen
syntaktischen Kleinheiten,
und dann kann man ja immer dieses berühmte Dokument des PHP a fractal of bad design rausholen,
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 PHP a fractal 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
schon 10 Jahre alt oder so. 2012.
8 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
nämlich an mindestens ein Thema
und die Funktionen, die er in den Parseur integriert hat, mit einem Variablen-Namen aufgerufen werden, aber niemals 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 das 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 stolperst dabei
ja, der wäre jetzt mal ganz interessant zu lesen
zum Thema irgendwie ein bisschen analytisch auseinander genommen
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
III.II
oder sowas
Ja
aber ich glaube
das war es dann auch schon mehr oder
weniger, ne?
Ich glaube sonst war da eigentlich nichts drin
Ja, ich glaube irgendwie noch was zu typen oder sowas
Oh ja, stimmt, man kann jetzt irgendwie
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 Typing, Typings 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 Typings.
Genau, das ist ganz nett.
Das macht es ein bisschen
einfacher das zu schreiben und muss nicht mal nachgucken, welche Impost das jetzt waren.
Ja, was steht an Veranstaltungen an?
Habt ihr irgendwelche?
Oh, hab ich jetzt dummerweise gar nicht so richtig nachgeschaut.
Die DjangoCon ist gerade vorbei.
Ja, gab es eigentlich die PyCon auch jetzt?
Oder war die PyCon dieses Jahr virtuell? Ich weiß gar nicht.
Welche meinst du, die deutsche?
Ja, die G.
Ne, 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
war es gewesen eigentlich.
Genau, und wir haben aber relativ frühzeitig
mit dem Veranstaltungsort
wie Wärm gewesen im
Haus des, nicht Haus des Lehrers, hier daneben
an.
In Berlin? Genau.
Ach, wie heißt denn das noch? Da wo immer der
Zivilkongress war. Da wo immer der Kongress war, genau.
Dieses UFO.
Ja, da wären wir gewesen eigentlich und wir 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 Jahr 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 in einem regulären Jahr wäre unsere Hochrechnung glaube ich bei knapp 2.000 Euro,
22 schon rausgehandelt. 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
pleite,
wären wir nicht pleite, aber
ansonsten müssen
im November.
Da gehen demnächst noch Einladungen raus,
wer beim Python-Verband Mitglied werden will.
Stimmt.
Dafür muss er tatsächlich noch mal kurz Werbung machen.
Die Webseite kurz nennen.
Genau, das wäre der
python-verband.org
der Python Software Verband
als die deutsche Interessenvorredung.
Und eine unserer
Hauptaktionen, das war dieses Jahr
leider auch ein bisschen
wenig durch Corona,
und was wir in der Webseite sehen, 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.
Und im Corona-Jahr war es jetzt auch so, dass wir tatsächlich ein, zwei schon länger bekannte Partner,
da gibt es die TechKids zum Beispiel im Schwäbischen,
die haben jetzt auch ganz schön duttel gelitten, weil denen die ganzen Veranstaltungen weggebrochen sind,
mit denen sie normalerweise dann ja auch wieder 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 viel
Ort sein, größeres Problem, ja.
Tja, ja.
Sonst ist dann demnächst Weihnachten. Ich habe heute die erste
Weihnachtswärmung gekriegt.
Ja, tatsächlich.
Weihnachtswünsche.
Ja, geht schnell vorbei mit so einer Pandemie
Ja
So oder so
Ja, also genau
Ich weiß nur, EuroPython
war jetzt auch vor kurz
Die Vorträge sind irgendwie da
und DjangoCon, das wollte ich mir auf jeden Fall
angucken, aber habe ich noch 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 wieder das Django Meetup Cologne.
Ja, ich weiß, aber das ist halt dann 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 gibt, glaube ich, noch wieder so eine neue Anmeldung für das nächste Jahr, die 21, die auch online statt sein wird.
Äh, Forstdem, diesmal.
Forstdem, achso, das ist dann Februar, Januar, Februar, die Forstdem.
Genau.
Nee, ich meinte die Frostcon.
Genau, die ist normalerweise
Sankt Augustin
Genau, ja
Ja, ansonsten
was mir noch so eingefallen ist, was jetzt geht
was früher nicht ging
iSort und Black sind kompatibel
Ja
das ist auch nett
Wie kam es?
Ich weiß es nicht genau
also
mit irgendeinem
Update von iSort ist das jetzt
und das war dann irgendwie erledigt.
Also iSort hat was gemacht damit Black nicht mehr dazwischen punktet Ja irgendwie so genau und ja jetzt geht es halt man kann es halt beides verwenden und hat dann da kein nicht mehr so
dass das eine immer die Sachen vom anderen umsortiert
was ja irgendwie ein bisschen doof ist. Jetzt müsste man das nur noch in
PyProjectHumil konfigurierbar machen, genau wie
PyTest und
Lake8 und dann... PyTest ist das?
Ist das schon?
Ja, aber mit so einem komischen
Ja gut, der Key
ist so ein bisschen komisch. Genau, PyTest
Ini Options oder so so ein Quatsch.
Ja.
Wobei ich sagen muss,
wir haben jetzt tatsächlich Black an 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 empfehlen mal noch ins Japf reinzuschauen.
Japf, okay.
Ja, Black wird auch ein Problem kriegen.
Black verwendet auch den
alten Parser
und spart es uns ab Python 3.10,
und wird es dann halt
einfallen lassen, weil das geht dann nicht mehr.
Kannst du kurz was zu JAPF noch sagen?
Ja, JAPF ist so ein,
wir waren ja vorhin schon beim JAK,
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.
Auch mit einer JAPF-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
Blackformatierung an vielen Stellen so richtig
gar nicht klar und
finde sie einfach
urpot hässlich. Ich fand sie auch sehr
agil, aber Jochen hat sie mir immer aufgezogen.
Ja, sorry.
Also ich unterstütze volle Kanne
das Thema, einen
Autoformatter einzusetzen,
Aber ich finde, Beck ist halt nicht der weiße Westerfluss
Ja, das mag, 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 da 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
nur gut, dann gebe ich dafür die persönlichen
Referenzen auf. Aber ja, ich kann auch
verstehen, dass man das...
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.
Ja.
Also das ganze Thema, dass die Indentation mir Dinge
sagt und dann irgendwie
über x Dutzend Zeilen hinweg wieder schließende
Klammerorgien zu sehen, dafür brauche ich kein Python. Also dann brauche ich kein Python,
kann ich da was Skript schreiben.
Ich verstehe ja, warum das passiert.
Sie versuchen ja eine Formatierung zu machen,
die möglichst wenig Diff erzeugt. Wobei ich das bisher
auch nicht gesehen habe. Da hätte ich gerne mal tatsächlich noch eine
Metrik gesehen. Und ich muss aber sagen, das verletzt dann so ganz
für mich jetzt halt an und wir haben jetzt tatsächlich
in einem Projekt, 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 Show Notes?
Na klar. Das wäre super, weil das da finde ich
sehr spannend, weil ich finde Black auch
mega ultra hässlich und genau das, was du sagtest,
also ein paar Sachen, wo ich dachte, wieso macht das
und das ist auch eklig.
Ja, naja, gut.
Ja, ist schon
was dran. 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 einer 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
Korriphä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
und Emex irgendwie geschrieben
in C oder die erste
ordentliche Version von Emex
und stand dann irgendwann vor der Entscheidung, okay, ich mache
jetzt entweder den Rest meines Lebens Emex
oder halt nochmal was anderes und dann
dachte ich so, naja, Emex, so geil ist es dann, also
weiß nicht, muss auch nicht sein.
Dann hat er lieber was anderes gemacht und das abgegeben irgendwie.
Also Emex und Java
sind eng verwandt, interessant.
Naja, also
in gewisser Weise.
Aber er hat halt auf jeden Fall sehr, sehr viel C geschrieben.
Die ungleichen Zwillinge.
und dann auch
größeren Projekten und dann sind
ihm halt so 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
aufzuräumen und das ist ja auch dann irgendwie gelungen
aber
der sagte dann etwas, als es
darum ging, wie das dann
so ästhetisch aussieht
daher die
Anknüpfung sozusagen
und er meinte so, ja, also wenn ich irgendwie
Code lese, es gibt ja immer so Leute, die sagen dann so
oh, ich finde das ästhetisch ist aber nicht so
hm, gefällt mir nicht so richtig
und er 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 einer 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
das ist mir auch total egal
und dann dachte ich so, okay
Ja, das erklärt natürlich einiges.
Aber
das ist aber halt, da ist er halt noch
auch schwierigen Positionen, 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
und die Programmiersprache Python
oder vielleicht sind unterschiedliche Leute da halt auch
einfach unterschiedlich, vielleicht gibt es Leute,
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.
Ich bin sehr an der ästhetischen...
Es ist viel schöner, wenn man die ästhetischen Patterns
direkt sehen kann und die einem klar ins Auge springen.
Ja.
Willst du ein anderes Thema
einleiten? Ich habe gerade versucht, einen kleinen
Übergang zu finden.
Ich weiß nicht, ob es mir geglückt ist.
wie geschickt.
Ja, aber es war wirklich so. 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, es 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 Drumherum 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 Sweet-Spot-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 sie sehr viel metasyntaktisch arbeiten
und das heißt aber, du musst teilweise schon überlegen,
hier ist ein Leerzeichen, deswegen bedeutet jetzt gerade,
und wenn das da hinter der Funktion ist, dann
da musst du schon auch
in diesen Mustern ganz schön
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
auseinanderklamüsert
aber ich merke auch, oh, jetzt ist es
auf eine Art geschrieben, die ist irgendwie von
durch die Brust ins Auge und
war irgendwie nicht zum Lesen gedacht
Ja
Ja, man muss ja schon irgendwie
Methode relativ schnell begreifen können irgendwie,
als ein Ziel, wenn man das so vernünftig
machen möchte.
Ich glaube auch da wieder,
dass halt für unterschiedliche Leute
vielleicht da unterschiedliche
Trade-offs besser funktionieren oder schlechter
und irgendwie so
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 habe,
was ich ganz interessanten Ansatz fand,
das war, wo habe ich das hin
gehört,
dass es ja auch noch andere Aspekte gibt.
Also 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,
was halt dann an Code dasteht, ist halt das
Entscheidende. Und der meinte dann halt auch so, ja,
also User-Interface der Sprache ist sehr wichtig und
Python voll gut. Wusste ich auch gar nicht, dass er da so
meinte, das ist total super.
Das Problem ist nur, es gibt halt auch noch andere
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 da drin 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
und Jochen unterhalten sich über die Programmiersprache Python
gibt es keine konsistente Art mehr, das so richtig zu debuggen.
Und das ist natürlich schon so ein Punkt.
Oder was er auch meinte, ist dann halt sowas wie,
ja, also
was ist eigentlich, kann ich 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 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.
Und natürlich, also in gewisser Weise, da ist
schon das auch ein Punkt dabei. Und das ist
natürlich in Python vielleicht jetzt nicht so
einfach wie in anderen Sprachen.
Ja, das...
Aber so zum
Lösen von Problemen finde ich das auch
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ß der noch mal? Wie hieß der Interviewer?
Lex Friedman
Lex Friedman, genau
Und da hatten wir diesen einen Chip-Designer
Der ist auch extrem spannend, den sich anzunehmen
Das ist gerade so ein thematischer Querschlag
Aber ich glaube, die muss ich einfach mal loswerden
weil der hat mich dermaßen begeistert
wie hieß er denn
Lex
Friedman mit
er hat zu viele Sachen gemacht
oh ja
der macht eine ganze Menge
genau
wo ist er, wo ist er, wo ist er
Chipdesigner, Chipdesigner, Chipdesigner
Namen sind
Schall und Rauch.
Ja, manchmal macht er auch so ein bisschen komisch.
Also manchmal ist mir das auch, ich weiß nicht, es gibt ja so eine,
also ich würde das mal, also wenn man das so
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, dass er jetzt nur noch Fleisch isst oder
keine Ahnung oder macht ganz viel mit
Cryptocurrency-Zeugs, was ja auch irgendwie
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 hab da gleich nach 10 Minuten
so ein bisschen so einen Man-Crush entwickelt
der ist so
intense
wie der da sitzt
und denkt und redet
und sein Minenspiel 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 80ern
ist der ins Chip Design 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
dieses Gefühl von
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 heißt übrigens Moore's Law.
Ja, genau.
Ja, also der war, der ist schon krass, der ist schon, der war richtig gut.
Ja, also ne, der Podcast kann man tatsächlich empfehlen, es gibt 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, es gibt Videos davon mit den Interviews, nicht nur als Podcast.
Und da ist, ja, die Niemieg ist, ja.
Die geht nach Norwegen.
Ja, ja.
Wenn man mal so durchscrollt.
Ja genau
Wo waren wir denn jetzt?
Wir wollten eigentlich ein Petra-Fall machen
Ja genau
Ja und
irgendwie gewisserweise
auch zu
Patterns hatte
was zu sagen und so
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,
was ist das eigentlich?
Man zeichnet dafür, dass die Sprache halt etwas nicht kann,
was sie vielleicht können sollte 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 Problem, das ist nicht nur bei Patterns 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 ein Pern.
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 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 jetzt
sich TypeScript anguckt oder so, wenn sich so ein
Type-System halt außerhalb der Sprache entwickeln kann, kannst du das natürlich deutlich
schneller tun, als wenn das immer nur alle 18 Monate oder jetzt alle
12 Monate updatable ist
mit dem Gedächtniskzyklus der Sprache. Also es ist nicht so einfach.
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.
Eigentlich hat das keinen Nachteil.
Ich glaube, Patterns ist sozusagen
das war gerade aufgekommen,
da war ich glaube ich im Studium,
in die Hand nimmt, ist das in der 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.
Er war ein Architekt und der hatte dieses Thema Python-Sprachen halt mal aufgegriffen
aufgegriffen und bzw. 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 Mosaikbaustein-Ding, 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 sie haben da 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,
und
und der hat so ein ähnlicher 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-pasted 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 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 ineinander greifen und zusammenspielen.
und die Sprache der Verknüpfungen.
dieses, man muss es sich selber zurechtschneiden
für den eigenen Anwendungsfall.
Ansonsten hätte man das ja auch in der Library kippen können.
Das hätte man sagen können, das ist jetzt der einmal
fertige Code und
der Trick ist aber, das Muster auf einer 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 sollst 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, weil wir haben jetzt ja abstrakt
vielleicht irgendwie da mit angefangen,
was so Patterns vielleicht
so
konzeptuell sein sollten und vielleicht gehen wir
noch 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.
Ja genau,
also ich meine, die Muster, die sind ja
sozusagen allgemeingültig.
Das sind ja tatsächlich
sehr abstrakte Ideen,
die da existieren.
Fangen wir vielleicht mal mit Anfang an, was ist denn Strategie gesagt?
Ja, ich würde woanders anfangen, ich würde beim Singleton
anfangen. Ja, okay, fangen wir beim Singleton an.
Was ist denn Singleton?
Die mäßige, schöne Übersetzung ist das Einzelstück.
Ich mag es
einfach nicht, wenn.
Es gibt ja so ein paar Kategorien,
also Singleton gehört zu
den Mustern aus dem Bereich
Creational Patterns,
Also wie werden in einer objektorientierten Sprache Objekte erzeugt?
Da gibt es 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 es nur ein einziges Objekt zu geben darf.
Und dieses Objekt soll aber auch gut zugänglich sein.
und das kann zum Beispiel so was sein wie das Objekt, es 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 fünf Logger haben nachher, sondern 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
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, man sollte es nicht Logging nennen, das geht gerne schief
wenn man die Standardbibliothek startiert. 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 instanziieren. Wenn du willst, löscht 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
und die Klasse aus dem Modul löscht, dann ist der Name zwar nicht mehr 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-Unterscore-Methode da die richtige war,
nicht init, sondern was?
Create?
Nee.
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 under new 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 liefer 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
und was hat das Pattern für einen Kontext?
Es gab eine ganze Zeit lang, und das wurde so ein bisschen diesen Java-Programmierer-Schmieden,
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 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 es 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,
und Jochen unterhalten sich über die Programmiersprache Python
das ist halt irgendwie fehlende Sprachfeatures
so ein bisschen relevant
weil tatsächlich
braucht man diese Patterns
vor allen Dingen in Sprachen
wo halt das
syntaktisch einen Unterschied macht, also wenn ich
zum Beispiel in C++ oder auch in Java
oder selbst in JavaScript
wenn ich da new sage, um ein neues
Objekt irgendwie
zu erzeugen
dann habe ich halt das Problem
also in Python ist es halt
ist ja sozusagen 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++ 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 rauskommen soll,
halt überlegen, wie gehe ich denn jetzt damit um?
Und dann kriege ich halt irgendwie
FLs-Kaskaden in Konstruktoren und dann
irgendwann denke ich mir so, das sieht aber hässlich aus, was mache ich denn jetzt?
Und dann brauche ich halt Python.
Oder ein bisschen Gagge-Pile 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, ich würde sagen, Ausnahme ist vielleicht
das Bilder-Pattern, das man halt auch in Python
vielleicht ganz gut verwenden kann.
Bitte noch erklären, was ist das Bilder-Pattern?
Bitte?
Also das Bilder-Pattern ist halt sozusagen, wenn man jetzt
nicht nur ein Objekt bauen möchte, sondern halt
eine ganze Menge von Objekten dann wird das halt unter Umst un Wenn ich das jetzt irgendwie muss ich halt einen Konstruktor machen der irgendwie riesig wird und ganz viele Argumente
oder so, das ist halt eventuell nicht so schön
ein gutes Beispiel dafür
ist halt
LXML hat da so
ein Ding, wie man sozusagen
XML-Dokumente zusammenbauen
kann, das ist halt quasi Bilderpattern
kann man sagen, also wenn man sich das mal angucken
will, da gibt es dann halt für jedes Tag
gibt es halt 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 Bilderpattern verwendet wird
in anderen Sprachen, in Python reicht es dann meistens irgendwie einfach
eine neue Klassenmethode an ein Objekt dran zu machen, die halt dann irgendwie Sachen zusammenbaut.
Das geht halt
Anderswo geht das halt nicht so gut
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
Da das irgendwie da
Funktionen First Class
Dinger sind in Python
gibt es eigentlich gar keine andere Zweifel.
Was ist denn das Factory Blatt? Dann fangen wir wieder so an.
Wir wollen ja auch ein bisschen erklären.
Ich weiß gar nicht,
ob ich das genau gut 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, du hast halt nicht irgendwie einen Hammer und ich mache jetzt irgendwie einen New Hammer,
sondern du hättest gerne jetzt einen sehr speziellen Hammer mit einem möglichen, keine Ahnung,
so einem 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 konfigurierst
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 ja, aber ich kriege es jetzt auch,
weiß ich nicht genau, ob ich das so super erklärt kriege.
Ich habe mir das auch schon lange nicht mehr angeguckt.
Ja, man muss an der Stelle halt
auch
gucken, 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 und du willst jetzt eine neue Farbinstanz haben
und sagst einmal create from RGB oder create from 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 heranzerrt
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 Usen sind halt auch nur ganz normale Funktionen,
die kannst du parametrisieren und benutzen, wie du willst. Da ist Python halt einfach eine Ecke voraus gewesen.
Nichtsdestotrotz kann man halt noch was daraus lernen. Ich mache das auch gerne manchmal, dass ich Konstruktoren habe,
oder solche Factories haben, die eben dieses aus unterschiedlichen Kontexten rausinitialisieren.
Es ist in der Python-Bibliothek selber auch drin, wenn man sich DateTime zum Beispiel anguckt,
dann gibt es da mehrere, das sind dann entweder Klassen- oder Statischulmethoden,
die heißen dann irgendwie fromTimestamp 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 auf den Füßen rumtreten dürfen
Ja
Ja, dann machen wir doch weiter
mit was für, würde ich sagen, Snickers
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
Anwendungsfälle, wo ich sowas habe, wie den Singleton,
meistens reicht es tatsächlich irgendwie
eine Variable in einem Modul.
Weil das ist ja, das Modul ist schon
Singleton irgendwie und wenn ich da halt
irgendwas anpacke, dann ist das halt überall
gleich, wenn ich das irgendwo
importiere. Es gibt
da so einen Pattern von
Alex Martley, wenn man tatsächlich sowas
braucht wie SharedState,
aber manchmal braucht man nicht unbedingt
immer die gleiche Instanz, sondern nur, dass sich alles
immer gleich irgendwie verhält und die gleichen
den gleichen State hält, da kann man das Borg-Pattern
verwenden. Das ist so ein bisschen ähnlich wie
ein Singleton. Wie das Borg-Pattern?
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,
man kann tatsächlich auch so machen, dass es halt so
ist wie Singleton in anderen Sprachen, dann meistens
irgendwie muss man dann so Metaprogrammierung 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.
Ja, okay. Also was für Paths haben wir denn noch? Also ich kann jetzt natürlich die Liste hernehmen, aber wir haben jetzt Single-Ding gehabt, wir haben kurz Factory.
Es gibt noch zwei, die jetzt aus meiner Historie immer relevant waren. Das waren Proxys und Adapter. Da muss ich mal die ganz ollen Gammellen rausholen.
also SOAP 3 war damals tatsächlich also SOAP 2 und deren Nachfolger SOAP 4 und SOAP 5.
Wie bitte was?
Da gab es auch einen.
Bitte?
SOAP, genau.
Das ist 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 Webanwendungen zusammenbauen konnte.
Es hat einfach nichts, so richtig gar nichts mehr mit dem vorherigen Ding zu tun gehabt
Da war halt eine der Grundideen, dass es möglich sein sollte
Libraries und Anwendung 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 Python
und da hatten wir
extra eine Interface
Typ für entwickelt
mit dem du dann deklarieren konntest
das hier ist ein formales Interface, es muss folgende Methoden haben
die Methoden müssen folgende Parameter haben
also Interface ist ja ein anderes Designpattern
ne Interface ist noch nicht mal so richtig
ein Designpattern, Interface ist
kommt eher aus dem
aufrufst, wenn du dir irgendwas
übergibst, musst du dir halt sagen, was das denn ist.
Du kannst dir nicht einfach irgendwas übergeben.
Und wenn du jetzt
Objekte
unterschiedlicher Art da reintun willst,
dann müssen sie zumindest
vom gleichen Interface erben, sonst geht das
halt einfach nicht. Du kannst halt, du könntest
zum Beispiel
sagen,
okay, ich habe hier irgendwie eine Methode, die
schreibt irgendwie, zum Beispiel, die lockt irgendwas
weg oder so.
Und ich gebe da jetzt irgendwas rein, aber
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
gern ein Ding, dass
das File-Interface
sozusagen
implementiert und
kannst dann sozusagen
darauf dann irgendwie write aufrufen oder so.
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 abstrakte Vordefinition.
Ja, also
wir hatten es damals so gemacht, es gab einen speziellen
Klassentyp,
und die
Programmiersprache Python
und die
Programmiersprache Python
und die
Programmiersprache Python
und die
Programmiersprache Python
und die
Programmiersprache Python
und die
Programmiersprache Python
und die
Programmiersprache Python
und die
Programmiersprache Python
und die
Programmiersprache Python
und die
Programmiersprache Python
und die
Programmiersprache Python
und die
Programmiersprache Python
und die
Programmiersprache Python
und die
Programmiersprache Python
und die
Programmiersprache Python
und die
Programmiersprache Python
und die
Programmiersprache Python
und die
Programmiersprache Python
und die
Programmiersprache Python
und die
Programmiersprache Python
und die
Programmiersprache Python
und die
Programmiersprache Python
und die
Programmiersprache Python
und die
Programmiersprache Python
und die
Programmiersprache Python
und die
Programmiersprache Python
und die
Programmiersprache Python
und die
Programmiersprache Python
und die
Programmiersprache Python
und die
Programmiersprache Python
und die
Programmiersprache Python
und die
Programmiersprache Python
und die
Programmiersprache Python
und die
Programmiersprache Python
und die
Programmiersprache Python
und die
Ducktyping
Das heißt, solange es sich so verhält, wie es soll, ist mir als Laufzeitumgebung völlig egal, was du reinstopfst. 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,
und die Funktionen.
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, 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 anders 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 Typtransformationen zu laufen haben
und dann kann ich plötzlich halt Anwendungen
auf Arten benutzen, die nie so vorgesehen waren.
Das 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 draufgingen, 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 auch extrem
aufwendig zu pflegen.
Also da spielst du dann halt Informatik
wieder mit in der Klasse von
wir ziehen uns 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 Anderes irgendwo rein gereicht wird und er emuliert alle Attributzugriffe und alle
Funktionsaufrufe, macht irgendwas und reicht den Originalaufruf dann an das Originalobjekt halt
und dann hast du hier gleich
sowas wie eine Middleware
nur genau umgedreht, im Prinzip.
Du injectest das Ding
in was anderes rein.
Eine Middleware ist ja typischerweise was, was
in der Pipeline irgendwo drin sitzt
und du kannst aber halt 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
Also die ernsthaften Proxys, die wir hatten, waren dann Security Proxys.
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
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-Proxys 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 abgewürgt worden mit das jezu nicht
da musst du halt dann noch einen Check gegenbauen und sagen, ah
der darf das nicht, dann wird das Template ordentlich gerendert und ansonsten hast du
aber immer den Safety-Belt, das ist 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
es geht nicht raus, im schlimmsten Fall wird die Seite halt abgebrochen
und er sagt so hier ist nix
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
das ist eine Klasse, die hat ein Init
da übergibst du das Objekt, was
und über die GetAttribute Protokolle
und dann kannst du über die GetAttribute Protokolle
dann halt sagen, aha hier versucht jemand gerade zuzugreifen auf folgendes Attribut
und jetzt kannst du ein bisschen Log-Output erzeugen
und danach halt das Original-Objekt 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-Underscore-Methoden
benutzen, um dann wieder
über das System selber zu reden.
Also 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...
An welcher Stelle das
injiziert werden soll. Wenn du jetzt sagst,
dass das schon gebaut wird, jetzt weißt du,
die Inlet ist dann quasi schon durch. Also der Konstruktor
ist quasi geschehen.
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 In-Edit-Methoden erst aufruft
und währenddessen...
Du hast ein Proxy-Objekt, das kriegt das
Objekt, was du
hinter dem Proxy haben möchtest,
das reichst du dem rein.
Also, ich versuche es 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 Personen,
Klassen oder irgendwas. Aber ich instanziere jetzt quasi den 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 der bei sich auf under under
Kontext zum Beispiel.
Wichtig ist under 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 under under getAddr
under under.
Die wird ja immer dann getriggert, wenn jemand
auf ein Attribut zugreift, was nicht definiert ist.
Da der Proxy
selber kein Attribut 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.under under context under under
get attra
dieses Objekt auf.
Diese Attributnahme auf. Er reicht sozusagen
den Methodenaufruf 1 zu 1 weiter
und gibt es auch wieder zurück.
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
Client-Code habe, eigentlich was auf.
Was wird da gemacht? Da könnte man auch einen Debugger bauen
oder sowas quasi. Kannst du dir einen Debugger mitbauen,
einen Flow-Debugger.
Genau.
Oder kannst du halt auch sozusagen,
ja genau, einen 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.
Und das
ist dann ein Proxy, du wickelst
etwas ein
und gibst das eingewickelte Ding weiter mit dem
anderen, mit dem Original drin.
Da kann er quasi alles mitlesen, was der da
an Daten aus der Datenbank zieht.
Genau, also in Python kannst du, wie gesagt, es ist immer die Frage, diese Double-Under-Methoden, wenn du sagst, der andere kann alles an Python schreiben, was es 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 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
damit kannst du keine Security bauen
aber du kannst halt
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 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 gibt es verschiedene Magie mit dem Flow irgendwie was.
Genau, genau.
Okay, also das war der Proxy-Pattern.
Das ist ein ganz interessanter 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 Jochen, magst du vielleicht noch eins?
Ja, also 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, ist ja eben
nicht das Pattern zu verwenden, sondern das halt irgendwie
in, dann da in
das 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
File liest, dann die Leerzeilen
wegschmeißen oder sowas?
Man rappt den Funktionsabruf und Input und Output
kann man dann immer modifizieren?
Nee, das ist ein Python-Decorator,
also das mit dem Add irgendwas drüber.
Ich meine, das Decorator-Pattern wäre ein bisschen anders.
Aber vielleicht höre ich mich auch quasi nicht mehr genau. Ich meinte, das wäre halt irgendwie sowas, dass du halt sozusagen tust halt so, als wäre das ein normales File, aber in Wirklichkeit schmeißt das Objekt, was du halt mit dem Deco-Hater-Pattern gebaut hast, halt intern sowas wie Leerteilen weg oder Dinge, die nicht gepasst werden können oder so.
und dann... 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 Decorator wird
nochmal explizit darauf hingewiesen,
dass man hier halt chainen kann.
Das kannst du im Proxy aber auch machen.
Dass du da mehrere hintereinander schaltest.
Ja.
und ansonsten
was mir noch, au,
letztens ist mir das aufgefallen,
Mysterium, ich weiß nicht in welcher Episode
wir das hatten, da habe ich mich irgendwann mal gewundert,
da dachte ich
zuerst, das muss irgendwann letztes Jahr gewesen sein,
ob das irgendwie eine Python 3.8 Neuerung gewesen
wäre oder so, ich weiß es nicht,
hat ja 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.
Eigentlich hätte ich jetzt mit deutlich mehr gerechnet.
Weiß ich nicht, eher so
23 oder
weiß ich irgendwas.
Darum ist 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 deutlich mehr sein müssen.
Ich wäre ja die Redundanzen weggelassen.
Das, was da tatsächlich passiert ist, ist halt intern 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,
es gibt halt sozusagen nur...
Ist ja auch eine Form von Singleton.
Es ist sehr ähnlich zu Singleton, genau.
Also eigentlich ist das halt für solche Dinge gedacht,
wie du hast halt,
wenn du jetzt
in einen Textprocessor
hast, so ein Programm, was sowas wie Word oder so, und wenn das jetzt
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 für 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
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 irgendwann zufällig gesehen, woran das lag.
In Python gibt es ja noch den Begriff in-turning für.
Das kann man dann auch ganz gut sehen, wenn man die Objekte dann mit einem Identitätsvergleich anguckt.
Dann sind es halt tatsächlich wirklich immer, dass das Is das Gleiche ist.
Und das gibt es bei Strings halt auch.
und Jochen unterhalten sich über die Programmiersprache Python
und die Programmiersprache Python.
und die Sprache, die wir unterstützen. Dann kannst du halt das lange LF so refaktorieren, 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 address format
und die Methoden darauf sind dann entsprechend zum Beispiel die ISO-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,
und die Programmiersprache Python noch andere ISO reinzuschreiben die ich halt noch nicht kannte und mein Code ist dann in der Lage jede beliebige Art der Formatierung aufzurufen Oder jemand anderes kann auch hergehen und sagen hey ich definiere dein Format f italienische Adressen gef mir nicht also ich jetzt diesen DICT von IT mit meiner eigenen Methode
und der Code, der aber jetzt
das aufruft, der hat halt jetzt keine
hartcodierten
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.
Hm.
Ja.
Und was ist ein Observer?
Hm.
Ich gucke nach.
Muss ich hier auch nachgucken.
Happy Google this for you.
Also ich glaube, das ist, ach doch, warte mal, das ist halt
wenn du benachrichtigt
werden möchtest, wenn sich
irgendwas geändert hat.
Also die, die den Bescheid sagt.
Ja, du
registrierst
dich 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 SOAP auch.
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
und die Programmiersprache Python.
zu registrieren oder Interface oder was immer, aber so im einfachsten Fall sagst du sowas wie
Event Trigger, Event Name 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-Arcs, Stern-Stern-KW-Arcs 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
unparteiischen Dritten hingehen und sagen, so, hier ist eine Funktion, die übergebe
und die rufst du bitte immer dann auf, wenn ein Record Change Event kommt.
Das ist so wie man es in 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, daraus baut man sich sein eigenes Framework.
In JavaScript ist über das DOM ja definiert, welche Events es da gibt und das ist eine Art, wie man sich selber solche Events halt bauen kann,
dass man sagt, okay, wenn auf einem Record-Objekt das Save 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
Also quasi Event-Signale abfangen quasi
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, das 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 Bestmatch 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 Record vom Typ Person war und solche Sachen.
Und dann kannst du halt solche Dinge machen wie
ein User setzt eine Bestellung ab und
ein 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 komplex... 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 mit sowas wie FeatureFlex
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.
Mhm, okay.
Und auch da wichtig,
und die
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
deutlich zum ersten Mal gehört
und das habe ich auch heute gelernt, weil du gerade
vom Blumenstrauß an Methoden sprachst, es gibt auch Welkeblumen
in Blumensträußen
ja genau, es gibt auch Welkeblumen
möchtest du Welke
möchtest du unter den Patterns Welkeblumen suchen
Ja, tatsächlich, du weißt ja nicht genau
was da stimmt, wenn du jetzt davon noch keine Ahnung
hast und die eben nicht durch
von vornherein verstehst, oh ja,
das ist das dies und jenes, sondern du versuchst
halt dich irgendwie an eine, ich sag mal,
clevere Architektur zu halten oder
eine, die du für clever hältst, vielleicht weil du es noch nicht verstehst
oder denkst, du müsstest halt in die Richtung
entwickeln, um möglichst
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 need it.
Also ich finde halt, man sollte sich bei der Anwendungsmöglichkeit
extrem stark auf den, erst mal
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
und die
und die Programmiersprache Python.
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.
Und ich glaube, was eben ganz wichtig ist, was bei den Patterns auch...
Also Yagni ist auch kein Pattern.
Persistency means having to say I'm sorry
und die
Programmiersprache Python
und die
Programmiersprache Python
und die
Programmiersprache Python
und die
Programmiersprache Python
und die
Programmiersprache Python
und die
Programmiersprache Python
und die
Programmiersprache Python
und die
Programmiersprache Python
und die
Programmiersprache Python
und die
Programmiersprache Python
und die
Programmiersprache Python
und die
Programmiersprache Python
und die
Programmiersprache Python
und die
Programmiersprache Python
und die
Programmiersprache Python
und die
Programmiersprache Python
und die
Programmiersprache Python
und die
Programmiersprache Python
und die
Programmiersprache Python
und die
Programmiersprache Python
und die
Programmiersprache Python
und die
Programmiersprache Python
und die
Programmiersprache Python
und die
Programmiersprache Python
und die
Programmiersprache Python
und die
Programmiersprache Python
und die
Programmiersprache Python
und die
Programmiersprache Python
und die
Programmiersprache Python
und die
Programmiersprache Python
und die
Programmiersprache Python
und die
Programmiersprache Python
und die
Programmiersprache Python
und die
Programmiersprache Python
und die
Programmiersprache Python
und die
das einmal auf Platte geschrieben hast,
dann kannst du aber wissen, dass das
sich in 10 Jahren noch verfolgt.
Ja.
Ja, und wenn man das richtig gemacht hat, dann
hat man halt
sozusagen auch später noch großen Nutzen.
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
durchaus auch und so.
Jaja.
Ich glaube an der Stelle auch, das ist halt der handwerkliche
Teil Teil Teil Teil
und die Programmiersprache Python.
Client Code auf Attribute zugreift, jemals noch irgendwie sich dazwischen zu hängeln.
Das ist ein reiner Future Proofing Aspekt und ich sehe immer wieder Leute, die aus der
Java-Welt kommen, die in Python Code schreiben und dann für jedes Attribut eine Getter Setter
Methode schreiben und du siehst sofort, dass es Java und wenn man dir dann irgendwann erzählt,
nein, es gibt, du kannst im Nachhinein eine Property draus machen, kannst machen was du
und die Technik der Sprache.
transportiert, muss man schon immer noch mal extrem gut auf die Suche gehen von
hat es hier nicht irgendeine andere Mechanik in Python, die das schon
überflüssig macht. Wir haben die Dekoratoren,
wir haben die Konstrukturen, wir haben New, wir haben
Properties, die ganzen Sachen
und die erschlagen viele von diesen anderen Sachen halt.
Ja, okay.
Also die Gang of Four Patterns habt ihr schon einigermaßen einmal kurz eingekringelt und erwischt.
Würde ich sagen, ja.
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 Designpattern oder sowas wie, ja, MVC, weiß ich jetzt nicht, ist das ein Designpattern, eher nicht, ein bisschen größer, keine Ahnung.
Model View Controller.
Ja genau
Schwer zu sagen oder sowas wie
Model View Controllers
älter
Das war nicht
Also Model View selber
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, die kam aber dann tatsächlich später, Datenbank, so ORM, so wie baue ich eigentlich ein ORM, also so was, eben Active Record oder halt Datamapper-Pattern, das ist halt auch so, tja, keine Ahnung, ob das Pattern sind oder
Was ist denn das hier schon wieder?
Ja, das ist halt die Frage, wie man sozusagen die Übersetzung macht zwischen Sachen, die jetzt in der Datenbank, vor allem in den relationalen Datenbanken liegen und halt Objekten in Python beispielsweise. Das sind halt diese beiden unterschiedlichen Dinge. Also Active Record ist halt das, was Django macht oder halt auch Ruby und Rails und Data Mapper ist halt das, was SQL Alchemy macht.
Und was ist der Unterschied?
und Jochen unterhalten sich über die Programmiersprache Python
Dann fangst du noch mit
XS Record an, Jochen?
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.
Wenn man halt
Dinge aus der Datenbank holt, dann hat man
halt eine Liste von diesen Objekten und
wenn man die Attribute ändert, dann speichert das halt
die, kann man halt sagen, auf dem Objekt, auf der Zeile
halt, speichert das und dann
geht das halt zurück in die Datenbank und
ja.
Genau, so sieht das halt ungefähr aus und normalerweise hat man eine Klasse, die definiert, welche Spalten es 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
diese Deskriptoren-Geschichte
ein bisschen eigenartig
definiert sind und
dann kann man halt auch aus diesen
Klassen die Tabellen direkt erzeugen
auch die sozusagen
ja
Relationen zwischen den Tabellen sind halt
in den Attributen enthalten
das heißt ich kann halt wenn ich mir so
diese Tabellen
hindefiniert habe, halt auch komplett
mein Datenbankschema aus den Dingern
erzeugen.
Immer wenn einzelne Sachen
passieren sollen auf einer Zeile, dann sind das
halt
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 Model Manager,
die dann halt irgendwie eine ganze Reihe von Sachen updaten oder halt
irgendwie
eine Reihe von Zeilen löschen
und so kann man das dann halt aufteilen, alle Methoden, die irgendwie 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 SQL-IDEMY
Ja, Datamapper
Genau, ich habe jetzt
erst mal wieder die Active Record Sache
angeguckt und das Interessante bei Active Record ist ja,
dass du relativ klar
Tabelle und Klasse aufeinander
mappst und beim
Datamapper ist es ja 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 kannst, 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 genauso
Und bei SQL Alchemist 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
und die
und ich beschreibe
Klassen und jetzt beschreibe ich, wie diese Tabellen auf Klassen gemappt werden.
Und da können halt auch alles mögliche reinspielen, dass irgendwelche Attribute
über komplexere Queries 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, der Herr hat hier 100 Objekte angefasst, jetzt machen wir ein großes Update-Statement,
das irgendwie einmal sinnvoll aussieht, bumm, anstatt halt dann die eher naiveren Varianten von,
okay, jedes Mal safe drücken ist jedes Mal 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 Mapper...
Blala, es ist Zeit fürs Bett.
Dann kannst du mit dem 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 denn da 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
das ist so ein Zeug von
du machst komplexere Abfragen und er weiß
okay wenn ich das jetzt mache
dann lade ich schon mal die nächsten Relations mit
und falte irgendwie die Relation-Objekte
schon mal in die originale
Seqquery mit rein, damit ich nur einmal einen großen
Bulk-Transfer am Anfang habe, anstatt
nachher bei jedem Attributzugriff nochmal zur
Datenbank zu laufen oder so. Und das
kannst du da extrem genau aussteuern.
Das hat ein Django-Dynamit, oder?
Ja, in Django ist
das, aber da gibt es das auch.
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
und Jochen unterhalten sich über die Programmiersprache Python
N plus 1 Queries
gegen die Datenbank
und das ist natürlich extrem
fies und ein Haufen Performance-Probleme
kommen genau deswegen, aber also in Django
sagt man dann halt Select Related
genau, dann zieht es die
oder Prefetch Related
für N zu M
Relationen und so, also das geht auch alles
Machst du das am Model oder musst du das
an der Query machen? Das machst du an der
Query. Genau, bei SQL
Alchemy kannst du das im Prinzip modellieren
da kannst du halt diese ganzen Relationen
alle ausdefinieren
auch so richtig mit
Vor- und Rückreferenzen will ich die
irgendwie als Listen oder Dicks kriegen
oder als Attribute oder
so ein Zeug und kannst dann halt sagen
die Richtung, die machst du bitte als Eagerload
und die bitte nicht und folgende 10 Attribute
bitte im Eagerload wieder rauslassen
und das kannst du ja 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
und du kannst bei SQL Alchemy auch sehr dynamisch
die haben halt auch eine voll getrennte Schicht
zwischen ich hab 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
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 Eager Load 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 diesen 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
naja
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 umgekehrt das 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 Alchemy
auch nicht. Man kann ja auch immer noch
auf rohes SQL zurückfallen,
wenn man irgendwas Spezielles
machen muss.
Ja.
Haben wir
alle Patterns durch, tatsächlich?
Also, du wolltest auch irgendwas zu Datenbanken sagen.
Ich habe da gestern noch so ein Solid-Modell
oder sowas.
Ja, achso, nee, das ist nicht Datman, aber das ist auch so genau, 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 Design Prinzipien, ja, ja.
Was ist das denn?
Ja, das ist
auch etwas, was, es gibt ja dieses
Buch Clean Code von
Robert Martin
und Uncle Bob.
Gibt es das auch in Python?
Das ist, nee, das ist
die ganze, das ist über uns,
ich meine, ehrlich gesagt, ich bin ja ein bisschen
peinlich berührt, wenn ich dann irgendwie so
Observer-Pattern, keine Ahnung, habe ich
schon mal gehört oder so. 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, da ist also für Juniorstellen
irgendwie, wenn man sich da,
wenn man da in Vorstellungsgesprächen ist, dann
wird halt erwartet, dass man die alle kennt und
ja,
das wäre dann schon sehr fein, wenn man sagt, also
ich habe keine Ahnung, was das eigentlich ist.
Aber ja, suche ich mal ja gerne 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 und Prinzipien 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ämpchen angehen,
du halt weißt, Moment, jetzt mal nochmal
nachdenken, warum geht das hier schief?
Damit du dann halt wenigstens weißt, wo du googeln musst.
Ich habe über Solid jetzt gerade nochmal schnell drüber geguckt
Oh, das ist aber schon ganz schön alte Schule teilweise
Also wenn ich halt Liskov Substitution höre, dann 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 gewisserweise
schon Sinn, also durchaus
und auch mehr Sinn halt, vielleicht als bei Python,
weil da viele Dinge einfach automatisch
erfüllt sind. Also eben, ich würde sagen,
ja, ich würde, Lischkows
Substitution Principle?
Nee, das ist ein Designthema, das musst du selber
als Programmierer richtig umsetzen.
Das ist Typtheorie
und das ist die Aussage, dass
Objekte
in einem Programm, also aller Programm
Code, 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 jetzt in der Vorschleife
so Fallunterscheidungen macht, also nehmen wir an, man hat eine Typarchie,
und Jochen unterhalten sich über die Programmiersprache Python
machen wir aber folgende Ausnahmegeschichten.
Wenn wir jetzt zum Beispiel Gehalt auszahlen wollen,
wir rufen nicht einfach Gehaltauszahlen-Methode
auf, sondern wir sagen nochmal,
okay, wir machen Speziallogik,
je nachdem, was das für ein Typ ist.
Du weißt schon, dass der Senior Vice President
Facility Management ein ziemlich stiller Witz ist.
Wieso?
Das ist voll wichtig.
Also dann hätte man sozusagen,
aus meiner Perspektive, hätte man jetzt
eben Lischkows 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 wird. Ja, noch nicht so ganz.
Also Spezialfälle
zu erlauben ist ja kein Problem,
es muss bloß die Korrektheit gewährleistet sein. Aber
Beispiel, wenn man zum Beispiel sagt,
der
und
Korrektheit ist tatsächlich auch immer eine spannende Frage
von, das 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, da ist wie immer 0, 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 Telefonliste der Mitarbeiter fertig
und machen die Secret Centers für hier und da und den 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,
das ist eine Designanforderung von Objekten, von Unterobjekten, von Unterklassen, von Subklassen.
Dass eine Subklasse den Raum der Möglichkeiten erweitern, aber nicht einstellen.
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.
Wir haben heute etwas Zeit.
Wir haben relativ gut zeitig angefangen.
Mit dem Nachteil, dass meine
Technik heute ein bisschen...
Du hast inzwischen für dich alleine geredet.
Ja, und auch bis wir zum Reden gekommen sind, dann weil irgendwie hier
alle 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 entschuldigen.
Wir haben den letzten Monat irgendwie verbasselt, aber ich meine,
es war viel zu tun und so.
Ja, es war viel zu tun und zwar ein bisschen sehr...
Ja, eigentlich wollten wir noch
2 aufnehmen, da ist wieder was ausgefallen und so.
Die Termin-Findungs-
Koordinationsschwierigkeiten kommen noch
ihr Ugriges dazu. Ja, wir geloben Besserung,
das kriegen wir auch schon irgendwie hin.
Genau, nee, dann am besten,
ja, wir haben ja auch schon echt viel
Zeug gemacht, dann verschieben wir das mal solid,
das ist ein gutes Thema.
Ja, und halt auch noch so diverse
Architektur-Patterns, 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
.com.
Ich glaube, das heißt dann auch tatsächlich, wenn man es als Buch kauft,
also kann man da online lesen.
Ja es ist halt auch Architectural Patterns for Python oder irgendwie sowas Ist von dem na wie hei er noch Der auch Obey the Testing
Code geschrieben hat.
Und einem anderen.
Verdammt. Okay.
Weiß nicht mehr genau.
Da kann ich eigentlich auch sofort
nachgucken.
Percival.
Kosmos hat sich
opposite auf Chaos und Gregory.
Aha, Kosmos ist die Opposite of Chaos.
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-Meeting, auch Event-Driven.
Und MessageBus klingt gut, Commands klingt gut.
Dependency Injection ist super.
Das klingt interessant, das kommt in die Leseliste.
Super, dann haben wir auf jeden Fall auch noch eine Menge Stoff für den nächsten, für den zweiten Teil.
Ja, wir haben einige Teil-Dateien noch offen übrigens.
Ja, ja, Async muss wir auch unbedingt nochmal dran.
Ja, vielen Dank, dass du wieder da warst, Christian, Conny.
Danke, dass ich dir bei sein durfte.
Na klar.
Und schön, dass ihr eingeschaltet habt.
Und gute Nacht, guten Morgen, guten Abend und so weiter.
Bis zum nächsten Mal.
Bis dann.
Tschüss.
Ciao, ciao.