So, meine Damen und Herren, schönen guten Morgen.
Kommen Sie langsam zur Ruhe, mittlerweile geht auch der Beamer.
Ich heiße Sie herzlich willkommen zur ersten Übung zur Softwaretechnik
1.
Und natürlich habe ich auch heute wieder einen Puzzler dabei.
Das ist im Grunde der gleiche Puzzler wie am Montag.
Nämlich haben wir wieder eine Map, da wird Mickey und Maus
reingesteckt.
Und diesmal gibt es auch keine Verwirrung, dass da irgendwie noch ein
Konstruktor drin ist.
Oder eine Main-Methode, die vielleicht nicht aufgerufen wird oder so.
Das ist einfach nur dieser Schnipsel.
Und es ist wieder die Frage, was kommt denn raus, wie groß ist denn M?
Und naja, dass es keine Ausnahme gibt, ich denke, das glauben Sie mir
einfach mal.
Weil das ist noch einfacher als beim letzten Beispiel.
Und auch da hatten wir gesehen, dass die zwei gleichen Mickeys hier
kein Problem sind.
Und es ist die Frage, wie groß ist denn diese Map M?
Und den ersten Vorschlag, den ich hätte, das wäre die Null.
Also hier kommt Null raus.
Möchte da irgendjemand ans Telefon gehen?
Oder möchte jemand summen für die Null?
Das wäre jetzt der Zeitpunkt.
Sicher niemand, okay.
Wer glaubt denn, dass da 1 rauskommt?
Das wäre dann die nächste Zahl.
Also wer für 1 ist, der darf bitte jetzt mal summen.
Okay, und jetzt dürfen noch die summen, die für das offensichtliche
Ergebnis sind, nämlich für die 2.
Das wäre jetzt der Einsatz.
Oh.
Okay.
Das ist ein bisschen gemein.
Das ist ein bisschen schade.
Also die mit Null, da hat glaube ich niemand gesummt von Ihnen.
Insofern war das okay.
Jetzt ist also die Frage, haben die recht, die paar wenigen, die sich
hier getraut haben, bei der 1 zu summen.
Und ich denke, die meisten von Ihnen wissen, wenn man eine Hashmap hat
und man steckt da was rein und verwendet dann nochmal denselben
Schlüssel, genauso wie das hier der Fall ist, dann wird es
überschrieben.
Was wahrscheinlich keinem aufgefallen ist, ist, dass das hier eine
Identity Hashmap ist.
Ich hoffe, ich erzähle jetzt hier keinen Quatsch.
Ne, Sie haben recht.
Aber es ist trotzdem eine Identity Hashmap.
Die nutzt die Referenz.
Und jetzt bleibt die Frage übrig, möchte jemand erklären, warum da
trotzdem 1 rauskommt, selbst wenn da eine Referenz benutzt wird.
Sie hatten letztes Mal einen roten Pulli an, richtig?
Okay.
Sie sind immer der Schnellste.
Ist noch jemand anders da, der sich mit der Identity Hashmap auskennt?
Es sind immerhin noch drei mehr.
Aber sie waren alle viel langsamer.
Und heute kann ich Ihnen wohl nicht abwürgen.
Also bitte.
Okay, er sagt, Java ist ganz schlau.
Und sieht, wir haben hier zweimal denselben String benutzt.
Also hier dieses Mickey.
Und deswegen gibt es da intern nur eine Instanz.
Und deswegen ist es dieselbe Referenz.
Und damit hat er recht.
Das gilt aber nur dann, wenn man die Zeichenketten auch so
hinschreibt.
Wenn man da hingeschrieben hätte, New String und in Klammern dann
Mickey, dann kriegt man tatsächlich eine neue Instanz mit einer
eigenen Referenz.
Und dann verhält sich das Beispiel ein bisschen anders.
Eine Lehre gibt es diesmal keine.
Außer, dass man genau lesen muss, was da eigentlich passiert.
Und dann können wir auch schon anfangen mit der Übung.
Ich hoffe, Sie hatten nicht allzu große Probleme und Sie verzeihen uns
den LEZ-Ausfall, der da in der Nacht auf Dienstag passiert ist.
Ich erzähle hier nochmal.
Ich habe das auf der Mailing-Liste schon geschrieben, deswegen nur
ganz kurz.
Die LEZ, die ist hauptsächlich ein Abgabesystem.
Das heißt, wenn Sie da was hochladen und die E-Mail bekommen, ach
übrigens, Sie haben gerade was hochgeladen, dann ist eigentlich schon
alles in Ordnung.
Weil dann ist Ihre Abgabe bei uns und Sie können uns hinterher
beweisen, dass Sie rechtzeitig abgegeben haben.
Alles, was danach kommt, das ist Bonus.
Und die Prüfung, die die LEZ da vornimmt, um dann eine Lösung
abzulehnen oder nicht, das sind nur ein paar sehr rudimentäre Dinge.
Nämlich können wir Ihr Paket bei uns übersetzen und stimmt die POM zu
gewissen Bestandteilen.
Und wenn das okay ist, dann gibt es eben dieses Approved und ansonsten
gibt es das Rejected.
Das heißt aber nicht, dass wir diese Lösung dann löschen.
Sondern wenn Sie um kurz vor Deadline was hochladen und dann nach der
Deadline gesagt kriegen, das war jetzt aber nichts, dann geht die
Datei trotzdem an Ihren Tutor.
Und der wird dann entscheiden, ob Sie dafür Punkte bekommen und wenn
ja, wie viele.
Das heißt nicht, dass die LEZ ablehnt und dann haben Sie automatisch 0
Punkte für die Aufgabe, sondern das geht trotzdem an Ihren Tutor.
Wir werden uns bemühen, die Fehlermeldung noch ein bisschen
ausführlicher zu gestalten, damit Sie auch wissen, was bei dem Maven
Compile fehlschlug.
Damit das in Zukunft etwas besser läuft.
Ich hatte Ihnen letztes Mal schon die Geschichte erzählt aus der U
-Bahn.
Diesmal habe ich was dabei, was ein bisschen weniger lustig ist.
Und zwar gab es Ende der 70er einen schweren Unfall mit einer
teilweise Kernschmelze in einem Atomkraftwerk in den USA.
Das lag jetzt mal nicht daran, dass irgendjemand ein Ventil abgedreht
hat und dann ins Wochenende gefahren ist oder dass da irgendwas
Hardware -mäßig komplett daneben war, sondern da ging es um eine
Pumpensteuerung.
Da gab es eben ein Ventil, das im Wesentlichen für Kühlwasser wohl
zuständig war.
Und im Kontrollraum gab es eine hübsche Lampe, die hätte leuchten
sollen, wenn das Ventil zu ist.
Wenn man nicht will, dass das Kühlwasser unten rausläuft, macht man
das Ventil zu, dann leuchtet dieses Lämpchen und dann ist alles toll.
Und genau so war das da.
Das Lämpchen hat geleuchtet, aber das Ventil war nicht zu.
Weil da hat jemand eine Software für geschrieben.
Das war natürlich kein Hardware-Lämpchen, sondern da war irgendwo
hintendran ein Rechner.
Und irgendjemand hat in die Spezifikation geschrieben, wenn die
Anforderung kommt, das Ventil zuzumachen, dann schaltet das Lämpchen
ein.
Und das haben die auch gemacht in der Software.
Das heißt, wenn man auf das Knopf gedrückt hat zum Ventil schließen,
dann hat man die Anfrage weggeschickt, dass das Ventil geschlossen
wird und dann ging das Lämpchen an.
Das hatte aber nichts damit zu tun, ob das Ventil auf war oder zu.
Das heißt, da ging es nur um die Anforderung, mach mal das Ventil zu.
Und wenn das Ventil offen bleibt, weil es verklemmt ist oder sonst
irgendwas, dann ist das Lämpchen trotzdem an und dann hat man
natürlich im Kontrollraum ein massives Problem.
Hinterher muss man nämlich die Suppe aufputzen.
Das heißt, wenn Sie so eine Anforderung haben und Sie sehen, ja gut,
die ist testbar.
Wenn jemand auf den Knopf drückt, dann geht die Lampe an.
Ja klar, natürlich kann ich das testen.
Und natürlich kann ich auch nachvollziehen, ob die Anforderung im Code
umgesetzt wird.
Aber die Anforderung ist trotzdem Quatsch.
Und wenn Sie solchen Quatsch sehen in Ihrem späteren Berufsleben, dann
sagen Sie mal Bescheid.
Irgendjemanden mal auf die Schulter klopfen und sagen, ich glaube, das
ist keine gute Idee, das so zu machen.
So viel zu der Anekdote.
Die erste Aufgabe auf dem Übungsblatt war im Prinzip nur, die hübsche
Altsoftware hernehmen und in das Maven-Kleid gießen.
Das Erste, was wir dazu tun mussten, war das Ganze aus dem SVN
rausziehen.
Bei Sourceforge, die URL hatten wir Ihnen ja gegeben, die hat sich
zwischendrin geändert.
Hier steht noch die alte, aber ich nehme nicht an, dass es irgendein
Problem gab.
Wenn man sowas eingibt auf der Kommandozeile, dann passiert relativ
viel, nämlich SVN sagt, was es da alles runterlädt.
Und am Ende kommt dann eben die Meldung, okay, ich habe jetzt einen
Export gemacht von dem Repository und zwar in der Revision 52.
Das ist zufällig genau die, die wir haben wollten.
Obwohl wir hier oben beim Exportbefehl nicht eingegeben haben, welche
Revision wir haben wollen, haben wir da zufällig die richtige
erwischt.
Hätte jemand bei Sourceforge zwischendrin weitergearbeitet an dem
Projekt, dann hätten Sie hier oben tatsächlich angeben müssen, gib mir
bitte die Revision 52.
Wenn Sie das gemacht haben erfolgreich, vielleicht sogar mit einem
grafischen Werkzeug, dann sieht das Ganze so aus, da hat man also eine
Menge von Dateien und ein paar Ordner, die da drin rumfleuchen und die
sind jetzt nicht unbedingt dort, wo Maven sie erwartet.
Und wir hatten Sie gebeten, das ein bisschen aufzuräumen und was man
eben braucht, mindestens, das sind diese Verzeichnisstrukturen.
Einmal Sourcemain.java für die Klassendateien und einmal Sourcemain
.resources für die ganzen Ressourcendateien.
Und naja, was kommt also nach Sourcemain.java?
Im Grunde alles, was vorher in Source drin lag.
Außer ein paar kleinen Ausnahmen.
Nämlich unter Source, da lagen auch die Icons und ein paar Property
-Dateien, nämlich Sprachdateien, die musste man in den Sourcemain
.resources -Ordner verschieben.
Und jetzt hat sich vielleicht der ein oder andere gefragt, warum muss
ich das denn machen, wenn ich alles hernehme, was in Source drin liegt
und nach Sourcemain.java schiebe und im Eclipse auf Play drücke?
Dann funktioniert doch alles.
Da haben Sie nicht ganz Unrecht, aber wenn Sie das Ganze nicht mit
Eclipse bauen, sondern Maven bauen lassen, dann passiert ein bisschen
was anderes.
Maven geht nämlich her und nimmt aus dem Verzeichnis Sourcemain.java
alle Dateien raus, die Quelltextdateien sind.
Und die werden an den Übersetzer weitergereicht.
Man hat also nach dem Übersetzungsvorgang kompilierte Klassen.
Alle, die hier unter Sourcemain.java drin standen.
Und die werden dann zur Ausführungsumgebung übergeben.
Zusammen mit allen Resource-Dateien, die unter Sourcemain.resources
liegen.
Und wenn da nichts drin ist, dann kommt da halt nichts an.
Sie hätten dann also ein Programm gebaut, das alle Klassen enthält,
aber keinerlei Ressourcen.
Und zwar einfach deswegen, weil das Bildwerkzeug nicht weiß, dass sie
Quelltext und Ressourcen gemischt haben.
Das heißt, an der Stelle fällt das Ganze dann auf die Nase.
Deswegen muss man das umziehen.
Es gibt noch ein Stapel weiterer Dateien in dem Projekt.
Die liegen in dem Verzeichnis Templates.
Das muss man leider dort liegen lassen, wo es ist, weil wenn man das
nach Resources verschiebt, dann ist es noch weiter weg vom Schuss.
Das liegt daran, dass die Autoren von JM2RST in diesem Galerie-Dialog,
der diesen hübschen Tippfehler enthält, die Templates einfach mit
einem Pfeilhändel aufmachen.
Und da steht drin, im aktuellen Verzeichnis gibt es ein
Unterverzeichnis, das heißt Templates, und da sind die ganzen Vorlagen
drin.
Das ist natürlich ein bisschen Panne, weil immer wenn man das Programm
jetzt ausliefert, muss man ins selbe Verzeichnis, wie das Programm
liegt, dann auch noch die Templates reinschieben.
Dafür gibt es ein paar andere elegante Lösungen.
Wenn Sie sich das mal anschauen wollen, können Sie gerne hier in die
Methode schauen, die in 379 anfängt in dem Galerie-Dialog.
Aber das werden wir im Rahmen der Vorlesung nicht weiter anfassen.
Was man da noch tun muss, damit das Ganze ein bisschen...
dass es überhaupt mit Maven funktioniert ist, man braucht noch so eine
POM.
Das heißt, wir hatten so ein paar Dateien, die wir aus Let's-Test
-Dummy haben kopieren lassen.
Und dann mussten wir noch die POM anpassen und dann war das eigentlich
schon okay.
Das ist so die Quick-and-Dirty-Variante, wie man die Aufgabe lösen
kann.
Was wir noch von Ihnen haben wollten war, machen Sie ein Git
-Repository und führen Sie Versionskontrolle durch.
Das heißt, wann immer Sie sinnvolle Abstände haben, wäre es gut
gewesen, wenn Sie ein commit gemacht hätten.
Das Ganze landet dann, das sehen wir später, in einem Changelog, damit
Ihr Tutor nachvollziehen kann, ob Sie so einigermaßen mit Git arbeiten
oder nicht.
Das wird es auf jedem Übungsblatt geben, die Hinweise, das zu tun, die
werden immer weniger werden.
Aber Sie werden immer ein Changelog mit abgeben und es wird immer
Punkte dafür geben, wenn man Git richtig benutzt.
Das heißt, wenn Sie die Aufgabe auf dem Übungsblatt runterladen, sie
komplett lösen und dann einmal committen, dann kriegen Sie diesen Git
-Punkt einfach nicht.
Das wird in aller Regel nicht viel sein, aber den haben Sie dann halt
verpasst.
Umgekehrt, selbst wenn Sie die Aufgabe nicht lösen können, wenn Sie
regelmäßig sinnvoll committet haben, dann kriegen Sie mindestens den
Git -Punkt.
Das ist also relativ einfach, hier Punkte mitzunehmen.
Das sind dann sechs Stück über die sechs Übungsblätter und das gleiche
gilt auch für Checkstyle.
Den Code, den Sie schreiben, den sollen Sie mit Checkstyle prüfen und
da sollen keine Fehler drin sein und wenn das so ist, dann kriegen Sie
einen Punkt.
Und wenn da noch Checkstyle-Warnungen drin sind, dann kriegen Sie den
nicht.
Sie haben also ungefähr zwölf Punkte, die Sie einfach so mitnehmen
können, indem Sie die Werkzeuge einsetzen.
Sie müssen nochmal anfangen und lauter sprechen.
Ja,
wir kommen noch zu dem Punkt.
Ich greife Ihre Frage dann nochmal auf.
Was wir noch wollten von Ihnen ist, dass Sie ein paar Konfigurations
-Einträge vornehmen für das Maven-JAR-Plugin, die hier in dunkelblau
eingefärbt sind.
Das waren die, die wir im Prinzip aufs Übungsblatt draufgeschrieben
haben.
Fügen Sie die hinzu.
Ich nehme an, das hat jeder hingekriegt.
Das hellgrüne in diesem schicken Kit grün, das sorgt dafür, dass
hinterher klar ist, in welcher Klasse die Main-Methode von dem
Programm ist.
Das sollten Sie sich ergoogeln.
Ich nehme auch an, dass Sie das hinbekommen haben.
Das ist ja nicht so furchtbar schwer.
Und jetzt ist die Frage, was passiert denn damit?
Offensichtlich, wenn man diese hellgrüne Zeile hat, dann fällt
hinterher aus dem Kompilierprozess ein JAR raus, das man unter Windows
mit einem Doppelklick öffnen kann.
Oder in der Kommandozeile mit dem Befehl java-jar.
Dann gibt man nur den Dateinamen an und dann weiß Java schon, wie das
Programm anzusprechen ist.
Ansonsten kommt da einfach diese hübsche Fehlermeldung, ich kann keine
Hauptmethode finden.
Jetzt ist die Frage, wie kriegt Java das dann raus, weil Java liest ja
nicht die POM-Datei.
Java liest die Manifest-Datei.
Das sieht man hier schon angedeutet an diesem Manifest-Knoten, der da
drin ist.
Wenn Sie das JAR mal aufmachen, ein JAR ist nichts anderes als ein ZIP
-Archiv.
Sie können das mit jedem ZIP-Programm öffnen.
Und da liegt eine Datei drin in dem Verzeichnis meta-inf und die heißt
manifest.mf.
Da steht relativ wenig drin, wenn man da nichts weiter einstellt,
nämlich meistens so die ersten fünf Zeilen, die hier schwarz sind.
Da steht also drin, mit welchem JDK wurde das Ganze gebaut und welche
Manifest -Version ist das.
Und wenn Sie nichts einstellen in Maven oder in Ihrer Bildumgebung,
dann ist das schwarze hier oben wahrscheinlich alles, was Sie sehen.
Natürlich steht dann da nicht Maven, sondern Eclipse oder sonst was
Sie benutzt haben, aber das ist nicht besonders hilfreich.
Wenn Sie diesen Eintrag machen mit der Main-Class, dann kommt hier
auch ein Eintrag dazu mit der Main-Class.
Und dann weiß die Java Runtime, wenn ich dieses Ja bekomme und mir
sonst nichts gesagt wird, dann finde ich in diesem Paket eine Klasse
Main und die hat eine Main-Methode und die soll ich dann rausholen.
Das ist ziemlich praktisch, weil Sie sparen sich dann ein bisschen
Tipparbeit und meistens, wenn Sie Anwender haben, die nicht so fit
sind, dann ist es äußerst praktisch, wenn Sie Ihre Programme mit einem
Doppelklick öffnen können.
Das dunkelblaue, was hier unten drunter ist, das kommt dazu aufgrund
dieser anderen Einstellungen, dieser Default Implementation Entries
und der Default Specification Entries.
Das sind jetzt Informationen, die Sie haben wollen, wenn Sie selbst
Softwareentwickler sind.
Wenn Ihnen jemand ein JAR gibt, das heißt BLAR 2017 Version 4 Beta 2
Update 14.JAR, dann wissen Sie im Prinzip, dass der Kerl sich einen
super guten Dateinamen ausgedacht hat, aber ansonsten wissen Sie
nichts über die Bibliothek, weil den Dateinamen können Sie einfach
ändern.
Wenn Sie dann diese Datei haben, im Normalfall wird man Ihnen ja nicht
sowas geben mit Versionsinformationen, sondern man wird Ihnen ein BLAR
.JAR auf den Schreibtisch werfen und das sollen Sie dann verwenden.
Da Sie die ganzen Schnittstellen kennen, ist das kein Problem, aber
wenn da drin ein Fehler ist, dann haben Sie eins.
Weil Sie gehen dann zum Hersteller oder dem Kollegen, der das gebaut
hat und sagen, also bitteschön, in diesem BLAR.JAR ist ein Fehler.
Ich weiß jetzt nicht von welcher Version und aus welcher Revision das
bei euch ist, aber das ist halt kaputt, macht das mal ganz.
Und wenn Sie diese Informationen hier nicht haben als
Softwareentwickler, dann wissen Sie halt nicht, oder dann brauchen Sie
irgendwo eine Liste, wo draufsteht, das BLAR.JAR, das ich dem Matthias
Landhäuser gegeben habe, das ist die Revision 52 oder sonst eine.
Wenn man diese Infos allerdings hat, dann steht hier halt relativ
genau drin, welche Version das ist, wie das Programm heißt.
Hier ist es jetzt die Matrikelnummer, weil das ist unsere Artifact-ID.
Also das wäre im Falle von einer Bibliothek eben ein sinnvoller Name.
Und dann gibt es halt noch Informationen dazu, wer das Ding vertrieben
hat.
Und glücklicherweise steht keine Telefonnummer dabei, weil sonst würde
ja andauernd bei mir das Telefon klingeln.
Aber wenn Sie mal eine Software ausliefern oder eine bekommen und
herausfinden müssen, was Sie da eigentlich in der Hand haben, dann
packen Sie einfach mal das JAR aus, gucken Sie in die Manifestdatei
und wenn Sie Glück haben, dann war der Entwickler so nett und hat die
Informationen da reingebaut.
Das bewirkt also die Änderung an der Maven-JAR-Plugin-Konfiguration.
Jetzt kommt ein Teil der Antwort auf die Frage, die von da oben kam.
Wie ist denn das mit Checkstyle?
Naja, wenn man die Checkstyle-Konfiguration für JMJ-RST verwendet,
dann kommen da relativ viele Fehler raus.
Das liegt hauptsächlich daran, hier diese 468 zum Beispiel, x should
be in the previous line, das sind fast immer geschwungene Klammern,
die im JMJ-RST-Quellcode eben nicht in der Zeile beispielsweise von
der IF-Anweisung stehen, sondern eine Zeile drunter.
Oder nicht in der Zeile der Methodendeklaration, sondern eine Zeile
tiefer.
Wir hatten Sie gebeten, da ein bisschen was aufzuräumen.
Was Sie da aufgeräumt haben, ist letztendlich egal.
Und um die Frage jetzt vollständig zu beantworten, Sie müssen nicht
dieser Fehler bis zum Ende des Semesters behoben haben, sondern der
JMJ -RST-Quellcode, der ist uns jetzt erstmal egal.
Dass da Checkstyle-Warnungen drin sind, ist uns bewusst.
Und wann immer wir Übungsaufgaben rausgeben, wo Sie in Checkstyle was
tun müssen, da achten Sie darauf, dass in Ihrem eigenen Code keine
neuen Warnungen entstehen, aber Sie müssen keine alten aufräumen.
Ich nehme an, das beantwortet Ihre Frage vollständig.
Was wir Ihnen auch noch nachgeliefert hatten, war ein Patch, den Sie
runterladen und anwenden konnten.
Dafür noch ein bisschen Hintergrundinformationen.
Dieser Patch, der wirkt sich auf Ihre POM-XML aus, unter anderem.
Und in der Maven-Einführung hatten wir Ihnen, glaube ich, erzählt,
dass man Einstellungen vererben kann.
Das heißt, wenn Sie eine Softwarefirma sind, dann können Sie bestimmte
Einstellungen einfach einmal für die ganze Firma festlegen, in ein POM
schreiben und quasi per Dekret sicherstellen, dass jeder dieses POM
auch benutzt.
Das sorgt dann dafür, dass Sie zum Beispiel irgendwelche
Projektleitungsvorgaben durchsetzen können, dass Sie
Versionsinformationen durchsetzen können, wenn Sie zum Beispiel
möchten, dass eine bestimmte Version von der Bibliothek verwendet
wird, dann können Sie das einfach einmal für die ganze Firma
festzurren und alle Ihre Mitarbeiter müssen dann leider damit leben.
Und genau sowas haben wir hier gemacht.
Und damit Sie an unsere POM drankommen, haben wir die verpackt.
Das heißt, so ein POM-XML selbst kann ein Maven-Artefakt sein und
dementsprechend kann man das in eine Maven-Depot ablegen.
Und genau das haben wir getan.
Wir haben also ein JAR bei uns auf dem Webserver liegen, in dem so
eine POM drinsteckt.
Und wenn Sie die Änderung erfolgreich angewendet haben, dann bekommen
Sie von uns ein paar Konfigurationen einfach aufgedrückt.
Und das macht es uns ein bisschen leichter und erspart Ihnen andauernd
in Ihrer POM rumzuwerkeln, wenn uns mal wieder einfällt, dass Ihr
wieder was Neues machen sollt.
Das Depot, in dem diese POM liegt, muss man Maven bekannt machen,
sonst weiß es ja nicht, wo es das runterladen kann.
Und das passiert mit der ersten Änderung.
Das heißt, wir haben hier einen DIV, den haben wir mit GIT gemacht.
Und der sorgt jetzt erstmal dafür, dass dieses Parent eingetragen
wird, damit die Vererbung funktioniert.
Das heißt, unser POM heißt Übungsparent und hat die GroupID edukit-ipd
-svt1 -ss2014 und die hübsche Version 001-snapshot.
Und damit Ihr Maven weiß, wo es die gibt, gibt es hier unten noch ein
Repository und da steht eben die URL drin, von der man dieses POM
beziehen kann.
Wenn Sie diese Änderung da drin haben, in Ihrem POM, müssen Sie sich
nicht weiter darum kümmern, weil Maven selbst nach Aktualisierungen
schaut.
Das heißt, wenn wir in diesem Übungsparent was eintragen, dann kommt
es früher oder später auch bei Ihnen an.
Wenn Sie sich das im Eclipse angucken, wenn Sie diese Änderung gemacht
haben, können Sie mal mit dem Eclipse-Editor die POM-XML aufmachen.
Das sieht dann so aus, dass Sie hier unten in diesem Parent-Block
jetzt diese drei Informationen drin haben.
Das sind genau die, die wir eingetragen haben über den Patch.
Und das hier oben, das ist die Artifact und die GroupID, die Sie
eintragen sollten, damit wir wissen, von wem die Aufgabe ist und
welche Aufgabe da gelöst wurde.
In dem Versionsfeld stand vorher auch noch 001-Snapshot drin.
Das steht bei Ihnen wahrscheinlich immer noch drin.
Das kann man aber weglassen, weil, wie gesagt, die Einstellungen
werden von dem Parent vererbt und hier unten steht ja auch schon 001
-Snapshot.
Wenn Sie also bei der Version 001-Snapshot bleiben wollen, dann können
Sie das hier leer lassen oder es drin stehen lassen.
Nur wenn Sie eine andere Version bauen möchten, aus welchem Grund auch
immer, dann müssen Sie hier oben wieder etwas eintragen.
Wenn Sie wissen möchten, was in unserem POM drin steht, dann können
Sie hier auf diesen Knopf drücken und dann kriegen Sie in Eclipse den
POM -Editor aufgemacht mit unserer POM drin.
Sie können also mal reinschauen, was da so alles gefuhrwerkt wird,
wenn Sie da Interesse haben.
Aber ich denke, das ist nur nachrangig für Sie von Bedeutung.
Wenn Sie den Patch also eingeführt haben, kriegen Sie die Einstellung
vererbt.
Sie haben im Eclipse einen Reiter, der heißt Effective POM.
Da können Sie sich anzeigen lassen, was Maven jetzt aus ihrer POM
macht, zusammen mit dem Übungsparent.
Sie kriegen also, wenn Sie auf Effective POM klicken, so ein Merge aus
unserer und Ihrer Konfiguration.
Sie können schauen, ob da alles Hand und Fuß hat.
Und wenn Sie Maven nicht als Eclipse-Plugin benutzen, dann sollten Sie
spätestens jetzt sicherstellen, dass Sie die Version 3 benutzen, die
aktuell ist, weil das Übungsparent mit der 2 früher oder später nicht
mehr funktionieren wird.
Wenn Sie diesen Patch angewendet haben, dann haben Sie hoffentlich
nochmal sichergestellt, dass diese Checkliste vom Übungsplant noch
funktioniert, also die Hauptklasse noch eingetragen ist, das Changelog
noch im ZIP ist und so weiter.
An der Stelle war die Aufgabe dann fertig, hoffe ich.
Und dann mussten Sie die hochladen.
Dann haben Sie entweder ein OK bekommen oder ein Reject oder eben in
der Nacht von Montag auf Dienstag ein Pending.
Ich hoffe, dass es nicht zu allzu viel Verstimmung gesorgt hat.
Hat irgendjemand Fragen noch zu dieser Aufgabe 1?
Ok, niemand traut sich oder keiner hat Fragen.
In beiden Fällen mache ich jetzt weiter.
Wenn noch was offen sein sollte, scheuen Sie sich nicht, Ihren Tutor
zu fragen, der wird dafür bezahlt, Ihre Fragen zu beantworten.
Die zweite Aufgabe hat sich mit Unit-Tests beschäftigt.
Es ging darum, den JMJ-RST-Quellcode etwas besser zu machen.
Also das Szenario war ja ok, der Chef hat mitbekommen, automatische
Unit -Tests sind eine super Sache und es gibt wohl ein Problem in
einem Generator, der ein ZIP-File anlegt.
Was man als erstes braucht, ist nochmal so ein Maven-Verzeichnis oder
zwei, in dem man die Java-Klassen ablegt, die für die Tests zuständig
sind.
Die kommen jetzt also in den Zweig Sourcetest-Java oder Sourcetest
-Resources und das ist parallel zu dem, was unter Source-Main-Java
steht.
Allerdings werden die Klassen und die Ressourcen, die hier drin sind,
nur für den Test benutzt und wenn Sie normalerweise ein Paket bauen
und ausliefern, also ein JAR, dann sind Ihre Tests da nicht dabei.
Das heißt, Sie können a.) sehr umfangreiche Tests machen, auch was die
Dateigröße angeht, ohne dass es den Kunden interessiert und b.) wollen
Sie vielleicht dem Kunden die Testfälle gar nicht geben, aber intern
behalten.
Deswegen trennt man die auf diese Weise und dann sorgt eben Maven
dafür, dass die Tests genau dort landen, wo sie hin sollen, nämlich
auf den Build-Server zum Ausführen, aber nicht in dem JAR, das wir
ausliefern an den Kunden.
Was Sie dann noch brauchten, war die Abhängigkeit zu JUnit.
Das konnte man einfach ins POM eintragen.
An der Stelle lassen Sie die Version leer, weil die kriegen Sie übers
Eltern -POM.
Das ist genau das, was wir sicherstellen wollten.
Und den Scope von der Abhängigkeit, den hätten Sie auf Test stellen
sollen.
Man kann den auch auf Compile stehen lassen, das wäre die
Standardeinstellung.
Weiß jemand, was der Unterschied ist oder was dieser Scope bewirkt?
Jetzt bin ich enttäuscht, weil nicht mal hier vorne links eine Hand
hochgeht.
Dieser Scope, der sagt Maven, wann die Abhängigkeit benötigt wird.
Und der Normalfall ist der, man braucht die Abhängigkeit zum
Übersetzen und dann notwendigerweise auch zur Laufzeit.
Es könnte aber auch sein, man braucht die Abhängigkeit ausschließlich
zur Laufzeit, aber gar nicht zum Übersetzen.
Dann würde man den Scope auf Runtime stellen und dieser Scope Test,
der sorgt jetzt eben dafür, dass die Abhängigkeit bei den Tests sowohl
zum Kompilieren als auch zum Ausführen da ist, aber zum Ausführen
später nicht benötigt wird.
Das heißt, wenn Sie das Programm ausliefern, dann liefern Sie JUnit
nicht mit aus, weil was soll der Kunde damit?
Der soll ja die Bibliothek benutzen und nicht testen.
Dementsprechend reicht es, wenn man hier den Scope auf Test stellt und
ab dann kann man anfangen, Tests zu schreiben.
Das erste, was Sie brauchen, ist eine Setup-Methode, in der der
Generator angelegt wird.
Dieser Generator war genau die Klasse, die zum Erzeugen der ZIP-Datei
verwendet wird in JMJ-RST.
Diese Setup-Methode kennzeichnen wir jetzt mit AddBefore.
Das heißt, sie wird vor jedem einzelnen Testfall ausgeführt, damit
dieser Generator immer frisch und jungfräulich ist und sich nicht
irgendwo aufhängt.
Man braucht dann natürlich auch noch eine Klassenvariable für den
Generator, damit alle Tests auch darauf zugreifen können und schick
ist es, wenn man auch eine Klassenvariable für die ZIP-Datei hat, weil
die braucht man später ja mehrfach.
An der Stelle kommt jetzt hier auf den Folien gleich noch die Teardown
-Methode.
Die bekommt die After-Annotation und wird dementsprechend nach jedem
Testfall ausgeführt.
Und die ist jetzt fürs Aufräumen zuständig, das heißt, die soll die
ZIP -Datei löschen, nachdem der Generator sie erzeugt hat.
Wir haben Ihnen da gesagt, fragen Sie bitte ab, ob dieses Delete
funktioniert hat.
Machen Sie aber kein AssertTrue auf diese Ultra-Variable, weil wir
nicht wollen, dass der Testfall fehlschlägt, wenn man die ZIP-Datei
nicht löschen kann.
Sondern wir wollen ja nur, dass der Testfall fehlschlägt, wenn die ZIP
-Datei nicht erstellt werden kann.
Dementsprechend an der Stelle nur eine Ausgabe auf der Konsole, aber
keine Zusicherung.
Wir haben in der Musterlösung, die Sie später auch bei uns im SVN
runterladen können, diese Setup-Methode auf Before Class gestellt.
Ganz einfach deswegen, weil der Generator nicht jedes Mal neu erzeugt
werden muss.
Man kann das tun, das wäre sauber und hübsch, aber in dem Fall ist es
nicht nötig.
Das heißt, ob Sie hier Before Class oder Before hin schreiben, sollte
bei der Benutzung am Ende keine Rolle spielen.
Das Teardown, das sieht dann so aus, dass wir hier, wie gesagt, das
Delete aufrufen und dann eben prüfen, ob es okay war oder nicht und
dann printen mit der Information, damit man eben lesen kann während
der Testausführung, ob das geklappt hat oder nicht.
Das hatte ich Ihnen schon gesagt.
Die erste Aufgabe, die jetzt tatsächlich ein Testfall war, das war die
Aufgabe D.
Da hieß es so schön, schreiben Sie einen Testfall, der die Methode
createZip aufruft.
Das heißt, das ist hier, generator.createZip.
Das erste Argument ist eine beliebige, gültige Instanz von File.
Also das F, das haben wir hier in der Setup-Methode gehabt.
Das heißt, hier haben wir ein Testfall Zip, das wir hier reingeben in
die createZip-Methode.
Und das zweite Argument, das sollte ein leerer Vektor sein von
Dateien.
Das ist also hier new Vektor File und eben nichts drin.
Die createZip-Methode, wenn man die so aufruft, die erzeugt dann eine
leere Datei, ein leeres Zip-Archiv.
Und das Einzige, was Sie prüfen sollten, ist, ist die denn da?
Also brauchen wir hier tatsächlich ein Assert True und dann möchten
wir wissen, ob F existiert.
Das ist also genau der Aufruf.
Und dieser String hier am Anfang, leeres Zip-Archiv, wurde nicht
erzeugt.
F getAbsolutePath.
Das ist nur die Fehlermeldung, die angezeigt wird, wenn diese
Zusicherung hier hinten eben fehlschlägt.
Das war, denke ich, relativ einfach und das ist auch ein Test, der
grün ist, wenn man an JMJ RST nichts kaputt gemacht hat, weil das ist
zufällig was, was funktioniert.
Genau, die nächste Aufgabe war das dann löschen, also die Zip-Datei
wieder löschen, das hatten wir aber schon gesehen.
Und die Aufgabe G, die war jetzt genau das gleiche, also der gleiche
Quellcode, nur dass man eben null übergibt, statt einem leeren Vektor.
Und dann habe ich noch eine Aufgabe dabei, das war die F.
Da sollten Sie einen Testfall schreiben, der die Methode createZip
aufruft und eine IllegalArgumentException erwartet.
Das erste Argument soll diesmal null sein und das zweite Argument wie
ein D, also ein leerer Dateivektor, aber wenn wir der createZip
-Methode nicht sagen, wo sie es hinspeichern soll, dann soll die bitte
abstürzen bzw.
die soll eben eine IllegalArgumentException aufrufen.
Und dass der Testfall das erwartet, das sieht man hier an diesem
Expected -Zusatz von der AddTest-Annotation.
Man kann diesen Test auch anders schreiben, nämlich indem man einen
Try -Catch-Block macht und eben erwartet, programmseitig, dass man in
den Catch-Block kommt.
Und wenn man da nicht war, dann muss man eben den Test fehlschlagen
lassen.
Wie Sie das implementieren, ist letztendlich egal.
Kleinen Moment.
Wenn man dieses IllegalArgumentException hier oben hinschreibt, dann
sorgt es allerdings nur dafür, dass der Test erwartet, dass irgendwann
in dem Testcode mal eine IllegalArgumentException auftritt, aber nicht
genau wo.
Wenn Sie das genauer spezifizieren möchten, also beispielsweise die
ersten fünf Aufrufe an den Generator, die funktionieren und beim
sechsten soll dann diese IllegalArgumentException kommen, dann müssen
Sie nochmal in die JUnit-Dokumentation schauen, weil auch das kann man
programmseitig vorsehen.
Jetzt bitte hier die Frage.
Ihr Kommilitone sagt, er hat es genau so hingeschrieben und dann
ausgeführt und dann ist der Testfall fehlgeschlagen, weil die
CreateZip an der Stelle eine NullPointerException ausgibt und eben
nicht diese IllegalArgumentException.
Und damit hat er recht, aber die Aufgabe, die geht noch weiter,
nämlich steht da hinten dran, passen Sie nun die Methode CreateZip so
an, dass der Testfall grün wird.
Das heißt, wir müssen jetzt die CreateZip-Methode aufmachen und
anschauen, was ist da denn eigentlich schiefgelaufen.
Oder wir können einfach ganz am Anfang prüfen, ist die übergebene
Datei null und wenn ja, dann werfen wir diese
IllegalArgumentException.
Wir werden gleich sehen, wie das aussieht.
Ich nehme an, dann ist auch Ihre Frage beantwortet.
Der Quelltext von JMTR-RST, der sieht an der Stelle so aus.
Wir haben also die CreateZip-Methode, die den Zip-Filename erwartet in
Form eines Fileobjekts und eben diesen Dateivektor.
Und hier unten in dem Try-Block, da wird der Zip-Output-Stream
geöffnet und da wird zugegriffen auf den Zip-Filename.
Und der ist null und an der Stelle kommt dann eine
NullPointerException.
Das ist aber nicht das, was man haben will.
Man möchte eigentlich vorher geprüft haben, sind die Argumente, die
mir übergeben worden sind Quatsch und wenn ja, dann beschwere ich
mich.
Und das könnte man so tun.
Man schaut eben, ist das Zip-File null, dann werfen wir eine neue
IllegalArgumentException.
Und natürlich wäre es ganz hübsch, wenn Sie die Ausnahme auslösen
zusammen mit einer Erklärung, damit der Aufrufer weiß, was er denn da
jetzt eigentlich falsch gemacht hat.
Das heißt, Erklärung in Anführungszeichen hinzuschreiben ist natürlich
nicht besonders geschickt, aber sehr viel mehr passt halt auf die
Folie nicht drauf.
Das war das, was Sie hätten tun sollen in der Aufgabe.
Dann gab es eine Bonusaufgabe.
Und zwar ist es so, unter Windows kann die Testdatei nicht immer
gelöscht werden.
Und zwar im Aufgabenteil G.
Im Aufgabenteil G war es ja so, das ist genau diese Korrektur, dass
wir die Zip-Datei...
Das ist nicht genau die hier, sondern das war die, die hier analog
ist.
Wir übergeben also null Vektor an Dateien und erwarten eigentlich eine
leere Datei.
Und wenn man Windows hat und den Quelltext von JMJ RST noch nicht
behoben hat, dann kann es passieren, dass die Zip-Datei angelegt wird,
aber im Teardown wird sie nicht gelöscht.
Das heißt, wenn man den JUnit-Testlauf komplett abgeschlossen hat,
dann ist dieses Zip-File immer noch da.
Und Sie sollten herausfinden, woran das liegt, ohne den Fehler jetzt
zu beheben.
Und an der Stelle greife ich die Frage nochmal auf.
Ihr Kommilitone fragt, ob wir nicht sagen müssen, dass wir eine
Illegal Argument Exception werfen.
Jetzt muss ich mal zu dem Quelltext zurückspringen.
Wenn wir hier diese Ausnahme reintragen, dann sind Sie ja eigentlich
gewöhnt, dass Sie hier oben bei der Methodendeklaration heranschreiben
müssen, welche Ausnahmen ausgelöst werden können, wenn man diese
Methode benutzt.
Der Kommilitone wollte jetzt wissen, müssen wir da nicht eigentlich
die Illegal Argument Exception dazuschreiben.
Ich bin mir nicht hundertprozentig sicher, aber ich gehe mal davon
aus, dass die Folien richtig sind.
Der Punkt ist der, es gibt in Java Ausnahmen, die man deklarieren
muss.
Das sind die ganz normalen Laufzeitausnahmen und die Errors.
Und es gibt Ausnahmen, die muss man nicht hinschreiben.
Null Pointer Exceptions muss man ja auch nicht hinschreiben, wenn man
mit Instanzen arbeitet, obwohl die da ja auftreten könnten.
Dementsprechend vertrete ich jetzt mal die Behauptung, dass die
Illegal Argument Exception genau so eine ist.
Also die Runtime Exceptions sind genau die, die man nicht prüfen muss.
Danke für den Einwand.
Können Sie mir auch sagen, ob die Illegal Argument Exception von
Runtime Exception erbt?
Ja, das tut sie.
Das heißt, der Quelltext ist tatsächlich richtig.
Und dementsprechend muss man das eben nicht deklarieren.
Der Aufrufer hat dann halt das Problem, dass es trotzdem passieren
kann.
Okay, jetzt zurück zur Bonusaufgabe.
Hier kann jetzt der Fall auftreten, dass diese ZIP-Datei stehen
bleibt.
Ist das irgendjemandem passiert?
Hat das irgendjemand gesehen?
Okay, ich habe mindestens drei, vier Hände gesehen.
Hat auch jemand sich die Mühe gemacht, rauszusuchen, warum das
passiert?
Und mag das jetzt kurz erklären, möglichst so laut, dass mindestens 20
Kommilitonen im Umkreis das auch hören?
Okay,
die Kommilitone sagt, es ist in der H passiert.
Ich wiederhole das einfach nochmal, damit die ganz am Rand auch sicher
verstanden haben.
Was hier passiert ist folgendes.
Man macht einen ZIP-Output-Stream auf, der sorgt dafür, dass jetzt
eben auf diese ZIP-Datei geschrieben werden kann von Java.
An einer späteren Stelle im Programm, nämlich hier unten in der
Vorschleife, wird auf dieses Selected, auf diesen Dateivektor
zugegriffen und dann kommt die Null-Pointer-Exception.
Und damit ist Java dann abgestürzt, aber die Streams, die sind noch
offen.
Und das sorgt dafür, dass Windows diese Datei nicht löschen kann, weil
die ist ja noch in Benutzung.
Das ist kein Problem von Windows, sondern das ist ein Problem von dem
Dateisystem, das da verwendet wird.
Unter Linux und ich bin mir annähernd sicher auch unter Mac, wenn man
da das richtige Dateisystem benutzt, ist es so, dass man Dateien
löschen darf, auch wenn sie noch geöffnet sind.
Das sieht dann für das Programm, das die Datei offen hat, so aus, als
wäre sie noch da.
Und alle anderen Programme, die nach dem Löschen kommen, die sehen die
Datei nicht mehr.
Solange das Programm aber noch läuft, ist die Datei virtuell noch
existent.
Erst wenn das Programm dann geschlossen wird, dann ist die Datei auch
tatsächlich weg.
Deswegen kann man unter Linux oder unter Mac im Testfall die Datei
löschen und dann passiert genau das, obwohl das Programm abgestürzt
ist und der Stream noch offen ist, sagt das Dateisystem, okay, ich
lösche das dann später.
Und wenn Java dann fertig ist mit JUnit, dann wird es ja geschlossen,
dann ist das Programm weg, das Dateihändel dementsprechend auch und
dann macht das Dateisystem Tabula Rasa und dann ist auch die ZIP-Datei
weg.
Das heißt, das Phänomen kann man da einfach nicht betrachten.
Wir hätten gerne gehabt, dass Sie da noch ein bisschen beschreiben,
warum das passiert und vielleicht, wie man das Problem lösen kann, was
man da tun kann.
Da gibt es verschiedene Möglichkeiten.
Die erste Möglichkeit ist, man selbst als Klient sagt, okay, ich
schreibe einfach an die Datei dran, delete on exit.
Das ist einfach was, was ich in der Testklasse noch dazu schreibe, das
könnte ich in der Before-Class-Methode noch machen.
Und das sorgt dann dafür, dass ganz am Ende, wenn die VM zugemacht
wird, die Datei tatsächlich auch aufgeräumt wird.
Das hat aber den großen Haken, dass das nicht mehr klappt, wenn die VM
tatsächlich komplett stirbt.
Also das geht nur, wenn die VM am Ende noch geordnet aufräumen kann.
Und das hat natürlich den zweiten großen Nachteil, dass die Datei
immer gelöscht wird.
Also nicht nur, wenn die Exception auftritt, sondern immer, wenn die
VM zugeht.
Das heißt, ganz am Ende ist die Datei dann halt weg.
Das ist nicht besonders empfehlenswert.
Das sollte man, wenn überhaupt, dann nur für irgendwelche Temporär
-Dateien machen, von denen man sicher ist, dass man sie nie wieder
braucht.
Wobei man sich dann auch fragen kann, warum man sie überhaupt da
hingeschrieben hat.
Eine Alternative ist, man passt den Quelltext von Create-Zip an.
Nämlich genau so, es gab ja diesen try-catch-Block ohnehin.
Da machen wir jetzt also noch ein Finally hintendran.
Und in dem Finally-Block schließen wir alle Ströme.
Und das passiert dann unabhängig vom Verlauf der Methode.
Das heißt, egal ob da drin jetzt eine Ausnahme auftritt oder nicht, am
Ende sind die Ströme alle zu.
Und das war das einzige Mittel, das man bis einschließlich Java 1.6
hatte.
Hat aber das Problem, dass man sich da Exceptions verdecken kann.
Das heißt, wenn in dem try-block eine Ausnahme ausgelöst wird, dann
springt Java in den Finally-Teil.
Da soll ja die Datei geschlossen werden.
Und wenn da drin wieder eine Ausnahme ausgelöst wird, zum Beispiel
dann eine IO-Exception, dann kriegt man außen die IO-Exception zu
Gesicht.
Und warum weiß man natürlich nicht.
Man weiß okay, es gab halt diese IO-Exception.
Aber man weiß nicht, dass das Programm vorher schon kaputt war.
Also man weiß nicht, warum das Programm die Datei geschlossen hat.
Man kann nur raten, entweder hat es geklappt und ich war halt sowieso
im Finally.
Oder zwischendrin ist was schief gegangen.
Aber was das war, das kriegt man dann leider nicht mehr raus.
Das ist also nicht das, was man eigentlich haben will.
Seit Java 1.7 gibt es eine Erweiterung von dem Try-Ausdruck.
Nämlich den Try-With-Resources-Ausdruck.
Da schreibt man direkt an das Try dran, welche Ressource man benutzen
möchte.
Das heißt, man macht einfach Try-Klammer auf und da drin schreibt man
dann rein, dass man diesen Zip-Output-Stream haben will.
Und hier hinten kommt dann der ganz normale Try-Block.
Und hinten dran dann Catch und Finally.
Das hier sorgt dafür, dass die Java vor allem sicherstellt, dass diese
Ströme geschlossen werden.
Und zwar genau in der Reihenfolge, in der man sie auch aufgemacht hat,
rückwärts.
Und das ist natürlich deutlich eleganter.
Insbesondere geht es überall da, wo Auto-Closable implementiert ist.
Das ist bei sehr vielen Klassen der Fall, die in der Java-Bibliothek
drin sind.
Und das hat dieses Problem mit dem Verdecken der Ausnahmen nicht.
Natürlich kann hier immer noch der Fehler auftreten, dass wenn die
Java vor allem hinterher diese Ressource wieder zumacht, dass da drin
dann eine Ausnahme ausgelöst wird.
Aber das verhält sich anders.
Es ist nämlich so, dass man die innere Ausnahme bekommt.
Stellen Sie sich vor, in dem Try-Block kommt eine Null-Pointer
-Exception.
Dann räumt Java auf und dann kommt eine I-O-Exception.
Das ist dann natürlich äußerst tragisch.
Und der aufrufende Code, der kriegt dann den Null-Pointer.
Weil das war eigentlich der ursprüngliche Fehler.
Und man kann dann den Null-Pointer fragen, ob unten drunter noch was
drunter steckt.
Ob da vielleicht noch eine I-O-Exception aufgetreten ist beim
Aufräumen oder irgendwas anderes.
Das ist also deutlich besser als das, was man bis Java 1.6 hatte.
Und einfach das Mittel der Wahl seit Java 1.7.
Und die Lehre daraus ist, bitte, Sie sind mündige Informatiker, wenn
Sie hier fertig sind.
Lesen Sie die Dokumentation von der Software, die Sie einsetzen.
Oder von den Programmierumgebungen, die Sie einsetzen.
Und schreiben Sie nicht bei alten Programmen ab.
Wenn Sie ins Internet reingehen und einfach nur zwei, drei Stichwörter
eingeben und die erstbeste Lösung kopieren, dann kriegen Sie
vermutlich was Altes und vielleicht ist das schlechter als das, was
Sie eigentlich haben können oder haben wollen.
Deswegen gucken Sie in die aktuelle Dokumentation zu der Software
rein, die Sie benutzen.
Das letzte, glaube ich, was wir genau von Ihnen wollten, war das
Erstellen eines Patches.
Das heißt, wir wollten zu der Aufgabe E die Änderungen an der Methode
createSip sehen.
Und das kann man entweder in der Kommandozeile machen mit Git oder
auch mit Eclipse.
Da gibt es auch durchaus das eine oder andere Kontextmenü.
Und dann fällt da eben ein Patch raus.
Wenn man das mit Git macht, dann sieht das so aus.
Wir haben hier glücklicherweise den Patch genau so machen können, weil
er die letzte Änderung betraf.
Man kann das aber auch zwischen zwei beliebigen Commits machen.
Man muss es dann nur entsprechend angeben.
Da kommt dann eine Datei raus mit einem E-Mail-Kopf, weil das will man
ja bestimmt per Mail verschicken.
Dafür ist diese Formatangabe gedacht.
Und dann kriege ich eben gesagt, okay, eine Datei hat sich geändert.
Keine Löschung, aber zwei Einfügungen, und zwar in der generator.java.
Und das ist genau dieser if, selected und gleich null.
Dann machen wir diese Schleife.
Ansonsten eben nicht.
Und am Ende müssen wir das dann noch zumachen.
Hier unten haben wir dann nochmal eine schließende Klammer, die
eingeführt wird.
Und an der Stelle ist der Patch dann auch schon vorbei.
Haben Sie Fragen zu dieser Aufgabe mit den Unit-Tests?
Die kommende Tunnel fragt, ob man diesen Patch auch mit git diff
erstellen kann.
Das kann man auch.
Im Wesentlichen wollten wir, dass da so eine Datei rausfällt, wo am
Anfang steht, was war die Datei, die sich geändert hat und von wo nach
wo.
Und wenn Sie hier genau reingucken, das ist tatsächlich genau die
Ausgabe von einem diff.
Wie Sie diesen diff erstellen, ist letztendlich egal.
Hauptsache er ist da.
Diese Ansage, wie Sie das erstellen, das ist uns eigentlich wurscht.
Das gilt für fast alle Aufgaben.
Wichtig ist das Ergebnis.
Wenn Sie das mit anderen Werkzeugen oder anderen Befehlen oder in
einer anderen Reihenfolge hinkriegen, dann ist das Ihre Sache.
Wenn das schneller geht, dann haben Sie gewonnen.
Erzählen Sie es möglichst vielen Kommilitonen, damit die auch Zeit
sparen.
Uns ist nur wichtig, was am Ende als Ergebnis rauskommt.
Gibt es sonst noch Fragen zu den Übungsaufgaben?
Das ist sehr schön.
Das war die letzte Folie für die Übung.