 Willkommen zur deutschen Übersetzung von Getting Software Wiked with Properties Generated Tests and Proofs von Mike's Berber. Live vom 36. Chaos Communication Congress in Leipzig. Alle Talks am Congress werden live zwischen Deutsch und Englisch und in einer weiteren Sprache übersetzt. Für weitere Details und Informationen, wie die Streams genutzt werden können, besucht c3lingo.org. Wir freuen uns über eure Rückmeldung, bevorzug mit Hashtag Hashtag C3T. Eure Übersetzungen für diesen Talks sind Pascaline und Bubbler. Vielen Dank. Benutzt jemand das Introduction Feature in den ersten Reihen? Okay. Lass mich einen kurzen Färber Einblendung machen. Wir machen eine Entwicklerkonferenz in Berlin im Februar genannt Bob. Die ist sehr nett, sehr klein und wir werden euch gerne das sehen. Das hier ist ein Einführungstalk. Wenn ihr die letzten Entwicklungen in Beweistaktiken sucht, dann ist alles, was ihr von diesem Talk kriegen werdet, eine leichte Begeisterung und ihr könnt auch gerne zu einem der anderen fortgesetzteren Talks gehen. Wenn wir von Einführungstalks gehen, hier ist ein Code-Auszug, den wir für diesen Talk benutzen. Okay, oh, da ist eine Person zurück da. Best aus dieser Programme. Also wenn irgendein Teil dieses Programmes nicht klar für euch ist, dann ist es auch nicht klar für einen der anderen Leute hier im Raum. Also wenn ihr Fragen habt, dann lade ich euch dazu ein, diese Fragen während diesem Talk zu stellen. Und obwohl es ein Einführungstalk ist, kann es sehr technisch werden. Also das hier ist ein klassisches Beispiel für funktionales Programmieren, was ich oft benutze als Beispiel über Daten auf Texanischen Straßen. Es gibt zwei Typen von Tieren auf diesen Straßen. Es gibt, wie heißt das, gut, wenn ihr diese zwei Definitionen für diese Tiere seht, dann seht ihr, dass die Pfeile lustig sind, aber ihr seht, dass jeweils zwei Eigenschaften haben. Es gibt Lebendigkeit, also dieses Tier kann also tot oder lebendig sein. Dann gibt es in der Typensignatur sagt, es gibt eine Lebendigkeit, ein Gewicht, was ein Tier ausmacht. Und für ein Papagei gibt es einen String und auch ein Gewicht. Und hier drüber seht ihr, was das Gewicht ist, das ist ein Typ, das ist etwas ungewöhnlich, aber das ist einfach nur das Gleiche wie ein Intrinscher. Und wenn ihr da unten seht, wo es A1, A2 und A3 sagt, da habt ihr drei Beispiele für diese Tiere. Also hier seht ihr, ein Amadillo ist ein Tier. Also A1 ist ein Amadillo, das noch lebendig ist und 10 kg wiegt. Und das zweite ist auch ein Amadillo, was tot ist und 12 kg wiegt. Und das dritte ist ein Piraten-Papagei und der wiegt drei Kilo. Alles in Ordnung soweit? Also wenn ihr irgendwelche Fragen über das habt, bitte stellt sie gleich. Also was passiert auf Texanischen Heibes, da fahren Leute mit dem Auto und Tiere werden überfahren. Wir machen funktionelles Programmieren. Was hier wichtig ist, es geht ein Tier rein, es geht ein Tier raus. Und das Tierobjekt, was ihr hier seht, ist nicht direkt das Tier, sondern der Status des Tieres zu einem gewissen Zeitpunkt. Also es geht rein, es geht raus. Also der Status des Tieres geht rein, bevor es überfahren wird und dann der Status des Tieres nachdem es hinauskommt. Und wir haben zwei Status für diese Tiere, also zwei unterschiedliche Gleichungen. Das eine sagt, was passiert am Amadillos, wenn es da rein geht. Und da passiert dann so etwas wie Pattern-Matching. Und das zweite ist ein Papagei geht da rein und auf der rechten Seite seht ihr, wenn ein Amadillo überfahren wird, dann wird die Lebendigkeit also tot. Es gibt ein neues Amadillo-Objekt, das hat das gleiche Gewicht, aber ist tot. Und die Gleichung unten auf dem Boden, die sagt, wenn man ein Papagei überfährt, dann wird er sehr, sehr leise. Wir werden am Ende des Talks zu diesem Beispiel zurückkommen. Aber jetzt werden wir etwas einfacheres machen. Jetzt werde ich ein bisschen hinterher springen. Vor zwei Wochen habe ich ein Kurs über Architektur vorgestellt. Und das ist wahrscheinlich ein Domain-Model. Und dann habe ich vielleicht einen Kunden und der hat irgendwelche Anforderungen und dann funktioniert das immer auf die gleiche Weise. Ich packe eine neue Zeile, neue Spalte in die Tabelle hinein. Und die Software wird dann immer alter und älter und immer mehr spalten werden hinzugefügt. Und jetzt ist natürlich die Frage, wie können wir Modelle bauen, die flexibel sind? So, was ist das jetzt? Das ist ja etwas ganz anderes, denkt ihr vielleicht. Das hier ist der Schlüssel, um flexible Modelle zu bauen. Erinnert sich da jemand daran oder kennt jemand das? Kommt darauf an, wo ihr zur Schule gegangen seid, könnt ihr euch vielleicht daran erinnern, dass das Assoziativität ist. Das heißt, dass wir zuerst das A und das B miteinander verknüpfen können und dann das C. Oder zuerst das B und das C und dann das A. Und wenn ihr eins mitnehmt vor diesem Talk, dann ist das, dass Assoziativität etwas eines der wichtigsten Dinge sind, die es in der Softwareentwicklung gibt. Und jetzt können wir diese Gleichung etwas mehr spezifischer machen. Das ist, dann wisst ihr zum Beispiel, dass nicht nur Additionen associative, sondern auch Multiplikation. Das ist ein bisschen Mathematik. Ihr habt dieses umgedrehte A, das bedeutet für alle. Das bedeutet für alle A, B und C, dann habt ihr dieses komische Epsilon-geformte Moodle. Das heißt, A, B, C sind Elemente in den natürlichen Namen, also die natürlichen Zahlen 1, 2, 3, 4 und so weiter. Was das bedeutet für alle natürlichen Zahlen A, B, C gilt die Assoziativitätseigenschaft, wenn man sie addiert. Das heißt natürlich, das gilt aber nicht nur für Zahlen und Additionen, sondern das gilt auch für Listen. Das gibt aber auch für ganz viele andere Dinge. Zum Beispiel, das ist ein anderes Beispiel. Wenn man zum Beispiel mit Listen arbeitet und diese 2 plus Zeichen hier, das bedeutet Listen, verknüpft Listen an, Aneinanderhängung, Konkretinierung. Natürlich könnt ihr auch drei Listen aneinanderhängen. Und das ist auch Assoziativität. Also es kommt nicht darauf an, ob ihr zuerst die B und C miteinander verbindet und dann das A vorne ran hängt oder ob ihr zuerst A und B miteinander verknüpft und dann C ans Ende ran hängt. Ihr bekommt immer das gleiche Resultat. Das heißt Listen und Konkretinierung, Verknüpfung haben auch diese Assoziativitätseigenschaft. Und hier ist ein Beispiel, was ich immer sehr, sehr erhellend finde. Ihr könnt zum Beispiel Bilder so konstruieren, das sieht man hier jetzt nicht. Das ist ein Bild von einem, einen bekannten Forscher von mir. Er hat eine Sprache um Diagramme, um von kleinen Teilen zu generieren. Es geht hier also um Operatoren, die Dinger aus Teilen konstruieren. Es gibt hier also verschiedene Formen. Es gibt schwarze Rechtecke, es gibt bunte Rechtecke. Und das hat das hier mit dem Term von H9 zu tun. Aber es geht hier eigentlich eher darum, dass das Bild aus verschiedenen Teilen besteht. Normaler objektantierter Programmierung, wenn man Graphik macht, da hat man in der Regel ein Canvas, ein Linewand und man mal Pixel auf dieser Linewand. Und dann malt man zum Beispiel kreisförmige Formen. Aber was wir hier machen ist, hier behandeln wir Bilder als ein Datentyp. Und die Definition ist gar nicht wichtig, sondern was wichtig ist, dass es Funktionen gibt, die einfache Bilder herstellen können. Hier gibt es zum Beispiel eine Beispiel, die ihr euch vorstellen könnt, zum Beispiel Star, die Funktion Star, mit der ihr Sterne konstruieren könnt. Oben gibt es eine typische Deklaration. Das heißt, dass die Star Funktion eine ganze Zahl erlangt und ein Mode, was auch immer das heißt, eine Fange, und dann erzeugt sie einen Image. Und wir können diese Star Funktionen aufrufen oder call mit den Variablen 200, Solid und Gold. Und damit bekommen wir ein Image. Und dieses Imagebild ist ein Objekt. Das ist vielleicht nicht so spannend, aber wir haben vielleicht eine zweite Funktion, Polygon. Polygon bekommt zwei Integers, zwei ganze Zahlen. Das ist die Größe des Polygons und auch die Anzahl der Vertices. Und dann den Modus und Color. Und das kann man zum Beispiel callen mit 180 und 5 und Outline und in Rot ist es dann. Und die Idee hier ist jetzt, dass wir die Sachen auch miteinander kombinieren. Genauso wie wir zwei Zahlen oder zwei Listen kombinieren können, können wir auch zwei Bilder kombinieren. Und das Einfachste, was wir machen können, ist, wir können zwei Bilder nebeneinander packen, zum Beispiel mit der Funktion Beside. Beside kriegt zwei Bilder und produziert wieder ein Image. Und genau das, und wenn wir über Soziativen nachdenken, dann denken wir auch über einen vineeren Operator nachdenken, der zwei Bilder bekommt, wie hier in diesem Beispiel, und dann ein neues Bild. Wir können uns auch einen anderen Operator vorstellen, nämlich ABOV, der zwei Bilder bekommt und die Bilder übereinander packt. Und wir können auch diese beiden Funktionen kombinieren. Und das ist gar nicht so, und das geht, weil man zwei Image reinpackt und da ein Image kommt wieder raus. Und dann können wir die Sachen wieder kombinieren und können Arrangements von Bildern herstellen. Beside und ABOV sind jetzt zwei möglichen Operatoren und ihr denkt vielleicht gerade darüber nach über Assoziatität, aber eigentlich die viel fundamentalere Operation ist Overlay, also zwei Bilder übereinander packen. Hat wieder den gleichen Typen, zwei Bilder kommen rein und ein Bild kommt raus. Und wenn man jetzt zum Beispiel diesen Goldstern nimmt und das Pentagon dann hat man und übereinander packt, dann sieht das so aus. Und jetzt können wir das Assoziativitätsgesetz formulieren für Bilder. Es sieht vielleicht ein bisschen anders aus, weil wir jetzt Overlay nach vorne geschrieben haben, anstatt die Overlay zwischen die Elemente zu packen. Aber ich möchte einfach nur zeigen, dass es die gleiche Idee ist. Es kommt also nicht drauf an, ob ich die A und B nehme, die übereinander lege und dann C drüber lege oder ob ich erst B und C übereinander lege und dann A übereinander lege. Habt ihr eine Frage? Ja, guter Punkt. Also das impliziert, dass es auch eine Art von Transparenz gibt, damit es Assoziativität geben kann. Eine sehr gute Frage. Das bedeutet, wenn ihr über dieses Bild nachdenkt und über die Fahrbahn bestimmten Koordinaten nachdenkt, müsst ihr darüber nachdenken, wie ihr diese Farben an diesem Koordinaten behandelt. Und da kann man sich dann vorstellen, dass es dann natürlich auch ein Kombinationsoperator für Farben gibt und auch der Assoziativ sein muss, damit die Overlay-Operation assoziativ sein kann. Sehr gute Frage. Da diese Assoziativitätseigenschaft nicht nur auf Zahlen, wie wir in der Schule gelernt haben, anwendbar ist, sondern auch auf Mengen. Und deswegen müssen wir darüber nachdenken, was die Eigenschaften in der Gruppe sind. Das hat einen Namen in der Matte, das sind dann Halbgruppen. Also ihr habt eine Menge S. Es kann die Menge von den natürlichen Zahlen oder von Bildern sein. Wir haben eine Operation, die heißt hier einfach Kreis. Die nimmt irgendwelche Elemente A, B, C von dieser Menge S und verknüpft die miteinander. Und für diesen Kreis könnt ihr dann Overlay, B, C, oder beispielsweise die Listkonkretation einsetzen. Assoziativität ist großartig, weil es heißt, dass wir alle möglichen Dinge verbinden können und wir können das in egal welche Reihenfolge wir die Klammern setzen. Das Ergebnis ist das Gleiche. Also können wir einen Ausdruck schreiben, indem wir die Klammern weglassen. Es hat auch praktische Anwendung, wenn ihr die Verarbeitung von großen Datenmengen macht, heißt das bei Assoziativität, dass wenn ihr große Datenmengen hat auf verschiedenen Hard drives, auf verschiedenen Datensourcen, wenn ihr die miteinander verbindet und eine assoziative Verbindung habt, dann heißt das, dass ihr diese Kombination, Operation beliebig neu anordnen könnt. Und das macht es wirklich sehr, sehr praktisch, wenn ihr die Verarbeitung von großen Datenmengen machen müsst. Das ist eine praktische Anwendung. Aber Assoziativität ist auch sehr nützlich, wenn ihr euer Domainmodell designt. So könnt ihr euer Domainmodell nicht als etwas sehen, was aus ganz, ganz vielen Eigenschaften besteht, sondern aus ganz vielen unterschiedlichen Blöcken, von Eigenschaften, die ihr beliebig kombinieren könnt. Hier ist ein meiner Lieblingsbilder von Brent Yoga. Ihr könnt sehen, es geht hier um Bilder, und diese Bilder werden aufeinander, übereinandergelegt. Dieser Titel ist sehr googlebar. Es sagt hier nicht Halbgruppe, es sagt Monuit. Ein Monuit klingt sehr komplizierter, aber es ist nicht sehr viel komplizierter als eine Halbgruppe. Also es ist eine Halbgruppe, die ein neutrales Element enthält. Und wenn wir etwas mit einem neutralen Element verbinden, dann ist es egal, ob wir das von vorne oder von hinten verknüpfen, sondern das gleiche Resultat kommt dabei raus. Das neutrale Element für die Addition von Zahlen ist 0. Für overlay, beside and above, kann man sich auch vorstellen, dann in dem Fall ein leeres Bild als neutrales Element zu haben. Also all diese Dinge, die ich euch gerade gezeigt habe, die ja associativ sind, sind also nicht nur associativ, sondern sie sind auch noch Monuit. So lange ihr euch associativitäten merken könnt, das ist das wichtigste. Monuits gibt es wirklich überall. Es gibt Zahlen, es gibt Listen, Bilder, Musik, Monoid-Operation, man kann Animationen und man kann Animationen miteinander verbunden, Finanzkontrakte, Semiconductor-Herstellungsrouten. Eigenschaften selber sind auch Monoide, alles Mögliche, sie sind überall um euch herum, und das ist wirklich der Schlüssel zu flexiblen Domain-Modellen. Wir suchen also nach Baustein und nach wegen diese Bausteine miteinander zu verknüpfen. Ich habe also gesagt, ihr könnt associativitäten oder Monoide zu benutzen um euer Design zu leiten. Hier ist eines von den Bildern. Ihr erinnert euch an die Beside und die above-Operation und die sind okay, um Bilder in vertikalen oder horizontalen Achsen anzuordnen. Aber das Problem ist, die haben jetzt eine Bounding Box um diese Bilder gemacht und haben dann die Bounding Boxes angeordnet. Das funktioniert sehr gut, wenn das Bild leicht rotiert ist, weil dann gibt es eine Lücke im Bild. Also Beside und above sind nicht besonders gute Operationen als Basis für eine Bilderbibliothek. Aber es löst das Problem, wie man bestimmte Bilder anordnet. Das ist das Problem, dass die Bilder in vertikalen oder horizontalen Achsen wie man bestimmte Bilder anordnen kann, dass sie nebeneinander übereinander sind. Die Idee von Umschlägen ist, wenn ihr mir ein Vektor gibt, der anfängt am Startpunkt und ihr diesen Vektor verfolgt, dann könnt ihr diesen Punkt finden, der gerade außerhalb des Objektes ist und das ist dann ein Envelope. Und ihr könnt das benutzen, um eure Bilder anzuordnen, nicht nur im horizontalen und im vertikalen, sondern auch, wenn sie rotiert sind, an den Punkten, wo sie sich probieren. So bändgelt dann von dieser Inspiration von Monoiden aus, dass alles ein Monoid sein muss und nimmt das als Leitungsprinzip für seine Bibliothek. Also es ist ein wirklich sehr interessantes Paper zu lesen, sehr interessante Resultate. Aber das bedeutet, dass ihr auch ein monoidisches, ein monoidischen Kombinationsoperator für Envelopes finden müsst. Glücklicherweise ist das wirklich sehr einfach. Also wenn ein Vektor in eine bestimmte Richtung ist, dann ist der Envelope einfach nur das Maximum an, von diesen zwei Punkten, um genau außerhalb von dem Objekt zu sein. Ich habe diese Eigenschaften als mathematische Eigenschaften eingeführt. Für alle Bilder können wir die overlay-Operation bestimmen. Wir können aber auch diese Eigenschaften als Code beschreiben. Es gibt hier nicht so viel Unterschiede, außer dass die Schriftart eine andere ist. Aber diese ganze mathematische Zeug ist immer noch darüber. Aber wir können jetzt einfach die mathematische Zeile nehmen und den Code umwandeln. Sie sieht jetzt nicht ganz gleich aus, aber vielleicht können wir die Struktur wiedererkennen. Also wir haben hier eine Eigenschaft, die heißt overlay associative. Es ist heiß gelöst, eine ESCII-Sprache immer noch großartig, also immer noch zum großen Teil. Deswegen haben wir kein umgedrehtes A. Und deswegen schreiben wir vorall. Also für alle arbitären, Trippel von allen arbitären Bildern, nehmen wir diese drei Bilder, Bild 1, Bild 2, Bild 3. Dieses lustige Backstash da ist ein Lambda. Und die fundamentale Eigenschaft ist, wenn wir das overlay von Bild 1 und Bild 2 und dann Bild 3 aufrufen ist, das ist gleiche wie wenn wir das overlay von Bild 1 und dem overlay von Bild 2 und Bild 3 aufrufen. Eine andere große Artikel-Sache ist, wenn wir es als Code aufgeschrieben haben, können wir es in einem Programm manipulieren. Wir haben hier einen anderen großen Forscher in funktionale Programmierung, John Hughes, der etwas geschrieben hat, das heißt Quick Check. Ich habe einen Quick Check für diesen Talk zusammengehackt, aber wenn es eine funktionale Sprache oder Java oder Python ist, dann gibt es bestimmt eine Bibliothek für Quick Check. Ich will das jetzt dieses Quick Check möchte ich jetzt einmal zeigen. Nicht um das Design darüber zu reden, sondern eher über die Eigenschaft für eine Sache nachzudenken. Wir wollen hier eine Darstellung für eine Darstellung von Mengen in natürlichen Zahlen darstellen. So machen wir das indem wir eine Menge als eine Liste von natürlichen Zahlen zu einem Paaren von natürlichen Zahlen darstellen. Oben haben wir eine Typ-Definition, die sagt ISET ist ein Typ, und dieser Typ ist definiert als ein Synonym für eine Liste von Paaren von natürlichen Zahlen. Das bedeuten diese runden Klammern und jetzt einfach nur zu sehen, was das bedeutet. Hier habe ich eine Funktion, ich habe die Definition nicht hingeschrieben, aber was wichtig ist, ist die Typ-Signatur. Es bekommt eine Integer-Set und erzeugt eine Liste von allen Elementen in dieser Menge. Wenn ich jetzt Eitelist-Anwender auf diese Liste anwende, diese Brackets sind einfach nur eine Liste und diese Liste von 0 bis 3, von 5 bis 7 und von 9 bis 10, oder alles ist inklusive, und da unten sehen wir die Liste alle Elemente. Und dann haben wir aus der Erstkommen 0, 1, 2, 3, und danach geht das 5 noch 7, also 5, 6, 7, und dann die letzte gilt von 9 bis 10, also 9 und 10. Macht das, ergibt das Sinn? Und jetzt, wie ich das machen möchte, möchte ich das Intervallmenge, möchte ich strukturiert haben, eine gewisse Menge. Hier habe ich eine Funktion, die beschreibt, was es bedeutet, dass es ein valides Intervall, eine gute Intervallmenge ist. Und jetzt, wie ich das machen möchte, ist, dass es eine gute Intervallmenge ist. Wir wollen also nicht, dass zwei Intervalle sich überschneiden, also wir wollen sie disjunkt haben und wir wollen, dass die Reihenfolge gut ist. Das heißt, es gehen wir auch durch und es wellet, das ist eine Funktion, die sagt uns, ob eine Intervallmenge valide ist oder nicht. Es gibt drei verschiedene Fälle, die erste Gleichung sagt, dass die Menge, die leere Menge, das heißt, die leere Menge ist gut, ist gut, ist okay. Die nächste Menge besteht nur aus einem einzigen Intervall und dieses Intervall geht von low nach high, also von niedrig nach hoch und dieses Intervall ist valide, ist erlaubt, wenn low, kleiner, gleich ist high. Ist das okay oder verständlich? Und jetzt wird es etwas ein bisschen komplizierter. Und der dritte Fall ist, wenn man mindestens zwei Intervalle innerhalb dieser Menge hat und diese zwei Intervalle geht von low 1 nach high 1 und das zweite geht von low 2 nach high 2 und die erste Bedingung ist, dass wir wollen, dass die Intervalle sortiert sind, das heißt, low 1 ist kleiner, gleich high 1 und es soll eine Lücke zwischen zwei konsequentiven Intervallen sein. Das heißt, deswegen muss da high 1 plus 1 muss echt kleiner low 2 sein. Das heißt, das Ende von dem ersten Intervall muss separiert sein von dem zweiten Intervall, von dem low 2, von dem zweiten Intervall. Und wir erwarten, dass der Rest der Menge auch valide ist. Jetzt stellen wir uns vielleicht eine Vereinigungsfunktion, Unionfunktion vor und die Vereinigung ist ein Monoid, respektive zu diesem Intervallset. Wenn ihr so etwas schon mal geschrieben habt oder implementiert habt, dann wisst ihr wahrscheinlich, das ist wahrscheinlich ein bisschen tricky, das zu implementieren. Aber wie können wir das sicherstellen, dass das richtig wird, was wir implementieren? Was wir also machen ist, wir schreiben diese Eigenschaften auf. Wir können natürlich Assoziativität aufschreiben, das lasse ich als Übung. Und eine sehr einfache Eigenschaft, die wir schreiben, ist, dass für beliebige Paare von beliebigen die Vereinigung von diesen beiden Intervallsetten auch wieder ein valides, ein valides Set ist. Ein valides Intervallset ist, macht das Sinn? Hier ist eine zweite Eigenschaft, die sagt, okay, ich habe hier euch, ich habe schon diese E-Toolist-Funktion definiert, die gegeben eine Intervallmenge gibt. Das heißt, wir können diese Darstellung von diesen Mengen können wir als Modell benutzen und sagen, okay, wenn wir die Vereinigung von beliebigen Intervallmengen anschauen, das heißt, die Union von ISD1, ISD2, und wenn wir diese Liste, und wenn wir das zu einer Liste konvertieren, dann können wir auch genauso gut erst jedes individuelle Menge konvertieren mit E-Toolist und danach die Merchfunktion verwenden, also die Konkretinierung. Das ist also ein sehr einfaches Modell für Intervallmengen und solche Sachen sind sehr, solche Modelle sind sehr schön zu haben. Und ich habe vorher schon ein bisschen angefangen damit, vor dem Talk. Das sieht dann so aus. Das war meine Implementierung, die ich geschrieben habe. Okay, da habt ihr dieses Union ISD, geht auf ISD, geht auf ISD. Und die erste Zeile sagt, okay, wenn die erste Menge leer ist und ich habe die zweite Menge, dann gebe ich einfach nur die zweite Menge zurück. Das ist die klassische Eigenschaft, wenn ich eine Vereinigung habe. Und jetzt seht ihr den dritten Case. Da wird es ziemlich tricky oder kompliziert. Und die Hauptsache, die eigentlich hier mitnehmen soll, ist, dass es kompliziert ist. Die dritte Eigenschaft sagt, okay, wenn beide haben mindestens ein Element, das ist Low 1, High 1, und im zweiten Fall ist es Low 2, High 2, und dann gibt es den Rest. Und wenn Low 1 echt größer High 2 ist, dann wollen wir mit Low 2, High 2 anfangen und damit der Union von dem Rest. Aber in den anderen Fall, wenn Low 2 größer ist als High 1, also wenn das andere in den Ball zuerst kommt, dann fangen wir andersrum. Und wenn das in allen anderen Fällen, müssen wir die Intervalle merken. Also wenn die Intervalle nicht sortiert werden können, dann müssen wir die Intervalle vereinigen. Okay, und jetzt habe ich euch ja über euch schon dieses Quick Check Tool vorgestellt. Und das coole ist, wir können dieses Quick Check Tool auf das Laden und dann haben wir so eine Kommandozeilen auf Foto. Kommandozeile. Ich hoffe, ich mache das hier richtig. Also wir wollen Quick Check und wir wollen Prop Union Correct brauchen wir. Ich hoffe, der Name ist richtig. Und jetzt sagt er hier, er hat 100 Tests ausgeführt. Das heißt, Quick Check nimmt die Code-Version von deinen Eigenschaften und automatisch testet eure Properties. Und das sagt jetzt hier, das was du beschrieben hast, das ist korrekt. Es wird also immer Intervallenmengen produzieren. Das heißt, immer wird euch immer das richtige Resultat liefern. Es gab aber noch das andere Quiterum, das wir Union Valid genannt haben. Und hier, hier ist das tatsächlich der bessere Teil von Quick Check. Hier sehen wir, es ist falsifiziert. Das heißt, es gibt ein Gegenbeispiel. Es hat 9 zufällige Tests generiert und es hat ein Beispiel gefunden, wo die Eigenschaft nicht valide ist, wo sie nicht stimmt. Was wir jetzt machen können, ist, wir können jetzt dieses Beispiel kopieren. Und dann können wir das erkollen. Und was wir hier sehen, wir sehen also 2 und 4, 1 und 1 und 3 und 5. Das ist übrigens zufällig, das heißt, es kann immer wieder anders sein jedes Mal. Okay, es sagt diese beiden Intervalle, die sollten einfach vereinigt werden und es sollte eigentlich nur ein Intervall sein. Und das hat es aber leider nicht korrekt getan. Und der Grund dafür, vielleicht habt ihr das gesehen schon. Okay, was hier passiert ist, ich bin also in diesem Fall reingelaufen. Low 1 ist größer als High 2. Und ich habe ja euch gesagt, da muss ja mindestens eine Lücke sein, die größer ist als 1. Und hier ist ein Off-by-1-Fehler, also um einen Falsch. Aber hier können sie immer noch genau nebeneinander sein. Damit wir aber sicherstellen können, dass der immer eine Lücke ist, müssen wir hier 1 addieren. Das heißt, wir fixen das so. Und jetzt führen wir wieder den Test aus. Und nein, das gibt immer noch ein Gegenbeispiel. Das können wir auch ausprobieren. Das heißt, wir kriegen so Testfälle, die uns sagen, wo sind die Fehler. Und hier, okay, diese Intervalle überlappen sich immer noch. Aber was ist denn hier passiert? Könnt ihr das sehen? Ihr könnt also sehen, dass die ersten beiden Intervalle müssen in den letzten Fall hineinlaufen. Denn die überlappen sich, denn wir haben das Intervall von 0 nach 3 und wir haben das Intervall von 0 nach 5. Okay, das hat also diesen Fall gemirkt, diese beiden Intervalle vereinigt. Es hat aber leider diese Intervalle nicht mit 6 und 7 vereinigt. Okay, wenn ihr euch das anschaut, das muss also da reingelaufen sein. Und dann ist es mit dem Rest weitergegangen. Lasst uns das nochmal angucken, um zu sehen, was tatsächlich passiert ist. Es hat also die beiden vereinigt. Also, die beiden haben das Intervall, das hat also die beiden vereinigt. Und dann ist es ein Symmetrieproblem reingelaufen. Vielleicht seht ihr es auch nicht, aber es ist ziemlich kompliziert. Das könnte ich auch nicht alleine machen. Das heißt, es pukt das Resultat auf Iset 1 Rest, aber das Resultat, aber das Maximum von High 1 und High 2 könnte vielleicht die Konsistitätseigenschaften invalidieren. Den Fehler habe ich noch nie gesehen. Macht das Sinn? Aber könnt ihr sehen, dass das symmetrisch sein sollte? Das Letzte? Also versuchen wir es symmetrisch zu machen. Wir machen das also so. Das funktioniert also nur, wenn High 1 kleiner als High 2, also wir müssen es sicherstellen. Dann ist das Maximum von den beiden Zahlen High 1. Und das Maximum von den beiden Zahlen ist High 1. Und dann ist das perfekte Valid. Das ist kein Problem, das auf Iset 1 Rest zu packen. Und in dem anderen Fall, wenn High 2 größer ist, da müssen wir etwas anderes machen. Entfernen wir das da und packen das da vorne ran. Und jetzt sollte es ihm durch sein. So, um das zu holen, und ah, es ist durchgelaufen. Super. Vielen Dank. Ich habe das geübt, das Gestick zu schreiben. Ich habe das geübt, das Gestick zu schreiben. Ich habe das geübt, das Gestick zu schreiben. Das geht immer mit der alten Age, und das GAZE immer das Schwäte an meinem Vorhör. Ich weiß, all by one, es gibt immer so viele Fälle, und Quicktrick ist das, was aus der Box herausliest. Es ist ein großartiges Werkzeug, empfehle ich wirklich es auszuprobieren. Lasst mir schon ein paar Beispiele aus der realen Welt geben. Es gibt Exmonet, das ist ein Tiling Wind Fenster Manager. Und das funktioniert, weil es ist korrekt. Und warum ist es korrekt? Das ist, weil die sehr viele Eigenschaften für die Geometrie aufgeschrieben haben und für das Tiling und das mit QuickCheck überprüfen. Und für das mit QuickCheck überprüfen können. Don Stewart hat ein paar Blogposts über die vereinfachten Eigenschaften von Exmonet geschrieben, die ich jetzt hier benutze. Hier ist ein Beispiel für ein Window Manager. Es macht keine Geometrie, es hat einfach nur mehrere Fenster. Hier ist also ein Datentyp, der heißt Stackset. Es ist parametrisiert durch ein Fenstertyp. Es gibt einen Typparameter. Und dann gibt es einen Konstruktor. Es hat zwei Felder. Das eine ist der, die Nummer des aktuellen Arbeitsbereichs und das andere ist DEX. Das meppt einfach die Liste von den Fenstern auf die Zahlen, auf ihre Nummern. Und dann gibt es ganz viele Operationen, die auf dieser Konfiguration von Fenstern operieren. Also man kann beispielsweise ein leeres Stackset konstruieren. Wir haben die Nummer von einem Fenster, das wir vorne haben. Aber rotier es mir bitte so, dass es sichtbar ist. Das war View Peak heißt, gib mir den Fenster ganz open. Rotier mir die Fenster durch. Push heißt, gib das Fenster nach oben. Insert heißt, ich will ein Fenster zwischen das Stackset einfügen. Delete, ich will ein Slushen. Shift heißt, ich will etwas mit den Windows bewegen. Ihr könnt euch vorstellen, genauso wie wir das mit den Eigenschaften gemacht haben. Wir können jetzt hier Eigenschaften, die geltend müssen definieren, also Invarianten. Also beispielsweise die Zahl des aktuellen Fensters sollte nicht größer sein, als die Anzahl der Fenster in dem Stackset. Und wir wollen keine Duplikate in dem Stackset haben. So, all diese Funktionsdefinitionen sind nicht sehr kompliziert, aber wir können alle möglichen Eigenschaften dafür definieren. Zum Beispiel für das erste, für alle Paare von natürlichen Zahlen, die es in diesem Stackset gibt. Wenn ich die Viewfunktion dafür aufrufe, dann will ich, dass die Viewfunktion einen konsistente Stackset aufruft. Und genauso kann ich durchgehen für alle anderen. Hier unten seht ihr ein paar Prägequisite, die geltend müssen für alle Stacksets. Wenn die Anzahl des Fensters kleiner ist, als die Anzahl der Fenster im Stackset, dann muss kleiner sein, als sonst gibt es Probleme. Das ist ein Weg, um Eigenschaften zu erfinden. Und ihr könnt euch das dann als Eigenschaften aufschreiben und Quickcheck, die dann für euch überprüfen lassen. Ihr könnt euch vorstellen, dass sie sind jetzt vereinfachte Beispiele. Ihr könnt euch vorstellen, wenn ihr einen echten Tiling Manager habt, dass das viel mehr ist. Aber ihr könnt die gleichen Eigenschaften auch dafür behalten. Dann gibt es immer noch viel Konsistenz, auch mit Tiling, dass auch, weil er prächtig gemacht wird. Aber auch das könnt ihr als Eigenschaften definieren, die ihr dann mit Quickcheck überprüfen könnt. Hier ist ein Beispiel von unseren Sachen. Vor ein paar Monaten haben wir eine größere Visual Basic-Applikation mikriert. Hier seht ihr die Typen Signature und hier halten wir eine Eigenschaft. Also wenn wir von einem Passwort ein Hash generieren und es dann mit dem Hash in der Datenbank überprüfen wollen, dann soll das der gleiche Hash sein. Und zu unserer großen Überraschung ist das fehlgeschlagen. Diese Eigenschaft hat nicht gegolten. Und wir mussten das dann korrigieren. Weil in dem Datenbankenschema gab es eine Restriktion, sodass wir das zu elf Charaktere zusammen auf elf Charaktere zusammen... ...restriktet ist. Und manchmal geht Quickcheck eben auch hin und überprüft Dinge, die wir nicht erwartet hätten. Ein anderes Beispiel, das wir hatten für einen großen Industrie-Kunnen, haben wir eine Applikation entwickelt, die von zwei Kommunikationspartnern, wenn die Daten miteinander tauschen wollten, dann wollten wir nicht, dass sie jedes Mal alle Daten tauschen müssen, sondern nur die Daten, die auf der jeweils anderen Seite gefehlt haben. Dafür gibt es bereits großartige Algorithmen, die sind sehr kompliziert. Aber glücklicherweise ist die Eigenschaft dafür, aufzuschreiben, sehr einfach. Hier habt ihr die Eigenschaft dafür. Unsere Synchronisation, so Alkorithmus, arbeitet auf Blöcken von Daten. Als das seht ihr hier für alle Paare von Mengen von Daten, von Blockset 1 und Blockset von der Blockmenge 1 und Blockmenge 2. Und wenn wir davon die Vereinigung machen oder die Synchronisation aufrufen, dann kriegen wir zwei neue Blocksets, und das sind die, die auf die andere Seite geschickt werden. Und das Kriterium hier sagt, wenn wir das eine Set haben und die Vereinigung von dem wir kriegen, dann sollten wir beide haben am Ende. Und diese Eigenschaft sollte für beide Seiten gelten. Und wir wollen nicht Blöcke transferieren, die nicht in der zweiten Menge sind, als wir wollen, dass die Vereinigung leer ist, sodass wir nicht jedes Mal alle Blöcke an den Kommunikationspartner schicken. Ich habe Blut geschwitzt bei diesem Algorithmus. Es war sehr schwer, das zu schreiben. Aber dieser eine Test, der hat alle Bugs herausgefunden, die ich auf dem Weg dorthin gemacht habe. Also es ist wirklich sehr, sehr effizient. John Hughes hat ein paar Paper-Dach übergeschrieben. Er hat zum Beispiel damit Fehler geschrieben in einer verteilten Datenbank namens Misha. Und der Fehler war, einen Datei zu öffnen, und wir ist sofort wieder zu schließen. Und das ist kein typischer Fall, den ihr mit Unitests abdeckt. Und das würdet ihr nicht mit Unitests finden. Und wenn ihr dann das Ding schließt und gleich wieder öffnet, dann geht es kaputt. Und hier ist ein anderes Beispiel für Dworkbox. Und ihr könnt euch vorstellen, dass für Dworkbox ihr könnt euch vorstellen, dass es dafür Eigenschaften gibt. Aber das gibt es tatsächlich nicht. John Hughes hat das gemacht. Und er hat damit auch ein paar Fehler gefunden. Also Client1 schreibt in eine Datei A. Und dann löscht er die Datei. Dann schreibt ein zweiter Client in die gleiche Datei. Er setzt der B in A. Dann schreibt 1C in die Datei, die gerade noch gibt. Dann ist er einfach ein sehr cool Lärfer. Aber wenn man dann liest, dann erwartet man entweder B oder C, aber eigentlich war die gelöscht. So, die haben das jetzt gefilgt. Das funktioniert jetzt. Dann Fixtom hatte gerade einen aktuellen Blockpost über den ScreenCast-Editor. aber es ist nicht das Gleiche, als sein Beweis zu haben. Sie können euch immer noch vorstellen, dass ihr Kfw-Fälle findet, die nicht von Quick Shake abgedeckt werden. Es ist nicht das Gleiche, wie festzustellen, dass es keine Bugs gibt. Ich denke, das Tolle an Idris ist und warum ich es für diesen Tag ausgewählt habe, es beinhaltet nicht nur Eigenschaften, sondern auch Beweise in der Sprache. Wenn ihr nach oben guckt, das ist die Definition von einer Funktion, die es in der Standardbibliothek gibt. Und hier seht ihr, ich konkateniere zwei Listen. Und das Erste ist, wenn es die leere Liste konkantiniert, dann ist es die Gästenliste. Und das Zweite ist eine rekursive Definition von der Verbindung von Listen. Und hier ist die Definition von einer Funktion, die heißt Append Assange. Die sagt, wenn ihr eine Liste A, B und C habt, dann sollte die Assoziativitätseigenschaft gelten. Und das ist jetzt der Status von dieser Funktion, dass es nicht das Gleiche wie ein Beweis ist. Wer hat gerne Beweise in Mathe geschrieben, das großartige an Idris ist, das hilft euch Beweise zu schreiben. Also hier ist das, was ihr gerade auf dem Slide gesehen habt. Und jetzt kann ich das hier laden. Und in Idris kann ich jetzt ein paar Knöpfe drücken. Und das sagt mir, oh, du solltest deinen Beweis für diese Funktion schreiben. Und dann kann ich einen zweiten Knopf drücken, der sagt, ach, wenn du das auf Listen machst, dann musst du zwischen zwei Fällen unterscheiden. Einmal von leeren Listen und einmal von Listen, die als erstes Element das Element X haben und dann XS. Dann kann ich noch einen Knopf drücken. Das habe ich nicht geschrieben. Das sagt mir dann Refle. Was könnte Refle wohl sein? Dann kann ich einfach fragen, was ist Refle? Dann sagt mir das, ach, Refle ist einfach nur ein eingebautes Weiß. Das sagt, dass zwei Elemente gleich sind, wenn sie gleich sind. Das macht irgendwie Sinn in der ersten Gleichung, weil die erste Gleichung von Append Assertion baut es auf der Definition von plus plus auf. Die erste Liste ist der, könnt ihr das sehen? Könnt ihr das sehen, wie die erste Liste leer ist? Und die ist der da oben mit dem plus plus? Könnt ihr das sehen? Okay. Und dann sagt es einfach nur, so wie die Definition funktioniert, passt das. Aber was sehr wichtig ist, ist, dass Edrys das akzeptiert. Im zweiten Teil ist es etwas komplizierter. Aber hier können wir uns auch helfen, weil wir wissen, dass Append Assertion recursiv ist, also es recursiviert auf dem ersten Element. Und wir können Edrys also sagen, dass es das benutzen sollte, also diese Eigenschaft. Hier ist der recursive Aufruf. Und wenn ich das jetzt schreibe, dann lädt es nochmal Refle. Das ist jetzt mysteriös für euch, wie das funktioniert. Aber das da ist jetzt ein Beweis von der associativitätseigenschaft von der Append Assertion. Da Edrys das alles euch dabei hilft, ist es sehr lustig, das so zu schreiben. Die Art mit Edrys zu programmieren ist, also viele Eigenschaften in die Typen zu schreiben. Und dann wird Edrys für euch die Definition herausfinden, und ihr müsst das nicht selber machen. Und diese sogenannten Beweisassistenzsysteme, wie ihr Edrys eins ist, gibt es dann noch andere, so wie Selv 4. Es wurde bewiesen, dass Selv 4 keine Probleme hat. Mit solchen Systemen, Konzert wurde auch mit solchen Systemen überprüft. Selv 4 wurde mit Isabel überprüft. Konzert wurde auch, das ist ein C-Compiler, der wurde überprüft. Der Source Code ist certifiziert, aber vorher weiß man, dass der Compiler auch korrekt den Code generiert. Aber jetzt wissen wir, dass es verifiziert worden ist. Und das ist alles sehr schwierig zu überprüfen. Und für je macht man, dass man halt Checker schreiben, den Code den Output überprüft. Dafür gibt es dann Tools. Wir haben jetzt Edrys gesehen, dann gibt es auch noch andere. Also, um einen Gang zurückzuschalten, es gibt sehr viele eigentliche Einschaften in euren Programmen. Zum Beispiel Kommentativität. Wenn ihr Vergnüpfungen habt, dann gibt es Reflexivität. Relation habt, dann gibt es Reflexivität, Symmetrie, Antisymmetrie, Transativität. Reflexivität bedeutet, dass es immer Relation zu sich selber ist. Symmetrie bedeutet, wenn A in Relation zu B steht, B auch in Relation zu A. Antisymmetrie ist das Gegenteil davon. Also, beispielsweise Ordnungsrelation sind antisymmetrisch. Und hier ist ein kleines Wörterbuch von nützlichen Eigenschaften. Dann gibt es etwas außergewöhnlichere Eigenschaften, wie zum Beispiel Funktor. Ja, vielleicht eine Funktion entdeckt in eurer Programmiersprache, in einer Bibliothek, Map. Selbst Chava hat diese Funktion, was also Map macht. Und dann habe ich eine Liste von Funktionen. Dann kann ich eine Funktion auf all diese Elemente anwenden. Das kann man aber noch generalisieren auf anderen Typen. Und in Idris kann man natürlich Gleichungen für Funktoren aufschreiben. In dem, wenn ihr euch hier anschaut, wo es Funktionen sagt. Und G gibt auf A zurück, also das ist die Identitätsfunktion. Also, wenn ihr die Identitätsfunktion auf jedes Element von der Liste anwendet, dann habt ihr die gleiche Liste wieder. Und hier gibt es noch Funktor-Composition. Also, wenn ihr ein Funktor auf einen anderen anwendet, also dann solltet ihr da wieder das gleiche Resultat rauskriegen. Aber da können wir uns ja noch, wo kann man sich Funktoren also anziehen. Also, vor ein paar Jahren in einer Fortbildung hat jemand gesagt, aber du fängst selber an mit dem Tierbeispiel, da könnte man doch sicher was finden. Und da habe ich mir überlegt, gibt es das. Und dann, wenn wir wieder zurück zu dem Tierbeispiel gehen, für Funktoren braucht man also einen Typenparameter. Und wenn wir uns hier Dilo und Papagei wieder ansehen, die haben beide dieses Gewicht. Und die beiden anderen Eigenschaften sind spezifisch für das Tier. Und hier habe ich also geändert, das erweckt ein Gewicht, von einem großgeschriebenen zu einem kleingeschriebenen Parameter wurde. Also, was habe ich jetzt hier gemacht? Wir haben jetzt unterschiedliche Darstellungen von Gewicht. Und wenn wir uns jetzt das Gewicht von Tieren ansehen, dann sehen wir, dass ein überfahrenes Tier nicht weiß, was sein Gewicht ist. Und das bedeutet, dass das Gewicht sich nicht ändern kann. Und das bringt mich jetzt zum Ende. Also in eurem Domainmodell sucht nach einer Funktion, die zwei Dinge miteinander kombinieren in ein größeres Ding. Schaut, ob ihr dieses Ding assoziativ machen könnt, ob ihr ein neutrales, neues Element findet, macht daraus ein Monoy. Sagt dieses Wort ein paar Mal, dann werden die es euch merken. Schreibt Eigenschaften, testet diese Eigenschaften mit QuickStack. Wenn ihr Zeit dafür habt, dann beweist sie auch, findet einen Funktor. Und das dauert ein bisschen Zeit, wie ihr sehen könnt, bin ich sehr alt. Aber es wird leichter mit den Jahren. Wenn die wichtigen Eigenschaften in eurem Programm entweder aufgeschrieben oder getestet oder sogar bewiesen sind, dann könnt ihr viel besser schlafen in der Nacht. Vielen Dank. Das war die deutsche Übersetzung von Getting Software Right with Properties Generative Tests and Proofs von Mike's Burger. Eure Besetzer waren Pascaline und Bubbler. Wir freuen uns über Feedback entweder per Mail ein Hallo C3Lingo oder über Twitter mit dem Hashtag C3T. Also QuickCheck hat 100 Tests generiert. Was wissen wir über diese Tests, sind 100 Tests gut? Sehr gute Frage. QuickCheck kommt mit sehr vielen Werkzeugen, das dir zum Beispiel die Verteilung der einzelnen Beispiele zeigt. Wir haben das so noch nicht gesehen oder ich habe das noch nicht gezeigt. Aber man würde normalerweise Generatoren für diese Beispiele schreiben. Man kann in diesen Generatoren über diese Verteilung nachdenken. Darüber sollte man auch drüber nachdenken, weil man sonst vielleicht große Bereiche seines Testraums nicht testen würde. Aber selbst wenn ihr das nicht tut, werdet ihr sehr viele Fehler wachsen. Oder ich finde auch sehr viele Sachen Fehler in meinem Code, selbst wenn ich nicht danach gucke. Aber ansonsten schaut euch Distribution an. Danke. Next one, please. Nr.2. Angenommen, ich habe ein Programm zusammengehackt in Java oder in C-Sharp. Wie kann ich das, was ich heute gelernt habe, dort an, wenn ich schon ein fertiges C-Sharp-Programm habe? Wie kann ich da QuickCheck drauf an? Jetzt kommt der Programmi-Sprach, weil es in C-Sharp geschrieben ist. Okay, um ganz konkret zu sein. Wenn ihr an Eigenschaften nachdenkt, zum Beispiel C-Sharp könnt ihr mit F-Sharp verknüpfen. Es gibt eine QuickCheck-Version für F-Sharp, das heißt FS-Check. Obwohl FS-Check in F-Sharp geschrieben ist, könnt ihr das aber auch in C-Sharp nutzen. Du hast also zwei Möglichkeiten. Du kannst entweder den Test in C-Sharp schreiben, ein bisschen merkwürdig vielleicht. Oder ihr schreibt eine F-Sharp-Test-Suite und macht das dort. Es gibt doch eine sehr praktische Java-QuickCheck-Version. Also das würde ich vielleicht etwas in fancyere, übschere Version in Scala verwenden. Was wird das für die Frage? Also für die Sprache, die ich benutze, muss ich herausfinden, was die richtige Inventation ist. Ja, genau. Aber in der Regel, in meinen Kursen, und es gibt in der Regel, fragt jemand irgendwie für PHP oder so, in der Regel gibt es einmal eine Version von QuickCheck.