 Willkommen zum ersten Tag dieses Tages. In der deutschen Übersetzung von Florian und viel Spaß. Sie ist in der deutschen Übersetzung von Florian und viel Spaß. Guten Morgen alle. Ja, Seelenzermahlen der Code. Ja, bevor wir darüber sagen, auch wiedersehen, sollten wir darüber nachdenken, was es tatsächlich ist. Und vielleicht können wir die Präsentation auch kriegen. Da ist sie. Also als erstes sollten wir darüber reden, was Seelenzermahlen der Code ist. Und wir haben ein paar Dinge für eure Unterhaltung mitgebracht. Und hier sind wir. Das ist etwas Code, das ich in einem Eclipse-Tutorial gefunden habe. Also wenn ihr Eclipse habt, könnt ihr an dieses Ding gucken. Ich habe keine Idee, was das hier macht, was eine Adapter-Factory ist. Dann kriegt man eine Adapter und dann passiert da Zeug. Und was macht das eigentlich? Okay, das gibt To-Do-Adapter. Das könnte ein Hinweis sein, dass es das berühmte To-Do-Example ist. Aber das hier ist natürlich nur Eclipse. In Eclipse ist alles ein Adapter. Ja, vielleicht ist es das. Ich hatte erwartet, dass du so etwas sagst. Also ich bringe ein anderes Beispiel. Das hier ist aus einem Open-Source-Projekt. Und das hier ist ein Native Query Interpreter. Also ein native Abfrage-Interpreter-Initiator. Ja, und ich frage mich, was ist das beeindruckend? Und dann ist der Hafenhafen Zeug. Und dann gibt es da unten ein Initiate-Service. Und dann haben wir ein anderes Initiate-Service. Und dann ganz am Ende haben wir, wow, Get-Service-Initiated. Okay, ja. Aber das ist nur ein Haufen Kids, die Open-Source-Software machen. Was erwartest du von so was? Ich habe ein professionelles Beispiel mitgebracht. So, hier ist ein professionelles Beispiel. Das ist ja ein Beispiel, das macht, ja, Übersetzung. Und das macht entweder Full-Text-Suche oder nicht-Full-Text-Suche. Und so bei der Initialisierung von irgendwelchen IC++-Klasse, checkt ein paar Flex und initialisiert dann ein Objekt entweder zu der Full-Text-Variante oder zu der nicht-Full-Text-Variante. Also das ist klares Design, es gibt eine Instanz-Variable. Und das ist nur der Konstruktor. Das ist nicht der schlechte Teil. Das Fiese ist, dass jede, jede Methode, was es tut, die checkt das Flag nochmal und ruft dann entweder diese Full-Text-Recherche auf oder wenn das nicht ist, dann nicht. Und da sind auch Auskommentierte zahlen und es gibt auch kein Kommentar, warum das jetzt auskommentiert ist. Und wenn man diesen Code warten will, dann muss man immer sich erinnern, man muss immer dieses Flag checken, bevor man irgendetwas mit dem Code macht. Okay, ja. Die Tatsache, dass jemand eine objektorientierte Programmiersprache benutzt, heißt nicht unbedingt, dass er weiß, wo Objektorientierung wirklich für ist. Vielleicht sind es einfach auch nur schlechte Programmierer. Ja, die haben das benutzt und dann haben sie es halt irgendwie kaputt gemacht. Und jetzt hast du mich mit der Frage verwirrt. Ich glaube, du hast ein anderes Beispiel. Ich habe ein viel besseres Beispiel. Ein wirkliches objektorientiertes Beispiel. Dies hier ist ja aus der Finanzwelt. Hier haben wir Optionen, in diesem Fall nur Calloptionen. Und die Finanzleute möchten über diese Optionen reden. Und es gibt so viele verschiedene Arten von Optionen, deshalb können sie nicht über jede Einzelne reden. Und deshalb wollen sie sie zusammentun in mehreren, etwas, das sie einen Basket nennen. Und hier können wir diesen Basket sehen. Und das enthält Google und Facebook. Und die gruppieren sie einfach in diesen Basket zusammen. Und dann möchten sie über diesen Eigenschaften von diesem Basket reden. Und all die Optionen, die in diesem Basket enthalten sind. Hier zum Beispiel implementieren sie diese Market-Data-Klasse. Das ist ganz klassisches objektorientierte Sachen. Einfach alles ist eine Klasse. Und es gibt zwei Methoden. Das ist auch Standard-Objektorientierte Programmierung. Wir haben eine Klasse und wir haben Methoden da drin. Und die erste Methode Gatspot, die gibt uns den Marktpreis der Option. Also alle diese Optionen haben eine Nummer in der wirklichen Welt. Deshalb haben wir diese Sikovam hier. Eine lustige Name, keine Ahnung, warum das so heißt. Kann irgendein französischer Name sein. Ich weiß nicht, was das bedeutet. Und dieses Maturity-Date, das ist das Datum, an dem die Option ausläuft. Genau, wir wollen die Volatilität für die Option haben. Also eine Option ist definiert durch das zugrunde liegende Asset. Und so das Datum, an dem sie fällig ist. Und dem Preis, den sie an dem Zeitpunkt haben soll. Und das ist das, was hier kodiert ist. Also wir haben diese Option mit dem Long. Dann haben wir die Maturity. Das ist ein Punkt in der Zeit, das ist klar, mit einem Double dafür. Und dann haben wir den Strike. Das ist ein Preis. Und ein paar von euch wissen vermutlich, dass es keine besonders gute Idee ist, Geld als Double zu modellieren. Aber es ist relativ üblich im Finanzbereich. Ja, das ist es. Ja, und dann, was sie tatsächlich haben wollen, sie wollen nicht nur auf die Welt gucken, wie sie jetzt ist. Also diese Typen mit den Dosen-Trägern. Sie wollen analysieren und sehen, was passieren könnte, wenn irgendwas passieren könnte. Also möchten, was wäre, wenn Spiele spielen. Deshalb nehmen sie hier den Marktpreis. Und was sie eigentlich möchten, ist den Verschieben. Was wäre, wenn der Spottpreis so wäre, was würde dann passieren? Und hier, wenn man etwas modifizieren will, in der Objekt orientieren, dann macht man eine abgeleitete Klasse. Das ist hier die abgeleitete Klasse, Spotshifted Market Data. Und diese Klasse schreibt die Methode GetSpot, um den Marktpreis zu kriegen. Und sie nimmt die Methode der Elternklasse und multipliziert es mit einem Faktor. Ja, okay, ganz straightforward. Und dann wollen sie das natürlich nicht nur mit einem Faktor multiplizieren, sondern wollen auch andere Modifizierungen machen. Und sie möchten in der Lage sein, alle diese Modifizierungen zu machen, ohne alles neu kompilieren zu müssen. Sie möchten nicht alles neu kompilieren müssen, wenn sie irgendetwas ändern wollen. Sie möchten etwas dynamisch konfigurierbar haben. Also dynamisch konfigurierbare Market Data haben. Und wenn man hier in die Objektorientierungsliteratur guckt, dann kommt man zu dem Dekorator-Pattern. Das Dekorator-Pattern erlaubt es, an etwas dynamisch zur Laufzeit zu verändern. Also man hat eine Komponente, man leitet davon ein Dekorator ab und der hat einen Delegator zu irgendetwas anderen. Das ist es, wie sie den Delegator implementieren. Sie haben den Decorator als eine abgeleitete Klasse. Dann haben sie das wirkliche Objekt, das darin gehalten wird, um die GetSpot-Method aufrufen zu können. Und um den Marktpreis zu kriegen, rufen sie einfach die GetSpot-Method auf von dem zugrunde liegenden Asset. Um jetzt zu dem Basket zurückzukehren, an dem wir angefangen haben. Wenn Sie jetzt diese eine abgeleitete Modifizierung haben, dann modifizieren Sie mit dem Faktor. In dem Basket haben Sie eine Menge von Objekten, also von Assets. Und jetzt wollen Sie diesen abgeleiteten Marktpreis von allen davon berechnen. Und Sie machen das Rekursiv und es ist relativ schwer zu sehen, was hier eigentlich passiert. Sie gehen halt rekursiv durch alle diese Objekte durch und machen es ... Rekursiv gehen dadurch und durch Latebinding passiert es, dass Sie immer wieder diese abgeleitete Methode da oben gehen und Adi an diesen Faktor immer wieder berechnet. Und natürlich haben Sie es nicht rausgefunden, indem Sie auf den Code guckten, weil das ziemlich hart zu und verstehen ist. Es ist natürlich nur kleine Snippets, aber es ist Teil eines größeren Programms. Und Sie haben es nicht gefunden durch den Blick auf den Code, sondern weil die Ergebnisse, die daraus gekommen sind, falsch waren durch die wiederholte Anwendung des Faktors. Zum Beispiel hier ist der interessanteste Teil, den ich kenne. Die ersten Marktdata, die von dem zweiten abgeleitet sind. So, hier checken Sie, ob Sie in dieser Kette sind. Und wenn Sie in dieser Kette sind, dann machen Sie was anderes. Ja, das hier ist jetzt Produktionscode. Und das wird tatsächlich noch benutzt und wahrscheinlich ist diese Methode inzwischen schon hunderte von Zeilen lang, weil Sie so viele Grenzfälle hatten, die Sie irgendwo berücksichtigen mussten. Ja, ich kann vorstellen, dass Sie hätten das richtig machen sollen in C++, in Objektorientierung benutzen. Ja, absolut. Wir hätten es nicht. Aber Leute hätten stattdessen funktionelle Programmierung benutzen sollen. Ja, wir haben wir davon. Funktional Programmierung hat alle diese Vorteile. Man hat unveränderbare Daten. Man hat weniger Kopplung zwischen weniger Effekte, die über Entfernung gehen. Funktional Programmierung ist sehr dicht an der Mathematik. Also man kann viele mathematische Dinge gehen, wie formale Dinge benutzen, formale Warn. Wir haben Katamorfissen. Wir haben Bifunktoren. Wir haben Monaden. Wir haben monadische Profunktoren. Und all diese. Und wir haben Kleißlayeros. All diese wunderbaren Dinge, die lösen alle diese Sachen. Ja, wer lacht? Ich hätte mir erwarten sollen, dass du so etwas sagen würdest. Hast du jemals überlegt, dass du das Problem aus der falschen Richtung angehst? Du und deine ... deine Horde von IT-Nerds. Ihr sitzt in euren Höhlen und habt die Hoodies über den Kopf und sitzt da und hackt und hackt und hackt. So, das Problem haben wir gelöst. Ich meine, wirklich, ihr werft Technologie auf das Problem. Das ist nicht die Lösung. Das ist Teil des Problems. Okay, ja, wir benutzen Technik. Bist du durch die Hallen gegangen? Ist überall Technik. Wie löst man das? Nun, vermutlich nicht neben meine Ecke setzt. Und einfach. Hast du schon mal daran gedacht, dass es vielleicht mehr dazu gehört, als nur Technologie, dass man vielleicht auch miteinander reden muss? Gestern habe ich diesen Roboter hier gesehen, der hier rumgelaufen ist, nur im Kreis. Und hat gesagt, ich brauche einen neuen Coach. Sprich mit mir. Und das ist sowas Ähnliches hier. Wenn wir miteinander sprechen, ist nicht nur Technologie. Technologie ist schön und alles andere. Das heißt, hast du eine Anleitung dafür? Eine Musteranleitung? Ja, es gibt Sprachmuster extra für dich. Ja, für Leute wie dich. Ja, fangen wir an. Du zeigst mir. Es gibt ganz viele Ansätze, die wir im Laufe der Jahre benutzt haben. Es gibt viele, die von, sind zum Beispiel, agile Software-Entwicklung. Und das bedeutet hier, Einzelpersonen und Interaktionen sind besser als Prozesse und Werkzeuge, Technologie. Also, lassen Sie darüber sprechen und Sachen zusammen rausfinden. Aber es steht auch, Software, die funktioniert. Ja, das ist nur eine von vier. Software, die funktioniert. Aber ich meine, natürlich nur reden und nicht programmieren, ist natürlich auch nicht die Antwort. Also, na gut, während wir hier in der Konferenz sind, so, ich habe die Keynote-Speech gehört und nicht nur mit Leuten gesprochen, und zwar von jemandem, der darüber gesprochen hat, was funktioniert und was nicht funktioniert in Software Engineering. Und das war eine agile Firma, die alles agile gemacht hat. Das heißt, die reden die ganze Zeit angeblich. Sie gucken, was sie alles machen, wo sie ihre Arbeit lassen. Dann das meiste ist, 53 Prozent ist immer noch Wartung und Komplexität. Und ich weiß nicht, was diese Professionalisierung sein soll, aber es hört sich gut an. Also, zurück zum technischen Problem. Ja, wir haben das schon gesehen, an dem Marktbeispiel. Und ich glaube, viel von dem hier Wartung und Komplexität von den Problemen ist verursacht, dadurch, dass wir in einer Welt leben, die aus Objekten besteht. Und deswegen springt jeder auf den Zug auf für der objektorientierten Programmierung. Und was wir dann kriegen, ist sowas wie das hier. Okay. Und das ist so eine Art, das ist einfach nicht hilfreich. Also, ich möchte das vielleicht mal anders zeigen. Moderne objektorientierte Programmierung. Ja, man kann da drüber lachen, aber man muss das technische Problem verstehen. Und das Problem ist dies hier. Und im Herz von objektorientierter Programmierung ist imperative Programmierung. Das heißt, alle die Objekte, die du uns gezeigt hast, die sind alle, haben einen encapsulated state. Und was passiert ist, die Welt verändert sich und die Objekte sind Nachrichten zu anderen Objekten. Und in dieser Nachricht wird Code ausgeführt, der den Zustand, den eingekapselten Zustand verändert. Und das Ding ist, objektorientierte Programmierung war ursprünglich eingeführt, um Simulationen der echten Welt zu programmieren. Und die echte Welt funktioniert einfach nicht so. Die echte Welt ist nicht einfach nur Objekte, die sich Nachrichten schicken. Ein Beispiel ist zum Beispiel der Elefant. Also wie der Elefant. Und der Elefant kommt aus dem Dschungel und läuft in ein Zimmer. Und das Modell dafür ist, alle Sachen werden Objekte. Und der Elefant hat ein Objekt, der Dschungel hat ein Objekt, und der Raum hat ein Objekt. Und man hat eine Sequenz von Methoden aufrufen. Und die versuchen, das zu reproduzieren, diese Sequenz von Ereignissen. Der Elefant geht aus dem Dschungel raus und der Elefant kommt ins Zimmer. Und das Problem ist, dass aus dem Dschungel rausgehen und ins Zimmer reingehen sind, dasselbe. Das heißt, die echte Welt hat Abhängigkeiten. Und es sind nicht nur einzelne Einheiten, die sich Nachrichten senden, sondern Sachen hängen einfach zusammen in der echten Welt. Ein besseres Modell ist vielleicht ein nützlicheres Modell. Wie Programmiere die echte Welt abbilden sollten, hat vielleicht eher damit zu tun. Wir sollten einfach sehen und verstehen, wie Dinge funktionieren. Wenn man ein Fußballspiel anguckt, dann gibt es ganz viele Objekte hier. Das heißt, man sieht 22 Spieler, einen Ball, die Schiedsrichter, man sieht ganz viele Zuschauer und die bewegen sich alle. Und alle ändern ihren internen Zustand in diesem unserem Modell. Wenn man wissen will, was auf dem Fußballfeld passiert, muss man alle diese Zustände beobachten. Aber man weiß sowas, was das objektorientierte Modell ist dafür. Das ist das Observer-Pattern. Das heißt, man bemerkt, welche Objekte sich ändern. Und dann, wenn sich etwas ändert, dann sendest du mir eine Nachricht. Wenn sich der Ball bewegt, sendest du eine Nachricht. Und mit allen 20.000 Zuschauern machst du das selbe. Und wenn man das Stadion verlässt, dann sendet man eine Nachricht. Es interessiert mich jetzt nicht mehr, aber die Welt funktioniert nicht wirklich so. Es gibt noch ein anderes Problem. Alle diese Nachrichten werden in einer Reihenfolge ankommen. Und das bedeutet also, dass alle diese Objekte, die sich bewegen, wir werden in Konsistenzen sehen, die ganze Zeit. Und so, wie was bei den Elefanten gesehen haben, der ins Zimmer kommt, es gibt ein inkonsistenter Zustand hier. Nämlich, dass der, nach dem ersten Stand, ist der Elefant nirgendwo. Denn er ist aus dem Dschungel raus, aber er ist noch nicht im Zimmer. Und dasselbe ist hier für das, wenn man hier ganz viele bewegte Objekte haben. Aber wir haben nie, beobachten nie einen Zustand, dass jemand geht und plötzlich woanders ist, oder zwei Leute zur selben Zeit am selben Ort sind. Denn das sind, und wir brauchen eigentlich hier konsistente Snapshots und im Speich. Und dann können wir darüber nachdenken und analysieren, was hier vor sich geht. Und wir erinnern uns natürlich an Sachen, die in der Vergangenheit waren. Und das kann das Objektorientierte Modell auch nicht abbilden. Und es gibt hier fundamentale Probleme mit dem Objektorientierten Modell, Programmiermodell. Und das ist eine der fundamentalen Dinge, und das erinnert mich an eine ganz interessante Sache, die viele Leute benutzen. Und das ist MVC, das MVC-Modell oder Model-View-Controller-Modell. Und wenn ihr damit schon mal gearbeitet habt, dann könnt ihr sehen, dass das alles hier immer im Kreis rumgeht. Und man kann in beliebige Richtungen gehen. Und man ist wieder hier, oder dann ist man da, oder man geht so rum, oder so rum. Oder man geht an dieser gestrichelten Linie lang. Und man kann von überall nach überall kommen. Und das führt zu dem offensichtlichen Problem, dass wenn man ein Problem hat und Änderungen im Modell oder Änderungen in der Ansicht, dann sollten die hoffentlich zusammengehören und korrespondieren, aber vielleicht auch nicht. Und was macht man dann? Und am Ende, wenn man genug da im Kreis rumgeht und wenn man nicht ganz vorsichtig ist, dann hat man am Ende dieses Spaghetti-Monster. Und ja, Programme haben natürlich, objektorientierte Programme haben immer so ausgesehen. Das sieht aus wie die Wirklichkeit. Und ich glaube, das ist auch das, was Ellen Kay gemeint hat, wenn er gesagt hat damals, das ist ein Zitat von 1996. Aber ich glaube, das Paper ist rausgekommen zu der Zeit, aber das Original-Zitat ist schon viel älter. Und er hat gesagt, ja, OOP hatte viele Motivationen, die hier beschrieben wurden, aber wir müssen eigentlich dieses Modell überwinden und etwas Besseres finden. Und das ist nicht wirklich passiert. Nein, ich glaube nicht. Und wenn man heute guckt, wie objektorientierte Programmierung funktioniert, das ist immer über eingekapselte Zustände und die wir dann loswerden wollen. Das ist das Erste, was ich, wenn ich das erst gesucht habe nach objektorientierter Programmierung für Schüler, für Studenten, dann ist das das Erste, was man findet. Man hat hier den Studenten und man kann einen Greatpoint-Average setzen. Und wenn man nicht zufrieden ist mit den Zensuren, die man kriegt, dann schickt man einfach eine Nachricht und dann hat man einen perfekten Notendurchschnitt. Und ich will das noch mal wiederholen und natürlich sollten Leute funktionale Programmierung benutzen. Einfacher Sprachen, weniger Komplexität, höre Produktivität, weniger Fehler. Wir können Eigenschaften, basiertes Testen machen und wir haben Setup- und Teardown-Methoden. Wir haben weniger Koppelungen, weniger Abhängigkeiten. Wir haben gar nicht Monaten erwähnt in dieser Liste. Und Leute sollten funktionale Programmierung benutzen, um die Probleme zu lösen. Er erinnert sich an Fred Brooks. Und er hat gesagt, es gibt keine Wunderwaffe. Okay. Fred Brooks, das ist ein alter Kerl, oder? Was ist mit dir? Ja, bin ich wahrscheinlich auch. Ja. Fred Brooks hat das gesagt, er ist ein alter Kerl. Lass mir ein Beispiel zeigen, warum das nicht wahr ist. In den Anfang der 90er war eine große Studie von der US Navy über die Effizienz von verschiedenen Programmiersprachen. Es gab ein Problem, wo man die Einflussregion von bestimmten Kriegsschiffen bestimmen sollte und verschiedene Teams sollten Lösungen in verschiedenen Programmiersprachen schreiben. Und sie haben das auch an ein paar Leuten gegeben, die in funktionalen Sprachen arbeiten. Hier ist es Haskell als ein Beispiel. Und ihr könnt sehen hier, ja, Haskell, ja, die Lösung ist extrem viel kürzer als die Lösung in C++. Ja, mehr als 10 mal kürzer. Java war damals noch nicht so verbreitet. Der Faktor wäre auch irgendwo zwischen drei und zehn. Und was auch interessant ist, das waren zwei Haskell-Lösungen. Einer am Anfang, ganz oben, und eine am Ende. Am Ende haben Sie nur den Kod geteilt, damit die Zahlen und Blätzer aussehen. Nein. Nein, was Sie tatsächlich gemacht haben, Sie hatten einen Haskell-Experten und Sie haben auch das Aufgabe an Studenten gegeben, die Haskell zwei oder drei Wochen benutzt hatten. Und wenn Ihr dann die Entwicklungszeit, es ist zehn Stunden und acht Stunden und die Gruppe, die acht Stunden gebraucht hat, das waren die Studenten. Und der Experte hat natürlich versucht, ein paar schöne Haskell-Sachen da einzubauen. Und so. Und wenn das es nicht ist, was eine Wunderwaffe ist, dann weiß ich nicht, was es ist. Okay, so die Yale-Studie, die hatten eine beschränkte Menge von Instruktionen und Sie mussten nur diese Instruktionen umsetzen. Erinner ich das richtig? Ja. Hast du das jemals in der realen Welt erlebt, dass du eine feste Menge von Anforderungen von deinen Kunden gekriegt hast und dann nur die einfach implementieren musstest und sie haben nie ihre Meinung geändert, haben nie mit neuen Ideen, neuen Anforderungen, haben nie gesagt, oh, Moment, ich habe etwas vergessen. Ich erlebe das nicht. Lass mich ein Moment darüber nachdenken. Vielleicht kannst du, das ist, woran wir nachdenken, um den Elefanten zurückkommen. Wir müssen miteinander reden. Jeder hat andere Ideen. Jeder hat andere Ideen, wenn sie auf etwas gucken und jeder beschreibt Dinge anders. Und was wir machen müssen, wir müssen dieses zusammen herausfinden. Wir müssen ein bisschen kurdieren, ein bisschen reden, ein bisschen programmieren, ein bisschen reden. Das ist agile Entwicklung. Ja, es bedeutet nicht Grum wenn wir jeden Tag in einem Kreis rumstehen. Also, okay. Ich mag gerne mit Code kommunizieren. Lass einen, hier ist ein Beispiel von Code, den wir gemacht haben. Das war eine Halblätterfabrik, also ernsthaftes Business. Also, Pierre, ihr wisst es also. Als wir das sagten, okay, als Halblätter gemacht war, du schickst den Waefer rein, ziehst einen Hebel und checkt und kommt raus, kommt ein Mikroprozessor. Das aber funktioniert nicht wirklich so. Eine der Gründe dazu ist einfach ein moderner Trip aus vielen, vielen Lagen bestimmt. Und es gibt viele, viele Arbeitsschritte, die nötig sind, um auch nur einen einzigen Lehrer zu machen. Und da gibt es auch viele Dinge, die gehen kaputt in so einer Halblätterfabrik. Also, es macht keinen, nicht wirklichen Sinn, einfach eine Fließbahn zu haben. Und dann drückt man ein Knopf und dann läuft alles dadurch durch die verschiedenen Maschinen und kommt raus. Also, was der Punkt ist, jeder Trip, jeder oder je Waefer, den man macht, und durchläuft in der Fabrik eine Reihe von Schritten. Und das muss in der Fabrik verwaltet werden. Also, ungefähr 1.000 Schritte. Also, man braucht etwas, das eine Route genannt wird. Hier ist ein bisschen Haskell Code. Haskell ist großartig, weil der Code so kurz ist, dass er auf eine Folie passt. Und wenn das nicht klar ist, dann unterbrücht mich und fragt. Also, erst mal liest man die Deklaration am Anfang, das heißt Data-Operation. Das ist ein vereinfachter Datentyp, was eine Operation sein kann. Und an diesem senkrechten Sprich als Oder-Richt lesen. Also, eine Operation ist either ein Track in oder ein, der Teil einem Waefer in die Maschine tun. Dann Prozess ist etwas, was in der Maschine passiert. Und Track out ist, dass man den Waefer wieder aus der Maschine rausnimmt. Und das nächste ist dann eine Route. Das ist einfach nur eine Liste von Operationen. Also, diese eckigen Klammern heißt Liste von. Also, was eine Route ist, ist eine Liste von Operationen. Also, hier unten habt ihr eine einfache Route. Das heißt, eine Route ist eine Liste von folgenden Aktionen. Man packt die Maschine rein, noch ein Prozess, und man nimmt den Waefer wieder raus. Ja, das ist verständlich. Wir alle wach und nickeln. Okay. Ah, es gibt keine Angst zu Haarfragen. Eine Sache, die du machst, wenn du einen Datentypen hast, dann definiert man Funktionen auf diesen Datentypen, die beschreiben, was auf bestimmten Aspekt davon beschreiben, was mit den Sachen passiert. Zum Beispiel in der Route, was man machen muss, man muss den nächsten Schritt ausführen. Und dafür machen wir eine Funktion Route hat. Und was man macht, man schreibt eine Typ-Signature. Typ-Signature sind, man schreibt hier einfach, man nimmt eine Route, und man kriegt eine Operation heraus. Und die beschreibt, was diese Funktion macht auf dieser Klasse von Input. Wir erinnern sich da, eine Route ist eine Liste von Operationen. Es gibt zwei verschiedene Arten von Listen. Eine Arte von Listen ist die leere Liste. Und das andere ist eine Liste, die besteht aus einem ersten Element und dem Rest der Liste. Deshalb, um die Funktion zu beschreiben, brauchen wir diese zwei Gleichungen. Das sieht man hier, Route hat, und dann gleich irgendwas. Die erste Gleichung für die leere Liste. Das sind diese beiden leeren, eckigen Klammern. Und das zweite Gleichung ist für die nicht leere Liste. Und das erste in der Liste ist halt den OP, das ist die erste Operation. Und das ist ja nicht man, der Muster oder Pattern Matching. Hier, das man halt schreibt. Also, die zweite Gleichung ist ziemlich klar, wenn man den Anfang der Route haben will, dann nimmt man einfach das erste Element aus der Route. Die andere Gleichung sagt, was machen wir mit der leeren Liste, weil eine leere Liste enthält keine Operation. Also, ihr sagt hier in der zweiten Slide, zweiten Folie von deinem wunderschönen Haskell-Code, und du weißt, sagst schon, du weißt nicht, wie man es schreiben will. Ja, da kommen wir noch. Ja, dann fragst du mit deinen Experten und sagst, ja, das ist eine leere Liste von Operationen. Was machst du damit? Was ist das erste, was du machen? Dafür können wir einen Datentyp kreieren, der sagt, dass manche mal etwas da ist, manchmal nicht, das heißt Option. Also, das ist in Haskell als der Maybe-Type eingebaut, aber hier beschreibt man, definierend als Option. Und hier irgendwie ein Option A heißt, es kann entweder ein A da sein oder es kann nein sein. Deshalb hat das Option zwei, zwei Konstruktionen. Das eine ist es Sam-Objects, das andere sind die Nann-Objekts. Also, irgendwas kann Nann. Das heißt einfach, irgendwas kann man vom Type Option A sein, das ist nicht da. Der andere Konstruktion, sagt, die Sache ist einfach da. Das heißt, dieser Konstruktor hat, muss etwas von Typ A akzeptieren und gibt dann halt eine Option von A zurück. Also, du hast das, pack dieses Objekt ein. Ja. Ein F-Sharp-Programmierer oder so würde sagen, ja. Heutzutage ist dieser Typ sogar in Java eingebaut, das Optional. Und das heißt jetzt, wir können unsere Rout-Hat-Funktion ändern und wir sagen Rout-File-Operation, sagen wir Rout-File-Option-Operation und sagen, jetzt können wir Rout-Hat-Fun der leeren Liste definieren. Das gibt einfach Nann zurück, das ist einfach nichts drin, leere Route. Oder wenn wir halt eine Operation in der Liste haben, dann kommt Sam-Ob zurück. So, jetzt, und wenn wir jetzt unsere Rout-Hat auf unsere Beispiel-Liste von vorhin anwenden, die war ja Track-In-Process-Track-In, dann ist Rout-Hat-Fun-R1 Sam-Track-In. Das nächste, was wir machen, ist, wir wollen manchmal nicht nur die erste Operation wissen, sondern wir wollen auch wissen, was danach passiert. So, ja, da können wir eine andere Funktion definieren, Rout-Advance, die nimmt eine Route als Argument, dann kommt der File und die gibt uns zurück eine Operation und eine Route. Deshalb haben wir diese Rout-Advance, eine Route, deshalb haben wir diese zwei Dinge hier, mit dem Komma dazwischen, das gibt uns also eine Operation und eine Route, aber manchmal existiert das halt nicht, deshalb ist es halt nicht Option und Route, sondern eine Option davon. Und wenn wir jetzt unsere Beispiel-Route nehmen, dann trennen wir das in die erste Operation und den Rest, also Track-In ist die erste Operation und der Rest der Liste ist dann Process-Process-Track-Out. Okay, das ist technisch, alle noch dabei, hat irgendjemand eine Frage? Okay, ja. Das ist jetzt einfach, ganz einfach zu schreiben, wir müssen wieder zwei Gleichungen aufschreiben. Ja, wir sind Liste, da brauchen wir immer zwei Gleichungen. Rout-Advance von der leeren Liste ist None und Rout-Advance von Up und Rest ist halt Some, Up und Rest. Ja, einfach, weil halt die Liste mit dem Put-A-Matching halt genauso aufgeteilt wird, wie wir es am Ende haben wollen. Das ist einfach Rekord, also jedenfalls kurzer Kord, der klar kommuniziert, was passiert. Okay, wenn ich mich wirklich korrekt erinnere, dann nimmt er den Wafer und packt ihn in die Maschine und dann processiert, also verarbeitet er es. Aber wenn ich überlege, manche von diesen Prozessschritten sind chemische Reaktionen und es kann sein, dass sie eine bestimmte Zeit brauchen. Also was wir also tun könnten, wir könnten als etwas sowas hier modellieren. Was wir könnten, ist, wir haben diese drei Schritte, die zusammenarbeiten in einem Set, in einer vorgegebenen Zeit. Die Reaktionen meinen, dass dein Wafer might go back. Ja, wenn du startest die Sequenz-Steps und du nicht mehr auf die Hand, dann hat man hier, wenn man eine Verarbeitungsschritt startet und die nicht rechtzeitig beendet, dann ist der Wafer kaputt. Und das ist immer das Problem in existierenden Systemen. So, dann lasst mir was versuchen, diese Ansatz in deinen Code zu modellieren. So, was wir zuerst ist, wir haben die Route, wir brauchen erst mal dieses Routen-Element mit dieser Operation. Und wir brauchen eine andere Darstellung für ein Routen-Element. Wir nennen das hier RouteQT Zone, für RouteQTime Zone. Das haben wir, die Dauer, die Duration, die Zeit, in der die Sequenz von Schritten beendet werden muss. Und dann haben wir diese Liste von Operationen. Und wir haben das schon gesehen. Und das gibt uns dann halt auch wieder ein Routen-Element zurück. So können wir halt normale Schritte, wie ein Wafer in die Maschine, zu tun. Da kommt es nicht drauf an, wie lange es drauf ist. Ja, blockiert die Maschine, aber sonst passiert nichts. Das macht, es sucht keine Probleme, anders als das Etzen und das Waschen. Das ist eine RouteQTime Zone, weil wir die Zeit beschränken müssen, die das dauern. Gut, ja. Und dann, wenn wir an unseren Beispiel gucken, wir hatten, ja, das Erste ist unsere ursprüngliche Liste. Einfach nur mit Route, ob darum gemacht. Und wir könnten eine andere Liste kreieren, hier dieses R2. Hier haben wir eine RouteQT Zone, die braucht fünf Zeit-Einheiten, Sekunden, Minuten, was immer. Und die müssen in der Zeit beendet sein, und dann machen wir das Track out. Soweit so klar? Dann, wenn wir uns an das hier angucken, dann sehen wir, dass wir hier dieses Route-Element einmal oben haben. Und unten haben wir dieses Operation-List. Das ist sehr ähnlich. Vielleicht können wir irgendetwas daraus machen. Vielleicht können wir dieses hier unten auch in Route-Elements tun. Ja, das hast du gemacht. Ja, mein Code hatte Route-Liste von Operation. Ja, mein Code hatte Route-Liste von Operation. Und du wirst jetzt was Ähnliches machen, richtig? Ja, jetzt ist es das Ähnliche. Nur jetzt ist es hier das Gleiche. Hier haben wir both Route-Element. Wenn wir uns das jetzt angucken, das bedeutet hier, dass das hier, dass hier nicht nur ein Liste von Route-Elements ist, sondern eine Liste von Route da unten ist. Also, dass wir hier tatsächlich entdecken, dass wir hier etwas aus dem Code ableiten können, sondern entdecken, dass hier unsere Route-Cuty-Zone tatsächlich eine rote enthält. So, wenn wir das hier angucken, dann können wir hier unten dieses Route-Element, irgendein Route-Element einbauen. Wir könnten hier auch einen Route-Cue-Time-Zone einbauen, was auch ein Route-Element ist. Also, wenn wir von diesem Beispiel hier kommen, wo wir nur eine flache Liste haben, unter dem Route-Cue-Time-Zone und von Route-Reparations, wir können auch ineinander verpacken, so wie es eine Route-Cue-Time-Zone könnte, wieder eine Route-Cue-Time-Zone enthalten. Das ist ziemlich cool. Das könnte passieren. Jetzt können wir Cue-Time-Zones verschachteln. Das ist etwas, das tatsächlich in der Realität passiert. Also, dein Modell hat etwas aufgezeigt, was unsere alte objektorientiertes Modell nicht modellieren konnte. Also, deshalb sagst du, dass funktionale Programmierung besser ist. Also, wir haben das hier in dem Code entdeckt, und dann können wir damit zurück zu den Anwendern gehen und mit ihnen checken, ob sie tatsächlich solche Struktur in der Praxis sehen und ob es diese, das ist eine, das ist ein wichtig, die Typinformation, die eine wichtige neue Einsicht hat. Und dann können wir damit weitergehen, und jetzt haben wir diese Liste von Route Elements. Okay, ja, Liste von Route Elements. Wir wissen, was es ist. Das ist tatsächlich eine Route. Also, eine Route. Jetzt gehen wir hier ein Level hoch. Sobald wir mehr über Routen lernen, solltet ihr das lernen, wird es automatisch in hier unten auch in der Route Cutie Time Zone reflektiert, weil wir es abstraktiert haben. Und das ist, worum es in Funktionaler Projenierung überhaupt geht, Sache zu abstraktieren und die gemeinsamen Strukturen zu erkennen. Ja, du bestimmst mit mir jetzt überein, das ist gut. Okay, und jetzt können wir auch gucken, wie unsere Funktionen modifiziert werden. Jetzt gehen wir wieder durch alle unsere Funktionen und gucken, wie sie, wie sie arbeiten. Also, wir haben Route Head und Route Elements Head. Wir müssen sie erweitern. Wir haben natürlich dieses Route Elements Head, das ist damals ein neues Route Elements, dieses Route Cutie Time Zone. Und das Route Elements Head an der Cutie Time Zone ist das Route Head von der enthaltenen Route. Also, wir haben da schon Route Head, das haben wir schon. Also, da können wir einfach die Funktion hier unten wiederholen. Also, dies ist für uns einfacher geworden zu implementieren, weil wir entdeckt haben, dass da halt in dem Route Cutie Time Zone eine Route ist und eine Liste von Route Elements. Und deshalb können wir hier einfach die Standardfunktion benutzen, die wir schon haben. Und wenn wir an Route Advanced gucken, wenn wir unsere Route zur nächsten Operation fortschreiten wollen, dann, ja, dann müssen wir natürlich auch diese Fall für Route Cutie Time Zone hinzufügen. Aber jetzt passiert natürlich, was passiert, wenn wir in eine Cutie Time Zone hinein fortschreiten. Weil wir müssen im Kopf behalten, wann muss diese Sache zu Ende sein, wann muss diese Cutie Time Zone beendet sein. Also, da müssen wir uns die Zeit merken. Und wir müssen halt überwachen, ob diese Zeit schon abgelaufen ist oder nicht. In diesem Fall, was wir tatsächlich machen müssen, ist, wir müssen ein anderes roten Element hinzufügen. Das ist das Route Cutie Time Limit, das sagt, wann eine begonnene Operation beendet werden muss. Also, das muss den tatsächlichen Zeitpunkt enthalten. Also, nicht die Dauer, sondern tatsächlich den Zeitpunkt. Und dann ist es das Gleiche wie, ab dem Davon ist es das Gleiche wie das Route Cutie Time Zone. Das bringt unseren Prozess dann bis zu dem Punkt in der Zeit. Und jetzt können wir diese unsere Route Advanced Funktion implementieren. Das heißt, immer wenn wir eine Cutie Time Zone hatten und wussten nicht, was wir hinschreiben sollten, immer wenn wir diese Rote weiterschalten, dann wissen wir, dass wir hier ein Cutie Time Limit brauchen. Und wenn wir dieses Cutie Time Limit haben und wir darüber weiterschalten, dann wissen wir, dass wir uns genauso verhalten müssen wie vorher. Wir müssen dieses aufspalten. Und wir brauchen natürlich, müssen natürlich unser Time Limit behalten und nur vorwärts gehen zu diesem Limit, während wir das Limit behalten. Und wenn wir hier starten, dann müssen wir feststellen, was der Endpunkt ist. Das heißt, wir nehmen die Zeit, die aktuelle Zeit, die wir oben eingeben und addieren die Dauer. Und dann wissen wir, wann wir mit dem Prozess fertig sein müssen. Und dann haben wir hier, ja, das machen wir einfach nur, bearbeiten wir jeden Schritt, behalten aber das Time Limit. Das heißt, der Code hat gezeigt, dass du nicht alles verstanden hast, dass deine Lücke war in deiner Verständnis. Ja, ich wusste nicht, was ich hier implementieren musste für das Fortschreiten der Route, aber jetzt weiß ich es. Ja, das heißt, wenn man sich dieses anguckt, dann, wenn ich das mit dem Auge des Domaine-Experten angucke, dann gibt es immer noch ein kleines Problem hier. Oh, ja, und wenn man, ein Routenelement ist das, was irgendwo in der Mitte oder am Anfang oder am Ende auftauchen kann, das heißt, man hat die drei Sachen, man hat Q-Time-Zones irgendwo, und wir können überall Operationen haben, aber wir können immer nur eine Q-Time-Zone beginnen, wenn sie am Anfang ist. Und das heißt, hier müssten wir eine Zufälligeliste und eine beliebigen Reihenfolge haben. Ja, ja, das stimmt. Und hier kann man, dieses zeigt, dass die Q-Time-Zonen, dass wir jetzt drin sind in dieser Q-Time-Zone, denn es gibt ein Q-Time Limit, aber es gibt immer noch eine Operation davor. Und das ergibt irgendwie keinen Sinn. Ja, das macht keinen Sinn. Wenn wir jetzt zurückgehen könnten von den Domainwissen zum Code, dann können wir das natürlich weiter verfeinern. Und wir können die Q-Time Limit hier rausziehen, denn das sind alle die Sachen, die in der Mitte passieren und können das zu einem höheren Leveltyp tun und der verbindet was am Anfang und was in der Mitte passiert. Oh, ja, das ist nett. Und jetzt haben wir dieses Vor- und zurück zwischen dem Code, was in einem Einblick ergibt in die Domäne und dann wissen aus der Domäne in den Code einbringen und benutzen den Code, um damit zu kommunizieren. Aha, das ist das, was ich machen wollte. Und du hast das verstanden. Ja, dieser Code zermalt meine Seele nicht mehr. Und ja, mir geht es genauso. Cool, ja. Und das war der Punkt, den wir heute euch zeigen wollten. Das heißt, wenn man funktionale Programmierungen benutzt und dazu noch Diskussion und Kommunikation nutzt und hin und her geht zwischen beiden und beide Teile von der anderen Seite lernen können, beide Seiten sich austauschen und Informationen von beiden Seiten kommt, dann hat man am Schluss doch eine Wunderwaffe. Und alle gucken etwas Konfußes. Das ist ein Bullet Train, also ein Zug, der wie ein Projektil geformt ist, die Wunderwaffe des Silver Bullet. So, thank you for a very entertaining talk. We have some time for questions, Q&A. So, if you have any questions, please line up next to the microphones. We have four microphones right across the room and we'll start from a question from the internet. Wir starten mit einer Frage aus dem Internet. Hey, so here is a question from the internet. As an FP beginner with a weak background in math, would it be anfänger in der funktionalen Programmierung? Wäre es besser in einer reinen funktionalen Sprache zu anzufangen oder mehr in einer hybrigen Sprache? So, shall I take that one? So, ja, soll ich das machen? Okay, also ich glaube, der Punkt ist, es gibt mehrere, viele verschiedene funktionale Programmiersprachen und Haskell ist eine reine funktionale Sprache, eine hybride objektorientierte funktionale Sprache. Zum Beispiel Scala ist ein wichtiges Beispiel. Scala ist eine tolle Sprache, aber das Problem ist, wenn man die beiden Paradigmen kombinieren will, dann kriegt man etwas, was sehr komplex ist. Scala ist eine sehr komplizierte Sprache und man braucht viel länger das zu lernen, um es zu beherrschen. Und weil man eben beide Paradigmen hat zu jeder Zeit, ist man manchmal etwas verwirrt, dass man dieses Paradigma jetzt benutzen soll in einer bestimmten Situation. Und ich glaube, wir beide haben wirklich keine großen Vorteile gesehen von einem hybriden Ansatz. Das Problem ist, wenn man noch anfängt funktionale Programmierungen lernt und das mit etwas wie Scala macht, dann wird man wahrscheinlich zurückfallen auf das, was man kennt, nämlich bei den Problemen. Also vielleicht einfach schon gleich ins Tiefe springen und mit dem Lernen und im Internet Hilfe finden. Danke für die Präsentation, ihr war sehr gut. Die Beschreibung war über funktionale Programmierung in IoT. Da war nichts IoT-spezifisches in eurer Präsentation, nichts über Interaktion mit Hardware, Interrupt Handling. Wie behandelt ihr das? Ja, ist ein guter Punkt. Und ich dachte, wir hatten eigentlich einige Folien dazu, aber haben sie einen rausgelassen, weil die Zeit fehlte. Aber mein Argument wäre, dass IoT ist eigentlich dieselbe Software, alle andere Software. Das Besondere ist das Risiko, was davon ausgeht bei Internet of Things. Wenn man z.B. Sachen macht wie Interrupt Handling, dann ist meine Antwort, das zu konvertieren in funktionale Datenstrukturen zu wandeln. Und das gibt ein deterministisches Modell, um das Hand zu haben. Und wir haben gesprochen über Observer-Patterns. Das ist so etwas ähnliches, wie was passiert beim Interrupt Handling und wie man das macht. Man hat natürlich ein kleines Stückchen imperativen Code, der mit der Hardware spricht. Aber um die Interrupts, kann man einfach in eine Liste konvertieren. Und Tascale macht das ziemlich gut. Und dann hat man alle die Vorteile der funktionalen Programmierung, wie Testbarkeit und die tollen Abstraktionen, die man benutzen kann. Und dann konvertiert man die Interrupts in andere Software, ganz normale Software. Ich muss Code für Microcontroller schreiben. Und meistens haben wir nur einen C-Compiler. Wenn ich Glück habe, bekomme ich einen C++-Compiler. Woher kriege ich dann meine Wunderwaffe? Die alten Haskell-Compiler, der erste Haskell-Compiler hat nach C kompiliert, aber heute macht er das nicht mehr als Voreinstellung. Aber man kann es immer noch benutzen, diese Funktion. Ja, ich glaube schon. Aber es gibt einige Funktionalprogrammiersprachen, die nach C übersetzen. Und es gibt keine einfache Antwort. Und wir haben viele Vorteile von Funktionalprogrammen, indem man Code in Haskell macht, der dann C-Code macht. Und es gibt nicht ganz einfach eine einzelne Antwort, ohne viele Details zu geben. Aber es gibt ein großes Spektrum und Optionen, die zur Verfügung stehen. Funktionale Programmierung ist sehr kompakt. Und kurz, niemand möchte wirklich lange Variablennamen benutzen. Und in eurem Beispielen sage ich Ds und Ts. Ich glaube nicht, dass es so viel besser ist, als die langen Version, die ihr vorher gezeigt habt. Ich habe auch ein Problem damit ein bisschen. Und eine Sache ist, dass dieses war ein ziemlich konkreter Code. Aber oft hat man Abstraktionen. Und in den Abstraktionen ist es dann so, dass es eher willkürlich ist, was man benutzt. Man kann kurze Namen benutzen, weil man nicht von konkreten Objekten spricht. Und deswegen ist es da einfacher, abstrakte variablen Namen zu benutzen. Aber was ich normalerweise mache, ist, ich benutze trotzdem lange variablen Namen. Und ich würde oft nicht unbedingt D und RT benutzen oder so, um das besser zu verstehen. Aber eine wichtige Sache, die man nicht vergessen darf, ist, dass dies, man hat hier eine Funktion. Und es sind zwei oder drei Zeilen. Und wenn man anfängt und versteht D und RT aus der Signatur und dann, wenn man dann drei, zwei oder drei Zeilen liest, mit D und RT, dann ist es nicht so schlimm. Und objektorientiert oder in Java oder so, hat man hunderte Codezeilen. Und dann hat man irgendwo D und RT. Und man hat schon eine halbe Stunde so was gelesen. Und dann hat man es schon wieder vergessen. Und es ist eine Abwägung. Ich benutze längere Namen normalerweise, aber manchmal auch kurze, weil manchmal ist der, weil der Code einfach so kurz ist. Ein Detail noch. Ich benutze auch meist in dynamisch typen Sprachen, nehme ich auch lange Namen. Und wenn man nicht den Typ hat, der sagt, was das Ding ist. Thank you for number one. In one of your slides, einer euren Folien habt ihr gesagt, dass funktionale Programmierung sich der für Beweise eignet. Hatte das tatsächlich gemacht? In der Praxis gibt es verschiedene Möglichkeiten, das zu tun. Zuerst kann man, wie ihr gesehen habt, Haskell ist einfach eine Reihe Gleichungen. Man kann einfach Algebra benutzen als mathematische Technik, um das, um der Schlüssel zu ziehen, um den abstrakten Teil der Frage zu beantworten. Man kann natürlich das auch mit Java machen, aber es ist sehr viel schwerer, um da eine allgebreiche Formulierung zu finden für Java-Programme. Es gibt auch ganz viele Werkzeuge hierfür, um Beweise zu finden für bestimmte Aspekte des Programms. Zum Beispiel ACL2 ist ein klassisches Tool. Es gibt Adress, was eine neuere Art von Funktionalprogrammierung ist. Es ist viel einfacher, Eigenschaften zu beweisen von funktionalen Programmen, weil man Algebra benutzen kann, als zum Beispiel von Java-Programmen. Ist das eine gute Antwort? Ein wenig, aber Adress benutzt abhängige Typen. Kann man das nicht auch in imperativen Programmen benutzen? Ist das spezifisch für funktionale Programmiersprachen abhängige Typen? Ja, Adress sagt auch, auch imperative Sprachen sind funktionale Programmierungen eigentlich. Es gibt auch Datenmonaten und es gibt dieses ganze Ding, darüber Schlussfolgerung über Effekte anzustellen. Aber es ist nicht unmöglich in anderen Programmiersprachen darüber Schlussfolgerung zu ziehen, aber es ist viel schwerer. In funktionalen Programmiersprachen, die nicht die Seele zermahlen, hat man ganz viele Teile, die rein funktional sind. Dann kann man einfach Schlüsse ziehen mit Gleichungen. Es gibt kleine Teile, die vielleicht schwerer sind über die Interaktion mit der Umgebung haben. Was wir gemacht haben mit dem Typsystem ist, wenn ihr euch daran erinnert, wir hatten erst diese Liste und dann hatten wir die Q-Time-Limits in der Mitte und das war ein illegaler Zustand, das heißt, wir haben das Typsystem geändert, um das zu verbieten. Und das heißt, der Compiler sagt uns schon, dieses verbotene Code, und es ist nicht syntaktisch falsch, sondern es ist semantisch falsch. Und das ist eine eher schwache Art von Validierung oder Verifikation, so wie ich das sehe. Ich habe bemerkt, dass ihr keine Mechanismen präsentiert hat, um eure Implementation zu verstecken oder Dinge privat zu machen, wie man zu C++ machen würde. Ich hätte gerne eure Meinung dazu machen, dass es nicht ein bisschen gibt. Doch, das gibt es in functionalen Programmiersprachen auch. Es gibt private Elemente und Module. Funktionale Programmiersprachen benutzen keine Objekte oder Klassen, und das ist der Hauptunterschied, glaube ich. Aber funktionale Sprachen haben auch Mechanismen, um das zu tun. Es sind einfach nur Verschieden zwischen den verschiedenen Sprachen. Das heißt, es ist ein bisschen schwierig, das in einem Vortrag zu machen. Man kann zeigen, wie es in Haskell geht, aber das geht in anderen Sprachen dann anders. Und dann hätten wir noch mehr Code auf den Folien gehabt. Und ein anderer Aspekt ist, dass man Sachen wirklich nicht verstecken muss, weil alles so rein ist. Und es ist egal, wie man die Funktion nennt. Man kann nichts zerstören. Und während in objektorientierten Sprachen hat man diese ChangeMyObject to endermann Objekte in etwas richtig schlechtes. Und niemand will, dass jemand anders das aufruft, dass jemand kaputt macht, aber in funktionaler Programmierung irgendwelche Variablen rein und man kriegt irgendwas raus. Mach einfach, mach einfach, das ist mir egal. Ihr habtet ein paar Folien über die Bedeutung der Kommunikation. Und ich sehe mich nicht, dass ich mit Anwendern rede in der Form von Haskell Code. Wie macht ihr das? Also, wir machen es etwas sauberer, aber es ist tatsächlich in der Praxis vorgekommen. Und manchmal ist es ein Prozess, da hinzukommen. Und was man aber auch, was man vielleicht merkt, an dem Code mit den Roten ist, das mit dem Haskell Code rumzuspielen, hat uns zu Domänenwissen geführt, was man auch zeigen kann und dann mitteilen kann, ohne wirklich den Code zu zeigen. Aber durch den Haskell Code haben wir Sachen gelernt und haben nicht durch den Code kommuniziert, sondern dadurch gelernt. Aber das passiert tatsächlich, man kann tatsächlich mit Kunden kommunizieren, indem man ihnen den Code zeigt und darüber redet und sie fragt, ist das wirklich, wie es funktioniert in eurer Domäne? Ja, es ist mir auch schon passiert. Und es hängt vom Kunden ab. Man muss etwas resilient sein. Und dann müssen sie akzeptieren, dass sie vielleicht nicht alles verstehen, aber man kann ihnen zeigen, guckt mal, das funktioniert hier so und das geht rein und das kommt raus. Und was haltet ihr davon? Und nicht einfach nur sie mit dem Code bewerfen, sondern wirklich eine gute Kommunikation haben. Man kann es auch durchaus in den Vertrag schreiben.