So, sie sehen hier heute Vorlesung 0-2.2.1.
Es ist ganz innovativ. Die erste Vorlesung dauert heute
ungefähr 20 Minuten und dann kommt 0-2.2.
Das sind nämlich zwei Themen, über die ich heute sprechen werde.
Das erste Thema ist das sogenannte Vertragsmodell der Softwareentwicklung.
Da werden wir uns so anschauen jetzt,
wie kann man die Beziehungen zwischen Klassen so gestalten,
dass eine höhere Zuverlässigkeit in ihre Software von ihnen eingebaut
werden kann
Und der zweite Teil der Vorlesung,
da greifen wir das schon aus SE1, bekannte Thema,
Testen auf. Wenn wir schon in der Lage sind,
zuverlässigere Software zu schreiben, dann schreiben wir noch lieber Tests,
die uns ein noch besseres Gefühl dafür geben,
dass die Software auch das tut, wofür wir sie geschrieben haben.
Und noch ein paar Gründe mehr. So,
diese zwei Themen werde ich heute versuchen mit Ihnen durchzuackern.
Dann wie immer nach 45 Minuten, Fred wird
das Ganze in Java grundieren
Motivation des Vertragsmodells. So ein paar Worte habe ich jetzt schon drüber gedacht,
gedacht auch, auch ein paar Worte drüber gesagt.
Dass so eins der größeren Ziele, die mit der objektorientierten Programmierung verbunden sind,
ist die sogenannte Wiederverwendbarkeit von Bausteinen, von Softwaresystemen.
Was haben Sie so an Bausteinen kennengelernt? Namentlich Klassen. Jetzt,
wenn da steht, Wiederverwendbarkeit, das ist also eigentlich
das Also es wird vielfach bei großen objektorientierten Entwürfen,
wird auf Wiederverwendbarkeit der entwickelten Bausteine hingearbeitet.
Mitunter geht dabei das Ziel verloren, das Primärziel der Softwareentwicklung,
nämlich Verwendbare Software zu schreiben. Deswegen sollten sie sich,
so wenn sie das hier lesen, Wiederverwendbarkeit von Bausteinen wird angestrebt.
Das erste Ziel, das sie verfolgen, ist Verwendbarkeit.
Erst Verwendbarkeit und dann kommt Wiederverwendbarkeit. Die Namen der Namen
. Irgendwas wird hier noch passieren
Im Laufe des... Nur so am Rande.
Am Sonntag wurde mein Auto aufgebrochen. Alles Mögliche geklaut.
Jetzt steht es in der Werkstatt und jetzt gerade fahre ich
hier hin und greife so automatisch zu der Klappe,
wo ich sonst immer den Adapter drin habe.
Natürlich habe ich ein anderes Auto und keinen Adapter dabei.
Da habe ich gesagt, Fred angerufen,
kann ich das auf deinem Laptop zeigen?
Sagt Fred, ja klar, aber ich habe keinen PowerPoint.
Es ist... In dieser Vorlesung ist der Wurm drin.
So, Verwendbarkeit
Von Bausteinen. So, das erste Verständlichkeit, Sinn und Zweck
einer Klasse und der darin enthaltenen Methoden mindestens der exportierten Methoden müssen verstanden werden.
Und die Frage ist dann, was liefert uns, also das sogenannte objektorientierte Modell?
Was haben Sie denn so an Möglichkeiten? Naja gut,
also Sie können Text, Klassentexte schreiben,
das ist also exportierte Operationen, die haben Namen,
die haben hoffentlich, also sprechende Namen, sprechende Parameter.
Ansonsten steht Ihnen eigentlich wenig zur Verfügung,
außer dass Sie Kommentare schreiben können und die Kommentare sind ja
so in natürlicher Sprache, ob das unbedingt verständlich ist,
man kann das hoffen, formal ist es eigentlich wertlos.
Deswegen steht da, was also fehlt,
wenn wir Programme schreiben und deren Verständlichkeit erhöhen wollen,
die Verständlichkeit von Klassen erhöhen wollen. Wir können die Semantik,
also das, was eine Operation bedeuten soll,
das können wir nicht mit den Mitteln ausdrücken,
die wir bisher kennengelernt haben.
Und das Vertragsmodell ist eine Idee,
wie wir eine Klassenspezifikation um semantische Informationen anreichern können.
Das hört sich jetzt alles ein bisschen wahrscheinlich noch
ein bisschen abstrakt an
Insbesondere Vertragsmodell, Verträge. Hat das jetzt was mit Rechtsanwälten zu tun?
Dazu mal eine Frage studiert, jemand im Nebefach, vielleicht Jura?
Gar nicht. Okay. Gut, dann nicht. Dann
kann ich ja frei über Verträge sprechen. Also was das
so bedeutet. Also ich habe jetzt nichts Besseres eingefallen.
Uns ist nichts Besseres eingefallen, als das mal im Wikipedia nachzuschauen.
Es schien uns noch eine halbwegs verständliche Definition.
Und für unsere Zwecke ist die alle mal ausreichend.
Also was ist so grundsätzlich ein Vertrag zwischen zwei oder mehreren Vertragspartnern?
Mal müsste wahrscheinlich stehen
Freiwillig geschlossene Übereinkunft, die hinterher herbeiführung als von den Parteien gewollten Erfolges.
Durch übereinstimmende Willenserklärung zustande, da weiß man doch,
warum man nicht Jura studiert. Das ist also
die Idee eines Vertrages und dann sehen Sie gleich drunter,
sehen Sie die softwaretechnische Interpretation, also im Rahmen des sogenannten Vertragsmodells.
Wir betrachten zwei Klassen, die zueinander in Beziehung stehen als Vertragsparteien.
Die eine Klasse nennen wir Dienstleister,
die stellt eine oder mehrere Dienstleistungen in Form von exportierten Operationen
zur Verfügung andere nennen wir den Klient.
Und die Beziehung, in der die stehen, ist die Benutztbeziehung.
Das ist die Beziehung zwischen Klassen, die wir jetzt, die sie bisher kennen.
Wir werden noch eine weitere Art von Beziehung zwischen Klassen,
im Laufe des Semesters kennenlernen. So, das heißt,
diese beiden Klassen, die eine als Klient,
die andere als Dienstleister, die sollen einen Vertrag miteinander schließen.
Und wir gucken uns jetzt mal an, wir schauen uns
jetzt mal an, wie dieser Vertrag gestaltet werden soll.
Die Idee ist, dass der Klient einer anderen Klasse,
der Klient des Dienstleistes, sieht, welche Vorbedingungen er liefern muss,
damit der Dienstleister bereit ist, diese Dienstleistung durchzuführen.
Aha. Ein Beispiel, wo ich gerade von Auto
und kaputt und Scheibe gesprochen habe. Die Dienstleistung, die
die Werkstatt anbietet, die Klasse Werkstatt ist reparieren. Okay,
da gehe ich also als Klient hin und die Voraussetzung dafür,
dass die mein Auto reparieren ist,
dass ich das da abliefere
Das heißt, unter dieser Voraussetzung und wahrscheinlich also noch meiner Zahlungsfähigkeit
sind die bereit, diesen Vertrag mit mir zu schließen.
Es ist also so eine Sichtweise, die ich so aus
dem normalen Leben auf Softwareentwicklung übertrage. In dem Moment,
in dem die Vorbedingungen für eine Dienstleistung gegeben sind,
muss derjenige, jetzt im Sinne von objektorientierten Programmen,
muss derjenige, der diese Dienstleistung anbietet,
sie erfüllen.
Und er muss
bestimmte Nachbedingungen garantieren
Also die Nachbedingungen in meinem Autobeispiel ist,
also ich habe euch das Auto gegeben und ich habe euch Geld gegeben und was ich gerne hätte,
ist ein Auto zurück, im Zustand repariert.
Das ist doch ganz normal, oder? Genau so möchte
ich die Verträge zwischen Klassen, als Klienten und Dienstleister,
möchte ich die auch formulieren. Das ist eine ganze,
wie will ich sagen, Programmierschule,
aber es ist so eine Art über objektorientierte Programmierung nachzudenken,
die ursprünglich von einem Menschen namens Bertrand Meyer in die Diskussion
gebracht wurde für die Franco Villen unter ihnen,
Bertrand Meyer
Der hat das sogenannte Design by Contract in die Diskussion, über objektorientierte Programmierung gebracht.
Und der hat mit der Programmiersprache Eifel, Effell,
hat er dieses Vertragsmodell erstmalig implementiert und nutzbar gemacht für die Objektorientierte Programmierung.
Jetzt sehen Sie gleich ein Beispiel, wie so eine
Beziehung zwischen Klienten und Dienstleister, wie die aussehen kann.
Wir haben hier so als Dienstleister, was haben wir hier,
The Task of Inscerting as certain element into addictionary,
also der Stictionary ist der Dienstleister und dieser Dienstleister
bietet eine exportierte Operation Put an
So, die, der Kommentar dazu sagt,
also züge das X so ein, dass es durch den Schlüssel,
den man auch als Parameter übergibt, dass es darum wieder zugreifbar wird.
So weit hätten sie das bisher auch in Java implementieren können.
Was jetzt hinzukommt, was also zur Spezifikation dieser exportierten Operation hinzukommt,
ist, sind diese beiden Vorbedingungen, diese beiden Randbedingungen,
Zusicherungen, die hier hinter dem Schlüsselwort Require stehen.
Require bedeutet, die Voraussetzung dafür, der Code der Operation
Putt überhaupt durchgeführt wird, ist erstens der Count.
Das wird wahrscheinlich eine exportierte Operation sein. Der Count,
der im Moment, also die Anzahl der Elemente,
ist kleiner gleich der Kapazität des Dictionaries.
Und die zweite Vorbedingung, die eingehalten werden muss, ist,
dass der als Parameter übergebene Key, dass der nicht leer sein darf.
Also der Schlüssel darf nicht leer sein. Das scheint mir
auch eine nachvollziehbare Vorbedingung zu sein. So,
und jetzt versuchen Sie sich für den Moment vorzustellen,
Sie wollen also ein Jig Dictionary benutzen.
Das steht in der Bibliothek, in einer Library-Neudeutsch,
steht Ihnen das als Klasse zur Verfügung.
Und jetzt sind Sie doch schon viel schlauer,
als Sie ohne diese beiden genannten Vorbedingungen wären.
Sie sehen also, okay, ich muss also als jemand,
der die Operation Putt aufruft, muss ich erst mal überprüfen,
passt noch was rein.
Ich sollte also erst mal die Operation Count aufrufen.
Wenn er noch was reinpasst, also die entsprechende Antwort bekomme,
dann kann ich diese Operation aufrufen unter der weiteren Voraussetzung.
Ich sollte nicht einen leeren Schlüssel übergeben
Umgekehrt bedeutet das für denjenigen, der diese Operation nach außen,
also für den Dienstleister, der sie zur Verfügung stellt,
ich liste jetzt hier mal eine Menge von Voraussetzungen von Vorbedingungen auf.
Und ich überprüfe diese Vorbedingungen auch zur Laufzeit, wenn diese Vorbedingungen
nicht erfüllt sind, dann werde ich diese Operation nicht durchführen.
Und das schafft jetzt auf beiden Seiten des Vertragsverhältnisses,
schafft es jetzt Klarheit darüber, wer ist hier eigentlich für was zuständig.
Und das ist ein nicht zu überschätzender Vorteil oder nicht zu unterschätzen davor,
naja, es ist jedenfalls ein Vorteil. Wenn man diese,
wenn man diese Vertragsrandbedingungen so klar benennen kann und sie auch zur Laufzeit überprüft,
so, weil dann ist immer klar,
wer ist hier eigentlich für was zuständig und für die Einhaltung der Vorbedingungen ist der Aufrufer, der Klient zuständig.
Die zweite Art von Randbedingungen, die hier beispielhaft genannt werden,
ist das, was hinter dem Schlüsselwort Enschuhe steht,
Enschuhe ist auch ein, also Schlüssel war den Eifel,
das bedeutet, nach Ausführung des Codes, dieser exportierten Operation,
gelten die folgenden Randbedingungen.
Also die Operation Hass liefert Two, so die Bedeutung wird wahrscheinlich sein,
nun, das X ist Element, also der Destiction Learies.
An der Stelle des Schlüssels steht auch tatsächlich das Item X.
Und das ist jetzt hier so eine Besonderheit von Eifel.
Man kann auf den Zustand des Objektes zugreifen,
der vor dem Aufruf der Operation gegolten hat.
Das macht man mit dem Schlüsselwort Old. Das ist wohl
was die Umsetzung anbetrifft, relativ aufwendige, teure Laufzeitoperation,
das gibt es also so in kaum einer anderen Sprache,
Ader, 2012 hat das Vertragsmodell auch implementiert.
Aber das ist oft ganz hilfreich,
also wenn man aus den alten Zustand zugreifen kann,
weil man ja durch die Ausführung des Codes in der Regel
jedenfalls oder nicht in der Regel häufig eine Veränderung des Zustands bewirkt,
und dann kann man diese Veränderung überprüfen.
So, für das Einhalten der Nachbedingungen ist jetzt nicht Der Aufrufer,
nicht der Klient zuständig, sondern dafür ist der Dienstleister zuständig.
Das, denke ich, ist auch sinnvoll,
weil der Aufrufer hat ja überhaupt keine Kontrolle darüber,
was eigentlich im Code der exportierten Operation, was da durchgeführt wird.
Insofern, der Dienstleister garantiert das Einhalten der Nachbedingungen.
So, Sie sehen, dieses Beispiel ist entnommen,
wenn ich richtig informiert bin, direkt aus den Eifelbibliotheken.
Das ist also, das Dictionary ist so eine Standard-Datenstruktur,
die da zur Verfügung gestellt wird.
Und Axel konnte sich nicht verkneifen, dass die Vorbedingung Count
kleiner gleich Capacity, die wohl ein bisschen schwach ist.
Also weil wenn man noch was einfügen sollte und der Account
ist gleich Capacity, dann wird es nicht klappen.
Also sollte die Vorbedingung besser Account kleiner Capacity sein,
aber um das mal wieder positiv zu wenden,
man sieht gleich, man guckt auf diese Spezifikation drauf,
sagt, also das sind die Vorbedingungen.
Okay, ich verstehe das, sowohl welche Dienstleistungen dort exportiert wird,
als auch unter welchen Randbedingungen ich sie aufrufen kann.
Und ich verstehe, was diese Operation liefert. Insofern erhöht das,
was sich in der ersten Ruhe auf der zweiten Folie gesagt habe,
erhöht diese Art von Spezifikation die Verständlichkeit von die Verständlichkeit von Operationen,
sprich die Verständlichkeit von Klassen letztendlich.
So, so sieht das dann also aus, die,
wenn man das nochmal auf dieses ursprüngliche Modell zurückführt,
der Dienstleister bietet Operationen an,
diese Operationen können aufgerufen werden unter bestimmten Randbedingungen.
Diese Randbedingungen sind bullsche Operationen und diese Bullschen-Operationen müssten dann natürlich
auch an der Export-Schnittstelle einer Klasse,
also hier des Dienstleisters vorhanden sein,
damit der Klient in der Lage ist,
diese Vorbedingungen auch aufzurufen
So, hier steht noch so als Randbedingung,
eigentlich ist das, oder als zusätzliche Information,
insbesondere dürfen keine privaten Exemplarvariablen im Vertrag auftreten,
da ein Klient keinen Zugriff drauf hat.
Ja, das, wenn man verhindern will,
dass eine Operation aufgerufen wird,
dann sollte man das als Vorbedingungen nennen und damit ist das Geschäft geschlossen.
So, ein weiteres Beispiel, der ist Deck,
den haben Sie ja auch schon in SE1 am Ende kennengelernt.
Wir haben letzte Woche,
hat Fred ihnen
einen Stack implementiert
So sieht ein Stack, jedenfalls ausschnittsweise. So sieht er
in Eifel implementiert aus. Sie können also die Operation Papp nur aufrufen,
wenn die Vorbedingungen gilt, dass das Ding nicht leer ist.
Ja, das ist so. Von einem leeren Stapel kann man nichts runternehmen.
Nur wenn diese Vorbedingungen gilt, dann kann die Anzahl,
dann ist es eine sehr einfache Implementation hier,
wird die Anzahl der Elemente um eins runtergesetzt.
Und dann kommt eine unfassbar starke Nachbedingung. Also unter der Voraussetzung,
dass der Stack nicht leer ist und ich nehme ein Element runter,
dann garantiere ich als Dienstleister,
danach ist er nicht voll
Okay. Sagen wir mal, das ist eine vergleichsweise schwache Nachbedingung, oder?
Was auch zeigt, Vorbedingungen und Nachbedingungen sind jetzt Sprachmittel,
die in dieser Sprache direkt zur Verfügung gestellt werden.
Sie werden kennenlernen, wie sie das in Java nachbilden können,
mit den dort vorhandenen Sprachmitteln.
Aber was sie letztendlich daraus machen, ist wiederum ihnen überlassen,
da wir wissen, dass die Narren immer etwas einfallsreicher sind
als wir
Voraussetzung, dass wir nicht schon darin sind. Dass wir sehen,
das ist also eine fast schon nerische Randbedingung hier,
wenn man von einem nicht leeren Steck was runternimmt,
ist er nachher nicht voll.
Okay. So, hier ist jetzt noch ein weiteres Sprachmittel genannt.
Das ist die In-Variante von Klassen. Die In-Variante bedeutet,
ich habe es glaube ich auch auf der nächsten Folie.
Ja, die Klassenin-Variante, die Das, was wir bisher kennengelernt haben,
sind also Vor- und Nachbedingungen für Operationen, hier Routinen genannt.
Die gelten jeweils für den Aufruf einer Operation.
Eine Klasseninnenvariante gilt für die gesamte Lebenszeit eines Objektes.
Beispiel für eine sortierte Liste gilt immer, dass die Operation issorted,
wenn die denn angeboten wird als exportierte Operation.
Eine Klasse sorted List, dass die True liefert.
Ja, so eine sortierte Liste sollte immer sortiert sein.
Abgesehen von ganz kleinen Ausnahmen, auf die glaube ich,
gleich noch zu sprechen. So, diese Randbedingungen gilt,
also die Klasseninnenvariante gilt immer, fast immer.
Und für jede Operation spricht sich das Vertragsmodell jetzt also so,
wenn der Klient die Vorbedingungen erfüllt, dann garantiert der Lieferant,
dadurch, dass er den Code der Operation ausführt, die Nachbedingungen.
Und jetzt weiß jeder, was er zu tun hat,
jeder weiß, wofür er zuständig ist,
das erhöht die Verständlichkeit von Softwarebausteinen ganz erheblich zusammen mit dem Element,
das wir jetzt gleich noch kennenlernen werden,
nämlich dem testen
Jetzt kommen wir mal zu der sogenannten Korrektheit oder das,
was man so im Rahmen dieser Vorlesung unter Korrektheit verstehen kann.
Korrektheit eines Objektes kann nur in sogenannten stabilen Zuständen geprüft werden.
Das heißt, vor und nach der Ausführung von Operationen.
So, das ist jetzt der Punkt,
auf den ich gerade schon so angespielt habe,
dass eine Innenvariante einer Klasse immer gilt.
Sie gilt immer in stabilen Zuständen. Was ist ein
stabiler Zustand? Ein stabiler Zustand ist vor und nach dem
Ausführen einer exportierten Operation. Ich mache Ihnen das wiederum,
versuche das
an einem Beispiel klarzumachen
Nehmen wir unsere sortierte Liste. Und der Sortieralgorithmus, den Sie verwenden
, ist es meinetwegen Bubble Thord. Das heißt also,
wenn hier oben das kleinste Element ist und da unten ist das größte Element und Sie fügen ein Element ein,
dann funktionierte dieser Algorithmus ja so, dass dieses Element,
ich merke gerade, dass meine Bubble nach unten bubbeln,
so kontraintuitiv,
aber meine Bäume wachsen ja auch nach unten.
Insofern ist es wieder nur konsequent. Das also beim Bubbeln eines Elementes,
bis an seine richtige Stelle, Liste zwischendurch mal nicht sortiert ist.
Nämlich bis zu dem Zeitpunkt, bis dieses Element seine richtige Stelle gefunden hat.
Also nicht das Element, sondern der Algorithmus, die richtige Stelle gefunden hat.
Das heißt, in all diesen Momenten wäre die Innenvariante verletzt,
ist die Liste nämlich gerade nicht sortiert.
Das interessiert aber keinen, weil es ist gerade keine stabiler Zustand.
Stabil ist der Zustand vor dem Aufrufen der Einfüge Operation
und nach dem Aufruf der Einfüge Operation,
weil dann muss garantiert sein,
dass die richtige Stelle
gefunden worden ist
Insofern sind diese stabilen Zustände, die Zustände, die uns interessieren,
wenn wir über die Korrektheit einer Klasse im Sinne des Vertragsmodells sprechen.
So, das ist auch damit gemeint, wenn hier steht zwischenzeitlich,
also während der Ausführung einer exportierten Operation,
kann die in Variante verletzt sein.
So, jetzt sehen Sie hier die Zusammenfassung.
Wann ist eine Klasse K im Sinne des Vertragsmodells korrekt?
Ben, erstens, beim Erzeugen eines Objektes,
die Vorbedingungen des gerufenen Konstruktes erfüllt ist,
weil da kann die Klasseninvariante noch nicht gelten.
Schließlich wird das Objekt
ja gerade erst erzeugt
Also du musst dann nur die Vorbedingungen des Konstruktors erfüllt sein.
Wenn die dann mit der Konstrukte ausgeführt,
dann muss die Nachbedingung des Konstruktors erfüllt sein und die In-Variante der Klasse und für jede gerufene,
exportierte Operation, das habe ich gerade gesagt,
also die einzelne Vorbedingung muss geprüft oder die Vorbedingungen der Operationen müssen gültig sein.
Die In-Variante wird jeweils logisch gewundet zu den Vorbedingungen und die Nachbedingungen müssen zusammen mit der Innenvariante gültig sein.
Dann ist eine Klasse also wenn diese Bedingungen alle gelten,
dann ist eine Klasse im Sinne des Vertragsmodells korrekt.
Nun zu Java. Gibt es da das Vertragsmodell? Nein, gibt es nicht. James Gosling,
derjenige, der Java mal, nicht mal, der Java entwickelt hat,
sie sehen das hier, der kannte das Vertragsmodell,
als er Java entwickelt hat und hätte es auch gerne eingebaut,
aber dann hat es wohl so Diskussionen darüber gegeben,
machen wir es oder lassen wir es.
Und er hat also, was sagt er,
das mangelnde Verständnis der meisten Programmierer, der damaligen Zeit,
das Konzept hat ihn dann aber davon abgehalten, was er inzwischen bedauert.
Ich bin da leider nicht auf dem letzten Stand, Fred.
Ist das nicht geplant, dass dann jetzt, ist es nicht geplant? Gut,
dann werden wir im nächsten Interview von James Gosling vielleicht lesen,
das mangelnde Verständnis der meisten Programmierer, streichen sie der damaligen Zeit für das Konzept,
hat ihn auch heute davon abgehalten, was er immer noch bedauert.
Es ist schon, es scheint eine gewisse intellektuelle Hürde damit verbunden
zu sein oder es engt Leute zu sehr ein, ich weiß es nicht. Jedenfalls,
also wir, die wir hier stehen,
auf dieser Seite des Podiums, wir halten das,
also nicht ich wir, sondern wir, wir,
wir halten das für eine extrem sinnvolle Angelegenheit und machen sie sich damit vertraut,
wenn es darum geht, langlebige Software zu bauen,
dann hast du das Vertragsmodell ein, ich will nicht sagen unverzichtbar,
aber mindestens ein extrem sinnvoller Bestandteil.
So, wir müssen also das Vertragsmodell in Java,
müssen wir nachbauen, es gibt dazu, Sprachmittel,
die wir so einsetzen können,
als wäre das Vertragsmodell ein Bestandteil von Java
Es wird ihnen Fred im Detail, wird er ihnen das erläutern. So was,
wie man, also das, was wir ausdrücken wollen,
nämlich, dass bei der Operation einzahlen auf ein Konto,
der Betrag größer gleich null sein muss.
Man könnte auch sagen, der muss größer als null sein.
Ein Betrag null einzuzahlen, also kann man gleich drüber reden.
So, wie man das mithilfe des sogenannten Third-Statements,
wie man das umsetzt und welche Alternativen sie dafür in Java
mit Eclipse zur Verfügung gestellt bekommen
So. Ein Wort noch dazu. Also das,
wir werden uns auch in den Übungen, werden wir uns fast,
nicht nur befasst, sondern ausschließlich mit der Implementation von Vorbedingungen beschäftigen.
Wir werden keine Nachbedingungen überprüfen. Sie sehen, also die
Begründung dafür, sehen Sie hier an die Wand geworfen.
Das Verhältnis zwischen Nutzen und Aufwand ist,
also bei Nachbedingungen ist es viel schlechter,
jedenfalls in dem Zusammenhang,
in dem wir uns jetzt damit beschäftigen,
als es bei Vorbedingungen
der Fall ist
Also werden wir uns jetzt auf Vorbedingungen konzentrieren.
Sie haben das Konzept dann kennengelernt und später in der Praxis,
hoffentlich werden sie sich dann auch mit der Implementation von Nachbedingungen
und wahrscheinlich sogar Klasseninvarianten beschäftigen.
So, das erstmal zum Vertragsmodell. Das ist also jetzt
eine Möglichkeit, konstruktiv, Qualität in die Software einzubauen.
Sie drücken, können sehr viel besser ausdrücken,
was sie ausdrücken wollen,
wenn sie solche Vor- und Nachbedingungen in ihren Code integrieren
Und dann haben sie das getan und jetzt testen wir,
ob das uns auch tatsächlich gelingt, diese Art von Verständlichkeit,
Verwendbarkeit, geschweige denn Wiederverwendbarkeit, also in die Software einzubauen.
So, wir haben jetzt also so,
sind jetzt so etwas weiter, die Klassen,
die wir implementieren können, werden immer hundert.
Das Ganze, wenn ich jetzt sage,
Zeug ist es nicht abwertend gemeint, aber das,
was wir implementiert haben, will auch noch entsprechend getestet werden.
Testen ist eine Beschäftigung, die Das ist eher eine sozialpsychologische Fragestellung.
Warum testen dich so eine der beliebtesten Tätigkeiten innerhalb der Softwareentwicklung
ist? Es ist auf jeden Fall ein integraler Bestandteil,
jeder professionellen Softwareentwicklung mit den entsprechenden Testwerkzeugen.
Sie haben insbesondere J.A. Unit schon kennengelernt,
damit auch also im Alltag umgehen zu können.
Weil ein fehlerfreies Softwaresystem gibt es derzeit nicht. Wer von ihnen,
also sie waren wahrscheinlich schon, doch,
sie waren schon auf der Welt,
als das Jahr 2000 Problem
uns beschäftigt hat
Sie sind alle älter als 15. Ja. Aber wahrscheinlich nicht so viel älter,
dass sie sich schon daran erinnern konnten, wie viel Piep
die Leute vor dem Jahr 2000 Probleme hatten, einzelne Ausnahmen.
Man wusste nicht so genau, was passiert eigentlich da jetzt beim Silvester
2000. Also beim Übergang von 1999 auf 2000, weil die Programme,
die da im Einsatz waren oder auch teilweise noch sind,
die konnte man so schlecht testen auf was passiert,
wenn 1999 aus 19099, 200 Wirt,
was unter anderem damit zu tun hat, dass also die Leute,
die diese Software in den 60er Jahren des letzten Jahrhunderts geschrieben haben,
dachten, für so eine Jahreszahl reichen eigentlich zwei Ziffern.
Also 65, 66, das geht dann halt bis 1999,
interessiert mich nicht, bin ich in Rente.
Ich unterstelle den Leuten jetzt etwas und diese Unterstellung
sagt mehr was über mich aus als über die Leute,
die das programmiert haben.
Also so, mich interessiert zum Beispiel
das Jahr 10.000 Problem auch nicht,
da bin ich hoffentlich in Rente
So, also 99 nach 2000,
wenn der Algorithmus nächstes Jahr so programmiert ist,
dass er plus eins auf dem Zwei elementiges,
auf eine zwei elementige Ziffer drauf zählt,
dann passiert da sowas wie das,
was Fred ihn so in SE1 zeigte,
wenn man so mit Floats irgendwas macht.
Also eins und eins ist irgendwie nicht zwei, kommt irgendwas anderes bei raus.
Also wenn man auf 99 eins drauf addiert,
also man hat nur zwei Ziffern,
kann da sehr gut Null bei rauskommen.
Und was das bedeutet, das weiß man nicht,
wenn man das Zeug
nicht testen kann
Wo die Wirkungen liegen für diese Art von Programmierfehler.
Und dann haben sich halt also auch Bekannte von mir,
haben sich also so mit Gaskochern versorgt.
Weiß man ja nicht. Und Dauerbrot und solchen Geschichten.
Weil wenn erstmal irgendwo ein Kraftwerk, um Gottes Willen,
irgendwas tut, was es sonst, also üblicherweise nicht tut,
dann ist man besser auf sowas eingestellt.
Nun, das hoffentlich, also motiviert so ein kleines bisschen,
warum, also testen im Kleinen und dann auch im Großen,
warum das so sinnvoll um nicht zu sagen, notwendig ist.
Darüber hinaus, wir werden uns im Rahmen des Moduls Software-Engineering,
Software-Technik, dass sie hoffentlich belegen werden,
werden wir uns noch mit etwas beschäftigen, einem Phänomen namens Software-Aging.
Soll man ja nicht denken, dass Software altert.
Wenn man eigentlich denkt, das ist etwas,
also zutiefst Menschliches oder von mir aus auch,
was mit natürlichem Leben zu tun hat,
nicht nur menschlichem Leben, auch Software-altert.
Und alternde Software neigt dazu,
die ursprünglich in sie hineingebaute Qualität zu verlieren
Man alte Software untersucht, die also von ihren Strukturen
her erodiert ist, dann ist die notwendige Voraussetzung,
um sie renovieren zu können, eine sogenannte hohe Testabdeckung.
Wenn man die nicht hat, dann weiß man nicht,
welche Effekte man erzielt, durch das sogenannte Refactoring.
Wir hatten diesen Begriff schon letzte Woche angesprochen.
Also durch das Ändern der inneren Struktur,
ohne dass die nach außen hin sichtbare Funktionalität dadurch verändert wird.
So, all das und noch viel mehr sollte sie motivieren,
zu testen
Sie sehen hier jetzt, was,
wir haben über Korrektheit im Sinne des Vertragsmodells gesprochen,
der Nachweis der Korrektheit ist für die Art von Programmen,
die wir hier diskutieren, ist sehr schwer nach,
sehr schwer führbar, um nicht zu sagen,
also es ist an der Grenze zur Unmöglichkeit,
also das Verhältnis zwischen Aufwand, um Korrektheit zu beweisen und dem Nutzen,
den man daraus ziehen kann, ist so wirtschaftlich,
mindestens wirtschaftlich ist der nicht tragbar.
Worauf es viel mehr ankommt, also weil wir das erstmal nicht können,
das ist die gesamte Diskussion über Correctness versus Presentness, Problem in der Softwareentwicklung.
Diese Diskussion hat sich über die letzten Jahrzehnte so ein klein wenig verschoben,
worauf es uns ankommt, ist also,
dass wir die Validität eines Stücks Softwares,
also die auf Deutsch die Gültigkeit, die Angemessenheit,
die Erwartungskonformität eines Stücks Software, dass wir die nachweisen können.
Und dazu ist das Testen eine Möglichkeit. Insbesondere,
ich will hier nur diesen einen Punkt hier aufgreifen,
erwartet es versus geliefertes Verhalten eines Stücks Softwares, heißt,
Zeug soll sich so verhalten, wie ich es erwarte.
Das ist die sogenannte erwartungskonformität. Und das einzubauen in ein Stück Software,
das ist halt so hinreichend schwierig. Wer von Ihnen,
also Navigationssysteme in Autos, wo ich schon bei Autos war heute,
sowas, also mal an verschiedenen Autos kennengelernt hat,
also der weiß auch, dass so erwartungskonformität im Auge des Betrachters liegt.
Insbesondere dann auch im Auge des Programmierers,
falls das nicht so ein Stück Software nicht erwartungskonform ist,
ist testbarkeit des Stücks Softwares eine der Voraussetzungen um diese Konformität herzustellen.
Weil sonst weiß man nicht, ob das,
was mal funktioniert hat, ob das immer noch funktioniert,
wenn man eine Änderung an der Funktionalität oder auch nur an
der Struktur der Software vorgenommen hat.
So, so zwei, drei kleine Begrifflichkeiten noch,
dann biege ich auch schon in die, auf die Zielgerade ein.
So, Meier, den haben wir ja schon kennengelernt im
Rahmen der Diskussion über das Vertragsmodells.
Der hat sich also verschiedene Arten von Fehlern unterscheidet,
der, die auch also unterschiedliche Arten von Behandlungen bzw. Folgen
Also erstens, das, was sie produzieren, ich meine,
sie sind sowieso die Quelle sämtlicher Fehler in Software.
Sie sind schließlich die Programmierer, Schrägstrich Softwareentwickler.
Sie begehen Programmierfehler. So, wie ist das definiert?
Hier steht jetzt eine falsche Entscheidung, die während der Softwareentwicklung getroffen wurde.
Das ist schon so ein bisschen tendenziös. Man könnte auch schreiben,
eine Entscheidung, die sich durch die Softwareentwicklung als falsch herausgestellt hat.
Oder durch die Softwarebenutzung als falsch herausgestellt hat.
Weil ob etwas ein Fehler ist, Oder, doch,
das muss so sein, das kann gar nicht anders sein.
Das liegt auch häufig im Auge des Betrachters.
Das ganze Reden über Testen dient jetzt aber dazu,
also das auch voneinander, also unterscheiden zu können.
Also ist ein Verhalten, das ein Stück Software zeigt,
ist, dass ein Fehler oder ist es etwas,
was also der Programmierer anders verstanden hat als derjenige,
der es benutzt, gemeint hat oder sehen möchte.
Und das ist im Wesentlichen sind das ja dann,
also Kommunikationsprobleme, wir beschäftigen uns jetzt hier mal mit den Harten,
Fakten,
also harten
Fakten in dem Sinne
Wenn ein Programm abstürzt, dann wird also kaum jemand behaupten können,
also auch der eloquenteste, juristisch versierte Programmierer nicht.
Das muss so sein an der Stelle. Sondern wir wollen
dann den Programmierfehler an der Stelle, also wir wollen dann
auf den Programmierfehler stoßen, an der er ausgelöst wurde.
Das heißt, zum frühestmöglichen Zeitpunkt wollen wir den entdecken.
Sondern das ist jetzt hier in der von Axel vermute ich
jedenfalls liebevoll dargestellten Animationen, kann man mal sehen.
Also was ich jetzt damit meine, wenn ich darüber spreche,
also zu diesem Zeitpunkt sei diese Variable,
über die wir hier sprechen, ist alles gut.
Dann zu einem Zeitpunkt etwas später, kriegt die einen Wert,
den sie nicht haben darf. Und jetzt geht die Katastrophe los,
nämlich es vergeht Zeit, es werden Operationen durchgeführt,
der Wert wird weitergegeben und er wird an anderer Stelle
verarbeitet und an einem sehr viel späteren Zeitpunkt dazu,
einem sehr viel späteren Zeitpunkt fällt auf,
da ist was
schief gelaufen
Also da an irgendeiner Stelle führt es jetzt halt zu einem
zum Beispiel Programmabbruch. Nehmen Sie das Beispiel mit dem Konto,
wenn Sie bei der Operation einzahlen, nicht überprüfen,
dass da nur positive Beträge übergeben werden als Parameter.
Sie werden das bei der Operation nicht überprüfen,
dann rechnen Sie irgendwas damit rum und an irgendeiner Stelle,
also fällt dieser negative Betrag, fällt er dann auf,
dann herauszufinden, wo ist dieser Fehler entstanden.
Das ist eine Arbeit, die ist,
also das grenzt an Arbeitsbeschaffungsmaßnahme
Das ist keine, das ist kein Vergnügen, solche Fehler zu finden,
weil bis man nämlich an die Stelle gekommen ist,
also muss man in der Zeit ganz schön weit vorwärts gehen,
um also die Ursache des Fehlers zu finden.
Also erstens hilft uns das Vertragsmodell, diese expliziter zu machen,
also welche Annahmen machen wir überhaupt über den Kontext und zweitens hilft uns testen,
die Fehler dort entdecken zu können,
wo sie auftreten und nicht später zu einem späteren Zeitpunkt,
also des Programmablaufs weil man dann,
wo man dann nicht mehr weiß,
wo ist eigentlich die eigentliche Ursache.
Deswegen so ein paar Grundsätze. Testen,
drei Folien sind das, garantiert keine Fehlerfreiheit.
Ja, dieser Satz von Dike Strap. Ich hoffe,
der kommt in der einen oder anderen Form,
auch in der Klausur vor.
Program Test, den can be used to show the presence of Bucks.
Also die Anwesenheit von Fehlern, aber nicht um deren Abwesenheit
zu beweisen. Das ist einfach so,
das ist eine der fundamentalen Einsichten über das Testen
Vollständiges Testen ist leider nicht möglich. Macht gleich nochmal
ein Beispiel, warum das nicht möglich ist.
Es ist möglich, theoretisch, es dauert halt bloß etwas länger.
Und also halbwegs komplexe Algorithmen überprüft. Mit dem Testen
sollte man frühzeitig beginnen. Und es gibt Leute,
ich sage gleich noch zwei Worte dazu, die sagen,
man sollte erst die Testfälle schreiben.
Fried zeigt das ja auch ab und zu,
wenn er ein Stück Software schreibt. Also ich schreibe erstmal,
also wogegen ich das Stück Software testen möchte, das ich jetzt gleich entwickle.
Also er nimmt gleich diese so nach Vertragsmodell diese Klienten Sichtweise ein,
bevor er den Dienstleister schreibt.
Also die Möglichkeit haben wir ja. Wir müssen ja nicht
also den Testfall nach einem bereit sein.
Sie müssen ja nicht erst den Dienstleister schreiben und dann also
die Testklasse als einen Klienten für diesen Dienstleister sein.
Die können ja auch erst, die Freiheit ist ihnen ja gegeben,
sie können erst den Test schreiben,
gegen den sie den späteren Dienstleister dann überprüfen wollen.
Jetzt kommt eine empirische Aussage, wo viele Fehler sind,
verbergen sich meist noch mehr. Tja, das ist so
wie mit der Ich will jetzt nicht über meinen Schreibtisch sprechen.
Da, wo eine Müllkippe ist, da sind auch noch mehrere.
Also das sieht man dann. Wer so schlecht strukturierte Programme neigen dazu,
also noch schlechter strukturiert zu werden über die Zeit,
also wo man Fehler findet, da ist das Testen,
wird das testen, umso dringlicher.
Tests müssen gewartet werden. Also das heißt eigentlich,
sie müssen weiterentwickelt werden
Tests, also Software entwickelt sich weiter,
wenn die dazu passenden, dazu gehörenden Tests nicht weiterentwickelt werden,
dann läuft es auseinander und dann sind die Tests irgendwann sinnlos.
Das ist sinnlos in dem Sinne, sind sie auch,
wenn die Testklassen, die sie schreiben, sich zum Kumpan,
der zu den testenden Klasse entwickeln. Also nach dem Motto,
ja, ich überprüfe jetzt mal so ein, zwei Vorbedingungen,
irgendwas, also was nicht weiter weh tut,
ich soll ja eine Testklasse schreiben,
die Metriken dann sagen oder die Metriküberprüfung sagt dann,
ja,
hohe Testabdeckung,
leider keine hohe Pfadüberdeckung,
aber ist immerhin
ein Anfang
Das ist ja also Tests, sollen sie das Schreiben von Tests,
soll sie nicht quälen, soll,
dann soll ihre Sicherheit für die Entwicklung, objektorientierter Programme erhöhen.
Testen ist abhängig vom Umfeld, ja, also man kann jetzt,
also so in der Regel so bei, sagen wir mal,
bei betriebswirtschaftlichen Anwendungen, wird man schon mal sagen, okay,
wir können jetzt nicht noch testen, das Zeug muss ausgeliefert werden.
Und das ist dann die sogenannte Bananensoftware,
reift beim Kunden, ruft an, sagt,
ist abgestürzt, okay, man guckt sich das an,
schreibt noch ein paar Tests,
aber wir müssen auf jeden Fall ausliefern
Also Keile besonders qualitativ hochwertige Haltung, die sich dahinter verbirgt.
Also alles, was sicherheitskritisch ist, da wird man
sich diese Haltung auf gar keinen Fall leisten können.
Und ich hoffe, dass sich diese Haltung dort,
also in solchen Bereichen auch niemand leistet.
Also wenn es um Menschenleben geht, um Gottes Willen.
Da wird also, das Testen hat da eine noch höhere Bedeutung.
Erfolgreiche Tests garantieren nicht die Benutzbarkeit. Ja,
man kann also hochgradig testbares System haben,
wenn es also schlecht zu bedienen ist,
schlecht in der Hand liegt oder das Falsche tut
Habe ich dann, es ist zwar getestet, aber was soll's.
Es sind zwei, einfach zwei verschiedene Paar Schuhe.
Was wir aber tun können, ist,
wenn das Zeug getestet ist, jetzt machen wir es benutzbar.
Wir haben eine hohe Testabdeckung, wir haben eine hohe Pfadabdeckung beim Testen,
dann können wir die Benutzbarkeit noch hinein implementieren.
Anders wäre das, wenn es nicht benutzbar ist und keine Tests hat,
dann wegschmeißen, neu machen, ist da eine häufige Alternative.
So, ich hätte gesagt, also ich wollte noch ein Wort zum Austesten sagen,
dass ja ein unmittelbar nachvollziehbares Programm, was da steht.
Also bei A geht es los und bei B hört es auf.
Dazwischen gibt es eine Schleife, wie man hier sieht.
Da geht es zurück und da oben drüber,
bevor es also zum Endpunkt der Schleife geht,
gibt es ein paar Fallunterscheidungen. So, wenn diese Fallunterscheidung,
so wie das hier auf der Folie steht,
also wenn die voneinander unabhängig sind, ist das also,
ist das die Anzahl der möglichen Programmdurchläufe, die es gibt.
Und wenn man 100.000 Tests pro Sekunde hat,
du weißt gar nicht,
ist das viel
Naja, hier so, wenn es sowas ist.
Also ich finde, 100.000 pro Sekunde jetzt erstmal nicht so viel.
Gut, aber 38 Jahre ist auf der anderen Seite auch nicht gerade kurz.
So, aber da hatten wir ja schon in SE1
drüber gesprochen. Grenzwerte und also die Normalen Werte,
die außerhalb liegen, was mich zum letzten Punkt bringt.
Das ist also positives und negatives Testen,
nur dass sie das von der Begrifflichkeit her auch mal
gehört haben
Also nur erwartete gültige Eingabewerte,
dann ist es das positive Testen und die anderen Eingabewerte dann spricht,
wenn man die verwendet, ist es das sogenannte negative Testen.
Man braucht eigentlich beides. Vertrauen, also erhöht,
das erhöhen die positiven Tests, so nach dem Motto,
das Ding tut das, was es tun soll.
Also im Sinne des Vertragsmodells habe ich eine korrekte Implementation und
die negativen Tests, die erhöhen das Vertrauen in die Robustheit.
Also das Ding bricht nicht, das Zeug bricht nicht zusammen,
ungeplant, also in einem inkonsistenten Zustand,
nur weil jemand mal was Falsches eingegeben hat oder falsche Parameter übergeben hat,
die Robustheit eines Programms ist also auch eine hohe,
also nicht funktionale Qualität eines Stücks Softwares.
So, einen Ausblick noch auf deine Software-Technik. Wir werden den Software-Technik,
werden sie so verschiedene Entwicklungsmethoden kennenlernen für die Entwicklung großer,
interaktiver Software-Systeme. Unter anderem auch sogenannte agile Methoden,
was das ist, also stark rückkopplungsbasierte Entwicklungsmethoden,
Rückkopplung zwischen Entwicklern und Anwendern,
um die zwei Hauptgruppen zu nennen
Eine Ausprägung einer solchen agilen Methode ist der sogenannte Test-First-Ansatz, Test-Driven-Development.
Das ist eine ganze Entwicklungsmethode, die darauf basiert,
dass man erst Test schreibt und also in verschiedenen,
auf verschiedenen Ebenen, um dann, also die zutestenden Klassen zu schreiben.
Das werden wir aber dann, also in einem späteren Semester,
so sie wollen, noch etwas vertiefen.
So, Fred, ich glaube, das waren jetzt 48
Minuten, aber sei es drum.
Wir können noch von mir aus bis vier machen,
die junge Zeit
Die sind doch hier, um was zu lernen.
Okay. Also, wir sehen uns ansonsten nächsten Mittwoch wieder.
Schönen Tag noch. Aber es scheint zu funktionieren. Okay,
ich rede einfach mal ein bisschen, damit die Stimme angepegelt werden kann.
Ich fand das andere Mikro eigentlich ein bisschen angenehmer, aber gut.
Das kriege ich jetzt gerade nicht angeschlossen. Gut,
ich muss noch ein paar Ansagen machen. Christian Spee hatte
mich heute darauf hingewiesen, mach doch ein paar Ansagen.
Was ist denn die erste Ansage, die ich machen muss?
Ja, genau, die Umwelde frisst in Stine.
Wir kriegen also nach wie vor viele E-Mails, hey,
ich kann nicht zu meinem Übungstermin hingehen.
Ich weiß nicht, wo ich mich ummelden kann
Und ihr könnt euch in Stine tatsächlich noch selber ummelden.
Ihr habt jetzt noch eine Woche Zeit,
der 16. April ist nächster Donnerstag.
Ihr könnt euch noch eine Woche lang selbstständig in Stine ummelden.
Dafür müsst ihr euch von eurer jetzigen Übungsgruppe abmelden,
bevor ihr euch für die Neue anmelden könnt.
Und beachtet bitte, dass ihr euch für Dimi und früh
nah nicht anmelden könnt. Die Termine sind also rappelvoll.
Also meldet euch nur ab von eurer eigenen Gruppe,
wenn ihr einen anderen Termin wechseln wollt als diese beiden.
So, das ist also das eine.
Dann muss ich nochmal auf die Scheinbedingungen hinweisen,
weil die dieses Jahr
ein bisschen anders sind
Wer von euch hat sich die Scheinbedingungen im Kommensee angeguckt für SE2?
Ja, sind nicht alle, das habe ich befürchtet.
Okay, also es gibt jetzt eine neue Regelung.
Es gibt keine freiwilligen Aufgaben mehr. Das heißt also,
wenn auf einem Blatt vier Aufgaben drauf sind,
dann müsst ihr vier Aufgaben abnehmen lassen.
Die vierte Aufgabe von der ersten Woche war zum Beispiel
die Sache, schreibt doch mal eure eigene Main-Methode.
Das kriegt ihr, glaube ich, hin, oder?
Okay, beachtet das bitte. Was haben wir noch?
Das Programmierdektat findet statt. Fängt nächsten Donnerstag an und geht
eine Woche, findet zu eurem regulären Übungstermin statt.
Ihr müsst also nicht speziell irgendwo anders hingehen oder so.
Kommt einfach in eure Übungsgruppe. Und dann werdet ihr
entsprechend verarztet
Ja. Gibt es bis hierhin erst mal Fragen?
Keine Fragen. Okay, dann ein bisschen Allgemeinbildung,
falls ihr mal bei Günther Jauch auf dem Stuhl sitzt.
Welche Software hat dieses Woche, diese Woche zehnjähriges Jubiläum?
Hat das jemand mitbekommen? Liest hier jemand so Reddit oder
so, okay, einer hat es mitbekommen?
Nein, okay, was sagst du? Git, sehr schön.
Git hat zehnjähriges Jubiläum. Und es geht immer wieder Anfragen von Studenten,
die uns fragen, hey,
könnt ihr nicht mal was mit Git machen oder so,
geht, ist doch irgendwie wichtig,
geht das doch trennen,
geht das irgendwie hip
Aber geht es tatsächlich eine relativ stabile Software mittlerweile?
Wie gesagt, das gibt es ja schon seit zehn Jahren.
Eigentlich wollte ich euch hier ein bisschen was im Internet zeigen,
noch mit GitHub, aber mein Internet, Internet geht hier leider nicht.
Also die Leute wollen was über Git wissen.
Ich kann euch nicht Git beibringen. Da baut man wahrscheinlich
eine eigene Veranstaltung für. Aber ich kann zumindest das,
was ich so meine, das, was ich über Git weiß,
kann ich vielleicht mal so im Hintergrund ein bisschen laufen lassen.
Und ich kriege natürlich auch immer anfragen, hey Fred,
das, was du in der Vorlesung programmierst,
kannst du uns das nicht irgendwie zur Verfügung stellen?
Ich bin immer so ein bisschen kritisch, weil ich denke,
naja, das, was wir hier programmieren,
das hat ja eine gewisse Geschichte.
Wir arbeiten hier wie eine Dreiviertelstunde dran.
Und dann zeige ich euch, wie die Lösung am Ende
und dann hat man da wirklich
so viel von
Und da dachte ich, das ist doch perfekt.
Ich kombiniere einfach diese beiden Anforderungen. Denn ich kann ja
, wer weiß überhaupt, was geht ist?
Wer weiß, was geht ist. Einmal Handtuch.
Okay, sind auch nicht besonders viele Hände, ne?
Ja, was ist das eigentlich? Git ermöglicht euch,
ohne jetzt mal besonders viele Fachbegriffe zu wenden,
quasi die Geschichte eines Softwareprojekts nachvollziehbar zu machen.
Dass ihr so sehen könnt, ah, alles klar,
heute um 16.20 Uhr wurde dies und jenes gemacht,
eine halbe Stunde später kamen Tests dazu,
eine halbe Stunde später kam das Vertragsmodell dazu.
Also ihr könnt die gesamte Geschichte eines Softwareprojekts nachverfolgen. Und dachte ich zumindest,
das kann man ja demonstrieren. Ich werde euch also nicht zeigen,
irgendwelche Vorteile, abgeschrittenen Dinge wie, hey,
zwei Programmierer wollen gleichzeitig irgendwie am selben Projekt arbeiten oder so,
sondern einfach nur, ich will die Geschichte dieses Projekts,
das wir hier zusammen entwickeln, einfach mal aufzeichnen.
Und dann könnt ihr später,
wenn ich das heute zu Hause ins Internet hochlade,
könnte das dann jederzeit nachvollziehen,
was haben wir eigentlich in der Vorlesung gemacht,
letzte Woche oder auch heute.
Okay. Also hier ist ja unser Projekt, was wir
letzte Woche gemacht haben, vielleicht erinnert ihr euch noch.
Und ich will jetzt einfach mal sagen, ich möchte eine Geschichte
sozusagen von diesem Projekt jetzt mal langsam in die Welt setzen.
Ich will also Git verwenden. Oh Gott,
da muss ich hier ein Repository createn,
nehmen wir doch, ach,
das ist eigentlich ganz okay,
dann nenne ich das mal Stack
Das ist hoffentlich alles in Ordnung. Also ich habe
Eclipse und Git zusammen auch noch nicht so lange benutzt,
aber man sieht hier, hat sich jetzt einiges getan.
Okay, das ist schon mal gut. Dann gehe ich doch mal
ganz kurz in das Verzeichnis und schaue mal ganz kurz.
Genau, also die Git-Experten merken schon, alles klar,
Git hat sich hier irgendwie initialisiert, okay,
dann können wir Git mal ganz kurz fragen, was ist los?
Und Git warnt mich und sagt, pass auf,
es gibt hier ein Verzeichnis, da sind Dateien drin,
von denen du mir bis jetzt noch nicht gesagt hast,
dass die Teil dieser Geschichte sein sollen.
Okay. Oh, das ist ja blöd
Ich hatte gehofft, dass wir solche Probleme nicht mehr haben.
Okay, dann schiebe ich es einfach noch hier.
Besser? Ja. Gut. Ich will jetzt,
geht also sagen, ich will irgendwie alles,
alles soll irgendwie Teil dieser Geschichte sein.
Ich glaube, das macht man so. Und Git-Experten dürfen mich jederzeit unterbrechen.
Ich benutze das selber auch erst seit ein paar Wochen,
aber ich glaube, die Grundlagen kriege ich hoffentlich noch hin.
Okay, mal sehen, was er mir jetzt sagt.
Habe ich alles der Geschichte zugeführt? Ja, sieht man.
Das ist jetzt also alles Teil der Geschichte meines Projekts.
Okay, und das soll auch das erste Kapitel sozusagen sein.
Ich kann jetzt also sagen, mach doch mal jetzt
das erste Kapitel aus dem aktuellen Stand des Projektes.
Dann kann ich noch sagen, wie soll das Kapitel heißen
quasi?
Sagen wir vielleicht
Wie man so in Version at the End of Lecture one.
So, das war ja der Stand von letzter Woche.
Ich habe ja seitdem überhaupt nichts daran geendet.
Ja, achso, das ist jetzt ja Englisch.
Wo kriege ich jetzt meinen Y auf der Tastatur?
Ist es hier? Ja. Okay, mal sehen,
ob sich jetzt irgendwas geändert wird. Sehr schön.
Ich muss einmal ganz kurz mir die Nase putzen.
In der Zeit könnt ihr schauen, wie schön sich
der Status verändert hat.
Und wir können auch einmal ganz kurz gucken,
wie jetzt unsere Geschichte bis jetzt aussieht.
Ah ja, das ist unsere Geschichte bis jetzt, ja.
Also um 15.13 Uhr. Heute, am 8. April,
wurde diese Version quasi in dieses Buch reingeschrieben. Toll. Okay,
jetzt gehen wir mal in die Clips und gucken mal,
ob der irgendwie gemerkt hat, dass sich hier was geändert hat.
Ja, sehr gut, die Symbole sind alle anders geworden.
Okay, jetzt hole ich mal einmal vorschlagen,
dass wir einmal ganz kurz hier rübergehen und schauen,
dass wir immer so ein bisschen Grundaufraumarbeit machen.
Ja, das ist zum Beispiel irgendwie blöd,
finde ich, dass jetzt hier so eine Lehrzahl ist.
Ja, die lösche ich jetzt mal, will ich nicht haben.
Haben wir noch so ein paar blöde, offensichtliche Dinge?
Nö, ansonsten ist das hier eigentlich okay,
die Formatierung
Dann schaue ich nochmal in den anderen Klassen,
ob es da so ähnliche, guck mal,
diese Leerzeile zum Beispiel, die ist doch blöd, oder?
Die hier ist auch blöd, die wahrscheinlich auch mal,
okay, wie sieht es hier aus?
Mach mal ein bisschen größer, dass ihr alles sehen könnt.
Ja, das hier zum Beispiel gefällt mir auch nicht.
Ich mache das mal wieder so, ich fand diese Variante
am besten. Okay. Was haben wir noch?
Ist hier irgendwas, was man schnell aufräumen kann?
Ne, die To-dos sind immer noch gültig,
wir waren da später mal bessere Fehlerbehandlungen machen.
Was haben wir hier? Ach, schon wieder so eine
blöde Leerzeile, weg damit. Was haben wir hier?
Das sind jetzt also nur wirklich völlig oberflächliche,
guck mal,
hier schon wieder
eine Leerzeile
Völlig oberflächliche Änderungen. So, die nehmen wir auch mal weg,
die nehmen wir auch mal weg. Warum sind da so
viele Lierzeilen? Guck mal, hier ist noch eine.
So. Okay. Eclipse hat eben auch Unterstützung für dieses Git.
Also ihr seht jetzt hier an diesem an diesem Dreieck oder
an diesem Fall, dass sich hier Änderungen ergeben haben.
Hier nicht und wir haben sich wieder Änderungen ergeben.
Ich könnte jetzt auch in Eclipse sagen, dass er irgendwas machen soll,
aber damit kenne ich mich noch nicht so gut aus.
Ich frage mal wieder auf der Kommandozeile,
was ist denn los in meinem Projekt? Ah ja,
diese Dateien haben sich also geändert seit dem letzten Mal.
Ich sage wieder, ich will,
dass das alles jetzt ins nächste Kapitel soll es einfließen
Guck mal, weil es zufrieden ist.
Ah ja, jetzt ist es grün. Also das,
alles, was ich jetzt geändert habe, soll,
wenn ich irgendwann mal bereit bin, das nächste Kapitel sozusagen zu veröffentlichen,
soll dann davon teil sein und ich bin jetzt eigentlich bereit.
So sage ich, das soll jetzt das nächste Kapitel werden.
Nennen wir das mal Clean-up of White-Space and,
habe ich irgendwelche Kommentare noch sonst geändert?
Habe ich da nicht diesen einen Kommentar gerne, ist auch egal.
Es ist jetzt erst mal nur solche Testnachricht.
Yes. So. Okay, das haben wir jetzt committed und
jetzt gucken wir uns nochmal an.
Seht ihr das jetzt? Jetzt haben wir zwei Kapitel in
unserer Geschichte. Das erste Kapitel haben wir also hier und
das zweite
haben wir da
Toll. Jetzt gucken wir, ob er das hier wieder
gemerkt hat, dass alles auf dem neuesten Stand ist.
Ja, ist es. Gut, was haben wir denn jetzt davon?
Man könnte zum Beispiel zwischen den verschiedenen Versionen hin und her switchen.
Das mache ich jetzt bei dem Beispiel nicht, das ist langweiliger.
Dann würde dann einfach nur wieder diese Leertasten dazukommen.
Okay. Gut, das ist also das ist das eine.
Wir haben jetzt so den ersten Eindruck von Git bekommen und
ich werde es heute den ganzen Tag weiter benutzen.
Also vielleicht, nachdem wir das Vertragsmodell eingebaut haben oder so.
Das heißt, ich komme jetzt gleich zum Thema der heutigen Vorlesung,
zum eigentlichen Thema Deuting-Vorlesung, das Vertragsmodell.
Wofür? Für welche Klasse wollen wir das Vertragsmodell einbauen?
Ich nehme mal diesen veränderbaren Stack. Das mache ich deswegen,
weil das so eine schön einfache Klasse ist, ja,
hier sind irgendwie keine Typhierarchien oder so, einfach nur die eine Klasse.
Ja, gut. Können wir hier schon ein sinnvolles Vertragsmodell implementieren?
Was haben wir denn so für Operationen? Also ich kann
was auf den Stack rauftun, ich kann gucken,
was obendrauf ist und ich kann was runternehmen.
Wenn man sich noch ein bisschen an die Folien von Guido erinnert,
dann waren da auch Verträge, die was damit zu tun haben,
ist der Stack leer oder nicht.
Wie viele Elemente sind auf dem Stack drauf? Ich glaube,
es wäre vielleicht ganz gut,
wenn wir diese beiden Operationen noch hinzufügen zu unseren Stacks,
dass ich fragen kann, ob er leer ist und dass ich fragen kann, wie viele Elemente drauf sind.
Ja, und da wir ja intern diesen Persistant Stack benutzen,
brauchen wir das dann natürlich auch
Okay, das heißt, vielleicht fange ich dann mal mit
der Implementation der beiden zusätzlichen Operationen beim Persistance-Deck an.
Ja. Die Operation, ob der Stack leer ist,
auch ich tue sie einfach mal hier unten hin.
Also, Booleon ist M-Team. Diese Operation sagt dem Klienten,
ob der Stack leer ist oder nicht.
Können wir eigentlich gleich implementieren, oder? Wir müssen den
ja jetzt in zwei verschiedenen Klassen implementieren. Ihr erinnert euch,
ihr sitzt in Stack Vale nur das Interface und wir hatten einmal
die Klasse Nil für Leere Stacks und einmal die Klasse,
kommt's für nicht leere Stacks.
Also gehe ich jetzt einmal hier rein
Man kann jetzt wieder Eclipse sagen,
Eclipse merkt jetzt wieder, Wiederholung von letzter Woche.
Ich verspreche hier das Interface zu implementieren. Jetzt ist aber
eine weitere Operation dazugekommen, nämlich dieses ESMT.
Und jetzt Merkel-Clips, das fehlt jetzt ja an diesem Typ.
Also kann ich sagen, add-un-implemented Methods. Und dann erscheint
es sich un. Gut. Schauen wir mal,
ob der Default jetzt hier vorgegeben ist, sinnvoll ist.
Also hier wird jetzt behauptet, dass der leere Stack nicht leer ist.
Ist das die richtige Implementation? Hat jemand einen Gegenvorschlag,
was da sinnvollerweise stehen sollte unten?
Wir haben die ganzen Gnade von Adrian. Das ist eine
Zeitfüllung bei der. Genau, der nähere Stack ist leer.
Sehr gut. Okay, das haben wir also jetzt hier
gemacht. Dann gehen wir mal in die andere Klasse.
Hier haben wir das gleiche Problem. Eclipse merkt wieder,
dass da was fehlt. Ich sage, ich implementiere das auch mal.
Und das haben wir dann hier. Wie sieht es hier
aus? Also ich habe einen Stack. Ja, nur,
also ich weiß, ich habe ein Element auf diesem Stack,
also dieses Element.
Und darunter können wir noch beliebig viele weitere Elemente folgen.
Ist dieser Stack leer oder nicht
Das war sehr daran. Genau, das Fold ist also
an der Stelle richtig, ne? Sehr gut. Okay,
ach, ich bin so ein Git-Fanatiker, ich gucke mal,
was jetzt hier los ist auf meiner Konsole. Ah,
er hat gemerkt, dass wir diese drei Dateien angefasst haben,
dann soll ich wieder, ich mache jetzt mal eine Abkürzung,
wenn ich einfach sage, wie wir alle Änderungen übernehmen,
dann brauche ich nicht sagen Add und Commitzone,
ich kann auch sagen Commitminus, ah,
dann werden diese Änderungen übernommen.
Und dann nennen wir das mal Add,
wie heißt die Methode jetzt, East Empty, ne?
Add Method, this Empty, trope,
this Stack
Yes. Ah, gut. Gut, schauen wir
noch mal kurz, ob das jetzt hier übernommen wurde.
Ja, genau. Ihr seht also, wir haben nur
fünf Minuten gebraucht, sind wir nicht wahnsinnig effiziente Programmierer.
Fünf Minuten für diese ESMT-Operation. Gut, welche Operationen
wollten wir noch haben? Wir wollten, oh,
wir haben den Kommentar vergessen. Das ist ja peinlich.
Man muss natürlich für öffentliche Methoden immer Kommentare schreiben.
Also, was schreiben wir denn da mal hin?
Vielleicht die Termins Weather this stack is MT
Jetzt will ich ja nicht ein neues Kapitel aufmachen.
Ich will eigentlich die Änderung, die ich gerade gemacht habe,
das soll jetzt quasi noch dazukommen.
Das geht zum Glück auch. Ich kann einfach sagen,
mit diesem wunderbaren Parameter, ich will den letzten Commit jetzt quasi verändern.
Es soll kein neues Kapitel dazukommen, sondern das ist das
letzte neueste Kapitel, soll bitte verändert werden.
Die Nachricht ist aber immer noch in Ordnung, die muss sich nicht ändern.
So, dann schauen wir mal kurz an, was passiert ist.
Ihr seht, es ist also kein neues Kapitel dazugekommen.
Es hat sich noch nicht mal die Uhrzeit geändert.
Da bin ich gerade ein bisschen erstaunt drüber, ehrlich gesagt.
Aber gut, schauen wir mal, ob Eclipse der Meinung ist,
dass jetzt hier alles in Ordnung ist.
Ja, ihr seht, die sind keine Pfeile.
Das wurde jetzt also übernommen.
Sehr schön
Ja, welche Operationen wollten wir noch machen?
Wie viele Elemente sind auf dem Stack drauf?
Das ist so eine Methode geliefert ein In zurück.
Das sind ja null oder ein oder zwei oder drei Elemente.
Und wir wollen uns mal nennen,
wie heißt immer die Methode, die mir die Größe zurückliefert,
in Java per Konventions-Size heißt sie, glaube ich,
nennen wir sie mal, Size.
Und jetzt vergessen wir nicht, den Kommentar zu schreiben,
also returns than number of elements on these Stack oder so.
Okay, müssen wir wieder implementieren. Also gehen wir zurück
zu Nill. Wie viele Elemente sind auf dem leeren Stack
Ja. Puls drauf. Ja, perfekt. Das heißt,
Equips versteht, was ich erreichen will mit meinem Projekt.
Nee, ist natürlich nur Zufall, ne? Also der
Default wird 0 wird immer genommen, wenn ihr ein In zurückliefert.
Okay, dann gehen wir mal zum Cons.
Wie viele Elemente sind denn auf dem Nicht-Lehrungs-Stack?
Irgendjemand hat eine Idee, ja. Richtig,
eins mehr als auf dem Feuer gegangen ist.
Also eins mehr als und der Stack unter mir ist
ja Tale
Punkt size. Für die Freunde der Rekursion haben wir das
dann auch implementiert. Toll. Achso, nicht schlecht, oder?
Gleich wieder ein neues Kapitel in unserer Geschichte. Also,
nennen wir das mal Ad Method Size, Jordan Crisis.
Yes. Schauen, ob alles funktioniert hat.
Hier ist unser neuestes Kapitel. Toll. Okay,
das ist also jetzt eine wunderbare Ausgangsbasis. Mal gucken,
wenn ich einmal hier klickere, dass diese Dreiecke verschwinden.
Ja, das ist also eine wunderbare Ausgangsbasis für das Vertragsmodell.
Fast, wir wollten das ja eigentlich in den Mutable-Stack einbauen
Hier fehlen ja noch diese Operationen, ob er leer ist oder nicht.
Ja, das kann man ja eigentlich ja genauso einbauen, oder?
Also Public-Bubble, ist MT. Wie kann dieser Mutable-Stack die Anfrage beantworten,
ob er leer ist? Ihr erinnert euch vielleicht noch,
wir hatten ja nur eine einzige Exemplarvariable,
einfach nur eine Referenz auf einen von diesen unveränderlichen Stacks.
Und wenn ich mich selber verändere, dann zeige ich einfach
auf andere unveränderliche Stacks. Wie kann ich jetzt beantworten,
ob ich gerade im momentanen Zustand leer bin?
Genau, wir delegieren einfach die Anfrage an diesen Stack
und fragen ihn, ob er leer ist.
Wir selber können diese Frage gar nicht beantworten.
Gut. Dann dasselbe noch für Size. Das ist dann
dasselbe Spiel, ne? Toll. Das ist eigentlich
schon fast wieder ein eigenes Kapitel wert.
Was haben wir jetzt gemacht? Add-Methods is elty and size
try mute. So, da sind wir
sehr gut
Ja, schön. Jetzt können wir langsam mal tatsächlich über das Vertragsmodell nachdenken.
Gut. Wir können eigentlich gleich mal mit dem Konstruktor anfangen. Ja,
wenn ich also so einen Konstruktor schreibe oder wenn er ausgeführt wird,
dann habe ich ja einen Mutable Stack,
der in einem gewissen Zustand ist.
Gibt es irgendwelche Vorbedingungen? Kann ich irgendwie sagen,
ich darf diesem Konstrukt nur unter bestimmten Bedingungen aufrufen?
Ich würde sagen, nö, new, new,
new Mutable Stack, darf ich immer sagen.
Aber kann jetzt im Gegenzug der Mutable Stack dem Klienten irgendwelche
Nachbedingungen versprechen. Kann doch irgendwie sagen, pass auf,
wenn du hier einen neuen frischen YouTube-Stecker kommst,
dann gelten garantiert folgende Eigenschaften,
Genau, also der Stack, der zukommt,
ist auf jeden Fall MT, ne?
Gut. Wie formuliert man das denn jetzt am besten? Vielleicht,
man hat da so eine Konvention, dass man sagt,
das Ergebnis des Aufrufs einer Operation bezeichnet man gerne in diesen Kommentaren,
ups, ich habe vergessen, das in Schule dahin zu schreiben.
Ensure, result. ist MT, so würde man
das formulieren. Ja. Kann man noch was formulieren?
Kann ich noch irgendwas sagen über diesen Stack,
der dazu kommt, außer dass er leer ist?
Genau, das könnte man auch noch machen, ne?
Das ist eine interessante Frage, ob das irgendwie redundant ist
oder nicht, aber ich schreibe es einfach mal hin,
dann kann man zumindest darüber diskutieren.
So. Das ist doch nicht schlecht. Okay. Warum
mal weiter? Push. Gibt es irgendwelche Einschränkungen darüber,
welche Elemente ich hier übergeben darf? Gut,
jetzt kann man sich streiten, darf man da diese Spezialwerte
wie Not in Number oder unendlich oder so übergeben?
Ich will das jetzt mal nicht weiter einschränken.
Also ich will also für meinen konkreten Fall sagen,
da darf der Client ruhig alles übergeben.
Kann man denn hier irgendwas über das Ergebnis aussagen?
Also ich Ja, ich weiß erst mal nicht,
in welchem Zustand der Stack ist.
Dieses Push könnt ihr ja auf jedem beliebigen Zustand aufgerufen werden.
Aber kann ich, nachdem das Push ausgeführt wurde, irgendwas ganz sicher sagen?
Jetzt muss er, wenn wir auf den Stacks landen.
Die Größe muss um eins höher sein, richtig?
Fällt einem noch was ein, ja? Oh,
das ist eine sehr spannende Nachbedingung. Du hast gesagt,
das oberste Element von dem Stack müsste dann das sein,
was ich aufgetan habe, richtig?
Wie formuliert man das denn
Das heißt also, wenn ich anschließend das Top aufrufe,
dann müsste da X zurückkommen. Ist das das,
was du sagen wolltest, ja, ne?
Okay. Dann hattest du gesagt, die Größe wächst um einen.
Ich glaube, das wird jetzt schwierig zu formulieren, oder?
Also dann müsste ich ja quasi so was schreiben wie Enschur, hm.
Tja, also ich meine, ich kann ja schlecht sagen,
die Größe ist einer mehr als die Größe.
Das ist ja mathematisch Unsinn, ne
Er ist nicht leer, das ist schön, das schreibe ich mal hier hin.
Also, Ensure not is MT, genau.
Und hier unten, wie wurde das auf den Folien gemacht,
wo über Eifel geredet wurde, ja?
Da gab es irgendwas wie Old Scise, ne,
genau, also das ist quasi sowas, ne.
Jetzt gibt es aber dieses Old nicht in Java und deswegen
schreibt eigentlich niemand solche Formen von Nachbedingungen. Ja, also ich,
ja, ich kann ja mal diesen Kommentar auskommentieren,
ah ne, das versteht er nicht so. Ja,
also das ist das, was wir eigentlich sagen wollen,
nachdem du also dieses Push aufgerufen hast,
wird Scis eine Zahl zurückliefern,
die um einen größer ist als das,
was das heißt,
vorher zurückgeliefert hätte
Aber es gibt dieses old nicht in Java.
Und deswegen wird es erstmal schwierig, das zu überprüfen.
Und pragmatisch schreibt man solche Nachbedingungen meistens nicht.
Aber ich lasse sie einfach mal als Kommentar da stehen,
dass klar ist, dass man zumindest diesen Gedanken haben kann.
Okay. Gut. Mal sehen,
ob man bei den anderen noch irgendwas Sinnvolles sagen kann.
Kann ich was darüber aussagen, was obendrauf ist?
Ich kann ja noch nicht mal sicher gehen, dass da überhaupt irgendwas drauf ist.
Möglicherweise ist der Stack ja leer. Das wird,
glaube ich, ein bisschen schwierig. Hier ist es wahrscheinlich
genauso. Hier kann man eigentlich auch nichts Sinnvolles zurückliefern,
weil ich meine, ich kann garantieren,
dass dann True oder Ford zurückkommt,
aber das macht ja schon das Typsystem für mich
Ach, hier könnte man tatsächlich was Sinnvolles garantieren.
Hat ihr mal eine Idee? Also, Int heißt ja
eine beliebige Zahl zwischen minus zwei Milliarden und plus zwei Milliarden, ja?
Über null, sagst du? Größer oder gleich null?
Genau. Ja, ist doch schon mal nicht schlecht.
Okay. Ja? Irgendwas in Frage?
Ja. Du meinst hier
Okay, also wurde zurückgenommen, der Einwand. Okay.
Ich glaube, Vorbedingungen fallen dann tatsächlich hier nirgendwo anders.
Wir erlauben alle Zahlen. Es ist nicht so,
dass man nur positive Zahlen auf den Stack pushen dürfte.
Ah, nee, ich glaube, man kann doch ganz,
ganz gute sinnvolle Vorbedingungen für das Top und das Pop formulieren.
Also, ich kann mich zwar nicht auf irgendwelche Parameter beziehen.
Hier wird da nichts explizit reingestopft bei dieser Methode.
Aber kann ich irgendwie dem Klienten sagen, pass auf,
du darfst diese Operation nur dann aufrufen,
wenn eine bestimmte Bedingung gilt
Ja. Richtig, der Stack darf nicht leer sein.
Also ich kann schreiben, Require, not is MT.
So, ne? Okay, und wie sieht das bei
dem Pop aus im Prinzip genauso, oder?
Ich darf das oberste Element nur entfernen,
wenn es das auch wirklich gibt.
Okay. Ja. Ist das mit eingeschworen? Ja.
Was haben wir hier im Prinzip,
den Wert von Hiddeburg
Ja, die Tatsache,
dass dieses Not and Number bei dem Passistance-Stack zurückkommt,
ist ja eigentlich so ein blödes Implementationsdetail,
was wir auch später mal ändern wollen,
wenn wir ein bisschen mehr über Acceptions kennengelernt haben.
Also eigentlich sagen wir ja, man darf die Frage gar nicht stellen,
welches Element auf dem leeren Steck drauf ist.
Okay. Sehr schön. Jetzt können wir doch auch mal
diese Vorbedingungen überprüfen. Also wir haben hier unsere erste Vorbedingung.
Jetzt hatte Guido das auf den Folien schon gezeigt,
wie wir das in Java überprüfen.
Ja, also wir schreiben dieses wunderbare Search-Schlüsselwort
Dann die Bedingungen, die wir prüfen wollen.
Nämlich, genauso wie sie da oben steht.
Und dann kann man noch irgendeinen String hier zusätzlich hinschreiben.
Dieser String taucht einfach auf, wenn diese Vorbedingung verletzt wurde.
Und deswegen schreiben wir gerne im Übungsbericht sowas wie Vorbedingungen verletzt.
So, wir hatten früher noch oft die Konvention,
dass man diese Vorbedingungen, die ja hier als bulischer Java-Ausdruck steht,
dass wir die nochmal in Textform hier mit reinkopiert haben.
Also dass hier quasi nochmal stand, so irgendwie.
Kann sich jemand vorstellen,
warum ich jahrelang dagegen angekämpft habe und dieses Jahr endlich erfolgreich war,
dass wir diesen Text da nicht mehr reinschreiben.
Nur was klingt ja erstmal ganz nett,
auch dann sieht man ja auf der Konsole
sofort,
was schiefgegangen ist
Ja, ja, ja, ja, ja,
ja, ja, ja, ja, ja, ja,
ja, ja, ja, ja, ja, ja.
Okay, also das ist erstmal ein grundsätzliches Prinzip der Softwareentwicklung,
man sollte nicht mehrere Stellen haben und denen exakt dasselbe steht.
Warum eigentlich nicht? Warum sollte man nicht an mehreren Stellen
exakt dasselbe stehen haben, ja? Genau, wenn man,
also wenn man so radikal ist und seine Software ab und zu mal ändert,
und das tun wir ja,
wenn ich jetzt zum Beispiel diese Methode irgendwann mal umbenennen würde,
ja, Dann wird dieser String hier nicht mit umbenannt.
Und ich würde euch, die Challenge,
ich würde einfach mal die Challenge in den Raum stellen,
schaut euch doch mal die Mediathek an und versucht mal,
ein Asserts zu finden, wo hier etwas anderes steht als hier.
Es würde mich wundern, wenn ihr das nicht finden würdet.
Weil da stehen bestimmt hunderte von Asserts drin und garantiert wurde irgendwann mal irgendeine Methode umbenannt,
ohne dass man daran gedacht hat, ach ja,
wenn ich die Methode umbenennen lasse, was ihr klebst,
ja so schön automatisch für mich tut,
E-Clips versteht ja nicht diesen String,
dann steht da möglicherweise Unsinn drin
Toll. Also das. Es nützt einem auch nicht großartig was,
wenn man das auf die Konsole schreibt,
weil als Programmierer muss man ja eh schauen,
oh Gott, in Cylo 29 ist irgendein Problem aufgetreten,
dann klicke ich mal auf die Fehlermeldung und dann landet ihr sofort hier.
Also es gibt einfach keinen Mehrwert, wenn ihr das dann nochmal reinschaut.
Okay. Gut, dasselbe würde man hier machen. Jetzt ist es immer so,
immer wenn man dasselbe schreiben muss, ich muss immer schreiben,
diese Doppelpunktvorbedingungen verletzt, das ist ja irgendwie nervig,
ab und zu vergisst man dann,
ich würde halt irgendeinen Buchstaben oder so.
Vielleicht kann man da ein bisschen Schmerz vom Programmierer wegnehmen,
dass er das nicht alles von Hand tippen muss.
Also es gibt hier irgendwie sowas,
das nennt sich
Code Templates
Nee, Moment. Ah, ich verwechsel das immer.
Editor Templates. Ja, genau. Editor Templas. Und
da kann ich mir mal so ein neues Template anlegen.
Das ist einfach nur eine, so ein Makro vielleicht,
wenn ihr aus World irgendwelche Makros kennt.
Ich kann nur so zum Beispiel sagen,
für Vorbedingungen schreibe ich mal irgendwas Griffiges,
drei buchstabige Abkürzungen, das sind doch immer tolle Informatiker.
Pre nenne ich das einfach mal, Pre-V, Pre-Condition. Dann vielleicht,
damit man in ein paar Wochen auch noch versteht,
was der Sinn davon ist,
nämlich Tesla einfach mal Vorbedingungen prüfen oder so oder Vorbedingungen reicht.
Und jetzt kann ich den Code hier reinschreiben,
der generiert werden soll von Eclipse, wenn ich dieses Pre verwende.
Okay, was soll dann generiert werden?
Das soll erst mal das Asset-Schlüsselwort generiert werden.
Dann soll der Programmierer eine Möglichkeit haben,
eine Variable einzufügen
Achso, nee, ich schreibe da einfach meine eigene Variable hin.
Also kann ich zum Beispiel sagen, Bedingungen,
da soll irgendeine Bedingung stehen. Okay, dann soll da
ein Doppelpunkt stehen und dann sollte der String stehen vor Bedingungen verletzt.
So, okay, das würde ich nicht immer selber schreiben müssen.
Ich will, dass Eclipse das für mich macht.
Okay. Und der magische Schlüssel ist eben dieses Pre,
das zeige ich euch gleich.
Okay, haben wir das gemacht? Jetzt versuche ich mal,
dieses Pre zu verwenden, also Pre, okay,
Steuerung leertaste. Ah, seht ihr das hier,
Pre-Vorbedingung, das will ich haben,
drücke ich ändern
Okay, und jetzt hat er das alles für mich hingeschrieben und da,
wo ich eben diese Variable mit dem Dollar und den geschweiften Klammern gemacht habe,
da steht jetzt diese Bedingung, da kann ich jetzt reinschreiben,
was ich will, zum Beispiel, not guess empty.
Ja, oh, da habe ich die Klammern vergessen.
Ha, Troy, das ist der Compiler, das überprüft und mich sofort darauf hinweist.
Ja, vielleicht mache ich hier nochmal eine eigene Zeile,
dass man sieht, das ist das Vertragsmodell und das ist die eigentliche Programmlogik.
Ja, ach, das ist doch nicht schlecht. Mal gucken,
ob wir noch irgendwo was Sinnvolles machen können, das heißt,
darf ich immer aufrufen, ich darf auch leere Stacks fragen,
wie groß sie sind, das E-Semty darf ich immer aufrufen,
das nur unter den Umständen Push, darf ich auflehren,
oder nicht lernen aufnehmen, das ist egal,
aber anschließend ist er definitiv nicht leer.
Das Element, was ich reinstecke, ist dann obendrauf,
das macht doch auch Sinn.
Oh, das sieht doch eigentlich ganz nett aus.
Dann können wir doch eigentlich direkt mal sagen,
da machen wir gleich mal ein neues Kapitel in unserer Geschichte.
Also, at contracts to, wenn im YouTube Stack and
not, ja, ne,
mutable Stack.
Okay, jetzt haben wir also diese Vorbedingungen,
da hatten wir eine Vorbedingung hier zum Beispiel,
wir haben sie einmal hier im Kommentar drin, okay?
Und wir überprüfen sie. Auch hier ist es jetzt leider schon so blöd,
ich habe es einmal hier, diese Vorbedingungen und einmal hier,
also ihr müsst höllisch aufpassen, dass das nicht irgendwann mal auseinanderlaufen wird.
Da braucht man einfach ziemlich viel Disziplin als Programmierer. Ist einfach so. Okay,
aber wir haben ja schon gesehen,
dass wir diese Nachbedingungen nicht überprüfen oder zumindest,
ich habe es nicht gemacht und ich habe auch gute Gründe dafür,
das nicht zu machen und es dauert ziemlich lange,
das zu erklären, aber auf den Folien stand es ja drauf.
Was könnte man denn jetzt machen oder
welchen Sinn könnte es haben, dass sich diese Nachbedingungen hier
reingeschrieben habe
Das ist jetzt ja erstmal nur Text. Bringt da so irgendwas
? Vielleicht für den weiteren Verlauf des Projekts oder so.
Was wäre jetzt ein sinnvoller nächster Schritt,
den ich machen könnte, wenn ich diese Nachbedingungen formuliert habe?
Okay, also es ist erstmal eine weitere Form der Dokumentation,
irgendwie eine formale Dokumentation, was hier passiert.
Also die Semantik dieser Operation finden müssen formal festgehalten.
Okay. Tatsächlich überprüfe ich es jetzt aber jetzt nicht mit
einem Assert. Welche anderen Möglichkeiten haben wir denn zu überprüfen?
Das ist eine Software, das macht,
was sie tun soll,
laut Dokumentation
Ja. Ja. Ja. Ja. Ja.
Ja. Ja. Ja. Ja. Genau. Sehr
schön, ne? Also ich sage immer ganz gerne,
diese Entschurs sind eine Inspirationsquelle für Testfälle. Und ich kann
mir das so gut merken, weil es sich reimt.
Inspirationsquelle für Testfälle. Okay. Yes. Ja,
dann machen wir uns doch mal eine Testklasse, oder?
Also sage ich mal,
ich will eine neue Und jetzt sagt man nicht einfach nur Klaas,
sondern es gibt hier einen speziellen Punkt für J. Unit Testcase,
das will ich machen.
Ich will einen J. Unit Testcase haben.
So, wie wollen wir den nennen? Die Klasse,
die wir testen wollen, heißt ja Mutable Stack,
dann nenne ich das doch mal Mutable Stack Test.
Okay, jetzt kann man hier noch ganz viele Optionen machen,
bevor ich verstanden habe, was die alle bedeuten.
Ich mache einfach Finnisch und wenn mir das nicht gefällt, was dabei rauskommt.
Achso, jetzt sagst du noch J. Unit 4,
muss zum Larry Part dazu, das ist auch in Ordnung.
So, und jetzt hat er mir hier so ein kleines Grundgerüst erzeugt.
Ich lösche erstmal wieder überflüssige Leerzahlen, ich weiß aber nicht,
wo die herkommen, mag ich nicht,
gefällt mir nicht.
Wie sieht so eine Testklasse aus? Wir hatten ein SE1
mal ganz kurz über Tests geredet. Das ist vielleicht schon
ein bisschen her, okay? Also was man immer gerne hat,
macht, oder wie man so einen Test oft systematisch aufhört,
ist zu sagen, wir machen uns erstmal eine Exemplarvariable,
die von dem Typ ist, von der Klasse,
die wir testen wollen.
Ich will ja Mutable Stack, diese Klasse will ich testen.
Und ich nenne sie jetzt einfach mal nur Stack,
dass ich nicht immer so viel tippen muss.
Dass das ein Mutable Stack ist, ist irgendwie klar,
die Testklasse heißt der Sohn,
der Typ steht hier auch noch rein.
Okay. Machen wir Konstruktor. Mutable Stack Test und erzeugen
uns vielleicht mal einen neuen Mutable Stack
So. Okay, und jetzt können wir mal gucken,
für welche Operationen wir, was sinnvolle Tests schreiben können.
Also schauen wir uns das nochmal in Ruhe an.
Was ist das Erste, was mir so spontan einfällt?
Gehen wir mal zu den leichtesten Operationen hier uns.
Dieses ist Empty und Size. Das gefällt mir eigentlich ganz gut.
Eigentlich ist das gar nicht gut, was ich euch gerade gesagt habe.
Ich habe euch gerade gesagt, wir schauen uns die Methoden an,
die wir testen können und daraus leiten wir Testfälle ab.
Eigentlich ist es nicht das, was man macht,
sondern man überlegt sich,
was sind tatsächlich Use Cases von diesem Stack und ein ganz einfacher Use Cases ist,
ich erzeuge mir ein Stack und ich schaue mir einfach an,
in welchem Zustand ist er eigentlich, nachdem ich mir erzeugt habe,
ja.
Also ich könnte zum Beispiel sagen, Test,
Fresh Stack ist in Deed, MT oder so.
Ja, ich nenne die immer gerne ganz lang,
da muss ich hoffentlich keinen Kommentar dazu schreiben, welchen Sinn dieser Test hat.
Okay, das nehmen wir jetzt mal raus, das ist Quatsch.
Wie kann ich jetzt J. Unit fragen oder bitten zu überprüfen?
Prüf doch mal, dass dieser Stack wirklich leer ist.
Weiß jemand noch, J. Unit, die API von J. Unit,
wie die Methoden heißen, mit denen man gewisse Dinge testet,
ist schon lange her,
oder?
Wenn ihr jetzt nicht J. Unit,
Das ist ja true, sehr schön. A sir true.
Und was ist, hörten wir, was true sein soll?
Genau, und diesmal natürlich auf Unterstrich-Stack.
Sehr schön. So. Das wäre also unser erster Testfall.
Wann habe ich eigentlich das letzte Mal einen Commit gemacht?
Ah, okay, vor fünf Minuten, was haben wir noch?
Ad Contract zu mir. Okay, ich habe seitdem also
nichts anderes gemacht, bevor ich das gemacht habe.
Okay. Das ist doch gut. Wie führe ich denn
jetzt so einen Test mal aus? Guck mal hier
unseren ersten Test ausführen, sag ich doch mal.
Run as J. Unit Test
Und ihr seht jetzt ähnlich wie in Blue Jade,
das ist so eine eigene Ansicht dafür gibt in den Clips,
wo man also sofort auf den ersten Blick sieht,
alles ist in Ordnung.
Ihr müsst euch also jetzt nicht durch großartige Logs durchquälen und
tausende von Zeilen lesen, dass ganz viel in Ordnung ist.
Und ihr seht sofort mit diesen grünen Balken,
alle eure Testfälle sind durchgelaufen, ohne dass es irgendein Problem gab.
Also einer von einen. Okay. Ja,
auch man kann eigentlich ruhig noch mehr hier reinschreiben.
Es ist ja nicht nur so, dass er leer ist,
sondern was gilt noch für den leeren Stack?
Also einmal, er ist leer, ja.
Hm? Keine Elemente, ne? Also wie schreibt man
das? Es hört Equals
null Stack.size
Ja, das können wir nochmal ausführen,
wenn ich den Test einfach nochmal ausführen will,
dann kann man, glaube ich, hier raufklicken, Rerun-Test.
Und es funktioniert immer noch. Sehr gut, mehr will
ich aber jetzt nicht in diese Methode reinstecken, ja.
Also versucht immer, dass eine Testmethode wirklich für einen konkreten Use-Case steht. Ich könnte,
im Prinzip könnte ich ja alle Tests sich jetzt schreiben,
in diese eine Testmethode reinschreiben, rein technisch geht das,
der Club wird sich nicht beschweren,
aber das ist einfach nicht besonders sinnvoll.
Genauso wie wir in Kerl gesagt haben,
macht nicht zu viel Kram in einer Methode,
das gilt genauso natürlich auch für Testmethoden.
Und ich finde, das gehört eigentlich logisch schön zusammen.
Der leere Stack ist leer und es sind null Elemente drauf.
Toll. Wie geht es weiter
Also wir haben jetzt noch überhaupt nicht zum Beispiel so was mal gemacht,
dass Push, das Top, das Pop,
also man sollte sich sicherlich nicht nur leere Stacks angucken,
sondern vielleicht auch mal Stacks mit mehr Elementen.
Und ich habe mal so einen wunderbaren Aufsatz gelesen über Testen,
immer wenn es um irgendwelche Sammlungen geht,
sollte man in Fahrt testen,
Null-Elemente sind in der Sammlung 1 und 2.
Dann hat man schon mal 90 Prozent abgetestet sozusagen.
Also das handelt sich um einen Test,
weil das muss man schon speziell annotieren.
Also könnte ich doch mal zum Beispiel sagen, Test,
keine Ahnung,
Single-Elements oder One-Elements,
So schauen, dass ich Stacks mit einem Element so verhalten,
wie ich das erwarte. Gut, dann tue ich doch
erst mal raus, was rauf auf den Stack.
Was wollen wir rauf tun? 42. Okay.
Könnte ich eigentlich hier direkt schon irgendwas testen?
Liefert mir dieses Push irgendwas zurück? Das liefert mir einfach
Volt zurück. Okay. Aber jetzt kann ich mich eben
an diesen Entschuss irgendwie langhangeln und daraus irgendwelche Testfälle ableiten.
Also diese Operation verspricht mir ja, dass der Stack anschließend
nicht leer ist. Das kann ich ja wunderbar testen.
Ich kann also sofort sagen, das wird sofort überprüft,
as hird fouls,
Stack is empty.
Ist es schon 15.45 Uhr? Bis wann geht die Vorlesung? Ah,
okay, wo ist die ganze Zeit auf einmal hin?
Gut, was haben wir noch? Dann hat er uns noch gesagt,
wenn man top aufruft, dann kommt das X zurück,
das kann man ja, das kann ich jetzt mal genauso testen,
also bleibt ruhig noch ein bisschen hier, vielleicht fünf Minuten oder so.
Wir haben ja die Umbaupause gehabt. So, konnte man
dann noch was Sinnvolles ableiten? Über die Größe zum Beispiel,
ich muss das jetzt gar nicht so abstrakt formulieren,
ich weiß ja, dass die Größe vorher null war,
was kann ich hier über die Größe,
oh,
was habe ich denn hier gemacht
Was will er hier von mir? Oh. Okay.
Das sagt mir nichts. Da muss ich mir einmal
ganz kurz angucken, was das Java-Doktor dazu sagt.
Das ist ja ärgerlich. Okay. Muss ich dann
zu Hause ausfinden, was das bedeuten könnte.
Was kann ich über die Größe aussagen?
Oh, ich bin in der falschen Methode drin.
Was kann ich über die Größe
diese Stacks aussagen
Bist du jetzt in Zalo 26 oder an seine 27?
26. Also du sagst, ich kann jetzt hier irgendwas...
Was soll ich denn hier konkret ändern?
Aber hier steht doch Double Expected, Double Actual.
Das ist auch genau das, was ich übergebe.
Ich will mich jetzt an dieser Warnung nicht zu lang aufhalten.
Kann mir jemand die Frage beantworten, wie kann ich überprüfen,
dass die korrekte Größe da zurückgegeben wird?
Ja. Genau. Bitte werdet noch nicht zu unruhig,
wenn ihr gehen müsst, weil ihr noch eine andere Veranstaltung
habt,
geht bitte leise
Okay. Interessant, dass es hiermit geht, aber damit nicht.
Möglicherweise hat es mit einem Typsystem zu tun. Nee. Okay,
jetzt die Tests, die wir bis jetzt geschrieben haben,
würden nicht nur für ein Stack funktionieren,
sondern auch zum Beispiel für eine Q.
Wenn ich also aus Versehen den Stack gar nicht als Stack implementiert hätte,
sondern irgendwie als Q, dann würden meine Tests das nicht aufdenken,
weil ich bis jetzt nur mit null und einen Elementen teste.
Ich muss das auf jeden Fall nochmal mit zwei Elementen testen.
Ich mache jetzt mal, damit es ein bisschen schneller geht,
kopiere ich mir den Quelltext einmal ganz kurz.
Ich nenne das mal Test, True-Element-Stack,
weil dann würde man es, glaube ich,
spätestens merken.
Dann tue ich mal
eine Eins auf den Stack
Dann tue ich mal eine 2 auf den Stack.
Und dann entfernen wir mal ein Element. Sagen wir mal stack.pop.
Und dann können wir mal schauen, dass das oberste Element...
Was würden wir jetzt erwarten bei einem Stack? Also ich
tue die 1 drauf, ich tue die 2 drauf,
dann entferne ich das oberste Element.
Welches Element sollte dann obendrauf sein? Ja,
die 1. Das ist also jetzt der erste Testfall,
der tatsächlich überprüft, dass es sich um einen Stack handelt.
Die beiden Testhülle davor haben das sonst noch nicht abgedeckt
Okay, so, dann mache ich noch mal einmal
ganz kurz eine Formatierung. Das alles schön formatiert ist.
Dann sagen wir noch mal einen Commit. Jetzt muss ich,
glaube ich, es gibt jetzt neue Dateien, oder?
Utable Stack Test kennt er nicht. Das muss ich einmal jetzt
so von Hand hinzufügen, weil er das sonst nicht übernehmen würde.
Und dann sagen wir mal, Version at the End of Lecture 2.
Und ich werde das dann im Internet bereitstellen und werde im Kommen,
die zeigen euch, wie ihr dann selber an den Quelltext rankommen könnt.
Das erstaunt mich gerade, dass ich so wenig Zeit hatte.
Ich weiß nicht, woran es lag.
Vielleicht ist das Thema einfach so spannend. Okay,
vielen Dank und bis nächste Woche