Transcript: Python 3.9 und Design Patterns (Teil 1)
Full episode transcript. Timestamps refer to the audio playback.
Ja, hallo liebe Hörerinnen und Hörer, willkommen beim Python-Podcast, 25. Episode.
Heute geht es um Patterns, Software-Patterns, Design-Patterns, Architektur-Patterns.
Und wir haben einen Gast dabei, der Antoni, hallo.
Hallo mal wieder.
Hallihallo.
Ich bin der Dominik, Jochen ist auch da.
Hoiho.
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 XKCD, wo ein Zeitreiser nach 2020 kommt
und fragt, welches Jahr es ist, und er sagt 2020.
Ja, aber das wievielte.
Das wissen wir auch nicht so ganz genau.
Ja, vielleicht noch ein paar News aus der Szene vorweg.
Genau, ja, was haben wir denn an News?
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.
Ja.
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 habe
überlegt, wir machen das bei 1 dann, bei 3, 9, 1.
Ja, ich bin tatsächlich
schon quasi zumindest mit den privaten
Sachen umgestiegen, aber
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 das natürlich auch so ein bisschen
hässlich, wenn man das irgendwie dann selber kompilieren
muss. Das heißt doch, im Baton
habe ich tatsächlich das in die
Travels-Liste schon mit aufgenommen.
Da kam auch
jemand vorbei, der sich gleich
irgendwie sofort beschwert hatte, dass es unter 3.9
nicht ging, weil
irgendwas ist rausgeflogen.
Achso, die haben im Async
irgendeine
API, die deprecated war, jetzt tatsächlich gestrichen
gehabt. Ich glaube, die in 3.7 hatten sie
irgendeine neue API, um alle
Pending-Tasks abzufragen
eingeführt
und die, glaube ich, in irgendein Untermodul verschoben
oder so, statt im direkten
Async-Modul. Das war was, da musste ich dann irgendwie
hinterher und in 3.9 war dann irgendwie die
Abwärtskompatibilität von der API jetzt weg.
Da flog es dann auseinander.
Ja.
Insofern, ja, ich habe es schon mal in der Hand gehabt, weil ich was
Was gibt es denn Neues?
Ganz viele spannende
Sachen. Union Operators?
Was ist das?
Was macht man damit?
Ja, zum Beispiel Dictionaries zusammenschübbeln.
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.
So, ich glaube, wenn man jetzt den Pipe-Operator verwendet,
macht es so mehr oder weniger genau das Gleiche.
Ja, aber warum macht man das?
Also ich habe es nicht genau verstanden.
Ich finde es irgendwie, weiß nicht,
das ist das Erste, was ich bei Python so richtig hässlich fand.
Naja, was fandst du hässlich?
Ja, diesen Operator, diesen Pipe-Operator
da stehen zu haben auf einmal für so eine Operation.
Och, ich weiß nicht.
Ich meine, das 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 irgendwie definieren möchte.
Oder gleich dieses
Assignment, irgendwie ist das komisch.
Naja, das ist halt so wie plusgleich oder
malgleich.
Das habe ich tatsächlich in Bato benutzt
oder gleich tatsächlich, auch Bato 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.
fühle ich mich in meiner Wahl von vor
sechs Jahren bestätigt.
Ja.
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 und Sternsteinen, da muss man
mal so ein bisschen nachdenken, was denn jetzt,
was man jetzt eigentlich genau machen
wollte. Es ist ein bisschen hübscher,
aber es ist jetzt keine so weltbewegende
Änderung.
Ja, das ist hübscher.
Und es ist vor allem, es erzeugt halt ja ein neues Dignam.
Also ganz
klassisch war ja immer das Thema, dass du
DictUpdate sagst.
Ja, und dann macht das
was anderes, als man denkt. Das modifiziert
den Original-Dict und genau.
Ja.
Ja.
Insofern ist vielleicht ein bisschen eindeutiger, was es macht.
Ja, also
mein Lieblingsfeature tatsächlich, oder
meine Lieblingsneuerung ist
der Pack-Parser. So ehrlich gesagt bin ich jetzt
kein Experte
für so Parser-Geschichten, aber ich fand das schon eigentlich
ganz nett,
was man damit dann eventuell alles dann
zusätzlich so machen kann. Also
es hieß irgendwie so, ja,
das macht dann irgendwie neue Sprachfeatures einfacher
oder so. Das stimmt nicht so ganz.
wirklich viel einfacher wird dadurch nicht,
aber es macht halt so ein paar Sachen, die bisher sehr hässlich
waren. Du musst uns den Hörer nochmal kurz erklären, was überhaupt
ein Pack-Parser ist, bitte. Oh nein!
Das wollte ich eigentlich vermeiden.
Das kann ich ehrlich gesagt nicht wirklich.
Also es gibt halt diese Standard-
Parser für so
Programmiersprachen. Also die meisten Programmiersprachen
sind halt, oh, oh je, jetzt kann man
nochmal positiv in die Informatik
hinabsteigen.
Da gibt es halt so, so Programmiersprachen
sind meistens, die Grammatiken dafür sind so
kontextfreie Sprachen.
Also, oh je.
Ja, ja, genau.
Ja, du musst halt
eine bestimmte
Form davon, so
LR1-Grammatiken oder so, das ist halt
LR1,
LR1-Grammatik zum Beispiel.
LR1-Grammatik.
Ja, also in dieser Form ist auch zum Beispiel immer die Java-Sprachspezifikation. Das ist das Erste, was ich in, 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 dachte ich schon, das ist eine komische Abkürzung und das ist halt genau die, die halt beschreibt, ja, wie die Grammatik für diese Sprache aussieht.
Und wenn man das sozusagen
in dieser Form notiert hat, dann kann man das in einen
Parser-Generator werfen
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.
Ist auch so ein rekursives Akronym.
Justiner sagt Compiler, Compiler.
Dem kann man
sowas vorwerfen und der spuckt dann halt
einen Parser aus und das gab es dann
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, ich kriege das auch nicht alles auf die Reihe,
aber es gibt halt den, 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,
da bestimmte Sachen halt nicht so einfach damit parsbar waren.
Und der ist auch handgeschrieben.
Wenn man sich das angucken will,
gibt es ein Modul, das nennt sich
ast.c oder so
in Python Source Code,
dass der alte Parser
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 das der Parser noch nicht irgendwie ordentlich gemacht hat irgendwie.
Und das heißt, wenn man jetzt irgendwie so ein Problem hat, auch ein Syntaxproblem, Funktion A plus Funktion B rechts von einem Gleichheitszeichen, dann ist halt komplett unklar, wenn jetzt da irgendwo ein Syntaxfehler ist, wo der eigentlich passiert.
das ja dann schon einem erst im Compiler
irgendwie um die Ohren fliegt oder so,
sodass halt der einem
sozusagen der Python-Interpreter auch gar nicht sagen kann,
wo der Syntaxfehler ist, was halt eventuell
ein Problem sein könnte. So, wenn man nicht mehr
weiß, wo der Fehler ist, dann ist es halt schwer, den zu fixen
und das sind halt so Hässlichkeiten,
sodass man halt da diese
Ü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
Und ich habe da so ein 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 eine User-Anfrage war halt so,
warum können wir das in RIS-Context-Managern mit diesem RIS-Statement
nicht einfach so machen wie bei Imports
oder halt mit
bei Strings, dass wir da Klammern drumrum
machen und dann haben wir mehrzeilige Dinge, weil
mehrzeilige With-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, ja yes, jetzt geht
es endlich, jetzt kann man das auch mit Klammern
machen, das ist viel besser, voll gut.
Obwohl das wahrscheinlich nie irgendjemand verwenden
wird wahrscheinlich, aber
ja, also
aber das
was jetzt oft erzählt wird
ist halt irgendwie, dass man damit besser
neue Sprachfeatures umsetzen kann oder so, das ist eigentlich
nicht unbedingt der Fall, es ist halt nur so, dass es jetzt konsistenter
ist, dass der Faser automatisch generiert
wird und
ja
Ja, nee, also
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 Rahmen. Irgendwer hatte
auch was erzählt von, dass sie jetzt per
Default sagen, also mehr als eine Million Zeilen
in einer passenden
Datei wollen sie jetzt bitte nicht mehr sehen.
Ja.
Oh Mist, was war ich denn jetzt?
Ja genau, da habe ich
eine ganze Firma drauf aufgebaut.
Ja,
also von der Performance her
ist kein großer Unterschied, sowohl von der Laufzeit
und Hauptspeicher 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
in funktionalen Programmiersprachen ist das schon länger
oder das ist halt ja so eins der grundlegenden
Geschichten.
ja, in Python ging das halt auch
vor allen Dingen wegen dem Parser bisher
nicht. Und das
geht dann eventuell. Und wenn man das darin hat, ist es natürlich
schon nett. Da hat man so eines der zentralen Features
von funktionalen Programmiersprachen auch mit drin.
Was sind denn Lisp-like-Makro?
Ja, das müssen wir
mal irgendwann machen, wenn wir irgendwie auch so ein bisschen
so, ja, noch mal funktionalen Programmiersprachen
und was ist Pattern-Matching und was sind Makros?
Da können wir das nochmal. Aber ich glaube, das ist einfach
Okay, das verschiebe ich auf eine folgende Folge.
Für die Leute, die gucken wollen,
wäre es 6-3-4.
Ah, 6-3-4, ja.
Das ist auch eins, wo Guido jetzt selber
wieder, Guido hat ja beim Parser natürlich
mit drin gesteckt
und das ist jetzt auch anscheinend
eins seiner Themen, wo er dran steckt.
Ja.
Ja, also auf jeden Fall, das klingt irgendwie
sehr vielversprechend und ich bin mal gespannt, was dabei so rauskommt.
Ja, ein Bug ist auch schon aufgefallen
wohl. Achso, Match war,
achso, ja, vielleicht tatsächlich
das ist
eine bessere Variante
dessen, was sonst in anderen Sprachen das Case
gewesen wäre.
Nur mal so als
zur groben Einordnung. Also mit
dem Match geht es dann am Ende
tatsächlich darum, die, wenn man sehr
komplexe If-Else
Zweige hat,
dann kann man die damit ein bisschen hübscher abbilden.
Also substanziell
hübscher.
Warum hat man das nicht Case genannt?
Das müsste ich jetzt nachlesen.
Also es macht schon, glaube ich, noch ein bisschen mehr.
Also ich meine, ja, naja.
Ach, keine Ahnung.
Genau, 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 Tuple Unpacking,
halt auch so Stern irgendwas in WIS,
so Context Manager 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 Kommando zahlen,
Optionen sagen, Minus X irgendwas, Old Parser oder so,
verwendet doch bitte den alten,
wenn man irgendwie mit dem neuen Probleme hat.
Der neue ist defaultmäßig aktiv
und der alte ist aber halt noch drin
und mit Python 3.10 wird es dann halt so sein,
dann wird der alte Parser komplett rausfliegen
und nur noch der neue drin sein.
Was mit Tablet-Uppacking 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 jetzt geht es nicht mehr.
Also warum will er das denn nicht machen?
Na ja, 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?
Na ja, Moment, da müsste ich auch gerade suchen.
Ich versuche so leise wie möglich zu tippen.
Ja.
Also ich kann mir schon vorstellen, warum nicht im Contact-Manager
einfach irgendeinen Tuple anpacken, das ist doch durchaus okay.
Nee, nee, die Frage
meinst du wahrscheinlich oben in der With-Expression.
Ja, ja, in der Expression selber.
Also With und dann irgendwas mit Tuple-Unpacking machen.
Also ich sehe da echt keinen Anwendungsfall
für. Und es ist, glaube ich, also die haben da ja
die komplette Standard-Bibliothek durchgejagt und noch viele
PyPI-Pakete und sie haben es
nicht, also das ist nie aufgetreten.
Also das ist nicht so, dass das irgendwie dauernd gemacht
wurde, sondern das hat bisher wohl noch nie jemand
gemacht. Quasi. Also jedenfalls
nicht 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 Paaren gab.
Ja.
Tja, was haben wir denn noch so?
Oh, na hier.
Also, was ich wirklich hübsch fand, war
jetzt irgendwie nochmal explizit
die String, Prefix,
Suffix-Removals.
Weil das ist einfach, das war
seit langen Jahren
ist ja, es gibt einen L-Strip und einen R-Strip
und da
fallen Leute ja gern drauf rein.
Dass Leute gerne irgendwie sagen
L-Strip oder
Strip und dann irgendwie
eine Zeichenkette und sie denken
damit wird irgendwie, also
wenn ich sage Strip,
ABC, also möchte ich
immer, wenn ABC ganz links steht, das
weggestrichen haben, aber das
macht es ja nicht, sondern das macht ja
Streich von links
so lange alles weg,
wie das, was links ein A, ein B
oder ein C ist.
Das heißt, da kommen ganz lustige Dinge dann manchmal raus.
Und
jetzt gibt es halt ein explizites
Remove Prefix, Remove Suffix und dann
wäre das auch geklärt.
Ja.
Das ist schon hilfreich.
Ja, ansonsten
Zeitzonenhandling
ist jetzt irgendwie mit drin.
Das habe ich noch nicht angeguckt,
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 nur eine API?
Genau, das ist halt auch der Grund, warum
im DateTime-Standard-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,
das halt so ein Objekt irgendwie
reintun kann, weil sich die Leute gesagt haben, ah,
Python-Release-Zyklus, viel zu lang für diese Updates
und dann wollen die Leute das mal selber machen
und dann haben es die Leute natürlich nicht selber gemacht,
weil keiner Bock hatte, das zu
machen und ja,
nee, wie es jetzt wohl ist, ist, dass
Ach, 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.
Dann
geht das da wohl irgendwie auch.
Aber
genau, so ist das dann. Ja, das ist so als
Fallback gedacht, für wenn das andere nicht da ist.
Und die intern
funktioniert das wohl
mehr oder weniger genauso wie
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 es implementiert halt so die
Kerngeschichten, aber viele von den fancy Features
von DateUtil sind halt nicht drin, aber
so die Kerndinge.
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. Ah, das wird wahrscheinlich auch kaum jemand
machen insofern.
Ja, obwohl, da kann ich mir jetzt KMR vorstellen noch.
Ja, dass man halt, 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 auswählt
und jetzt geht es halt direkt.
Ja, auch nicht so schlecht.
Es ist ja eine Frage von
in solchen Momenten immer bei diesen
syntaktischen Kleinheiten
dann kann man ja immer dieses
berühmte Dokument des
PHP, a fractal of bad design
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
a PAPEffect of Bad Design?
Also, um nicht auf
anderen
Sprachen rumzuhauen.
Gibt es aber ein
wirklich berühmtes Dokument
zum Thema, warum PHP
so ein massives Problem im Sprachdesign
hat. Und da gibt es
in dieser Blogpost, der ist jetzt auch
bestimmt schon 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
ich erinnere mich
an mindestens ein Thema,
wo allein von
dieser syntaktischen Genauigkeit
tatsächlich irgendwie,
ich glaube, war das
das Type-of-Äquivalent
bei PHP oder so, war so
im Parser integriert, dass tatsächlich
die Aussage war, diese eine Funktion kann
immer nur exakt mit einem variablen Namen
aufgerufen werden, aber niemals
jemals mit einer
Expression, wo du dann von dem Ergebnis
den Typen haben
möchtest. Weil halt
jemand das in den Parser so reingestrickt hat.
Und dieser Artikel geht 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 ist mal ganz interessant zu lesen,
wird zum Thema irgendwie
ein bisschen analytisch auseinandergenommen,
was das liebe PHP
da so ein bisschen auf die schiefe Bahn
geraten lässt.
Ja, müssen wir mal in die Shownotes packen.
Ja.
Ja, mit den iii.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 Typins oder sowas, aber
Oh ja, stimmt, man kann jetzt irgendwie
List, man muss nicht mehr
diese List mit Großbuchstaben vom
Typing importieren. Wahrscheinlich
war das halt auch so gedacht, ja, wer
weiß, wie lange, ob die Leute das gut finden mit
dem Typing, Typins und so.
Nehmen wir mal nicht
irgendwie, machen wir nicht den Aufwand, das
direkt so zu ändern. Und jetzt kann man,
muss man das halt nicht mehr aus Typing
irgendwie
Listen mit großem L importieren, sondern kann halt
die Build-ins verwenden und das
funktioniert dann halt auch in den Type-ins.
Genau, das ist ganz
nett. Das macht es ein bisschen
einfacher, das zu schreiben und man muss nicht immer nachgucken, welche
Imports 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 Python auf jetzt?
Oder waren die
War die PyCon dieses Jahr virtuell?
Ich weiß gar nicht. Welche meinst du?
Die deutsche? Ja, die D.
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 wir haben gewesen, im
Haus des, nicht Haus des Lehrers
hier daneben an.
Ja.
in Berlin, genau
ach, wie heißt denn das noch, da wo immer
der CCC-Kongress 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 2000 Leuten gewesen
und das kannst du halt
gerade knicken, das geht gar nicht.
Und gleichzeitig war halt auch schon
eine Anzahlung geleistet gewesen,
deswegen mussten wir mit denen entsprechend verhandeln
und jetzt ist die Aussage, wir probieren es 2021
und 2022, also wir haben uns committet
2021 und 2022 nochmal in Berlin zu machen
und haben uns gedacht, na gut,
um dann halt sozusagen die
Anzahlung zu retten.
Dadurch dürfen wir die für das nächste Jahr mit
verrechnen und haben jetzt auch
garantierte Preise
für 2021 und 2022
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
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 Hinterpolse muckeln,
ansonsten
sind wir pleite,
wären wir nicht pleite, aber
ansonsten müssten wir da
irgendwie Dutzende, Zehntausend Euro
vergraben.
Ja, nee, genau,
das wäre es gewesen, das haben wir verschoben.
Was tatsächlich im November noch ist,
vielleicht für alle, die auch im Peißenverband
schon Mitglied sind, ist
Mitgliederversammlung tatsächlich.
Das hatten wir auch ursprünglich geplant,
die jetzt, weil es ja eigentlich ganz gut aussah, im Oktober
mit vor Ort
hier in Halle zu machen, aber
sind gerade dabei.
Ich glaube, morgen wird das beschlossen
und dann wird das wahrscheinlich auch eine digitale
Veranstaltung werden,
im November. Da gehen demnächst
noch Einladungen raus, wer beim
Python-Verband Mitglied werden will.
Stimmt, kann ich das gerne noch machen.
Ja, dafür muss er tatsächlich noch mal kurz Werbung machen.
Die Webseite kurz nennen
und... Genau, das wäre der
python-verband.org
der Python Software Verband
als die deutsche Interessensvorredung
und eine unserer
Hauptaktionen, und das war diesmal jetzt leider
dann auch ein bisschen
wenig durch Corona,
ist, dass wir alle möglichen
Community-Aktionen fördern.
Sowohl organisatorisch
als auch mit Geld. Das heißt, wir
verstehen uns da ein bisschen
als eine Drehscheibe.
Python selber ist ja gut bekannt, aber
was wir stark unterstützen wollen,
ist halt, Python
noch in Communities zu tragen, die es vielleicht
nicht so kennen und aber auch Veranstaltungen
zu fördern. Das heißt, man kann da auf der Webseite
unser Förderprogramm nachschlagen
und dann kann man sich relativ
unkompliziert Geld für Ideen abholen,
die man mal mit, wie man Python an andere
Leute ranbringen will, mal was coden möchte,
etc., etc.
Genau. Okay, interessant. Und
im Corona-Jahr war es jetzt auch so, dass wir tatsächlich
ein, zwei schon länger
bekannte Partner,
da gibt es die TechKids zum Beispiel
im Schwäbischen, die haben
jetzt auch ganz schön drunter gelitten, weil denen die ganzen Veranstaltungen
weggebrochen sind, mit denen sie normalerweise
dann ja auch wieder so Teilnahmegebühren reinholen
und haben da jetzt dieses Jahr
im Fördertopf tatsächlich dann auch eher mal
großzügig gesagt, okay, wir sponsoren 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. Ja. Das ist tatsächlich
vielerorts ein größeres Problem, ja.
Ja.
Tja, ja.
Also es 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,
Juro Python war jetzt auch
vor kurzem. Die Vorträge sind
irgendwie da und Django Con,
das wollte ich mir auf jeden Fall angucken, aber habe ich
noch bisher nicht geschafft. Gibt es auch die ganzen
Vorträge online.
Und was jetzt in Zukunft kommt, weiß ich gar nicht.
weil ich es nicht nachgeguckt habe.
Ja, wir verpassen übrigens gerade wieder das Django-Meetup
Cologne, ne? Ja, ich weiß, aber das ist halt
dann blöd, muss man...
Ja, die Froscon 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, genau.
Ja, und es gibt, glaube ich, noch wieder
so eine neue Anmeldung für das nächste Jahr, ne?
Die 21, die auch online statt
sein wird, äh, Forstdem, diesmal, ja.
Forstdem, achso, das ist dann Februar, Januar, Februar
irgendwann die Forstdem, genau.
Nee, ich meinte die Frostcon.
Genau, die ist normalerweise
St. Augustin. Genau, ja.
Damals, ja.
Ja, ansonsten, was mir noch so
eingefallen ist, was jetzt geht, was
früher nicht ging,
Icehorde und Black sind kompatibel.
Ja, das
ist auch nett.
Wie kam es?
Ich weiß es nicht genau,
also
mit irgendeinem Update
von Icehorde ist das jetzt
sozusagen erledigt dann irgendwie gewesen.
Also iSort hat was gemacht, damit Black
nicht mehr dazwischen punkt.
Ja, irgendwie so, genau.
Und ja, jetzt geht es halt, man kann es
halt parallel, also man kann halt beides
verwenden und
hat dann da kein, nicht mehr so, dass das eine
immer die Sachen vom anderen umsortiert, was ja irgendwie ein bisschen doof ist.
Jetzt müsste man das nur noch in PyProjectHummel
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.
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 empfehle mal noch ins Japf reinzuschauen.
Japf, okay.
Ja, Black wird auch
ein Problem kriegen, Black Fernandes
auch den alten Parser
und
spätestens ab Python 3.10 wird es dann halt
muss er sich
was einfallen lassen, weil das geht dann nicht mehr.
Naja.
Kannst du kurz was zu JAPF noch
sagen? Ja, JAPF
ist so ein, wie auch, wir waren ja vorhin schon
beim 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 Jap Ignore, ich hab's grad
gesehen.
Und der erzeugt
für mich, find ich, deutlich
lesbareren Code. Also das ist
die, ich komm persönlich mit
der Black-Formatierung an
vielen Stellen so richtig gar nicht klar
und find sie einfach
urpot hässlich.
Ich fand sie auch sehr ugly, aber Jochen hat's mir immer aufgezogen.
Ja, sorry.
Also ich unterstütze
volle Kanne das Thema,
einen Auto-Formatter einzusetzen.
Ähm, aber ich finde
Black ist halt nicht der weiße letzter Schluss
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
Das ist schon so ein bisschen
Auf der anderen Seite würde ich sagen, naja gut
Also, äh
Selbst wenn man es nicht so hübsch empfindet
Äh, wenn alle den gleichen
Auto-Format verwenden, ist das
ein so viel größerer Gewinn, als
dass ich dann sage, nur gut, dann
gebe ich dafür die persönlichen Präferenzen auf
Aber ja, ich kann auch verstehen, dass man das, ja.
Weil mein Streit sozusagen schon über das, was ich als persönliche Präferenz empfinde, rausgeht, weil es verletzt mein ästhetisches Gefühl so, dass ich wirklich daneben stehe und sage, nee, das ist volle Kanne gegen die Designziele von Python als Sprache.
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, dann kann ich JavaScript schreiben.
Ja, naja.
Und sie wollen, also 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, dass das wirklich, also da hätte ich gerne mal tatsächlich noch eine Metrik gesehen und ich muss aber sagen, das verletzt dann so ganz klassische Clean-Code-Aspekte auch von Code optisch ist zum Lesen für Menschen da und wenn das Ding halt tatsächlich erfordert,
dass meine Kognition massiv mehr Aufwand leisten muss, um es zu lesen.
Und alle Leute dann mehr oder weniger mit einem Stockholm-Syndrom ankommen
und sagen, ja, ich habe mich daran gewöhnt.
Dann erinnert mich das so ein bisschen eher wie an die alten Leute,
die ich hatte, als ich ein Haus gekauft habe und die Flugzeuge drüber fliegen
und die sagen, ich höre die schon alle nicht mehr.
Ja, so fühlt sich das für mich jetzt halt an.
Und wir haben jetzt tatsächlich in einem Projekt,
in einem größeren Projekt, das eben nochmal umgestellt von Black
auf einen anderen Formatter.
Auf Japf.
auf JAPF halt mit entsprechenden
anderen Optionen und
siehe da, plötzlich hat man wieder so ein
Ah, stimmt, so muss das aussehen. Danke, das ist Python.
Kannst du dafür mal
die Config irgendwie
teilen mit uns in den Show Notes?
Na klar. Das wäre super, weil das
finde ich sehr spannend. Weil ich finde Black auch
mega ultra hässlich und genau das, was du
sagtest, also ein paar Sachen, wo ich dachte so, ah, wieso
macht das so? Das ist auch eklig.
Ja, na ja, gut.
Ja, so, na 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 immer schön lang,
der heißt irgendwie Lex Friedman
und der spricht so mit allen möglichen Leuten
und halt darunter sind halt
auch viele der so Korrifäen.
Zum Beispiel hatte er letztens
ein Interview mit
James Gosling,
zu dem
ja 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
ja, seine lange Erfahrung mit C
auch sowas, was ich nicht wusste, der hat
Emacs irgendwie geschrieben
in C, oder die erste ordentliche Version
von Emacs und stand
dann irgendwann vor der Entscheidung, okay, ich mache jetzt entweder
den Rest meines Lebens Emacs
oder halt nochmal was anderes und dann dachte ich so
naja, Emacs, so geil ist es dann, also weiß nicht,
muss auch nicht sein.
Dann hat er lieber was anderes gemacht und das abgegeben irgendwie.
Also Emacs und Java sind eng
verwandt, interessant.
Naja, also, ja.
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, halt 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 weiter so, ja, also
wenn ich irgendwie Code lese, es gibt ja mal so Leute,
die sagen dann so, oh, ich finde das ästhetisch ist aber
nicht so, gefällt mir nicht so
richtig. Und dann 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 und das ist mir auch total egal.
Jetzt wissen wir, was uns da war. 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 halt im Studium auch Linguistik gemacht
und deswegen bin ich an der Stelle auch immer ein bisschen mit dran zu gucken,
wie hängt das zusammen und unser Gehirn, kognitive Last ist halt was,
das zwingt uns irgendwann halt dann nicht mehr über die Sache nachzudenken,
sondern das Gehirn ist dann halt nur noch damit beschäftigt,
dieses komplizierte Zeug zu lesen.
Deswegen hast du halt sowas wie Brainfuck.
Da bleibt dann halt nicht mehr viel über für
was macht der Code eigentlich?
Buchstabensalat.
Das ist halt schon eine echte Balance.
Ja, 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. Also wenn ich
bin sehr an der ästhetischen...
Wenn man die ästhetischen Patterns direkt
sehen kann und die einem klar ins Auge springen.
Ja, du willst
ein anderes Thema einleiten.
Ich habe gerade versucht, einen kleinen Ü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 unermichtiger, aber ich finde, das ist ein sehr essentieller Teil.
Also gerade, weil auch die Hürde dadurch deutlich gesenkt wird.
Selbst wenn es jetzt ein sehr hochentwickeltes Feature ist,
ermöglicht es halt auch einen deutlich einfacheren Einstieg,
weil durch diese ästhetische Klarheit man das Konzept auch deutlich einfacher verstehen kann.
Man kann ja auch tatsächlich Ästhetik mal zur Seite legen und an der Stelle einfach,
also es gibt ja mehrere andere Kriterien, die man ansetzen könnte,
eben zum Thema Lesbarkeit, Menge der Zeichen auf dem Bildschirm,
Menge an Noise, an syntaktischem 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,
meint, hier ist ein Leerzeichen,
deswegen bedeutet jetzt gerade hmm, und wenn das
dahinter eine Funktion ist, dann
da musst du schon auch
in diesen Mustern ganz schön
arg drin stecken, um das halt wirklich lesen
zu können. Und ich habe bei Python halt immer
das Gefühl, egal wie es
geschrieben ist, irgendwie kriege ich
es dann schon auch wieder relativ schnell auseinander
klamüsert. Aber ich
merke auch, oh, jetzt ist es auf eine Art
geschrieben, die ist irgendwie von dort durch die Brust
ins Auge und war
irgendwie nicht zum Lesen gedacht.
Ja, man muss ja schon irgendwie
Methode relativ schnell begreifen können irgendwie,
das ist zumindest ein Ziel, wenn man das so
vernünftig machen möchte.
Naja, es ist halt so, ich glaube auch da
wieder, dass halt für unterschiedliche Leute
vielleicht da unterschiedliche
Trade-Offs besser funktionieren oder
schlechter und irgendwie
so die, wie sieht das aus oder wie kann man,
wie schreibt man Dinge dran, ist halt irgendwie so das
User-Interface der Sprache,
was ich auch letztens noch gehört habe,
was ich ganz interessanten Ansatz fand,
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,
ja gut, was halt dann an Code dasteht,
ist halt das Entscheidende.
Und der meinte dann halt auch so,
ja, also User-Interface der Sprache sehr wichtig
und Python voll gut.
Wusste ich auch gar nicht, dass er da so meinte,
das ist total super.
Das Problem ist nur, es gibt halt auch noch
andere Dinge,
die halt auch eventuell wichtig sind, wie zum Beispiel
so etwas wie, wie gut ist das denn jetzt nicht,
wenn ich da drin irgendwas
programmieren will, was dann irgendwie mein Problem löst,
sondern wie ist das eigentlich,
wenn ich jetzt ein Framework 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 jetzt irgendwie so ein Basis
zum Beispiel sowas wie ein Machine Learning Framework oder so
bastelt, dann
kommt man da nicht aus ohne relativ
große Anteile C, C++, irgendwie
sowas. Und
dann wiederum hat man das Problem,
dass das User Interface sozusagen
von dem Use Case ausgesehen halt
nicht mehr so schön ist, weil jetzt kann man nicht mehr richtig
debuggen, weil man hat halt ein Teil
in C und ein Teil
in Python und
ja, was macht man jetzt, wenn irgendwie
und wenn
da irgendwo Fehler auftreten, gibt's
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 so was
wie, ja, also
was ist eigentlich, kann ich so was
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.
Also ja,
aber
zum Lösen von Problemen
finde ich das auch, das ist halt irgendwie
schon sehr, sehr angenehm im Vergleich zu allem anderen.
Aber kann auch sein, dass ich da einfach nur
komisch bin und das halt für mich funktioniert.
Und 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...
Der hat zu viele Sachen gemacht.
Oh ja.
Der macht eine ganze Menge, ja.
Ah, 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...
Wenn man versteht...
Also es ist halt auch sehr amerikanisch, muss man sagen.
Und manchmal macht er auch einfach so
etwas seltsame Dinge, irgendwie so
sagt er, dass er jetzt nur noch Fleisch isst
oder keine Ahnung oder macht ganz viel mit
Cryptocurrency-Zeugs, was ja auch irgendwie
so ein bisschen ist, aber
ja, aber es sind auch auf jeden Fall
super interessante Sachen dabei.
Genau, also hier Lex Friedman Nummer 70,
Jim Keller. Ah, okay,
gut. Jim Keller
ist tatsächlich einer, der
also ich habe da gleich
nach 10 Minuten so ein bisschen so 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
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
so diese, dieses Gefühl
von, ah, dieser
Kampf zwischen AMD und Intel,
der wird eigentlich nicht irgendwie da weit
oben ausgetragen, sondern die Frage ist nur,
ob Jim gerade bei AMD oder bei Intel ist.
Die Folge heißt übrigens
Moore's Law, wenn ich das so sagen würde.
Ja, genau.
Also der war, der ist schon krass.
Der war richtig gut.
Ja, der Podcast kann man
tatsächlich empfehlen. Es gibt auch andere tolle Folgen,
die man hören kann, mit Donald Knoos oder
Paul Krugman 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 Mimik ist
Peter Norweg.
Ja, ja.
Wenn man mal so durchscrollt.
Ja, genau.
Wo waren wir denn jetzt?
Wir waren eigentlich bei Petra Kohl
gemacht.
Ja, genau.
Ja, und
irgendwie gewisserweise,
da, genau, da, da
auch zu Patterns hatte
Dirk Fresslater noch was zu sagen und da meinte er dann so,
ja, also Patterns sind ja auch immer so,
es wird halt gesagt,
wenn man Patterns braucht, dann hat
die Sprache eventuell, ja,
einfach nicht genug, also hat,
was ist das eigentlich?
Das ist ein Zeichen dafür, dass die Sprache
halt etwas nicht kann, was sie vielleicht können sollte, ne,
und deswegen muss man halt einen Pattern machen
und das kenne ich auch schon
lange und er
fügte halt dann noch was hinzu, was mir dann
Und ich dachte so, oh ja, das stimmt, das ist ja auch eigentlich so ein Punkt, 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 eben wie bei Python eine relativ große Standardbibliothek hast, dann hat das natürlich eventuell den Vorteil, dass du dir so etwas erspaarst wie JavaScript, ja, die haben das da halt nicht und dann kriegst du halt NPM.
Und das ist halt sozusagen
ein Pattern, um halt
diese fehlende Standardbibliothek
irgendwie dann aufzufangen,
sozusagen außerhalb von
dem, was die Sprache tatsächlich macht.
Und das 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
irgendwie sich TypeScript anguckt oder so,
wenn sich so ein
Typesystem 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
updatbar ist.
Mit dem Release-Zyklus 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.
Naja, eigentlich hat das keinen Nachteil.
Also Patterns, ich glaube Patterns ist sozusagen
Das war gerade
aufgekommen, da war ich glaube ich im Studium.
Ich weiß nicht, wann das
Buch rauskam. Ich glaube 1994
war es. Wenn man das typatisch jetzt wüsste,
dann war ich da nicht im Studium.
Oh, Tatsache.
94. Ne, da war ich
bei weitem noch nicht im Studium.
Oh.
Ja, Tatsache, 94.
Und
wir hatten ja vorhin schon mal kurz angerissen,
dass das in C++
Ja, also du wolltest über das Buch
reden, ging auch vor, Design Patterns.
Ging auch vor, Design Patterns, genau. Das ist
wenn man diesen Begriff Patterns 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 Patternsprachen halt mal aufgegriffen
und beziehungsweise entwickelt,
um sich städtebaulich so einem Gesamtkunstwerk anzunähern.
Um halt auf der einen Seite zu sagen,
okay, Patterns sind Dinge, die immer wieder auftauchen,
die halt in leichten Variationen anwendbar sein müssen.
Und es ging ja nicht darum, dass Patterns,
es sind ja Patterns und nicht Templates.
Also was ist das denn?
Ist das sowas wie ein Mosaik-Baustein-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 die 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,
Hinweise zu einer allgemeinen Oberflächenstruktur,
Akteure, das ist jetzt sehr C++ nah, dann schon so Klassen, die daran beteiligt sind,
aber auch das Zusammenspiel davon und eine Abwägung von Konsequenzen mit Vor- und Nachteilen,
Implementierungen und Beispielcode häufig.
Und da geht es halt darum, dass man für einen bestimmten Fall, wenn man merkt,
ich schreibe jetzt hier Code, der hat so 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.
Also das ist ja auch ein Thema, dass das nicht irgendwie eine wahllose Menge von Patterns ist,
wo man sagt, die lerne ich jetzt auswendig und dann nehme ich einmal das und einmal das und einmal das,
sondern das soll eine Sprache ergeben, wo man dann anhand von diesem Zusammenspiel,
von den Verknüpfungen zwischen den Teilen dann immer weiß,
ah, wenn ich hier drüben das mache und da das mache, dann sollte ich wahrscheinlich hier drüben gleich mal aufpassen,
dass ich nicht noch x, y, z versaue.
Und diese Sprache, da geht es ein bisschen um Kräfteverhältnisse zwischen den Dingen,
aber eben auch immer dieses, man muss es sich selber zurechtschneiden für den eigenen Anwendungsfall.
Ansonsten hätte man das ja auch in 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 solltest du mal darüber nachdenken, ob du das vielleicht anders anordnen möchtest.
Aber das ist jetzt ja vielleicht noch mal
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.
Also,
Ja, genau. Also ich meine, die Muster, die sind ja sozusagen allgemeingültig. Das sind ja tatsächlich sehr abstrakte Ideen, die da existieren.
Fangen wir vielleicht mal mit der Antwort an. Hast du eben irgendwie 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 der Singleton gehört zu den Mustern aus dem Bereich
Creational Patterns, also wie werden in einer objektorientierten Sprache Objekte erzeugt.
Da gibt es so verschiedene Muster und es gibt manchmal den Effekt und gerade in Java ist
das halt noch ein stärkerer Fall, dass ja alles muss eine Klasse sein und manchmal brauchst
aber Code, wo das Objekt
nur ein einziges, wo es nur ein einziges
Objekt zu geben darf.
Ja. Und
dieses Objekt soll aber auch gut
zugänglich sein. Und
das kann zum Beispiel sowas sein wie
das Objekt
in Python ist, 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 will es nicht, will sie fünf
Logger haben nachher, sondern du willst halt
irgendwie, wo ist denn hier die Log-Konfiguration,
mit dem Ding möchte ich jetzt reden, da soll jetzt
bitte Log-Output rausgehen.
Und
da gibt es dann halt
entsprechende Muster, wo man sagen kann, okay,
wenn irgendwer die Klasse in die Hand kriegt und die
nochmal neu instanziiert, dann dreht die sich um
und gibt einfach statt
ein neues Objekt zu machen,
dir das eine erzeugte Objekt
schon wieder zurück.
Und dieses konkrete Singleton
lässt sich aus Java
so auf Python, du kannst es glaube ich
codemäßig sogar
so
bauen, das hat aber nicht
die gleichen Eigenschaften, weil die Sprache ja eine andere ist
und in Python gibt es
dafür halt andere Möglichkeiten sowas zu machen
dass du zum Beispiel sagst, du hast einen Namespace
bei dir
in deiner Anwendung, ein Modul, das heißt dann
Log, Tipp, man sollte es nicht
Logging nennen, das geht gerne schief
wenn man die Standardbibliothek startiert
das heißt
vielleicht Log und da drinnen
gibt es eine Klasse, das ist dann dein
Logger und nach der
Definition der Klasse würdest du gleich
dieses Objekt instanziieren und wenn du
willst, löschst du danach
diese Klasse einfach aus dem
Namespace von dem Modul wieder raus.
Dann kann auch
keiner aus Versehen so eine
zweite Instanz machen und dann
muss man wieder dazu sagen, naja, Python als Sprache
für Erwachsene, das stimmt halt so auch nicht, weil wenn du
die Klasse aus dem Modul dann löschst,
dann ist der Name zwar nicht mehr ansprechbar,
aber du kannst natürlich auf diesem Singleton-Objekt
wieder nach under, under class 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-Underscore-Methode da die richtige war.
Nicht init, sondern was?
Create?
New, genau.
Ich habe es zu lange nicht mehr in der Hand gehabt.
Ich merke, ich mache in letzter Zeit
zu wenig Metaprogrammierung in Python.
Du könntest aber under 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,
wie gesagt, was hat das Pattern für einen Kontext?
Und es gab eine ganze Zeit lang,
und das wurde so ein bisschen diesen Java-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 die willst und wenn du feststellst, ah, du hast hier ständig irgendwie Dinge, die eigentlich nach diesen Patterns riechen und dafür ist es dann wichtig, dafür muss man sie halt kennen, dann kannst du es damit leichter und schneller strukturieren und musst das Rad nicht jedes Mal neu erfinden.
Ja, genau. Ich würde auch sagen, eben genau diese Creational Patterns, das ist halt so ein, es gibt irgendwie drei Teile, Creational, Structural und Behavioral oder sowas, glaube ich.
würde ich sagen, ist auch
schon eine der Hauptpunkte, dass es 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 halt 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, dass das, 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 dabei rauskommen soll, halt überlegen,
wie gehe ich denn jetzt damit um? Und dann wird es halt,
kriege ich halt irgendwie If-Else-Kaskaden
in irgendwie Konstruktoren und dann irgendwann denke ich mir
so, hm, das sieht aber hässlich aus, was meine ich denn jetzt?
Und dann brauche ich halt Patterns.
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.
Dann bitte noch mal erklären, was ist das für ein Bilder-Pattern?
Also das Builder-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änden unübersichtlich.
Wenn ich das jetzt irgendwie,
muss ich halt einen Konstruktor machen, der irgendwie
riesig wird und ganz viele Argumente übergeben oder so,
das ist halt eventuell nicht so schön.
Ein gutes Beispiel dafür ist halt
LXML hat da so ein Ding,
wie man sozusagen XML-Dokumente zusammenbauen kann.
Das ist halt quasi Bilder-Pattern, kann man sagen.
Also wenn man sich das mal angucken will,
da gibt es dann halt für jedes Tag gibt es halt ein Objekt
und dann kann man das halt ineinander schachteln
und dann sieht das quasi syntaktisch so ein bisschen aus,
als würde man XML zusammenbauen
und hat dann aber tatsächlich eigentlich quasi
halt eine Reihe von Objekten zusammengebastelt.
Meistens reicht es aber,
also das, wofür dann das Bilder-Pattern verwendet wird,
in anderen Sprachen, in Python reicht es dann
meistens irgendwie einfach eine neue
Klassenmethode an ein Objekt ranzumachen, die halt dann
irgendwie Sachen zusammenbaut.
Das geht halt. Anderswo geht das
halt nicht so gut. Da muss man halt
das ein bisschen komplizierter machen. Aber es gibt
auch in Python Fälle, wo man das
Pattern tatsächlich braucht.
Und es ist halt schön, das Pattern zu kennen, auch wenn es
halt nicht primär um komplizierte Syntax geht.
Hat das was mit Factory
zu tun, weil das Builder-Pattern heißt?
Ja, also Factory-Pattern würde ich sagen, braucht man
fast nicht. Das ist genau so etwas,
das ist, da das irgendwie
da Funktionen
First Class Dinger sind in Python,
gibt es eigentlich gar keine.
Was ist denn das Factory Python? 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.
Äh,
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 Objekt
Konstruktionen konfigurierbar
machen möchtest. Dass du nicht
sagen möchtest, also du hast halt nicht irgendwie einen Hammer
und ich hätte was jetzt irgendwie
New Hammer, sondern du hättest gerne
jetzt einen sehr speziellen Hammer mit einem
möglichen, keine Ahnung,
so ein 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 konfiguriert es zu
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
es geht wieder
um Syntax halt auch an der Stelle.
Das eine ist, du benutzt
halt plötzlich keinen New Operator mehr an der
Stelle. Das geht weg, sondern du
änderst halt den Aufruf eines
traditionellen Konstruktors in
halt eine ganz normale
Funktion oder Methode
und kannst halt
tatsächlich auch
unterschiedliche
Semantiken haben. Also hier wird zum Beispiel
gerade ein Beispiel aufgeführt von
hab eine Farbklasse, ja, und du willst jetzt
eine neue Farbinstanz haben und sagst
einmal create 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
ranzerrt,
da sind Konstruktoren halt häufig
einfach extrem begrenzt,
was die Flexibilität angeht.
Und das ist tatsächlich in Python halt ein, naja, Init und 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 habe, die eben dieses aus unterschiedlichen Kontexten heraus initialisieren.
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 Statische Methoden, 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, dann machen wir doch weiter
mit was würdet ihr als nächstes nehmen?
Eigentlich hatten wir ja mit dem Singleton angefangen
und mit den verschiedenen Arten.
Achso, ja, ja, genau, auch zu Singleton wollte ich auch noch
kurz, genau, was ich meistens verwende
oder was für meine Anwendungsfälle, wo ich
sowas habe, wie den Singleton,
meistens reicht
ist tatsächlich irgendwie eine Variable
in einem Modul, weil das ist
ja, das Modul ist schon ein Singleton irgendwie
und wenn ich da halt irgendwas dran packe,
dann ist das halt überall gleich.
Wenn ich das irgendwo importiere,
es gibt da
so einen Pattern von Alex
Martley, wenn man tatsächlich sowas braucht wie Shared State
über, dann aber
manchmal braucht man nicht unbedingt immer die gleiche
Instanz, sondern nur, dass sich alles immer gleich irgendwie
verhält und den gleichen State hält,
da kann man das Borg-Pattern verwenden.
Das ist so ein bisschen ähnlich wie ein...
Das Borg-Pattern?
Kein originales Gang of Four.
Nein, aber das ist halt sozusagen irgendwie
eine etwas pythonischere Variante.
Und es gibt dann natürlich auch noch die, also man kann
tatsächlich auch so machen, dass es halt so ist wie
Singleton in anderen Sprachen, 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 Appletten haben wir denn noch? Also ich
kann jetzt natürlich die Liste hernehmen, aber
wir haben jetzt Singleton gehabt, wir haben kurz Factory
Ja, es gibt noch zwei, die jetzt aus meiner Historie immer relevant waren. Das waren Proxys und Adapter. Da muss ich mal die ganz ollen kleinen Kamellen rausholen. Also SOAP 3 war damals tatsächlich, also SOAP 2 und deren Nachfolger SOAP 4 und SOAP 5.
Wie bitte was?
gab es auch einen. Bitte?
Soap, genau.
Es ist der
Open-Source-Urgroßvater
der Applikationsserver.
Z-O-P-E, Soap.
Ach, Soap. Ja, okay. Ja, genau.
Und
das war ursprünglich ja so ein
Through-the-Web-Entwicklungs-
Umgebungstool,
wo man halt nur durch einen Browser
mit Python und so ein paar HTML-Template-Sprachen
sich extrem schnell
Webanwendungen zusammenbauen konnte.
Das war original 96 entstanden, glaube ich, und 2001 rum gab es da einen Aufschlag zu sagen, so bauen wir alles nochmal neu mit besserem Engineering und da kam dann so ein SOP3-Projekt raus und da gab es schon mal so eine Zwei-nach-Drei-Transition, die nicht so smooth war.
Für SOAP war es tatsächlich, glaube ich, so ein bisschen auch dann der Untergang im Sinne von, das war sowas anderes, man hätte es nie SOAP 3 nennen dürfen. Es hat einfach nichts, also 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 in Python. Und da hatten wir extra einen Interface-Typ für entwickelt, mit dem du dann deklarieren konntest, okay, das hier ist ein formales Interface, es muss folgende Methoden haben, die Methoden müssen folgende Parameter haben.
Also ein Interface ist ja ein anderes Design-Pattern.
Nee, Interface ist noch nicht mal so richtig ein Design-Pattern.
Interface kommt eher aus dem Bereich der Typsysteme
und ist in einigen Sprachen sozusagen
eine Möglichkeit, Schnittstellen zwischen Code zu explizieren.
Also in Java ist es ja sehr explizit und in C++ auch.
Ich glaube, Modula 3, damit hatte ich gelernt,
ist es auch so ein Ding,
weil Dinge, die du nicht deklarierst,
kannst du nicht ansprechen, sozusagen.
Ja, du musst halt sozusagen immer,
wenn du eine Funktion aufrufst oder eine Methode aufrufst,
irgendwie, wenn du dir irgendwas übergibst,
musst du dir halt sagen, was das denn ist.
Kannst du dann nicht einfach irgendwas übergeben.
Und wenn du jetzt Objekte unterschiedlicher Art da reintun willst,
dann müssen die zumindest quasi vom gleichen Interface erben,
sonst geht das halt einfach nicht.
Du könntest zum Beispiel sagen,
okay, ich habe hier irgendwie eine Methode,
die schreibt irgendwie zum Beispiel,
die 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 ich gern ein Ding,
dass das File-Interface sozusagen implementiert
und kannst dann sozusagen darauf dann irgendwie
write aufrufen oder so.
Und die Menge der Methoden sozusagen,
die man da aufrufen kann, das ist halt das Interface.
Also die Idee ist, der wichtige Unterschied ist,
dass du mit Interfaces halt Implementationen und Spezifikationen voneinander halt trennst.
Das heißt, ich habe eine Art abstrakte Vordefinition.
Ja, also wir hatten es damals so gemacht, es gab einen speziellen Klassentyp,
also eine Basisklasse Interface, die konnte auch keinen richtigen Code haben.
Da wurde also, da hattest du immer nur Rümpfe von Methoden gehabt
Und dann konntest du halt deklarieren, dass eine bestimmte Klasse dieses Interfaces implementiert.
Und wichtig ist eben, dass die Implementationen nicht voneinander geerbt haben.
Es gab nicht irgendwie eine Basisimplementation oder du könntest das Interface gegebenenfalls
so etwas wie eine abstrakte Basisklasse nennen.
Aber das ist expliziter noch viel weiter voneinander entkoppelt worden.
Und Python, normalerweise, da gibt es ja das sogenannte 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,
dann wird nicht einfach gesagt, nee, du implementierst dieses Interface nicht,
sondern was dann passiert ist, dann wurde ein Adapteraufruf gemacht,
man hat also das Ursprungsobjekt genommen, was jetzt als Parameter in die Funktion reingereicht wurde
und hat dann geguckt, welches Interface soll es denn erfüllen,
hat einen Adapteraufruf gemacht und hat gesagt,
so, liebe Laufzeitumgebung, ich habe hier ein Objekt gekriegt,
mach bitte, dass es ein iLogger ist.
Und dann konntest du in der Laufzeitumgebung vorher registrieren und sagen,
ah, also, wenn jemand einen iLogger braucht und einen String bekommen hat,
dann mach bitte folgendes und dann kommt da dieses Objekt raus.
Oder wenn eine Methode einen iLogger braucht und da kommt ein Socket raus,
da wurde ein Socket übergeben, dann mach bitte das und geh dann weiter.
Und da kannst du sozusagen immer wieder beliebige Typtransformationen mitten reinsetzen
und hast dich dadurch flexibilisiert, dass jemand anderes plötzlich anfängt,
okay, ich gebe dir, liebes Programm, jetzt plötzlich Objekte anderen Typs rein
und deklariere an der dritten Stelle, wie diese Typtransformationen zu laufen haben
und dann kann ich
plötzlich halt Anwendungen auf Art benutzen,
die nie so vorgesehen waren.
Hört sich nach großer Magie an.
Das war ein Haufen Magie, da war ein Haufen Engineering
drin, um das auch schnell zu kriegen.
Also das war wirklich so, wenn man
bei Soap nachher in einer ernsthaften
Anwendung mal eine Seite aufgerufen hatte,
dann waren in einem Call bestimmt eine halbe Million
Adapter-Calls drin.
Und die waren aber auf C-Ebene
halt so optimiert, das waren halt nur ein paar Millisekunden,
die dafür 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, 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
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, was da auch eine Rolle
gespielt hat, waren sogenannte Proxy-Patterns.
dass also ein Objekt anstelle eines
anderes irgendwo reingereicht wird
und er emuliert alle Attributzugriffe
und alle Funktionsaufrufe,
macht irgendwas und reicht den Originalaufruf
dann an das Originalobjekt halt weiter.
Damit kannst du
zum Beispiel sowas machen wie ein Logging-Proxy
und das geht in Python tatsächlich total
super. Du kannst ein Objekt bauen,
der alle Attribut- und Methodenzugriffe
halt an ein anderes übergibt
und währenddessen zum Beispiel mitschreibt,
ja hier wurde gerade folgende Methode mit folgendem
mit folgendem
Parameter aufgerufen
und der Code, der das Objekt reingereicht kriegt,
der muss aber noch von nichts wissen. Der denkt einfach
nur, hier kommt ein Objekt, was halt irgendwie
keine Ahnung, eine Datei ist.
Eine Middleware quasi.
Genau, und
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
mit irgendwelchen Metafunktionen auf die Schnauze
fliegen möchtest.
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 geht so nicht.
Da musst du halt dann noch
einen Check gegenbauen und sagen, ah, der darf
das nicht, dann wird das Template ordentlich gerendert.
Ansonsten hast du aber immer den Safety-Belt,
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, das geht nicht raus. Im schlimmsten
Fall wird die Seite halt abgebrochen und du sagst, so hier
ist nichts.
Und die mussten wir aber tatsächlich auf
C-Ebene schreiben, um wirklich
alles komplett unterbinden zu können an
Protokollen, die Python so kann mit den
Doppel-Underscore-Methoden.
Einen einfachen Proxy kannst du in Python
schreiben, indem du einfach nur sagst, das ist eine Klasse,
die hat ein Init,
da übergibst du das Objekt, was geproxied
werden soll, also was eingepackt werden soll
und dann kannst du über die
GetAttribute
Protokolle
dann halt
sagen, okay, aha, hier versucht jemand gerade zuzugreifen
auf folgendes Attribut
und jetzt kannst du ein bisschen Log-Output
erzeugen und danach halt das 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.
Und jetzt müssten wir im Podcast sozusagen ein bisschen Live-Coding machen, um da...
Ja, ich kann mir nicht ganz genau vorstellen, an welcher Stelle das injiziert werden soll.
Wenn du jetzt sagst, dass das schon gebaut wird, jetzt weißt du, die Init ist dann quasi schon durch.
Also der Konstruktor ist quasi 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 Init-Methoden erst aufruft.
Nein, 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 Personenklassen 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.
Dann ein Contact, ja. Genau. 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
getAttribute under under.
Die wird ja immer dann getriggert,
wenn jemand auf ein Attribut zugreift, was
nicht definiert ist.
Da der Proxy selber kein Attribute hat,
wird es immer getriggert.
In dem Moment
würde er dann zum Beispiel ein Print machen
von, ja, hier wurde jetzt auf folgendes Attribut
zugegriffen
und ruft dann self.under
under context, under under, get attra
dieses Objekt auf.
Diese Attributnahme
auf. Erreicht sozusagen den Methodenaufruf
eins zu eins 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 würde ich auch noch 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.
Ja. So, 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 ich 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 casht.
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 Code-Basen im Prinzip nichts zu tun hatten.
Ja, da gibt es
verschiedene Magie mit dem Flow irgendwie was.
Genau.
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 Max,
Jochen, magst du vielleicht noch eins?
Ja, also ich würde
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
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 ein 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 irgendwas.
Input und Output kann man dann immer modifizieren.
Nee, das ist ein Python-Decorator.
Also das mit dem Add irgendwas drüber.
Aber ich meine, das Decorator-Pattern wäre ein bisschen anders.
Aber vielleicht täusche ich mich auch.
Weiß nicht mehr genau.
Ich meinte, das wäre halt irgendwie sowas,
dass du halt
sozusagen
eben
du tust halt so,
als wäre das ein normales File, aber
in Wirklichkeit schmeißt das Objekt,
was du halt mit dem Decorator-Pattern
gebaut hast, halt intern, weiß ich nicht,
sowas wie Leerzeilen weg oder Dinge, die nicht gepasst werden können
oder so. Tatsächlich ist es gerade
auch so ein bisschen ähnlich zu
dem Proxy, wie wir es beschrieben haben.
Da ist in Python der Unterschied nicht so groß.
Ja, ja. Hier wird nochmal,
Also ich gucke gerade immer so ein bisschen nochmal die Wiki-Seiten
nebenbei nach. Beim Dekorierer
wird nochmal explizit darauf
hingewiesen, dass man hier halt chainen kann.
Das kannst du mit Proxy aber auch machen.
Dass du da mehrere
hintereinander schaltest.
Ja.
Ja.
Ansonsten, was mir noch
letztens
ist mir das aufgefallen.
Mysterium, ich weiß nicht, in welcher Episode wir das hatten.
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. Ich hatte mit Listen von irgendwelchen Dingen zu tun,
mit Listen von Integers
und das war
deutlich kleiner, als ich das
gedacht hätte.
Ich dachte so, hä, komisch,
also es braucht tatsächlich nur
irgendwie
8 Byte irgendwie pro
Integer. Eigentlich hätte ich jetzt mit
deutlich mehr gerechnet. Irgendwie, weiß ich nicht,
eher so
23 oder weiß ich irgendwas von dem
Dreh. 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
100 Millionen Integers und
das war halt dann bloß 800 Megabyte im Hauptspeicher
und ich hätte aber eigentlich erwartet, dass es deutlich mehr
sein müssen.
Okay, hat er Renundanzen weggelassen, oder?
Ja, nee, das, was da tatsächlich passiert ist, ist halt intern benutzer der 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 einen, weiß ich nicht, einen Textprocessor hast,
irgendwie so ein Programm, sowas wie Word oder so, und wenn das jetzt irgendwie Buchstaben rendert,
dann willst du halt nicht immer quasi alles, was halt in, der Buchstabe ist halt ein Objekt,
dann willst du nicht immer alles für jeden Buchstaben, was da dran hängt, nochmal haben,
sondern du willst es halt nur den Teil
in dem Buchstaben austauschen, der halt ausgetauscht
werden soll und der ganze Rest bleibt ja 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 E in
Range, weiß ich nicht, 100 Millionen,
aber dann sagt man halt irgendwie sowas
wie 0 oder 5 oder so, dann ist das halt
sehr klein. Aber wenn man sagt,
nicht, also
nicht 0, sondern irgendwie
i, dann wird es plötzlich sehr groß.
Also dann hat man den Vorteil nicht mehr.
Aber genau, da hatte ich mich
irgendwann mal drüber gewundert und jetzt
habe ich irgendwann zufällig gesehen,
woran das lag.
In Python gibt es ja noch den Begriff in-turning
für. Das ist zu sagen,
da wird,
das kann man dann auch ganz gut sehen, wenn man halt die Objekte
dann mit einem Identitätsvergleich
halt anguckt.
Dann sind es halt tatsächlich wirklich immer,
dass das Is das gleiche ist.
Und das gibt es bei Strings halt auch.
Da gibt es auch in einem bestimmten Bereich
irgendwas mit Strings,
die kürzer sind als so und so lang
und kein Leerzeichen enthalten.
Und du machst ihn zweimal,
also du jagst ihn auch zweimal durch den Literal durch,
sind am Ende die gleichen Strings.
Das ist so ähnlich wie bei den Integern.
Ja.
So.
Wow.
Okay.
und also das, was ich halt sonst immer noch
ganz gerne mag, ist das Strategy-Ding
und das ist im Prinzip halt das Thema von
wie du halt Code flexibilisieren möchtest
und zwar
gegebenenfalls auch noch auf eine Plugable-Art
du könntest halt normalerweise, wenn du
ein komplexes If-Else
hast, oder
If-Else, If-Else, If-Else-Else
ähm
äh, Elif
ähm, und
du willst es flexibilisieren, weil da kommt noch ein Fall dazu
noch ein Fall dazu, noch ein Fall dazu
Zum Beispiel sowas wie, aha, du möchtest unterschiedlichen Code ausführen, je nach Sprache, die wir unterstützen.
Dann kannst du halt das lange Elif 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 da drauf 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, ich kann ja auch einfach ein Dictionary irgendwo hinlegen, wo diese ISO-Codes drinstehen und lade damit sozusagen andere Drittanbieter-Packages ein, in dieses Dict hinein, andere Arten von, noch andere ISO-Codes reinzuschreiben, die ich halt noch nicht kannte und mein Code ist dann in der Lage, halt jede beliebige Art der Formatierung aufzurufen.
oder jemand anders kann auch hergehen und sagen, hey, ich definiere dein Format für italienische Adressen, gefällt mir nicht,
also überschreibe ich jetzt diesen DICT-Eintrag von IT mit meiner eigenen Methode
und der Code, der 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.
Und was ist ein Observer?
Ich gucke nach.
Muss ich hier auch nachgucken.
Let me google this for you.
Also ich glaube, das ist, ah doch, warte mal, das ist halt,
wenn du benachrichtigt werden
möchtest über, wenn sich irgendwo was geändert hat.
Also bei dir auch, ob sie dir einen Bescheid
sagt.
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 verständigt habe.
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 passieren soll.
Das heißt, du hast sowas wie, okay, ich habe hier eine Methode,
ein Datensatz wird geändert, dann änderst du den Datensatz
und am Ende von der Methode schreibst du einmal sowas rein wie
Eventsystem.event
oder Trigger
und dann kannst du zum Beispiel
übergeben den Namen eines Events
à la Changed
Record
kannst auch alle möglichen Sachen
machen, um das zu identifizieren, du kannst auch
Singleton-Objekte machen, um Events zu registrieren
oder Interface oder was immer, aber im einfachsten Fall
sagst du sowas wie Event Trigger
Event Name
und danach übergibst du zum Beispiel
irgendeinen event-spezifischen Payload
Und das ist in Python ja auch schön zu machen, weil du ja auch mit Stern-Arcs, Stern-Stern-KW-Arcs arbeitest.
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 ich dir jetzt, 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
definiert, welche Events da gibt
und das ist eine Art, wie man sich selber solche Events
halt bauen kann, dass man sagt, so, okay,
wenn auf
einem Record-Objekt
das 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 Eventsignale 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 dann nach, da kann man auch überlegen, darf es mehrere Händler geben oder nur einen, in welcher Reihenfolge werden die aufgeführt, das sind dann so wirklich so differenzierte Betrachtungen von dem konkreten Eventsystem, was man sich baut.
Oder gibt es nur ein Best-Match von, je nachdem, dass ich auch noch auf Typen von den Parametern matche, sowas wie, ich will aufgerufen werden beim Rekord-Change, aber nur, wenn der Rekord vom Typ Person war und solche Sachen.
Und dann kannst du halt solche Dinge machen wie, der erste, ein User setzt eine Bestellung ab und anderer Code von dir, ein anderes Modul, ist zum Beispiel dafür da, eine E-Mail rauszuschicken, wenn der User seine allererste Bestellung abschickt.
Ja, da kannst du das halt als völlig komplex, da geht es immer, also häufig geht es bei diesen Sachen darum, wie kann ich Code so geschickt modularisieren, dass ich halt später, wenn ich die Anwendung umbaue, möglichst wenig umstricken muss und mir selber auf den Füßen stehe.
Idealerweise kannst du halt dann auch 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.
Und auch da wichtig, Patterns sind etwas, die entstehen erst, wenn man etwas macht, deswegen ist das ja ein sehr handwerkliches Buch, ein handwerkliches Konzept, im Sinne von, die haben halt, das ist nichts, was man sich hinsetzt und sagt, so wir designen jetzt hier mal ein paar Patterns, sondern das ist halt ein so, wir haben jetzt hier so und so viel drölfzig Anwendungen geschrieben und das da sehe ich ständig in Variation.
was ist denn jetzt die Essenz von
diesem Ding in Variation? Ah, okay, das ist
ein Published Subscriber, das ist ein Observer.
Okay, alles klar, da hat man also dieses Ende
und jenes Ende und das Ende und hier jetzt geht der
Blumenstrauß auf von, wie könnte man das eigentlich
alles bauen? Und das heißt aber nicht,
dass man das halt jedes Mal ständig in der Vollausprägung
baut. Ich weiß, ich sage das jetzt
zum dritten Mal, aber ich habe
auch gelernt, wenn man Dinge zum siebten Mal sagt,
dann hat es die Hälfte der Leute zum ersten Mal gehört.
Und ich habe heute
gelernt, weil du gerade vom Blumenstrauß an Methoden sprachst,
es gibt auch welche Blumen in Blumensträußen?
Ja, genau. Es gibt auch Welkeblumen. Möchtest du unter den Patterns Welkeblumen suchen?
Ja, tatsächlich. Du weißt ja nicht genau, was da stimmt, wenn du davon noch keine Ahnung hast und die eben nicht durch Pattern-Publishing 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öchtest halt in die Richtung
entwickeln, um möglicherweise
flexibel oder modular zu bleiben oder so
oder halt verschiedene Schnittstellen aufmachen
zu können, wenn du sie brauchst, dann
könnte sowas ja passieren, dass man eine welke
Blume baut, weil man da irgendwelchen Unsinn gebaut hat.
Also speziell halt,
das kommt dann eher aus dem Agilen, das
you ain't gonna need it. Also ich finde
halt, man sollte sich bei der Anwendungsbewegung 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.
Da ist Python als Sprache natürlich auch wieder
extrem gut positioniert, weil
ich habe jetzt
in den letzten Jahren häufig Projekte
angefangen mit so, ich fange mit einer einzigen Datei an,
ich baue bei keinem Package kein Nichts,
eine einzige Datei, keine
Dependencies, erstmal nur die Standard-Library
und mal gucken, wie weit ich komme,
um das eigentliche Problem mal so
80% zu lösen, was ich eigentlich gerade habe.
Und wenn ich dann weiß, worum es hier eigentlich geht, weil ich bin ständig dabei, dann alle Steine wieder auseinander und zusammen und auseinander und zusammen und vorwärts und rückwärts, wenn du da schon zu viel Code angehäuft hast in so einem Moment, dann macht dich das halt langsamer.
Und das ist ab einem gewissen Punkt dann auch halt legitim, wenn du feststellst, so, jetzt brauchen wir hier irgendwie ein Plugin für NFS und für Ceph und für ein S3 und für so, jetzt müssen wir anfangen, diesen ganzen Code zu restrukturieren, dann ist es halt schön, wenn man in der Hinterhand hat, was gibt es denn da für Patterns, wenn man sowas umstrukturiert, also bauen wir da jetzt, okay, guck mal, hier passt jetzt irgendwie eine Strategy und da passt noch ein Event-Handling-System und dann haben wir den ganzen Code irgendwie reduziert, dann ist es jetzt so, jetzt gefällt es mir.
Aber für mich ist das immer eine Sache,
das geht erst am konkreten Objekt.
Ich kann mich nicht vorher hinsetzen und sagen,
so, wir bauen jetzt ein neues Backup-System.
Wir brauchen einen Observer.
Und ich glaube, was eben ganz wichtig ist,
was bei den Patterns auch...
Also Yagni ist auch ein Pattern.
Nee, Yagni ist eine Methode,
die aus dem originalen Extreme-Programming kam.
Und das ist immer, wenn jemand sagt, ah, vielleicht könnten wir, nein. Aber irgendwann in Zug, nein. Aber wenn dann in zwei Jahren, nein.
Wichtig gegenüber Iagni ist halt, wenn wir auf der Ebene bleiben, ist immer noch Persistence. Persistency means having to say I'm sorry.
Also, wenn dieses
you ain't gonna need it wird ein bisschen,
kriegt ein Gegengewicht durch.
Ja, aber alles, was du
als persistente Daten wegschreibst, wird dir
halt auf Gedeih und Verderb im Nacken hängen.
Ja, Code ist flexibel.
Code ist total easy. Kannst
umbauen, kannst drehen, kannst wenden, solange das
Interface das gleiche bleibt, alles super.
Aber wenn du es einmal auf Platte
geschrieben hast,
dann kannst du aber wissen, dass das dich 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...
Genau.
Genau. Wer hat das geschrieben?
Oh, das war ich.
Ja, da kann ich mir so ein paar Sachen erinnern.
Ich habe letztens
einen Anschluss gekriegt von Jochen.
Unmöglich, nee, so kannst du das nicht machen.
Furchtbar, was sieht das denn aus?
Nee, das geht aber gar nicht. Jochen, das ist von dir.
Ja, eigentlich
gar nicht so schlecht, ja.
Ja, naja, das
passiert auch
demnächst. Das passiert durchaus ab und zu.
Jaja.
Ich glaube an der Stelle auch, das ist halt der handwerkliche
Teil wieder.
Und jetzt mach ich mal die Schleife, wo ich gerade eben hin wollte, die Gang of Four-Leute, die haben alle ein extrem gutes Sprachverständnis selber gehabt von der Sprache, um die es eigentlich geht, mit warum ist das hier ein Problem und welche Mechanik der Sprache steht mir eigentlich im Weg und wie kann ich die halt counteren, sowas wie, wenn ich einen Konstruktor habe, dann bin ich halt auf den Typen festgelegt und kann ich das nicht machen, kann ich das nicht machen, nee, deswegen muss man...
Und ein Beispiel ist halt bei Java das Getter-Setter-Pattern.
Wenn du Leute ernsthaft Java-Code schreiben siehst,
dann bauen die halt für jedes Attribut immer ein, keine Ahnung,
Klasse Person, Geburtsdatum als Attribut
und dann ein Set-Geburtsdatum, Get-Geburtsdatum.
So, warum?
Weil es in Java später, wenn du mal irgendwie meinst,
du musst hier was ändern,
dann hast du keine Chance mehr, wenn irgendwelcher Client-Code auf Attribute zugreift, jemals noch irgendwie dich dazwischen zu 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, das ist Java.
Und wenn man dir irgendwann erzählt, nein, es gibt, du kannst im Nachhinein eine Property draus machen.
Du kannst machen, was du willst, dann ist alles schick.
Ja, aber, nee, nee.
Das ist halt, da merkt man halt, es ist extrem wichtig zu verstehen, wie die Sprache selber mechanisch funktioniert.
Weil nur dann diese ganzen Patterns tatsächlich irgendwie Sinn haben oder keinen Sinn haben.
Und das ist glaube ich was, was ich halt an der Stelle wieder diesem handwerklichen und sich selber weiterentwickeln mitgeben würde, ist, wenn man halt so Patterns gerade aus anderen Sprachen halt nach Python transportiert, muss man schon immer nochmal extrem gut auf die Suche gehen von, hat es hier nicht irgendeine andere Mechanik in Python, die das schon überflüssig macht.
Ja, wir haben die Dekoratoren,
wir haben die Konstrukturen, wir haben New,
wir haben Getter Setter,
also 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 so einigermaßen einmal kurz
eingekringelt und
erwischt. Würde ich sagen.
Ja, 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 Design-Pattern oder sowas wie
ja,
MVC, weiß ich jetzt nicht, ist das ein Design-Pattern?
Ja, nicht, ein bisschen größer, keine Ahnung.
Model-View-Controller.
Ja, genau, genau.
Schwer zu sagen, oder sowas
wie...
Model-View-Controller ist älter.
Das war nicht,
also Model-View ist 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?
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 jetzt schon wieder?
Das ist halt die Frage, wie man
sozusagen
die Übersetzung macht zwischen Sachen,
die jetzt in der Datenbank, vor allem in
relationalen Datenbanken liegen und halt
Objekten in Python
beispielsweise und das sind halt
diese beiden unterschiedlichen Dinge, also
Active Record ist halt das, was Django macht
oder halt auch Ruby on Rails
und Data Mapper ist halt
das, was SQL Alchemy macht
und Hato.
Und wo ist der Unterschied?
Naja, also
du hast
du
Kennst du dich
Kennt sich jemand mit SQL-Alchemy gut aus?
Ja, ich kenne mich halt mit SQL-Alchemy aus.
Ich kenne mich wiederum mit Active Record nicht aus.
Super gut.
Ich lese jetzt gerade mal schnell mal wieder.
Dann fangst du noch mit Active Record an, Jochen?
Ja, also da ist es halt so,
dass quasi jedes Objekt repräsentiert halt eine Zeile in einer Datenbank
und die Attribute sind halt die Spalten.
Und genau, wenn man halt irgendwie Dinge aus der Datenbank holt,
dann hat man halt eine Liste von diesen Objekten.
Und wenn man der 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 halt eine Klasse, die,
jedenfalls, ich sage jetzt mal so, wie es mit Django ist,
hast du halt eine Klasse, die definiert,
welche Spalten es halt in dieser Tabelle gibt.
Also du hast pro Tabelle eine Klasse
und die Spalten sind halt Attribute auf dieser Klasse,
die halt so ein bisschen,
das ist halt diese Deskriptoren-Geschichte,
ein bisschen eigenartig definiert sind.
Und dann kann man halt auch aus diesen Klassen
die Tabellen direkt erzeugen,
Auch die Relationen zwischen den Tabellen
sind in den Attributen enthalten.
Das heißt, ich kann, wenn ich mir diese Tabellen hindefiniert habe,
auch komplett mein Datenbankschema aus den Dingern erzeugen.
Immer wenn einzelne Sachen passieren sollen auf einer Zeile,
dann sind das Methoden auf dieser Klasse.
eine einzelne Instanz ist eben eine konkrete Zeile
und wenn etwas alle
Sachen betreffen soll oder viele Zeilen,
dann sind das halt sogenannte, also in Django heißen die
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 und 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 Psycholagmy.
Ja, Datamapper.
Genau, ich habe jetzt selber
erstmal noch mir die Active Record-Sachen
angeguckt. Das Interessante bei Active Record ist ja,
dass du relativ klar
Tabelle und Klasse aufeinander
mappst. Und beim Datamapper
ist es tatsächlich so, du entkoppelst es komplett
und die Objekte
müssen halt, also beim Active Record hat
zum Beispiel die Klasse gerne
irgendwie eine Save-Methode, wo du
sagen kannst, ich äh, ändere ein paar
Attribute und dann kannst du irgendwie Save aufrufen
und dann ist die irgendwie in der Datenbank.
Ähm, das ist zumindest das klassische Pattern dafür,
äh, wie es bei Django jetzt gerade aussieht, weiß ich nicht.
Ja, ja, doch, ist genauso, ja. So, genau,
und bei Secret Alchemist ist es so, dass im Prinzip
deine Klassen von der Datenbank
überhaupt nichts wissen.
Ähm, es gibt
einen deklarativen Stil, bei dem du tatsächlich
dann wieder innerhalb, da kannst du wieder sagen,
doch, die Klasse weiß was davon, weil du es
halt eng aneinander koppeln möchtest, um solche Effekte zu haben,
wie dass du deine Datenbank anhand deiner Klassendefinition halt ableiten kannst.
Aber im Prinzip gibt es dann zwei getrennte Schichten von einmal,
okay, ich beschreibe hier Tabellen und ich beschreibe Klassen
und jetzt beschreibe ich, wie diese Tabellen auf Klassen gemappt werden.
Und da 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, was irgendwie einmal sinnvoll aussieht,
bumm, anstatt halt
dann die eher naiveren Varianten
von, okay, jedes Mal safe drücken
ist jedes Mal irgendwie einmal
zur Datenbank laufen und speichern drücken oder so.
Und da
ist es halt einfach viel, viel flexibler, wenn
du das Datenbankmodell entkoppeln möchtest.
Das ist zum Beispiel auch dann, wenn du
konfrontiert wirst mit, ich habe hier eine fertige
Datenbank, die besteht seit 20 Jahren, die muss
jetzt hier irgendwie mal rein. Und dann
kannst du mit dem Datameter...
Blala, es ist Zeit fürs
Bett.
dann kannst du mal einen 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, dass so Zeug von
Du machst komplexere Abfragen und er weiß irgendwie, okay, wenn ich das jetzt mache, dann lade ich schon mal irgendwie die nächsten Relations mit und falte irgendwie die Relation-Objekte schon mal in die originale 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 macht ein Django-Manager, oder?
Ja, in Django ist das, aber da gibt's
das auch, da werden halt die Sachen,
also
das, was man halt nicht will,
das droht bei Active Record natürlich, ist, dass
wenn du jetzt zum Beispiel
irgendwie ein Objekt hast
und das hat halt irgendwie einen Foreign Key,
ist halt mit einem anderen Objekt verknüpft
und dann greifst du auf ein Attribut von dem
verknüpften Objekt zu und das am besten
in einer Liste irgendwie von Dingen,
auf so einer Webseite, wo du halt eine Listenansicht hast
und dann hast du halt irgendwie, zeigst du halt
eine Tabelle zum Beispiel an oder halt
eine Liste von Dingen und nimmst dann halt
das Attribut von einer verknüpften
anderen Geschichte, zum Beispiel einen Username
oder so, der halt an einem von diesen Listenobjekten
dranhängt, dann kann es halt
sein, dass du halt, wenn du das naiv machst,
kriegst du halt
N plus 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
oder so, ja. Genau, dann
zieht sie, oder Prefetch-Related
für N
zu M-Relationen und so, also das geht
auch alles, man muss halt ein bisschen aufpassen. Machst du das am Model
oder musst du das irgendwann in der Query machen?
Das machst du an der Query.
Genau, bei SQL-Icon, wie kannst du das im Prinzip modellieren?
Da kannst du halt diese ganzen
Relationen alle ausdefinieren,
so mit diesem, auch so richtig mit
Vor- und Rückreferenzen
will ich die irgendwie als Listen oder Dicts kriegen
oder als Attribute oder
so ein Zeug und kannst dann halt sagen, so und
irgendwie die Richtung, die machst du bitte als
Eager-Load und die bitte nicht und folgende 10
Attribute bitte im Eager-Load wieder rauslassen
und das kannst du halt so alles
zurecht tunen, damit du halt dann möglichst
dummen, konkreten Query-Code
schreiben kannst, der über so ein Zeug
nicht mehr nachdenkt.
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 hin.
Der hat im Prinzip einmal SQL
in Form von diesem Bilder-Pattern.
Ja, da kannst du auch sagen, ich hätte gerne eine
Query, also Query, Klammer auf,
von folgendem gemappten
Objekt und dann Punkt
ähm
Filter
Punkt Join, Punkt
hast du nicht gesehen, immer so Funktions-Chains
hintendran und er baut dir
dann nachher tatsächlich einen für die Datenbank,
die du eigentlich hast, also Postgres und MySQL
ein syntaktisch korrektes und
optimiertes Query halt auf
unter Berücksichtigung von allem, was er über diese
Mapper weiß, was er gleich noch als irgendwie eager load
oder nicht machen soll und du kannst
halt mittendrin immer wieder die Ebenen
wechseln, ja, du kannst irgendwie im Object Mapping Teil
sein, drei Zeichen dann
von diesem generativen, also dann irgendeine Query mit
dem generativen SQL machen, da dann aber wieder
gemappte Objekte reinstecken und der kriegt das immer
so vor und zurück und vor und zurück
hat halt das Problem
wenn es, also es tut
sehr selten nicht, aber man muss sich halt dann
schon relativ viel mit, schon gut
mit dem relationalen Datenmodell auskennen,
um mit dieser Komplexität dann auch umgehen zu können.
Weil wenn es dir dann mal um die Ohren fliegt,
dann kommen da halt auch Fehler raus mit so,
was will der jetzt von mir?
Ja.
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, ja auch
ich meine, man kann ja auch immer noch dann einfach auf
groß SQLs rückfallen, wenn halt
irgendwas, wenn man irgendwas Spezielles machen
unbedingt, ja
ja
da haben wir
alle Patterns durch, tatsächlich
Also du wolltest noch irgendwas zu Datenbanken sagen.
Ich glaube, da gibt es noch so ein Solid-Modell
oder sowas.
Achso, nee, das ist dann nicht Datenbanken, 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, Uncle Bob.
Gibt es sowas auch in Python?
Das ist, nee, das ist...
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 dann im Vorstellungsgespräch ist,
dann wird halt erwartet, dass man die alle kennt
und ja,
das wäre dann schon sehr peinlich, wenn man
sagt, also ich habe keine Ahnung, was das eigentlich ist.
Aber ja, zum Glück
mache ich ja kein Java.
Ja, das Interessante ist auch, man kann
das Zeug ja im Alltag eben nicht
so benutzen wie
bei jeder Zeile Code, die ich schreibe, gehe ich
nochmal alle mir bekannten Patterns und Prinzipien
durch, ob ich die jetzt ja nicht verletze.
So funktioniert es halt nicht.
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 muss ich nochmal nachdenken, warum geht das hier schief?
Damit du dann halt wenigstens weißt, wo
du googeln musst.
Ich habe über Solid jetzt auch,
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.
Es ist halt auch alles relativ
alte Geschichte und das macht halt in diesem
Kontext von so statisch typisierten
Programmiersprachen, macht das auch alles irgendwie
gewisserweise schon Sinn,
also durchaus und auch mehr Sinn halt
vielleicht als bei Python, weil da viele
Dinge einfach automatisch erfüllt sind, ne, also
eben, ich würde sagen
ja, ich würde
Lischkows Substitution Principle
Ne, das ist ein Design-Thema
das musst du selber als Programmierer richtig umsetzen
Das ist
Typtheorie und das ist die
Aussage, dass
Objekte in einem Programm
also aller Programmcode, der Objekte verwendet
also mit Objekten arbeitet
sollte
immer in der Lage sein, alle
Subtypen dieser Objekte zu
akzeptieren, ohne die Korrektheit des
Programms zu verletzen.
Genau, also ich würde jetzt mal so als
konkretes Beispiel, wäre
jetzt für mich sowas wie,
man macht eine Vorschleife über Mitarbeiter
und wenn man
in der Vorschleife so
Fallunterscheidungen macht, also
nehmen wir an, man hat eine Typarchie,
es gibt halt irgendwie eine
Oberklasse Mitarbeiter und dann
gibt es halt Konkretere, die
halt irgendwie davon erben, also weiß ich nicht, irgendwie
keine Ahnung, CEO
oder irgendwie Senior Vice President
Facility Management oder sowas
und
wenn man jetzt aber in der Vorschleife
iteriert über alle und weiß jetzt nicht genau, welchen
konkreten Typen man hat, man weiß nur, es sind halt schon
irgendwie Mitarbeiter und macht dann Fallunterscheidungen
wie, also, wenn das jetzt
irgendwie, keine Ahnung,
der CEO ist, dann machen wir aber folgende
Ausnahmegeschichten, wenn wir jetzt zum Beispiel
Gehalt auszahlen, wir rufen
nicht einfach Gehaltauszahlen-Methode auf, sondern
Wir sagen nochmal, okay, wir machen Speziallogik, je nachdem, was das denn für ein Typ ist.
Also du weißt schon, dass der Senior Vice President Facility Management ein ziemlich stiller Witz ist.
Wieso? Das ist doch voll wichtig.
Also dann hätte man sozusagen, aus meiner Perspektive, hätte man jetzt eben Lischkoffs 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, und Korrektheit ist tatsächlich auch immer eine spannende Frage von, das gehört eigentlich auch für mich dazu, im Sinne von erfüllt tatsächlich auch nachher für den User was Sinnvolles.
Und du sagst zum Beispiel, alle Mitarbeiter müssen eine private Telefonnummer haben und bei den CEOs legt man dann fest, nee, da ist die immer null, weil die privaten Nummern der CEOs werden nicht rausgegeben und das würde einem Subtyp entsprechen.
dann hättest du halt in dem Moment das verletzt, im Sinne von, ja jetzt machen wir hier mal für Weihnachten die Telefonliste der Mitarbeiter fertig und machen die Secret Centers für hier und den kannst du anrufen, um noch ein bisschen was abzufragen und plötzlich kommen bei den CEOs halt da keine Telefonnummern raus.
Ja, nee, das war jetzt halt kaputt.
Und das ist eine Designanforderung
nicht von dem Client-Code, der damit
arbeitet, sondern das ist eine Designanforderung
von Objekten, von
Unterobjekten, von Unterklassen.
Von Subklassen.
Dass eine Subklasse
den Raum
der Möglichkeiten erweitern, aber nicht einschränken
darf.
Okay, das ist L.
Jetzt haben wir noch
S-O-I-D.
Das würde ich gerne
verschieben.
Ich habe vorhin schon meinen
Zungenbrecher
gehabt und wir haben heute etwas
Zeit, wir haben ja relativ gut
zeitig angefangen, mit dem
Nachteil, dass meine Technik heute ein bisschen
Ja, du hast inzwischen durchführlich alleine geredet.
Ja, und auch bis wir zum Reden gekommen
sind, 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.
In drei Monaten. Schön, dass ihr aber
alle wieder eingeschaltet habt heute. Ja, genau.
An der Stelle müssen wir uns eigentlich auch entschuldigen. Wir haben im 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. Corona. Ja.
Ja, eigentlich wollten wir auch zwei aufnehmen,
da ist wieder was ausgefallen und so. Ja, ja.
Die Termin-Findungs-Koordinations-
Schwierigkeiten kommen noch übrigens dazu.
Ja, aber wir geloben Besserung, das kriegen wir auch schon
irgendwie hin. Genau.
Genau, nee, dann am besten,
ja, wir haben ja auch schon echt viel Zeug gemacht,
dann verschieben wir das mal. Solid 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 sei dann schon sozusagen Vorbereitung aufs nächste Mal.
CosmicPython.com
Ich glaube, das heißt
dann auch tatsächlich, wenn man es als Buch kauft,
also kann man da online lesen.
Ja, es ist halt auch
Architectural Patterns for Python
oder irgendwie sowas.
Ist von dem, na, wie heißt er noch?
Der auch Obey the Testing Goat geschrieben hat.
Und einem anderen.
Verdammt.
Okay, weiß nicht mehr genau.
Da kann ich eigentlich auch sofort nachgucken.
Percival.
Percival, ja.
Kosmos ist die Opposite of Chaos.
Aha, Kosmos ist die Opposite of Chaos.
Genau, das ist auch einer der Gründe, warum ich dieses Pattern-Thema überhaupt irgendwie interessant fand, mal darüber zu sprechen, weil ich gerade momentan halt auch zum ersten Mal irgendwie so ein bisschen eine größere Geschichte habe, wo es einfach nicht reicht, einfach nur so Django-Modelle zu haben oder irgendwie so, sondern wo man das vielleicht trennen muss, irgendwie Business-Logik von.
Ja, das kannte ich noch nicht und das sieht aber tatsächlich
gut aus. Das sind so tatsächlich die Patterns,
die ich auch kenne, die in Python
gerne kommen. Unit of Work
ist so ein SQL-Alchemy-Ding auch, Event-Driven
und Message-Bus klingt gut,
Commands klingt gut,
Dependency-Injection ist super.
Das klingt interessant, das 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.
Okay.
Ja, wir haben einige zweite Teile noch offen übrigens.
Ja, ja, Async muss man auch unbedingt
nochmal dran.
Ja, vielen Dank, dass du wieder da warst, Christian, Conny.
Danke, dass ich dir bei sein durfte.
Na klar.
Und ja, schön, dass ihr reingeschaltet habt.
Und gute Nacht, guten Morgen, guten Abend, gute und so weiter.
Dann bis zum nächsten Mal.
Bis dann.
Tschüss.
Ciao, ciao.