Engineering Kiosk Episode #93 Barbara Liskov - Das L in SOLID (Liskovsches Substitutionsprinzip & Abstraktion)

#93 Barbara Liskov - Das L in SOLID (Liskovsches Substitutionsprinzip & Abstraktion)

Diese Episode in deiner Podcast-App hören...

Shownotes / Worum geht's?

Liskov Substitution Principle: Das L in SOLID von Barbara Liskov

Heutzutage wird die Informatik und Softwareentwicklung leider primär von Männern dominiert. Doch schaut man ein paar Jahrzehnte zurück, haben viele Frauen maßgeblich die heutige Software-Entwicklung geprägt. Eine Frau war Barbara Liskov. Liskov? Das kennt man doch irgendwoher? Genau. Sie ist unter anderem die Namensgeberin für das L in den SOLID-Prinzipien (die ersten 5 Prinzipien des objektorientierten Designs).

Als zweite Frau überhaupt hat Barbara Liskov 2008 den berühmten Turing Award erhalten. In dieser Episode besprechen wir ihr Lebenswerk.

Bonus: Barbara Liskov war an den Sprachkonstrukten Exceptions, yield, multiple assignments und multiple returns beteiligt.

**** Diese Episode wird gesponsert von https://www.workshops.de

Ob öffentliche Schulungen, die du einfach buchen kannst oder maßgeschneiderte Schulungen für dein Unternehmen – Workshops.de bietet deutschsprachige Kurse in den Bereichen Angular, React, VueJS, Spring Boot, Typescript, Docker, Security, Data Science und den Grundlagen von HTML, CSS und JavaScript an.

Alle Infos unter https://www.workshops.de

****

Das schnelle Feedback zur Episode:

👍 (top) 👎 (geht so)

 

Sprungmarken

(00:00:00) Intro

(00:01:13) SOLID-Prinzipien und die Anwendung in der Praxis

(00:03:02) IT-Schulungen bei Workshops.de (Werbung)

(00:04:05) SOLID-Prinzipien und die Anwendung in der Praxis

(00:07:07) Frauen in der Informatik und Turing Award-Gewinnerin "Barbara Liskov"

(00:11:20) Erfindung von Grundlagen der Software-Entwicklung und GOTO Statements

(00:14:10) GOTO Statements considered harmful

(00:18:14) Venus Betriebssystem

(00:19:20) Forschung zu den heutigen Grundlagen der Software-Entwicklung

(00:21:49) Global variable considered harmful

(00:23:18) Abstraktion, Spezifikationen und die Programmiersprache Clu

(00:31:53) Das L in SOLID: Liskov Substitution Principle (LSP)

(00:44:23) The Power of Abstraction

Hosts

Feedback (gerne auch als Voice Message)

 

Transkript

Das Transkript wurde automatisiert per Speech-to-Text erstellt und kann daher Fehler enthalten.

Andy Grunwald (00:00:01 - 00:00:11) Teilen

Also umso mehr ich da einsteige, denke ich so, wow, wow, wow. Und da frage ich mich, warum ist diese Dame eigentlich nur für das LSP in Solid bekannt, also für das L in Solid.

Wolfi Gassler (00:00:11 - 00:00:17) Teilen

Wir sind jetzt genau 50 Jahre seit diesem Paper und globale Variablen haben wir immer noch nicht geschafft abzuschaffen.

Andy Grunwald (00:00:20 - 00:01:09) Teilen

Willkommen beim Engineering-Kiosk, der deutschsprachige Software-Engineering-Podcast rund um die Themen Engineering-Kultur, Open Source, Technologie und Menschen. Diese Episode handelt vom Lebenswerk eines ganz besonderen Menschen, einer Turing Award Gewinnerin. Es geht um Barbara Liskov. Den meisten wird der Name Liskov durch die Solid-Prinzipien etwas sagen, dem Liskov Substitution Principle. Aber durch ihre Forschung hatte sie einen viel größeren Einfluss auf uns. Sie prägte maßgeblich Vorgehensweisen aus der heutigen Softwareentwicklung und war eine große Inspirationsquelle für diverse Features von modernen Programmiersprachen, wie zum Beispiel Multiple Assignments, modernem Exception Handling oder dem Yield Statement. Warum das alles nicht geplant, sondern eher eine Art Zufall war und welches Ansehen das GoTo Statement und globale Variablen in den 1970er Jahren hatten, darum geht's in dieser Episode. Wir springen direkt rein und los geht's.

Wolfi Gassler (00:01:13 - 00:01:19) Teilen

An die Hand aufs Herz hättest du ohne Vorbereitung die Solid Principles herbekommen, sodass man still greift.

Andy Grunwald (00:01:19 - 00:01:48) Teilen

Von den fünf Buchstaben hätte ich, glaube ich, den einen oder anderen hinbekommen. Was ich auf keinen Fall hinbekommen hätte, wäre der wirkliche Name von den einzelnen Buchstaben. Also ich hätte dir sehr wahrscheinlich umgangssprachlich erklären können, was es ist. Aber ich muss auch zugeben, ich bin mir gar nicht sicher, ob ich außer in meinem Studium und in meiner Fachinformatiker-Anwendungsentwicklungsausbildung jemals eine Klasse oder ein objektorientiertes Software-Design nach SOLID geschrieben habe.

Wolfi Gassler (00:01:49 - 00:01:58) Teilen

Du bist schon wie so ein Politiker. Ich stelle eine einfache Ja- und Nein-Frage und du kommst mit irgendeiner langgezogenen Antwort. Also nein, du hättest es nicht hinbekommen.

Andy Grunwald (00:01:59 - 00:02:03) Teilen

Ja, wenn wir wirklich binär sind und hätte ich alle fünf? Nein, hätte ich nicht.

Wolfi Gassler (00:02:03 - 00:02:39) Teilen

Ich bin ja zugegebenermaßen auch mal gefehlt in einem Jobinterview. Also ich bin gar nicht in einem Jobinterview gesamt gefehlt, weil ich habe den Job am Ende bekommen. Danke Tom übrigens dafür. Aber ich habe die Frage bekommen, was ist das Solid Principle? Und ich hatte damals keine Ahnung. Also ich hatte im Kopf, ich habe irgendwas geantwortet, so wie du, politisch. Es ist irgend so ein Ding, um schöner zu coden. Aber das war schon alles, was ich hinbekommen habe. Ich habe dann noch die Frage bekommen, was ist denn Dependency Injection? Und die Frage habe ich dann beantworten können. Und glücklicherweise war ja das D oder ist das D immer noch von Solid, ist Dependency Injection.

Andy Grunwald (00:02:39 - 00:04:19) Teilen

Ich weiß, ich mache mir jetzt gegebenenfalls viele, viele Feinde. Doch ich bin ja oft der Ansicht, dass immer wenn ich eine Klasse schreibe und die strikt nach den Prinzipien von Solid schreiben würde, dass da eine ganze Menge Zeitverschwendung drin ist. Denn ich denke, der Code bei kleinen bis mittelgroßen Anwendungen wird nicht so wiederverwendet, wie er wiederverwendet werden könnte. Werbung Suchst du nach Möglichkeiten deine Karriere in der Webentwicklung voranzubringen? Dann sind die erstklassigen deutschsprachigen Schulungen von Workshops.de etwas für dich. Egal ob du dich für Angular, React, Vue.js, Springboot, Docker, Security, Data Science oder einfach für die Grundlagen von HTML, CSS, JavaScript und Typescript interessierst. Workshops.de bietet ein breites Spektrum an hochwertigen Schulungen. Du hast die Wahl. Du kannst einen einzelnen Platz in den Remote-Schulungen buchen oder du investierst in maßgeschneiderte Inhouse-Schulungen, die speziell auf die Anforderungen deines Unternehmens zugeschnitten sind. Ein besonderes Angebot von Workshops.de sind die sogenannten Lifetime-Schulungen. Das sind Videotrainings inklusive wöchentlichen Livecalls mit erfahrenen TrainerInnen, Musterlösungen, regelmäßigen Updates und uneingeschränktem Zugang zu allen Lernmaterialien. Du bestimmst dein Tempo und behältst lebenslang Zugriff auf sämtliche Ressourcen. Schließlich wissen wir alle, dass im Leben manchmal etwas dazwischenkommt. Alle Infos auf workshops.de oder in den Show Notes. Werbung Ende. Und deswegen bin ich halt eher so der Freund, okay, mach mal so zweieinhalb Solid Principles. Nicht fünf, sondern zweieinhalb, die sind dann gut genug.

Wolfi Gassler (00:04:19 - 00:04:27) Teilen

Was sind dann deine zweieinhalb, die du da anwendest? Bin übrigens nicht deiner Meinung, nur dass ich das mal schon vorerst schicke. Aber was sind dann die zweieinhalb, die du anwendest?

Andy Grunwald (00:04:27 - 00:05:02) Teilen

Ich glaube, das D, Dependency Inversion Principle, also halt Abhängigkeiten reinreichen und allem drum und dran, fürs ordentliche Testing auf jeden Fall und auch zum Austausch, dass man es wirklich flexibel hält. Dann ein Prinzip, was in der Go-Programmiersprache sehr oft verwendet wird, das I, Interface Segregation Principle. Das sagt ja umgangssprachlich, mach dein Interface einfach nicht so groß mit 35 Methoden, wenn man nicht alles dafür braucht. Ja und dann kommt es halt ein bisschen drauf an ja so das würde ich auch noch mit rein nehmen aber da ist halt schon wieder so so ein grenzfall würde ich sagen.

Wolfi Gassler (00:05:02 - 00:05:10) Teilen

Also der vollständigkeit halber mach mal die anderen drei buchstaben auch noch in deiner super schnellen erklärungsweise einsatz pro buchstabe.

Andy Grunwald (00:05:10 - 00:06:14) Teilen

Mit D und I hatten wir gerade, dann das L ist das Liskov Substitution Principle. Darum geht es eigentlich darum, dass das Verhalten von Kindsklassen in Vererbung nicht unerwartet sein darf. Da kommen wir aber gleich nochmal im Detail drauf. Genau, dann gibt es noch das O, Open Close Principle. Da geht es um Klassen, Module oder Funktionen, die offen für Erweiterung, aber geschlossen für Veränderung oder Modifikation sein sollen. Und dann geht es um das S, den Anfangsbuchstaben, das Single Responsibility Principle, dass eine Klasse wirklich nur eine Bedeutung oder eine Aufgabe haben soll. Also das bedeutet, wenn ich jetzt irgendwie was zu berechnen habe, dann berechnet diese Klasse das nur und gibt danach nicht noch die Berechnung in JSON oder HTML oder XML aus, sondern das wären dann zwei Klassen eigentlich. Aber, wie gesagt, ich hätte es auch nicht ohne Vorbereitung hingekriegt. Und ich bin auch nicht der Typ, der jemals ein Software-Architekt wird. Denn, wie gesagt, ich mache mir Feinde. Ich denke, wenn man das immer anwendet, dann... Ich denke, man kann sich schneller durch die Software bewegen. Und ich denke, die Parts werden öfter neu geschrieben, als man gucken kann.

Wolfi Gassler (00:06:15 - 00:06:38) Teilen

Also Solid soll ja nicht unser Thema heute sein, aber ich muss schon sagen, dass es einfach eigentlich schon Sinn macht, diese Prinzipien zu beachten und meiner Meinung nach ist es auch nicht nur für Objektorientierung, weil es gilt für jedes Modul, Ersetzerklasse durch Modul, dann hast du dieselben Properties, die du da eigentlich haben solltest in dem modularen System und es gilt eigentlich für jede Sprache, aber du in deiner Go-Sprache, schönes Programmieren habt ihr ja nicht erfunden.

Andy Grunwald (00:06:39 - 00:06:49) Teilen

Das Lustige ist ja eigentlich, wenn man sagt, OK, SOLID ist ein Akronym für die ersten fünf Prinzipien von objektorientiertem Software-Design, dann hat Goda eigentlich gar nicht mitzureden, weil Objektorientierung gibt's da nämlich nicht.

Wolfi Gassler (00:06:49 - 00:07:30) Teilen

Ja, aber das hat ja nur Uncle Bob damals so definiert, falls er es überhaupt für Objekte definiert hat ursprünglich. Aber ich finde, man kann es auch ganz allgemein sehen. Und so wie du es ja auch richtig erklärt hast, du hast es schon teilweise erwähnt, Funktionen oder Module oder in irgendeiner Form gekapselten Bereichen, wie das dann in der Programmiersprache auch immer gemacht wird. Und eigentlich geht es genau um diese Kapselung heute, und zwar um dieses L. Und wenn man noch weiter geht, dann ist diese Episode eigentlich eine Turing-Award-Episode, die wir wieder machen. Und zwar, ich glaube, die dritte, wenn ich das richtig im Kopf habe. Wir hatten Tim Berners-Lee und Turing selbst. Und jetzt machen wir weiter mit einer der wenigen Frauen in der Liste von Turing-Award-Gewinnern und Gewinnerinnen.

Andy Grunwald (00:07:30 - 00:08:33) Teilen

Und wenn wir über Frauen in der Informatik sprechen, dann ist der aktuelle Stand, glaube ich, eigentlich sehr sehr schade, denn wenn man sich die Informatik und die Softwareentwicklung mal so ein bisschen anschaut, dann ist der Bereich eigentlich, ich sag mal, von Männern dominiert, beziehungsweise ist eine sehr geringe Anzahl von Frauen in diesen STEM-Berufen vertreten. Wenn man sich jetzt aber mal die Historie ansieht und mal ein bisschen tiefer schaut, wo kommen eigentlich so die großen Würfe so her, dann sind da schon eine ganze Menge Frauen vertreten. Ich meine, so zwei, drei große Namen sind dann Ada Lovelace, laut Historie soll sie das erste Computerprogramm überhaupt geschrieben haben, 1800, schieß mich tot. Grace Hopper hat den ersten Compiler geschrieben, war beim Militär und hat ganz ordentliche Vorarbeit zur Programmiersprache Crowboy geleistet. Adele Goldberg mag vielleicht dem einen oder anderen noch ein Begriff sein, hat ordentlich an der Programmiersprache Smalltalk mitgeschrieben. Also sehr, sehr viele Frauen waren, ich würde sagen, in den ersten Jahrzehnten Informatik an maßgeblichen großen Dingen, die heutzutage auch eine ganze Menge bewegen, beteiligt.

Wolfi Gassler (00:08:33 - 00:08:50) Teilen

Hättest du gewusst, dass das Liskov'sche Substitution Principle, dass da eine Frau dahinter steckt? Also ich habe den Namen gekannt, aber ich hatte keine Ahnung, wer da eigentlich dahinter steckt. Und ich habe das mal gehört bei Solid, SSL, Liskov, aber wer das war, war mir nicht im Begriff.

Andy Grunwald (00:08:50 - 00:09:01) Teilen

Offengesprochen mache ich diesen Podcast ja auch, weil ich dann jedes Mal etwas Neues lerne. Und ich wusste noch nicht mal, dass Liskow ein Nachname ist. Ich habe gedacht, das wäre irgendwie ein mathematisches Gesetz.

Wolfi Gassler (00:09:01 - 00:09:06) Teilen

Wobei die meisten mathematischen Gesetze ja auch immer benannt sind nach den ErfinderInnen.

Andy Grunwald (00:09:07 - 00:09:14) Teilen

Ja, oder vielleicht irgendwas aus der Physik. Ich weiß es nicht. Aber ich wusste halt nicht, dass Liskow ein Nachname ist.

Wolfi Gassler (00:09:14 - 00:09:49) Teilen

Auf jeden Fall die heutige Episode, es geht um die Barbara Liskow. die die zweite Gewinnerin war bei Turing Awards. Also es hat schon eine Frau davor gegeben, aber es hat schon sehr lange gebraucht, bis da überhaupt eine Frau nominiert wurde bzw. dann den Preis gewonnen hat. Und sie war eben 2008, auch relativ spät. Die zweite Frau, die den Preis gewonnen hat für ihre Gesamttätigkeit. Normalerweise wird der Turing Award eher für Lebenswerke in dem Sinne vergeben und weniger eine spezifische Erfindung. Ist ja auch schwierig, sowas zu pinpointen.

Andy Grunwald (00:09:50 - 00:10:11) Teilen

Ihr Lebenswerk. Ich frage mich immer, was ist denn ein Lebenswerk? Und ich habe mir natürlich bei der guten alten Barbara jetzt auch mal nachgeschaut, wofür sie das Ganze eigentlich bekommen hat. Und zwar für Beiträge zu Programmiersprachen und Betriebssystemdesign, insbesondere im Zusammenhang mit Datenabstraktion, Modularität, Fehlertoleranz, Persistenz und verteilten Rechnern.

Wolfi Gassler (00:10:11 - 00:10:30) Teilen

Ja, sie war eigentlich ziemlich breit unterwegs. Es ist auch ganz witzig, sie ist eigentlich in die Informatik reingestolpert. Sie ist eigentlich Mathematikerin und hat einfach keinen Job gefunden. Und dann hat sie halt irgendwo so eine Programmierstelle angeboten bekommen, hat mit dem angefangen und sie wollte eigentlich nie in den ganzen Bereich reinkommen und hat es eigentlich durch Zufall gewählt.

Andy Grunwald (00:10:31 - 00:11:03) Teilen

Ich habe ein Interview von ihr gehört und da hat sie über ihren ersten Job gesprochen. Eigentlich genau das, was du gerade gesagt hast. Und die Firma, wo sie angefangen hat, die haben eigentlich nur Leute angestellt, die noch nie programmiert haben. Denn zu der Zeit gab es super wenig Leute, die wirklich Software entwickelt haben. Sie kam dann also dahin, hat dann Computer gekriegt und hat dann erstmal so ein großes manual book bekommen ich glaube das war fortan zu der damaligen zeit und hat dann angefangen zu programmieren also eigentlich könnte man das grob übersetzen wie heute einen junior entwickler oder.

Wolfi Gassler (00:11:03 - 00:12:37) Teilen

Eigentlich ein Quereinsteiger, beziehungsweise ich glaube, das ist eigentlich für Mathematiker ja auch ziemlich oft der Werdegang heutzutage, dass man dann doch sehr viel mit Coding macht am Ende. Und ganz viele Informatiker waren ja eigentlich auch ursprünglich Mathematiker. Also das verschwimmt ja immer allgemein sehr stark, muss man auch dazu sagen. Und interessanterweise, obwohl sie dann eigentlich in der Softwareentwicklung tätig war, kommt sie eigentlich aus der Systemarchitektur. Also sie hat sich eigentlich eher so um Betriebssysteme gekümmert und die ganze Softwareentwicklung interessanterweise ist auch so entstanden aus der Systemarchitektur und der Systementwicklung, weil natürlich die ersten Programmiersprachen eigentlich aus dem Operating System kommen und natürlich die Trennung dann erst langsam vollzogen wurde und früher hat man natürlich viel näher noch am Prätrib-System gearbeitet. Und das, was man heutzutage so eigentlich als Standard ansieht, das hat es damals noch nicht gegeben. Also sie ist da eigentlich federführend gewesen oder eine der vielen Personen, die da federführend waren. um eben solche Trennungen dann überhaupt zu machen, dass man eben modularisiert, dass man gewisse Schnittstellen hat und diese Dinge. Das war zu ursprünglichen Zeiten, gab's das alles nicht. Also das, was für uns absolut selbstverständlich heute ist, war damals einfach nicht gegeben. Und für mich war das irgendwie schwierig zu verstehen, dass man so Grundlagen auch erst erfinden muss in dem Sinne, sodass man irgendwie eine API hat, eine Funktion, eine Schnittstelle oder solche Dinge. Es hat Leute gegeben, die halt gedacht haben, okay, irgendwann Spaghetti-Code ist schlecht, Go-To-Befehle sind schlecht, irgendwie muss es doch was Besseres geben.

Andy Grunwald (00:12:37 - 00:12:56) Teilen

Also, du redest ja speziell darüber, dass zu dieser Zeit es keine Funktionen gab, wo du wirklich Code kapseln konntest, keine Module, wo du Logik bandeln konntest, sondern man hat wirklich Zeile unter Zeile unter Zeile unter Zeile und ich nenn's mal Kontrollstrukturen halt auch erst nach und nach erfunden werden musste, richtig?

Wolfi Gassler (00:12:57 - 00:13:09) Teilen

Genau, also es war in den 70er Jahren, beziehungsweise sogar Ende der 60er, da ist es so langsam aufgekommen und davor war eigentlich alles Spaghetti Code. Natürlich hat es Funktionen in irgendeiner Form gegeben.

Andy Grunwald (00:13:09 - 00:13:10) Teilen

Was heißt denn hier in irgendeiner Form?

Wolfi Gassler (00:13:11 - 00:14:56) Teilen

Ja, es hat dann natürlich schon, also zu der Zeit hat es LISP zum Beispiel gegeben, FORTRAN, PL-1 war damals, ALGOL, COBOL, da gibt es natürlich schon Funktionen in dem Sinne, aber wie man damit umgeht und ein GoTo ist ja eigentlich auch fast eine Funktion, wenn man irgendwo hinspringt in einen anderen Scope, könnte man ja auch als Funktion sehen und wenn man tiefer nach unten geht, ist ja heutzutage auch eine Funktion irgendwo ein GoTo, man springt ja zum Funktionsblock. Also auf der untersten Ebene ist das ja eigentlich auch ein Go-To, aber man spricht das natürlich anders an und hat dann natürlich andere Möglichkeiten und einen Stack und so weiter. Und es ist eigentlich auch super interessant, wie das eigentlich damals entstanden ist in den 70er Jahren. Also es hat da so eine gewisse Bewegung gegeben, die in die Modularisierung gegangen ist. Und wer sich dafür interessiert, dem kann ich wirklich empfehlen, sich diese Turing Lecture anzusehen, von der Barbara Liskov. Man gibt ja da dann immer so eine Vorlesung, wenn man den Turing Award gewinnt, und sie erzählt sehr genau, wie das eigentlich alles entstanden ist mit den Figuren damals, also zum Beispiel mit Dijkstra. Der hat 1968 dieses Paper veröffentlicht, Go-To Statement Considered Harmful. Und dann gab es einen extremen Gegenwind, weil viele für dieses Go-To-Statement waren. Und das, was man sich heutzutage eben gar nicht mehr vorstellen kann, dass man überall Go-To verwendet, die Leute damals waren natürlich schon überzeugt von ihren Go-To-Statements und wollten das auch weiterverwenden. Und das war eigentlich so die Zeit, wo Wieskopf dann überhaupt in die Richtung gegangen ist und sich überlegt hat, okay, Dijkstra hat vielleicht recht, vielleicht sollte man da was verändern. Und sie war dann eigentlich Teil dieser ganzen Community. Nikolaus Wirth war damals auch ein großer Name, kennt man vielleicht. Und Liskov ist dann erst 1971, 1972 mit ihrem großen Paper zu diesem Substitution Principle eigentlich rausgekommen.

Andy Grunwald (00:14:56 - 00:15:37) Teilen

Naja, aber wegen dem GoTo noch mal. Ich kann schon verstehen, dass der Herr Gute-Dijkstra damals Gegenwind bekommen hat. Ich mein, wir müssen uns einmal ganz kurz zurückerinnern, was war das denn? Zu dieser Zeit gab's keine modernen Programmiersprachen. Zu dieser Zeit waren das alles unstrukturierte, prozedurale Programmiersprachen wie Basic, frühe Dialekte von Fortran und Co. Also, da war GoTo wirklich, ich sag mal, das Mittel der Wahl. Und ... Jeder Code sieht eigentlich auch aus so ein bisschen wie Spaghetti-Code in der ganzen Thematik. Wenn du dir das Star Trek Game von 1972 mal ansiehst, das verlinken wir auch gerne in den Shownotes, dann siehst du da schon 10.000 ... Du sprichst.

Wolfi Gassler (00:15:37 - 00:15:42) Teilen

Über das Game, als hättest du es selber miterlebt. Ah, Star Trek Game von 72, das können sich sicher noch alle erinnern, klar.

Andy Grunwald (00:15:43 - 00:15:57) Teilen

Nein, der Soundcode ist aber noch im Webarchiv verfügbar und ich habe es versucht zu verstehen und es ist heutzutage wirklicher Spaghetti-Code und ich glaube, der größte Hacker, der größte Mensch, der da Code hinrotzt, wird sagen, uh, aber schon eine harte Geschichte.

Wolfi Gassler (00:15:57 - 00:15:59) Teilen

Was war das für eine Programmiersprache?

Andy Grunwald (00:16:00 - 00:16:16) Teilen

So viel ich das lesen kann, ist das alles in Basic geschrieben. Auf jeden Fall war GoTo halt damals, ich sag mal, wirklich das Mittel der Wahl. Und heutzutage würde man sagen, das Sprachkonstrukt GoTo ist ja immer noch in vielen Programmiersprachen vorhanden, auch noch in Go, so viel ich weiß.

Wolfi Gassler (00:16:16 - 00:16:23) Teilen

Und es wurde heutzutage durch globale Variablen ersetzt, würde ich sagen. Der Hate geht jetzt gegen globale Variablen und weniger gegen GoTo.

Andy Grunwald (00:16:24 - 00:16:41) Teilen

Ja, das könnte sein, aber es gibt ja immer noch valide Anwendungsfälle von GoTo im modernen Programmieren. Also sind super viele Router, also nicht Router im Netzwerk, sondern wirklich URL-Router, Symphony, Framework, React und Co. Da wird GoTo sehr viel genutzt.

Wolfi Gassler (00:16:41 - 00:16:48) Teilen

Ja, aber das ist ein anderes GoTo, oder? Also das ist ja kein Sprung, dass ich irgendwo hinspringe zu einer Programmierzeile und dort weitermache im Code.

Andy Grunwald (00:16:48 - 00:16:53) Teilen

Warum nicht? Natürlich, du setzt Marker in deinem Code und du springst zu diesen Markern.

Wolfi Gassler (00:16:53 - 00:16:54) Teilen

Warum macht man das freiwillig?

Andy Grunwald (00:16:54 - 00:17:03) Teilen

Also im Endeffekt kannst du ja sagen, okay, du hast eine dreifach verschachtelte Schleife und machst jetzt ein GoTo, um da rauszuspringen oder einen Early Return. Also beides ist ja möglich.

Wolfi Gassler (00:17:03 - 00:18:04) Teilen

Ja, ein Early Return ist ja noch mal was anderes. Also, was ja auch Dijkstra damals bequittelt hat, warum GoTo eigentlich schlecht ist, also ist ja nicht so, dass man einfach sagt, wir mögen den Begriff nicht oder das Keyword, sondern seine Argumente waren natürlich, dass man gerade im Debugging extrem schwierig nachvollziehen kann, wie man denn an eine gewisse Stelle gekommen ist. Also man springt da quer durch den Code und man hat keinen Stack wie mit Funktionen, wo du durch einen Funktionsstack durchgehst und automatisch immer den Aufruf Stack nach oben gehen kannst und genau weißt, okay, die übergeordnete Funktion war diese und ich komme daher und von der anderen Funktion. Du kannst da natürlich wesentlich besser debuggen und damit umgehen, als wenn du kreuz und quer durch den Code springst und die Übersicht geht da natürlich einfach verloren. Und das war nicht sein Hauptargument. Und da würde ich sagen, Wenn das heutzutage immer noch so ist mit Markern, vielleicht ist auch das Debugging verbessert worden und ihr habt dann Trace drauf, wo ich dann durch die Welt gesprungen bin, dann macht es das vielleicht besser. Aber ganz allgemein besteht das Problem natürlich weiterhin, wenn du einfach kreuz und quer durch den Code springst.

Andy Grunwald (00:18:05 - 00:18:14) Teilen

Ja, da bin ich auch bei dir, weil wenn ich mir das durchlese und da 25 Gotos sind und du musst wirklich immer komplett links und rechts springen, dann ist die Rehability halt auch nicht mehr gegeben, würde ich sagen.

Wolfi Gassler (00:18:14 - 00:21:24) Teilen

Und dieses Paper interessanterweise von Dijkstra hat eben die Barbara Liskov auch so ein bisschen mitgenommen und sie kommt ja wie erwähnt eigentlich aus der Systemarchitektur, also sie hat 69 ihr eigenes Betriebssystem namens Venus entwickelt. Das war ein experimentelles Betriebssystem. Und sie hat eigentlich in dem Bereich geforscht, auch so mit Schachcomputern hat sie scheinbar zu Beginn mal begonnen. Wie sie es nennt, eigentlich die frühe Zeit der AI damals. Das Einzige, was AI gegründet hat, waren Schachcomputer eigentlich. Und sie hat eben in den Betriebssystembereichen gesehen, dass man angefangen hat, die Sachen zu separieren, dass man da eben Schnittstellen einführt, dass man Möglichkeiten dem System-User an die Hand gibt, dass der selber coden kann, dass der über gewisse Schnittstellen im Betriebssystem Sachen aufrufen kann. Und da hat man eben diese Schnittstellen langsam geschaffen. Und aus dem Bereich heraus hat sie sich eigentlich gedacht, okay, das müsste man ja auf der Software-Seite eigentlich auch schaffen können. Also, dass man diese Abstraktion, die man im Betriebssystem hat, dass man die auch auf der Software-Seite hat, um die Software-Entwicklung zu verbessern. Und was auch noch super interessant war bei ihrem Vortrag, war, dass sie eigentlich, so wie sie durch die Geschichte gegangen ist, extrem viele andere Leute erwähnt hat. Also ihr habt es schon lange nicht mehr erwähnt, gerade bei Turing-Gewinnern, und das jetzt absichtlich nicht gegendert, dass so viele andere Personen erwähnt werden. Und sie hat eben auch ihren Mitarbeiter erwähnt. Er war eigentlich bei IBM, oder es war, glaube ich, nicht mal ein Mitarbeiter, aber mit dem hat sie extrem viel gemacht. Und sie hat ganz viele Namen erwähnt. Nikolas Wirth eben, David Barnas, Dijkstra eben. Und alle waren eigentlich in dem Umfeld unterwegs. Und man muss sich das ja auch vorstellen, früher in den 70er-Jahren oder auch später noch, man hatte ja als Forscher und Forscherin eigentlich nicht das Internet und den Zugang zu allem, was veröffentlicht wird. Das war ja sogar in Amerika, wenn das in einer anderen Stadt war, Du hast natürlich nichts mitbekommen. Die einzige Möglichkeit war irgendwelche Journals und Konferenzen, dass du was mitbekommst. Aber wenn da irgendwo in China was veröffentlicht wurde oder in Europa, das war natürlich super schwer, da überhaupt was mitzubekommen. Also ich habe das auch selber noch erlebt, wie ich an der Uni war. So in frühen Internetzeiten, da hast du einfach nicht die Möglichkeit gehabt, alles zu finden auf die Schnelle, was so veröffentlicht wird. Und darum ist es natürlich von vielen Seiten auch gekommen. Aber es hat natürlich auch viele Papers gegeben, die sie beeinflusst haben. Nikolas Wirth eben, der hat diese Herangehensweise mal aufgeschrieben oder entworfen, dass man so, wenn man programmiert, eigentlich eine schrittweise Verfeinerung macht. Also man fängt ganz oben an bei einem Problem, überlegt sich, wie kann ich das Problem lösen? Und dann geht man eine Stufe tiefer und überlegt sich, okay, diese drei Schritte, die man jetzt überlegt hat, wie kann ich jeden Schritt wieder lösen? Und dann geht man wieder eine Stufe tiefer und entwickelt quasi Funktionen für diesen Schritt. Und dann geht man wieder eine Stufe nach unten und überlegt sich, wie kann ich das wieder aufsplitten? Also so eine klassische mathematische Herangehensweise eigentlich an ein Problem. Aber auch da wieder absolut selbstverständlich heute, aber das war damals eben nicht selbstverständlich. Und Wirth hat das aufgeschrieben, dass man eben so einen Baum eigentlich erzeugen muss, um ein Programm überhaupt zu erschreiben, also um ein Problem zu lösen, dass man so einen Baum hat und die Probleme immer nach unten immer verfeinert und strukturiert und löst.

Andy Grunwald (00:21:25 - 00:21:27) Teilen

Ich wollt schon sagen, so programmier ich heute noch.

Wolfi Gassler (00:21:27 - 00:21:28) Teilen

Ja, eben.

Andy Grunwald (00:21:28 - 00:21:31) Teilen

Das ist einfach der klassische Weg.

Wolfi Gassler (00:21:31 - 00:22:17) Teilen

Aber man kann sich eigentlich nicht vorstellen, dass das damals eigentlich nicht Standard war. Und es hat eben Leute gebraucht, die das eingeführt haben. Und da ist dann eben sie auch beeinflusst worden von diesen ganzen Bewegungen. Und drum hat sie dann auch begonnen mit dieser Abstraktionsebene und wie man eben besser abstrahieren kann. Und bevor wir jetzt noch tiefer in ihre Idee reingehen, was mir auch sehr gut gefallen hat, ist eigentlich, Das 1973 hat schon ein Paper gegeben, Global Variable Considered Harmful, bei Wolff & Shaw. Das heißt, eigentlich 1973 war das schon ein Thema und es ist immer noch ein Thema mit diesen globalen Variablen und sie schwirren immer noch herum. Also da hat man eigentlich sehr wenig gelernt. Es sind jetzt genau 50 Jahre seit diesem Paper und globale Variablen haben wir immer noch nicht geschafft abzuschaffen.

Andy Grunwald (00:22:18 - 00:22:35) Teilen

Ich bin gerade am überlegen, natürlich programmiere ich ab und zu auch kleine Skripte mit globalen Variablen, ab und zu, weil es schneller geht. Es schießt mich ruhig. Aber sie funktionieren ja dann immer. Und vielleicht haben die Seiten Effekte, die mich dann aber auch nicht interessieren, weil sie mir noch nie aufgefallen sind. Aber ich frage mich gerade, was ist denn der Use Case von globalen Variablen heutzutage?

Wolfi Gassler (00:22:35 - 00:22:54) Teilen

Ja, genau das, was du eigentlich gesagt hast, meiner Meinung nach. Man macht es halt einfach, weil es schneller funktioniert. Und bevor man das irgendwie sauber abstrahiert wegkapselt, kann man halt schnell eine globale Variable machen, weil du einen globalen State brauchst oder dir denkst, du brauchst einen globalen State. Und dann wächst das Programm und irgendwann hast du diese globalen Leichen im Keller.

Andy Grunwald (00:22:55 - 00:22:59) Teilen

Ich glaube, du hast was sehr Schönes gesagt, weil man denkt, man braucht einen globalen State.

Wolfi Gassler (00:23:00 - 00:23:17) Teilen

Also, man braucht sicher globalen State, aber man kann das natürlich auch in irgendeiner Form wegkapseln mit irgendwelchen sinnvollen Registries oder doch durchreichen. Vielleicht braucht man eben gar nicht. Dependency Injection ist ja auch in gewisser Weise eine Möglichkeit, um globalen Variablen entgegenzuwirken. Also da gibt es sicher viele Bereiche.

Andy Grunwald (00:23:18 - 00:23:27) Teilen

Gut, jetzt haben wir ziemlich viel über die Forschungen von Barbaros Kollegen gehört. Dijkstra, Wulfenschau, Wirth. Aber was war denn jetzt Ihre Idee?

Wolfi Gassler (00:23:27 - 00:24:39) Teilen

Also ihre Idee war eigentlich Kapselung. Sie hat mehr oder weniger Kapselung, abstrakte Datentypen erfunden. Also auch da wieder, sie hat erwähnt, netterweise, wie gesagt, es war wirklich super zu hören. Sie hat gemeint, David Barners, 72, der hat eigentlich so Module erfunden, die frühen APIs. Das hat sie gar nicht so am Schirm gehabt, dass man da schon in einem anderen Bereich was erfunden hat. Das heißt, es ist alles sehr Gleichzeitig würde ich sagen, was passiert, so 71, 72, sie hat den Talk 71 gehalten, dann ist Paper 72 veröffentlicht und es geht natürlich alles in eine stark ähnliche Richtung. Und die Grundidee war eigentlich, dass man, ich würde es mal jetzt Module nennen, sie jetzt damals Partitionen genannt, in ihrer Programmiersprache Clue, die sie entwickelt hat, um das eben auch zu zeigen und zu prüfen, Und eine Partition hat einen internen Zustand und definierte Operationen nach außen. Und von außen kannst du nur diese definierten Operationen aufrufen. Also einfach ein Modul, kannst du eine Klasse dazu sagen, wie du das auch immer siehst, oder Objekt. Du hast definierte Schnittstellen nach außen und einen internen Zustand, auf den du nicht direkt zugreifen kannst. Und du weißt von außen nicht genau, was in dieser Blackbox drinnen vorgeht.

Andy Grunwald (00:24:39 - 00:24:42) Teilen

Eigentlich hat sie Public und Private erfunden.

Wolfi Gassler (00:24:42 - 00:25:03) Teilen

In gewisser Weise, wenn du es so sehen willst, ja, also diese Abstraktion, die es in der Betriebssystem-Welt schon gegeben hat, weil du hast den Betriebssystem-Code und den User-Code und du hast natürlich Schnittstellen zwischen Betriebssystem und User-Code und sie hat das ausgeweitet auf Programmiersprachen und hat dann in Programmiersprachen oder in ihrer CLU-Programmiersprache diese Partitionen eingeführt und damit Kapselung.

Andy Grunwald (00:25:04 - 00:25:13) Teilen

Und was versteht man jetzt als Partition in diesem Kontext? Ist das dann Modul, Datei, Package? Wie würd man das heutzutage nennen?

Wolfi Gassler (00:25:13 - 00:26:43) Teilen

Ja, du kannst alles dazu sagen. Es kommt auf die Programmiersprache an. Objekt würde genauso passen. Du hast ein Objekt mit Schnittstellen, und du kannst nicht auf den inneren State zugreifen, musst über diese Schnittstellen zugreifen. Das war die Grundidee von ihr. Und als Erweiterung sind dann noch die abstrakten Datentypen gekommen. Das heißt, sie hat begonnen, Datentypen auch so zu definieren. So Objekte und so hat es ja teilweise schon gegeben, aber auf Datentyp-Ebene hat es es eigentlich noch nicht gegeben, dass man da Schnittstellen definiert für Datentypen, was ja dann schlussendlich dann erst ermöglicht, dass du zum Beispiel Polyphemismus hast, weil du da eine Hülle hast für deine Datentypen. Und wie die dann implementiert sind, ist eine andere Geschichte. Also es geht eigentlich sehr stark in den Grundgedanken, dass du das Ganze spezifizierst. Das war auch sehr interessant. Damals zum Beispiel hat es keine Spezifikationen von Programmiersprachen gegeben. Die Spezifikation von Programmiersprachen damals war der Compiler. Das heißt, du hast was ausprobiert und wenn der Compiler das geschluckt hat, dann hat es gepasst. Es ist nirgends gestanden, die Programmiersprache ist so spezifiziert. Das heißt, diese ganzen Schnittstellen, Definitionen, Spezifikationen, das hat es damals alles nicht gegeben. Es war einfach Spaghetti-Code und der Compiler hatte immer recht und die Sprachdefinition war der Compiler. Und dann ist eben alles in die Richtung von Spezifikationen gegangen. Datentypen, Spezifikationen, eben diese abstrakten Datentypen, diese Moduldefinitionen. Dann einen harten Contract zu haben zwischen innen und außen. Und bei Betriebssystemen hat es diesen Contract gegeben und in Programmiersprachen eben noch nicht.

Andy Grunwald (00:26:43 - 00:27:02) Teilen

Naja gut, aber das würde ich sagen, passiert heute dann noch genauso. Wenn ich irgendwas prototype, dann habe ich ja auch nicht erst eine Spezifikation, sondern ich hack erstmal den Compiler runter oder das Programm, was das, was ich darüber mache, passt oder ähnliches. Und später dokumentiere ich, was eigentlich überhaupt alles supported wird. Also viel anders war das ja damals nicht und zu heute, oder?

Wolfi Gassler (00:27:03 - 00:27:28) Teilen

Ja, nur war das halt damals das produktive System, die produktiven Programmiersprachen, die herumgefleucht sind damals. Und da hat es halt keine Spezifikationen gegeben. Also das ist heutzutage schon anders, wo du dann auch mathematisch teilweise was durchdefinierst oder überhaupt den Beweis lieferst. Darum hat sie ja auch ihre eigene Programmiersprache entwickelt, weil sie das beweisen wollte und dann damit auch zeigen wollte, dass das überhaupt funktioniert mit so abstrakten Datentypen.

Andy Grunwald (00:27:28 - 00:27:54) Teilen

Also kann man eigentlich auch sagen, sie hat so schon den Grundstein gelegt für alternative Compiler, oder? Weil ich meine, wenn sie dafür gekämpft hat, dass unter anderem Programmiersprachen oder abstrakte Datentypen halt auch spezifiziert werden, das ist ja halt alles notwendig, damit ich dann für Java einen alternativen Compiler bauen kann oder für C oder ähnliches, ja? Ich meine, deswegen haben wir ja jetzt CLang und LLVM und was weiß ich nicht noch alles für Compiler gibt für C oder für andere Sprachen.

Wolfi Gassler (00:27:54 - 00:28:22) Teilen

Im Prinzip schon, ja. Also es war natürlich, wie gesagt, nicht sie alleine, klarerweise. Es haben viele auf der Ebene gekämpft damals. War wahrscheinlich sogar im Nachhinein gesehen eine sehr überschaubare Truppe. Aber das ist genau in den Anfang der 70er Jahren entstanden, dass wir in die Richtung mehr gemacht haben. Und sie mit ihrer Clou-Programmiersprache hatte sicher auch einen großen Anteil gehabt. Und es war die erste wirkliche Implementierung von abstrakten Datentypen. Und auch Iteratoren, interessanterweise.

Andy Grunwald (00:28:23 - 00:28:35) Teilen

Ich habe gerade mal nachgesehen, vor 13 Jahren gab es nochmal eine neue Version von Clue. Also so alt ist die Programmiersprache anscheinend doch nicht. Beziehungsweise wurde sie, ich sage mal partiell weiterentwickelt.

Wolfi Gassler (00:28:35 - 00:28:52) Teilen

Also sie basiert ja auf ALGOL. Keine Ahnung, ob das wirklich noch ein Thema ist oder wirklich noch funktioniert, ob es da irgendwie neue Versionen gibt. Aber es war damals ein Aufbau auf ALGOL und sie hat eben diese abstrakten Datentypen, sie jetzt Cluster genannt, damals eingeführt in Clue auf ALGOL basieren.

Andy Grunwald (00:28:53 - 00:29:08) Teilen

Ich lese gerade hier auch, dass Clue, also dass die zwei Programmiersprachen Clue und Ada maßgebliche Inspiration für C++-Templates geliefert haben. Und da muss ich jetzt zugeben, weiß ich nicht, ob das wirklich ein positiver Influence ist.

Wolfi Gassler (00:29:08 - 00:29:48) Teilen

Wie gesagt, die ganze Abstraktionsschiene war eigentlich dann danach aufbauend darauf. Ist ja auch witzig, by the way, Clue heißt die Programmiersprache, einfach, das sind die drei ersten Buchstaben von Cluster und Cluster ist eben dieser abstrakte Datentyp. Interessanterweise, sie hat übrigens auch das Exception Handling, in Clue verbessert beziehungsweise überhaupt eingeführt, dass man das, was man heute eigentlich als Exceptions kennt, dass man sowas in der Programmiersprache handeln kann, weil früher war das ja auch so, dass du einfach Go-Tos hattest. Du bist dann irgendwo rausgesprungen zu einer Fehlerbehandlung, zu einer Fehlerroutine und dass du wirklich so Exceptions hast, die du fangen kannst und dann auch weiterreichen kannst und solche Dingen, die hat sie auch in Clue dementsprechend eingebaut.

Andy Grunwald (00:29:49 - 00:30:19) Teilen

Ich lese auch noch gerade, dass Clue die Sprache war, die als erstes Multiple Assignments und Multiple Returns in Funktionen hatte, und dass Pearl und Lua diese Funktionalitäten von Clue haben. Und da muss ich mal ... Also, umso mehr ich da einsteige, denke ich so, wow, wow, wow. Und da frage ich mich, warum ist diese Dame eigentlich nur für das LSP in Solid bekannt, also für das L in Solid? Meines Erachtens nach hat sie durch Clue einen viel größeren Influenz die heutige Informatik ab.

Wolfi Gassler (00:30:20 - 00:31:19) Teilen

Naja, das LSP, also das Substitution Principle, das ist natürlich Clue in irgendeiner Form und sie hat es damit bewiesen, Clue. Also die mathematische Form dahinter, das Substitution Principle, wurde halt angewandt dann in Clue. Aber klar, sie hat auch Iterators eben da eingebaut und quasi den Yield Operator, den hat es damals zum ersten Mal gegeben, dass man wirklich so Iterator, wie man sie heute kennt, eigentlich verwenden kann. Also auch das war in Clue drinnen. Das war also wirklich eine Sehr coole Leistung von ihr. Und Steven Zilles, der war eigentlich ein Student von ihr, ich glaube ein PhD-Student, aber hat auch gleichzeitig für IBM gearbeitet, war also schon sehr weit. Und sie hat gemeint, es war nicht ein klassischer Student. Und mit dem hat sie scheinbar extrem viel diskutiert und er hat auch sehr viel dazu beigetragen. zu dem ganzen System. Und auch da wieder muss ich sagen, wir bräuchten mehr Leute, wenn sie den Turing Award gewinnen, auch darauf hinweisen, wer da nicht alle mit dabei war und nicht nur sich selbst in den Vordergrund stellen. Habe ich sehr, sehr cool gefunden in dem ganzen Vortrag.

Andy Grunwald (00:31:19 - 00:31:34) Teilen

Es ist natürlich schon eine Hausnummer, wenn man 2008 den Turing Award kriegt, dass man sagt, ja, also vor knapp 30, 40 Jahren, da war der, der, der und der mit am Start. Und da haben wir das alles gemacht. Ich weiß noch nicht mal, mit wem ich gestern ein Bier trinken war.

Wolfi Gassler (00:31:34 - 00:31:46) Teilen

Ja, sie hat natürlich den Vortrag schon vorbereitet. Und die Leute, die dich stark beeinflussen, so wie ich zum Beispiel, die kennst du ja wahrscheinlich in 20 Jahren auch noch, wirst du ja auch sagen, Wolfgang hat mich so stark beeinflusst. Das bleibt dir natürlich im Kopf.

Andy Grunwald (00:31:46 - 00:31:52) Teilen

Ja, ich meine, eine gesunde Portion Selbstbewusstsein sollte jeder haben. Und ich glaube, Wolfgang, du hast sie.

Wolfi Gassler (00:31:53 - 00:32:33) Teilen

Wenn wir übrigens gerade bei Selbstbewusstsein sind, ist es auch ganz nett, sie hatte das veröffentlicht, also sie hat glaube ich eine Keynote irgendwo gehalten, wo sie das zum ersten Mal eigentlich so erwähnt hat, Substitution Principle oder die Theorie dahinter und hatte dann eben ein Jahr später glaube ich das Paper geschrieben und erst zehn Jahre später hat sie bemerkt, dass alle immer von so einem LSP sprechen. Und sie ist erst nach zehn Jahren draufgekommen, dass die alle über dieses Liskov Substitution Principle sprechen und sie hat das gar nie eingeführt, diesen Term. Das heißt, nach zehn Jahren war der einfach so weit verbreitet schon und erst da hat sie dann gemerkt, dass Leute ihren Namen verknüpfen mit diesem Principle und dem Principle einen Namen gegeben haben und darüber schreiben und es so ein Standard geworden ist.

Andy Grunwald (00:32:33 - 00:33:04) Teilen

Was dann dazu geführt hat, dass 1993 die ganze Sache erst offiziell formuliert wurde. Und zwar war sie es ja nicht alleine, sondern mit Jeannette Wing. Aber das ist auch faszinierend. Eigentlich wurde dieses Prinzip vor 30 Jahren, vor exakt 30 Jahren, formuliert. vorher wurde es irgendwie angewandt und das habe ich so das gefühl so wie das beschreibt es war so eine art selbstläufer die hat so ein paper veröffentlicht und jeder hat das dann irgendwie angewandt und irgendwann sagte hey was ist das denn hier für eine bewegung lass daraus doch mal was machen.

Wolfi Gassler (00:33:04 - 00:33:20) Teilen

Genau da liegen 20 jahre eigentlich dazwischen ja also es war ja selber scheinbar damals auch gar nicht so bewusst was sie da da angestoßen hat, Und im Nachhinein hat man dann erst gemerkt, was das für Auswirkungen hat. Und heute ist es das L in Solid.

Andy Grunwald (00:33:20 - 00:33:45) Teilen

Kommen wir doch mal zum L in Solid. Also eigentlich, wofür diese Dame jetzt hier gerade so gefeiert wird. Und gehen wir mal da tiefer ein. Gebt mir doch mal den wissenschaftlichen Abriss oder die offizielle Formulierung vom Liskov Substitution Prinzip oder wie es auf deutsch heißt das Liskov Substitution Prinzip oder vielleicht auch ein bisschen einfacher das Ersetzbarkeit Prinzip.

Wolfi Gassler (00:33:45 - 00:36:09) Teilen

Also vielleicht, bevor wir ins Detail gehen, man kann das sehr schön umschreiben. Sie hat eigentlich mit dem Substitution Principle gezeigt, dass Vererbung Kapselung unmöglich macht. Also sie ist kein großer Fan von Vererbung. Vielleicht gleich dazu gesagt, falls das noch nicht klar war. Und es ermöglicht erst Polymorphismus. Das, was wir heute alle kennen unter dem Begriff. Und zwar hat sie das so definiert, das ist jetzt sehr mathematisch, aber ich erkläre es gleich. Also wenn S ein Subtyp von T ist, dann kann man den Typ T einfach durch irgendein Objekt vom Typ S ersetzen, ohne dass irgendwas passiert, ohne dass was schiefläuft, dass alles korrekt bleibt. Also ich bin kein großer Fan von diesen ganzen klassischen objektorientierten Beispielen, aber auf der Audiospur ist es vielleicht auch einfach zu verstehen, wenn wir jetzt einfach zum Beispiel Fahrzeuge nehmen und ein Auto und ein Fahrrad. Autofahrrad sind Subtypen von Fahrzeug und wenn man jetzt einen Code hat, der mit Fahrzeugen arbeitet, dann muss ich da auch jederzeit ein Auto einsetzen können statt dem Fahrzeug und alles soll weiterhin funktionieren. Also die Mutterklasse kann durch eine Subklasse ersetzt werden und alles funktioniert weiterhin. Jetzt würde man vielleicht sagen, ja Moment, warum ist da dann Vererbung ein Problem? Weil das funktioniert ja mit Vererbung eigentlich auch. ist es eben nicht, weil die Vererbung ja so definiert ist, dass wenn du eine Subklasse jetzt zum Beispiel definierst, kannst du ja Methoden überschreiben und Verhalten ändern. Das heißt eine Subklasse, das Auto, könnte jetzt theoretisch die Methode maximale Geschwindigkeit in irgendeiner Form verändern und das Verhalten ändern. Und damit ist das Substitution Principle von Liskov nicht mehr gegeben, weil es eben definiert, dass das Verhalten nicht verändert werden darf in der Subklasse. Und nur so kannst du Polymorphie garantieren, dass das funktioniert, also dass du in der Programmiersprache eben das einfach beliebig ersetzen kannst. Du hast einen Code, der die Funktion aufruft, gib mir die maximale Geschwindigkeit. Dann musst du erwarten können, dass das immer sinnvoll funktioniert, egal ob du ein Auto hast, ein Fahrrad, die Mutterklasse, also ein Objekt der Mutterklasse, es muss immer funktionieren, das heißt, du darfst das Verhalten in der Subklasse nicht ändern und das ist in der Vererbung nicht definiert und darum ist es so wichtig, dass du das Liskowsche, wie heißt das auf Deutsch eigentlich nochmal?

Andy Grunwald (00:36:09 - 00:36:11) Teilen

Das Liskowsche Substitutionsprinzip.

Wolfi Gassler (00:36:12 - 00:36:28) Teilen

Danke. Ich werde jetzt immer dich fragen, damit du das aussprichst, weil ich schaffe das, glaube ich, sowieso nicht. Also das Substitution Principle, ich bleibe mal beim Englischen, garantiert dir eben die Polyphomie und darum ist es in Solid einfach so wichtig, dass man das auch beachtet, weil sonst eben die reine Vererbung garantiert dir das nicht.

Andy Grunwald (00:36:29 - 00:37:24) Teilen

Wobei man natürlich sagen muss, dass die klassische Polymorphie ja heute statisch durch den Compiler gecheckt wird. Das bedeutet, ob jetzt dein Auto von dem Interface oder von der abstrakten Klasse Fahrzeug erbt, ob die Funktions- beziehungsweise Methodensignatur gleich ist. Also ich meine, das, was du gerade beschrieben hast, die klassische Polymorphie, die wird hier schon statisch durch den modernen Compiler gecheckt. Wovor das LSP natürlich steht, ist ja wirklich das, was der Compiler nicht checken kann. Also ich sage das richtige Verhalten, weil das ist ja die Verantwortlichkeit und die Aufgabe des Autors. Nehmen wir jetzt mal dein Fahrzeug-Beispiel und dein Auto-Beispiel, dann dürfte die Funktion bzw. Methode im Gib-mir-mal-die-maximale-Geschwindigkeit jetzt nicht eine Not-Implemented-Exception schmeißen, weil eine Not-Implemented-Exception ist nicht das erwartete Verhalten, sondern das erwartete Verhalten ist, dass ich bei einem Lamborghini 300 zurück kriege.

Wolfi Gassler (00:37:25 - 00:37:35) Teilen

Also es geht ja auch in die Richtung, genau wie du richtig sagst, die ganzen Funktionsköpfe und so weiter, das wird alles gecheckt. Ich glaube sogar, das Non-Implemented wird eigentlich gecheckt.

Andy Grunwald (00:37:35 - 00:37:37) Teilen

Kommt, glaube ich, auf die Programmiersprache drauf an. Genau.

Wolfi Gassler (00:37:37 - 00:38:25) Teilen

Aber was du natürlich nicht checken kannst, ist, wenn wir mal annehmen, du hast im Fahrzeug eine Variable, die heißt Boolean-Variable, kann fahren zum Beispiel, die ist true und gibt immer zurück, ob das Ding fahren kann. gibt True zurück, jetzt könntest du in der Subimplementierung bei Auto theoretisch diesen Zustand überschreiben und damit hast du nicht mehr garantiert, dass Fahrzeuge immer fahren können. Das heißt, du hast einen Zugriff auf den State von deiner Mutterimplementierung. Also dieses klassische Protected, wenn du das mal so sehen willst. Also wenn du Protected hast, dann kannst du natürlich Sachen ändern und damit ist es eigentlich nicht mehr garantiert, dass du das richtige Verhalten garantieren kannst. Und darum ist das so wichtig und darum kannst du das auch nicht statisch checken, weil da brauchst du natürlich die semantischen Informationen dafür, um das überhaupt zu verstehen, was da im Hintergrund passiert.

Andy Grunwald (00:38:25 - 00:40:09) Teilen

Ich habe aber noch zwei wunderschöne Beispiele von unserem ehemaligen Podcast-Gast Stefan Macke aus dem IT-Werufe-Podcast, weil der hat nämlich über das LSP 2019 für Fachinformatiker in der Fachrichtung Anwendungsentwicklung nämlich ebenfalls eine Episode veröffentlicht. Und da finde ich so richtig zwei schöne Beispiele. Jetzt stell dir mal vor, wir sind in der Sprache Java und stell dir mal vor, wir wollen einen neuen Listendatentyp erstellen. In Java gibt es einen Listen-Typ, das ist eine Klasse oder ein Interface, die hat irgendwie so 40 Methoden oder so. Und wir machen jetzt eine Liste, wo man keine Einträge rauslöschen kann. Und wir erben dann von dem klassischen Java-Listen-Interface und sagen jetzt, okay, Die Methode DELETE, die machen wir einfach leer. Ja, also sie hat einfach keinen Code. Jetzt könnte man sagen, ja, aber das geht doch, denn alle 39 anderen Operationen sind ja vorhanden. Ja, das Problem hier ist aber, wenn wir uns Gedanken machen über das richtige Verhalten. Ja, wir haben eine NON-DELETABLE-List oder eine List, wo du keine Items draus löschen kannst. Dennoch ist das Anbieten einer DELETE-Methode natürlich irreführend und nicht das richtige Verhalten. In diesem Beispiel wäre jetzt der Fall, dass wir von der Listeninterface oder von der Listenklasse geerbt haben, die falsche Abstraktion. Da hätte man dann eine andere Abstraktion wählen sollten oder vielleicht seine eigene. Ein anderes Beispiel ist auch sehr schön und jetzt muss ich mich ganz stark konzentrieren, damit ich es richtig hinkriege. Und zwar, stell dir vor, wir haben eine Mutterklasse, geometrische Form. Und stell dir vor, die Subklasse ist Rechteck. Und jetzt wollen wir ein Quadrat implementieren. Und das Quadrat ist eine Unterklasse von Rechteck.

Wolfi Gassler (00:40:10 - 00:40:13) Teilen

So wie man es immer lernt in der klassischen Objektorientierung.

Andy Grunwald (00:40:13 - 00:40:44) Teilen

Ganz genau, weil jedes Quadrat ist ein Rechteck, aber nicht jedes Rechteck ist ein Quadrat. Und in einem Rechteck würdest du etwas erwarten wie, setze die Länge der x-Achse und setze die Länge der y-Achse. Also der Seite A und der Seite B. Und jetzt haben wir die Kindsklasse Quadrat. Und was ist ein Quadrat? Ein Quadrat hat nur eine Seitenlänge, da alle vier Seiten gleich lang sind. Wenn ich jetzt also auf der Quadratklasse SetzeSeiteA aufrufe, dann wird Seite B automatisch mit dem Wert von Seite A überschrieben.

Wolfi Gassler (00:40:44 - 00:40:52) Teilen

Wenn du einen Test hättest, der das prüft, ob XY, wenn du setzt, auch im Nachhinein so ist, dann würden diese Tests fehlschlagen.

Andy Grunwald (00:40:52 - 00:40:59) Teilen

Ganz genau. Und das ist eigentlich meines Erachtens nach ein unglaublich gutes Beispiel für, die Polymorphie ist gegeben.

Wolfi Gassler (00:40:59 - 00:41:01) Teilen

Die Polyphomie ist nicht gegeben, meinst du?

Andy Grunwald (00:41:01 - 00:41:10) Teilen

Naja, also die Vererbung, compiler-technisch funktioniert alles. Das LSP-Prinzip ist jedoch nicht gegeben, weil das Verhalten unerwartet ist.

Wolfi Gassler (00:41:11 - 00:41:40) Teilen

Und sogar fehlschlägt, wenn man einen Test wirklich darauf schreiben würde, würde das wirklich fehlschlagen. Da sieht man wieder mal, was du für ein guter Co-Host bist. Du lässt mich da mit irgendwelchen aus der Luft gegriffenen Beispielen mit Fahrzeugen zuerst herumstottern und du hast schon ausgepackt bei deiner perfekten Vorbereitung. Dank Stefan übrigens. Also bitte übrigens, wer es noch nicht gehört hat, die letzte Episode mit ihm kann man gerne nachhören, auch wenn wir nicht über das LSP reden. Du kommst jetzt mit diesem idealen Beispiel. Vielen Dank Stefan dafür.

Andy Grunwald (00:41:41 - 00:42:10) Teilen

Stefan hat eine starke Empfehlung in seinem Podcast ausgesprochen. Und zwar hat bei der Vererbung ein Quadrat und Rechteck miteinander nichts zu tun. Bitte weglassen. Es mag in der Spieleentwicklung anders sein, wenn man Grafiken macht und allem Drum und Dran. Aber ich mein, Rechteck und Quadrat ist auf der einen Seite ein Beispiel. Man kann aber das Gleiche machen mit einer Ellipse und einem Kreis. Weil ein Kreis ist auch eine Ellipse, halt nur ohne Stauchung. Und eigentlich kann man diese Beispiele halt kontinuierlich durchfeiern.

Wolfi Gassler (00:42:10 - 00:42:31) Teilen

Ich muss auch sagen, wenn ich meine letzten Jahre so Revue passieren lasse, bin ich eigentlich immer weiter weg von der Vererbung gekommen. Und interessanterweise, Barbara war ja auch nie ein großer Fan von Vererbung. Da gibt es, glaube ich, so die zwei großen Lager in der Softwareentwicklung. Und in Go gibt es ja auch keine Vererbung, oder? Wenn ich das richtig im Kopf habe.

Andy Grunwald (00:42:31 - 00:42:46) Teilen

Ja es gibt es gibt eine art von vererbung auf basis von von struts und co aber es gibt jetzt nicht die klassische vererbung wie die objekt orientierung oder ähnliches gibt schon interfaces und allem drum und dran aber, Und ich komme.

Wolfi Gassler (00:42:46 - 00:43:23) Teilen

Eigentlich immer in der Realität ganz selten zu irgendeinem Punkt, wo ich sagen würde, da war jetzt eigentlich Vererbung irgendwie gut oder das könnte man mit Vererbung gut lösen, weil du einfach so viele andere Konstrukte hast, Abstraktionsmodelle, Module oder was es dann auch immer ist, die dann eigentlich fast bevorzuge. Meiner Meinung nach ist das echt selten der Fall oder keine Ahnung, vielleicht bin ich da einfach immer in dem Bereich unterwegs, wo es weniger Anwendungsbereiche gibt, aber da mögen mich jetzt auch alle irgendwie angreifen, aber meiner Meinung nach ist Vererbung in meinem Leben, zumindest in meinem Programmierleben, wesentlich unwichtiger geworden in den letzten Jahren.

Andy Grunwald (00:43:24 - 00:43:52) Teilen

Also ich glaube schon, dass Vererbung seine Daseinsberechtigung hat. Ich denke da immer so an das klassische Java Enterprise, an irgendeine Allianz oder an so eine Ergo-Versicherung und dann so Versicherungsberechnung. Also ich glaube, da stelle ich mir das schon sehr sinnvoll vor, wenn man da wirklich eine gute Softwarearchitektur und Software-Design hat mit wirklich wiederverwendbaren Klassen, die man dann, ich sage mal, man hat jetzt eine neue Art von Versicherung, dann wieder zusammengestöpselt zur Berechnung.

Wolfi Gassler (00:43:52 - 00:44:02) Teilen

Aber da wage ich zu bezweifeln, ob das wirklich überhaupt gemacht wird in der Realität zu Businesslogik. Aber gut, könnt ihr uns gerne schicken. Schaut vorbei bei uns im Discord.

Andy Grunwald (00:44:03 - 00:44:22) Teilen

Ja oder oder halt alle für wo auch Vererbung immer ziemlich viel ist zur Systemanbindung von Message Queue System von Loggern irgendwie sowas da habe ich oft so das Gefühl da wird ziemlich viel mit Vererbung gemacht aber du vielleicht arbeiten wir einfach nicht an den richtig großen Projekten und vielleicht bin ich da auch einfach glücklich drüber.

Wolfi Gassler (00:44:23 - 00:45:52) Teilen

Also, wie gesagt, ich glaube, dass die Abstraktion an sich super stark ist. Und das, was sie eigentlich ja auch so erwähnt hat, diese ganze Spezifikation, dass man alles besser spezifiziert, dass man die APIs hat, saubere Schnittstellen, einen internen State, eine Blackbox, wenn man so will. Da bin ich ja schon eigentlich ein großer Verfechter davon. Und ihr Vortrag, ihr Turing Award Vortrag, hat ja auch den Titel gehabt, The Power of Abstraction. Also es ist ja mehr um die allgemeine Abstraktion gegangen. Es war halt damals in der Softwareentwicklung eben diese Datentypen und so weiter, aber auch Iteratoren im Prinzip sind ja auch eine gewisse Abstraktion. Und ich habe mir da auch gedacht, wie ich den Vortrag angesehen habe, wie wichtig eigentlich Abstraktion mittlerweile ist. Und du kannst es ja in alle Ebenen weiterspielen, also auf die Team-Ebene. Wie hast du Abstraktionsmöglichkeiten auf der Team-Ebene mit Conway's Law, for example, sage ich schon, zum Beispiel, wo man auch da Abstraktionsebenen einführt. Also du hast die Abstraktionsebenen eigentlich überall bis bis auf die menschliche Ebene ganz nach oben, auf die Firmenstruktur, die du anwendest. Und wenn du es da schaffst, eben durch diese Abstraktionen Abhängigkeiten zu reduzieren und das Ganze modularer zu machen, egal auf welcher Ebene, dann ist es meiner Meinung nach ein guter Ansatz und der einzig wahre Ansatz, wie du sinnvoll skalieren kannst, egal ob auf Architekturebene, auf Firmenebene, auf Teamebene, was es auch immer ist. Diese Abstraktion geht wirklich sehr, sehr weit. Und alles, was man auf abstrakte Datentypen anwenden kann, finde ich, kann man dann auch auf Teamstrukturen und Firmenstrukturen anwenden.

Andy Grunwald (00:45:52 - 00:46:44) Teilen

Jetzt werden wir ein bisschen philosophisch dennen. Ich habe in der Vorbereitung auch mal, ganz doof, The Power of Abstraction bei Google eingegeben. Und da habe ich ein unglaublich schönes Beispiel gefunden. Sprache ist ja, könnte man eigentlich so sagen, die höchste Form von Abstraktion. Nimm dir einfach nur mal das Beispiel, das Wort Liebe. Wie viel das unten drunter eigentlich ausmacht und wie viel das eigentlich weg abstrahiert. Wenn ich aber das Wort Liebe in den Mund nehme, dann weißt du, du grinst auch schon so ein bisschen, dann weißt du auch, was gemeint ist. Und darunter ist das ja wahrscheinlich eine achterbahn von gefühle und so weiter und so fort ja ich merke schon wir werden philosophisch aber wenn du mal zwei minuten drüber nachdenkst, mein kopf platzt power of attraction und wir reden jetzt hier gerade nur über irgendwelche fahrzeug und geometrie und rechteck und ellipsen klassen.

Wolfi Gassler (00:46:44 - 00:46:50) Teilen

Also ich sehe schon den andy in irgendeiner tonne so auf social media wie er sagt geh mir aus der sonne wolfgang oder so.

Andy Grunwald (00:46:50 - 00:48:04) Teilen

Jedes Mal, wenn ich mir über eine Turing Award Gewinnerin oder Gewinner mal so ein bisschen recherchiere, platzt mir einfach der Kopf. Denn man scrollt so durch die Wikipedia-Seite und dann sieht man, aha, die Person hat jetzt irgendwie den Turing Award für das und das, für ihre maßgebliche Contribution zu Betriebssystemdesign und Programmiersprachen gekriegt. Und dann geht man mal rein und dann merkt man, Multiple Assignments und Multiple Function Returns gehen auf sie zurück. Und auf einmal ... Und ich hab mir auch noch nie die Frage gestellt, wer hat dieses kleine Ding in Lua, Perl oder auch in Go, gibt's ja auch Multiple Assignments und Multiple Returns, wer hat das eigentlich erfunden? Und faszinierend. Also, ich find's immer wirklich, wirklich faszinierend. Und ich stell mir grad so ein bisschen vor, wie groß muss der Schmerz damals 1965, 1970, 1975 eigentlich gewesen sein. Und wie viel Code musst du eigentlich schreiben oder musstest du eigentlich schreiben, um irgendwas Sinnvolles hinzukriegen? Ich glaub, jeder von uns kennt dieses Foto von Grace Hopper, wo sie neben diesem Riesenberg an Papier steht. War das Grace Hopper? Ich glaub, das war Grace Hopper, richtig?

Wolfi Gassler (00:48:04 - 00:48:08) Teilen

Kann gut sein. Oder es sind wahrscheinlich eher Lochkarten gewesen damals, aber was auch immer.

Andy Grunwald (00:48:09 - 00:48:29) Teilen

Es war nicht Grace Hopper, es war Margaret Hamilton. Auf jeden Fall, das Foto verlinken wir euch natürlich auch in den Show Notes. Ich weiß nicht, jedes Mal wenn ich drüber nachdenke, denke ich mir, wie privilegiert sind wir heute eigentlich, dass wir dann unter anderem zum Beispiel mit, weiß ich nicht, Bootcamps innerhalb von drei Monaten Coden lernen können. Also dieser Kontrast, der ist einfach, ich krieg den nicht in meinen Kopf.

Wolfi Gassler (00:48:30 - 00:48:54) Teilen

Ja, ist auch ganz nett. Sie hat da so eine Anekdote erzählt, wie sie den Turing Award bekommen hat. 2008 haben so Leute gesagt irgendwie, warum hat sie denn dafür einen Turing Award bekommen? Das weiß doch jeder. Und sie hat dann nur gemeint, ja, heutzutage weiß das jeder, aber damals gab es das einfach nur nicht und sie ist nur froh, dass es jetzt wirklich jeder weiß und die Welt einfach besser geworden ist und einfach mehr Abstraktion mittlerweile in der Software verwendet wird.

Andy Grunwald (00:48:54 - 00:49:04) Teilen

Da finde ich aber auch immer ein bisschen schwierig die Aussage, das weiß doch jeder, denn wie wir auch schon in dieser Episode festgestellt haben, globale Variablen sind immer noch im Umlauf und ja, sie werden heutzutage auch immer noch neu hinzugefügt.

Wolfi Gassler (00:49:05 - 00:50:08) Teilen

Das hat sie auch gemeint, ich glaube sogar genau in dem gleichen Satz, wo sie gemeint hat, aber globale Variablen, die gibt es leider immer noch. Also so schlau sind wir noch nicht geworden. Und auch ganz interessant, sie hatte am Ende irgendwie so eine Frage bekommen, wo sie denn die Zukunft zieht oder so irgendwas in die Richtung. Und sie hat auch gemeint, ja, ganz interessant, also wir reden von 2008, das heißt vor 15 Jahren, hat sie gemeint, ja, es wird spannend, wie das mit der Parallelität eigentlich aussieht, weil mittlerweile macht man alles parallel und programmiert auf parallelen CPUs. Aber es gibt eigentlich noch keine Programmiersprache, die das irgendwie mit rein nimmt, dass das parallel ausgeführt wird. Es sind immer nur Programme, die einzeln parallel dann in irgendeiner Form ausgeführt werden. Und es gibt da eigentlich noch nicht so richtig, was das mit inkludiert, während man programmiert, also im Design der Programmiersprache, diese Parallelität. Sie hat gemeint, MapReduce steht so am Schirm, vielleicht entwickelt sich das in diese Richtung oder vielleicht wird es die große Neuerung werden. Aber wenn ich es mir so überlege, 15 Jahre später hat sich noch nichts geändert und MapReduce ist fast wieder in Vergessenheit geraten.

Andy Grunwald (00:50:09 - 00:51:00) Teilen

Ich find's aber sehr, sehr spannend, denn 2008 war die Dame 67 Jahre alt. Ich find's sehr, sehr spannend, dass sie eine solche Äußerung macht. Ich glaube zwar nicht ... Also, spannend in dem Hinsicht beachtlich. Beachtlich, dass sie mit 67 immer noch für 2008 so top-notch unterwegs ist. Und auch noch so tief, ich sag mal, in der Forschung von Programmiersprachen, in der Entwicklung von Programmiersprachen. Ich mein, die Dame wurde 1939 geboren. Und vielleicht kann man schon sagen, Die Dame hat wirklich ihr ganzes Leben auf dieses Spektrum ausgerichtet. Also, wenn du das jetzt gerade hörst und schon immer Spaß hattest oder immer deine eigene Programmiersprache entwickeln wolltest, dann mach doch mal der lieben Barbara nach. Nenn sie vielleicht nicht Clou, sondern nenn sie anders und fokussier dich aufs parallele Programmieren.

Wolfi Gassler (00:51:01 - 00:51:40) Teilen

Ja, ist meines Wissens immer noch ein ungelöstes Problem. Oder ob es ein Problem ist, keine Ahnung. Aber es wäre auf jeden Fall, würde wahrscheinlich einiges vereinfachen, ja, in der Parallelität. Oder falls wir irgendwas übersehen haben, bitte schaut vorbei bei uns im Discord und erklärt uns, was wir vergessen haben. Wir akzeptieren auch immer noch E-Mails. Wir bekommen fast keine E-Mails mehr. Ist ganz cool, dass alle auf Discord diskutieren, aber wenn jemand E-Mail bevorzugt, geht natürlich auch immer noch. Wir freuen uns über jedes Feedback stetig at engineeringkiosk.de. Und wenn ihr uns ganz einfach Feedback senden wollt, geht mal in die Shownotes nach unten, da gibt es so zwei Daumen nach oben oder nach unten, um uns einfach mal ein super schnelles Feedback zu geben. Gerne da mal auch draufklicken.

Andy Grunwald (00:51:41 - 00:51:54) Teilen

Das war eine weitere Episode von Wolfgangs Geschichtskurs über Turing-Award-Gewinner. Ich hoffe, ihr habt so viel gelernt wie ich, denn mir platzt immer noch der Kopf. Und wenn ihr noch mehr von diesem Format hören wollt, lasst es uns wissen.

Wolfi Gassler (00:51:54 - 00:52:03) Teilen

Und denkt mal in Zukunft drüber nach, ob ihr nicht noch irgendwo vielleicht was sinnvoll abstrahieren könnt und ihr euch das Leben selber einfacher macht durch Abstraktion.

Andy Grunwald (00:52:03 - 00:52:06) Teilen

Das gute alte Solid-Prinzip. Nun gut.

Wolfi Gassler (00:52:07 - 00:52:27) Teilen

Eines muss ich noch loswerden, Andi. Ganz, ganz wichtig. Wenn euch solche Episoden gefallen, natürlich uns sagen, aber bitte auch anderen Leuten sagen. Wenn ihr irgendwen habt in der Firma, in eurem Umfeld, andere EntwicklerInnen, Techies, was auch immer, bitte einfach weitersagen. Schickt mal die Episode rum. Wir würden uns wirklich freuen.

Andy Grunwald (00:52:27 - 00:52:32) Teilen

Das war der Werbeblog von Wolfgang. Ich sag einfach Tschüss. Bis nächste Woche.

Wolfi Gassler (00:52:32 - 00:52:32) Teilen

Ciao.

Andy Grunwald (00:52:34 - 00:52:40) Teilen

Und nicht vergessen, Schulungen im Bereich der Webentwicklung gibt es bei unserem Episodensponsor workshops.de. Link in den Shownotes.