Okay, moin. Ich glaube, wir können es langsam
anfangen. Die meisten sollten schon da sein. Okay,
erst mal herzlich willkommen zum Repetitorium,
beziehungsweise so ein bisschen geht es in die Richtung Panik-Tutorium und
wir schauen uns ein bisschen mal an, was wichtig ist,
Uni Claud Susu, äh die Klausur zu bestehen.
Genau, ich habe ein paar Sachen vorbereitet für euch.
Ich werde erst mal so drei Themen,
die ich für wichtig halte und die häufig gerne relativ gut zum Punktesammeln genommen werden,
durchgehen, dann werden wir uns ein paar Aufgabentypen anschauen und auch noch ein paar Beispiele aus den Klausuren anschauen.
Genau, falls es Fragen zwischendurch gilt,
schreibt die bitte gerne in den Chat,
ich werde sie dann für alle laut vorlesen und wird nach
besten gewissen beantworten
Genau, die Folien wird es übrigens danach geben,
sowie wenn es, wenn alles klappt,
eine Aufzeichnung.
Okay. Also, nochmal
ein bisschen etwas vorweg
Das Ziel von diesen anderthalb Stunden plus Fragen danach,
wird es sein, dass ihr eine App,
hoffentlich eine etwas bessere Chance habt, die Klausur zu bestehen.
Das wird jetzt, also das heißt im Konkreten natürlich,
wir werden jetzt hier nicht sehr, sehr tief in Materien einsteigen,
um so in den Bereich von die Aufgaben,
die man da bearbeiten muss, um dann die entsprechende Eins zu bekommen.
Also das werden wir jetzt nicht machen, so tief in die Materie,
sondern wir schauen es einfach mal ein bisschen an,
was, wie man am besten die Klausur vielleicht besteht,
mit einem befriedigend oder sogar mit einem gut.
Genau. Natürlich hat das überhaupt keinen Anspruch, ja, Vollständigkeit. Das heißt,
wenn ich jetzt irgendwas nicht behandle, dann wird das trotzdem,
kann das Thema trotzdem auch in der Klausur Thema sein.
Das bedeutet einfach nur, dass ich,
als ich mir die Klausuraufgaben angeschaut habe, zum Schluss gekommen bin,
dass das Thema eventuell nicht so häufig falsch verstanden worden ist
oder in der Vergangenheit häufiger dort falsch antworten gegeben worden sind.
Genau, und das Repetitorium gibt auch in einigen,
also gerade bei der Wiederholung,
Denkanstöße und nochmal wieder und soll jetzt
kein Ersatz sein für euer Selbststudium
Okay, diese drei Themen, die ich rausgesucht habe,
werden sehr, sehr gerne in der Klausur für die Punktesammler-Aufgaben,
wie ich sie gerne nenne, benutzt.
Das heißt, das sind Aufgaben, die man,
wenn man fit in den Definitionen ist,
relativ schnell bearbeiten kann und dadurch entsprechend gut Punkte sammeln kann.
Das eine wäre, also die sind alle im Bereich der Softwarequalität
Das heißt, das sind diese Aufgaben, die hier auch sehr gut bearbeiten könnt.
Wenn ihr nicht so gut im Coden seid,
sondern mehr so im Fit da drin seid,
das große Ganze zu betrachten im Rahmen von,
was ist eigentlich Softwarequalität?
Und so weiter. Genau, wir fangen dann einfach mal
erst mal mit der Kohäsion an.
Das eins der größten Ziele in Bezug auf die Softwarequalität,
in Softwareprojekten ist es, möglichst immer eine hohe Kullision
zu erreichen
Das heißt, das ist so ein bisschen unser Ziel,
was dann natürlich die wichtige Frage ist, was heißt nein,
ich kohle Kollision, das bedeutet in der Regel,
wenn ich mir eine Kodeinheit anschaue,
sei es jetzt irgendwie eine Methode,
eine Klasse,
dann muss ich halt darauf schauen,
dass sie diese
genau einem logische Aufgabe erfüllt
Das ist ein sehr gutes Beispiel für hohe Kursion. Beispiele,
die Negativbeispiele dafür sind natürlich,
wenn wir sogenannte Gottklassen haben oder Gottmethoden,
wo halt eine Methode beispielsweise sehr, sehr viele verschiedene Aufgaben übernimmt,
wo es dann zum Beispiel irgendwie, wenn man,
wo man dann zum Beispiel sagen kann,
Es gibt irgendwie drei verschiedene Aufgaben, die diese Methode ausführen kann.
Und sie sind halt in Abhängigkeit davon, welche Parameter eventuell gewählt worden sind.
Also zum Beispiel ein Zeichen für niedrige Koalision. Und,
oder was auch ein Zeichen für niedrige Korrision ist,
wenn ich sage,
ich habe eine logische Aufgabe,
die ich
überall verteilt im Code habe
Genau, also auch nochmal für die Aufnahme.
Die Frage war, wenn nicht eine Methode habe,
die einfach nur Heber abheißt beim Konto und die macht auch
wirklich nur das, dann ist das halt hohe Kollision,
Genau. Das nächste, was sehr, sehr häufig drankommt,
ist natürlich das allseits beliebte Thema der Kopplung.
Das ist, das finden wir sehr, sehr,
sehr häufig, werden wir ja beispielsweise anfangen,
ein Projekt in UML zu modellieren.
Daran kann meistens sehr, sehr schnell immer erkennen,
ob ich eine lose Kopplung oder eine sehr enge Kopplung habe.
Und das Ziel ist eigentlich immer,
möglichst eine lose Kopplung zu erhalten
Ja, diese Merkmale für die Kopplung erkenne ich immer daran,
welche anderen Klassen benutzt diese, benutzt diese Einheit, die ich gerade betrachte.
Und wo kommt diese Klasse her? Also wenn ich jetzt zum Beispiel,
wenn ich jetzt zum Beispiel eine Klasse habe,
die beispielsweise zehn Interfaces implementiert,
dann ist das schon eine relativ enge Kopplung,
weil ich halt diese Ja, sage ich mal,
weil wir halt diese Abhängigkeiten auf diese entsprechenden Interfaces haben.
Genau, und maximal, und das ist ein Negativbeispiel für
bei der Kopplung, ist dann halt die sogenannte maximale Kopplung.
Davon sprechen wir, wenn wir dann sagen,
ich habe alle meine Klassen in meinem Software-Projekt, sind mit allen anderen Klassen verbunden.
Und diese Kopplung betrachtet man dabei halt teilweise auf Methoden. Das heißt,
wenn ich, ist jetzt eher nicht so kommen, aber,
also du bist jetzt nicht so häufig, dass das vorkommt,
eher, wo wir eher betrachten, ist die Kopplung zwischen Klassen.
Oder auch die Kopplung zwischen Paketen. Ihr habt ja
in der Vorlesung dann irgendwann zur Beherrschung der Komplexität gelernt,
dass es sinnvoll ist, Hierarchien zu bilden mit Paketierungen,
dass man beispielsweise ein Paket baut für für die logisch,
also für die Services, also das,
was die sozusagen Anwendungslogik ist des Programms.
Und man hat dann ein Paket, was halt für die Benutzeroberfläche da ist.
Das wäre dann halt diese Kopplung zwischen Paketen und Subsystemen.
Und das grobe Komplexi ist halt immer versuchen, das zu reduzieren.
Das kommt so ein bisschen daher, weil das,
was diese lose Kopplung dann letztendlich bewirkt in Softwareprojekten,
ist einerseits, wenn ich jetzt als neuer Software-Developer ein so
ein größeres Projekt mit reinkommen und mir irgendwie an ein Subsystem arbeiten soll oder an einer Klasse arbeiten soll,
dann kann ich diese Klasse relativ schnell verstehen, wenn diese möglichst unabhängig zu anderen Klassen ist.
Also wenn man sich jetzt halt vorstellt, ich möchte eine Klasse editieren,
die jetzt 20 Exemplarvariablen auf 20 verschiedene andere Klassen hat,
dann muss ich ja im, sage ich mal,
Worst-Case-Fall, wenn ich irgendwas an dieser Klasse ändern möchte,
Mich auch mit diesen 20 anderen Klassen auseinandersetzen und schauen,
was ist eigentlich, also was machen diese Klassen,
was ist deren Ziel, wie ist deren Schnittstelle,
was muss ich eventuell in Bezug vielleicht auf das Vertragsmodell beachten und so weiter und so fort.
Und dadurch habe ich natürlich auch das Problem,
wenn ich eine sehr enge Kopplung habe,
dann kann ich Änderungen nur noch sehr schwer durchführen,
weil ich eventuell halt entsprechende Seiteneffekte in anderen Klassen
haben kann
Genau, also. Genau, also das Ziel,
also die Frage war, ob das, ob das Ziel ist,
so wenig Kopplung wie möglich zu haben und ja,
das ist es, also wir versuchen halt,
möglichst immer eine, also natürlich klar kann man nie,
also das Idealbild von loser Kopplung erreicht man meistens eh nie,
weil eine gewisse Kopplung braucht man immer,
aber es lohnt sich halt schon gerade in,
sage ich mal, sehr, sehr frühen Anfängen einer Softwareentwurf ist,
auf möglichst lose Kopplung zu setzen.
Genau, und was vielleicht noch ein bisschen wichtig ist,
zu unterscheiden, ist es, dass wir zwei verschiedene Arten noch von Kopplung haben.
Die eine ist relativ leicht beherrschbar. Das ist die explizite Kopplung. Das ist,
wenn ich beispielsweise in einer Klasse eine Exemplarvariable vom Typ Buch habe,
dann kann ich das formal nachweisen, dass meine Klasse mit der Klasse Buch gekoppelt ist.
Das lässt sich sehr einfach nachweisen. Wenn ich jetzt aber zum Beispiel eine implizite Kopplung habe,
das ist dann eher so auf den Bereich von Methoden,
wenn ich als Entwickler beispielsweise weiß,
wie das interner einer bestimmten Klasse oder einer bestimmten Methode funktioniert und dadurch entsprechende Annahmen mache,
Also ein sehr schönes Beispiel ist es, wenn ich eine Methode habe,
die mir eine Liste von Elementen zurückgibt und die derzeitige Implementierung ist so,
dass diese Liste immer sortiert ist.
Also halt von A bis Z sortiert ist.
Die Schnittstelle von dieser Methode, aber sagt eigentlich,
dass dies nicht so, also dass das keine Nachbedingungen sozusagen ist.
Das heißt, es wird nicht zugesichert, dass die das sortiert ist.
Und dadurch habe ich so eine gewisse implizite Kopplung,
weil ich jetzt, weil jetzt meine Klasse oder meine Methode,
die ich gerade schreibe, sehr stark davon abhängt,
wie eine bestimmte Implementation einer Methode ist.
Und wenn jetzt... Achso, also bei der impliziten ist es...
Also wenn wir uns das jetzt mal anschauen,
ich habe jetzt die jetzt irgendwie meine neue Klasse Neu.
Und ich schreibe hier jetzt irgendwie meine, eine Methode. Sie macht irgendwas und sagt,
geht es jetzt explizit davon aus, weil in diesem Beispiel,
sage ich mal, irgendwie, ich habe hier eine Bücherliste.
Und dabei rufe ich jetzt auch, dass er mir die
Bücher zurückgeben soll. Und in den nachfolgenden Code,
weil ich mir die Implementation als Entwickler von dieser Bücherliste angeschaut habe,
Gehe ich jetzt davon aus, weil in diesem Code gesagt wird,
also weil in diesem Code die Liste vorher sortiert wird,
bevor sie rausgegeben wird.
Hier gehe ich jetzt davon aus, dass diese Liste ist sortiert.
Das heißt, das Problem, was daraus erscheint, ist halt,
dass sich eine entsprechende Abhängigkeit beziehungsweise Kopplung auf diese konkrete Implementation von Gebücher habe.
Das heißt, ich depenne, also ich habe eine Abhängigkeit,
dass die Bücherliste immer bei Gebücher eine sortierte Liste zurückgibt
Wenn jetzt aber in einer etwas späteren, sag ich mal,
Änderung von der Bücherliste diese Eigenschaft verloren geht,
dass diese Bücherliste sortiert ist, dann fällt,
dann kann ich das formal vorher nicht prüfen,
dass hier diese Methode,
die ich geschrieben habe,
davon ausgeht,
dass diese Bücherliste sortiert ist
Ich hoffe, das macht es ein bisschen klarer. Also es ist halt,
also ich habe da halt eine Abhängigkeit von einer bestimmten Implementation,
die aber nirgendwo sinnvoll, also die halt nicht dokumentiert ist.
Also es geht davon aus, also es geht halt darum,
dass ich mich abhängig mache von interner,
die für ein Außenstehenden eigentlich gar nicht sichtbar sind.
Und wenn ich,
und das kann dann halt natürlich zu entsprechenden Fehlern führen,
die eventuell erst,
sage ich mal,
deutlich später auffallen
Oder, ja, oder halt, oder eventuell teilweise
auch gar nicht auffallen. Also das sind dann solche,
sind dann halt so eine sehr, sehr fiesen Bugs,
die dann halt vielleicht irgendwann, sag ich mal,
auftauchen wieder.
Genau. Genau. Genau, und eine,
was jetzt natürlich eine Variante ist, um sich,
um sich, diese Kopplung ein bisschen zu verhindern,
ist das, so genannte Lore of D-Meter.
Und das kann man eigentlich im Groben zusammenfassen,
als eine Art von Richtlinie,
um lose Kopplung
Zu bekommen. Das heißt, wir schauen uns an,
also es geht im Chrom und Ganzen halt darum,
dass wir eine Methode haben von einem Objekt, mal wieder.
Und in dieser dürfen wir andere Objekte nur dann verwenden,
wenn wir diese entweder selbst erstellt haben.
Wir selber sind Oder Exemplare als Exemplarvariablen sind. Was ist
das denn im Konkreten heißt? Ist, ich habe hier
wieder meine Methode, meine Methode M. Und diese soll,
wenn diese jetzt beispielsweise an der Feld war, also irgendwie an der Exemplarvariable,
an einer Exemplarvariable irgendwas aufruft, beispielsweise gibt Buch,
obwohl Buch ist ein relativ doofes Beispiel, Gib Verleihkarte.
Ja, um das mal über das Beispiel mal zu spannen,
zu den anderen Systemen. Und wenn ich jetzt an dieser,
das ist jetzt ja etwas, was noch okay ist.
Ja, aber wenn ich jetzt auf einmal anfangen würde zu sagen,
okay, ich rufe direkt Saal dran,
irgendwie etwas auf mit,
gib Kunde
Und dann geht es halt so weiter. Das würde halt
dafür sorgen, dass ich jetzt für diese Methode M,
die ich hier gerade am Implementieren bin, weitere Kopplungen hinzufüge.
Weil jetzt muss ich ja M auch noch darum,
hat ja auch jetzt auf einmal eine Kopplung zur Kunde.
Ja, und wenn ich das jetzt noch weiterspiele, wenn ein Kunde,
gibt es dann eventuell auch noch eine Objektsreferenz auf eine Kundennummer oder auf ein Geburtsdatumsobjekt,
und so weiter und so fort.
Und dann kommen wir halt dann irgendwann zu diesen,
sag ich mal, zu dieser Maximalauslegung.
Alle Klassen sind dann irgendwie mit alle hingekoppelt. Genau. Ja,
also das heißt, das ist so ein bisschen die Ideen,
die sind dahinter, dass man sagt, man möchte,
wenn man dieses Law of the Meta befolgt,
einschränken,
dass man nicht eine ewig verkettete Aneinanderreihung von Objekten hat,
die man sich
immer wieder herholt wurde irgendwo
Musik Genau, also hieß das mit so einfachen Sachen wie Gets,
also ich habe irgendwie ein Objekt da dran,
hole ich mir irgendwie ein,
beispielsweise ein String und rufe dann an diesen Stringpunkt Get Langf aus,
Na, das ist ja, das hat ja den,
sag ich mal, Bankanda argumentieren, dass das eigentlich schon,
dass den Lore of Demeter verletzt in einer gewissen Art und Weise.
Aber wie so häufig, ich sag mal,
wie so häufig bei diesen Richtlinien und Konzepten ist es halt immer ein bisschen auch anzu,
zu überlegen, was, was möchte ich eigentlich noch erreichen?
Also ich kann ja jetzt,
also jetzt bei so einem String-Objekt zu sagen,
ich rufe dann noch Punkt Lenk auf, Ist jetzt,
äh, erzeugt jetzt keine, sag ich mal,
engere Kopplung, weil die Wahrscheinlichkeit sehr hoch ist,
dass ich in meiner Klasse eh schon Streams benutze.
Das ist so ein bisschen, ähm,
da weicht man dann sozusagen in der Praxis dann häufig auch mal ein bisschen von der Theorie ab,
um halt sich das Leben nicht schwer zu machen,
so ein bisschen, ne?
Und vor allem, wir haben ja auch das Problem,
wir können ja nicht,
ähm, wir wollen da ja jetzt nicht irgendwie,
ähm, ja,
kann ich das sagen,
Ja, also es kommt halt sehr stark drauf an. Also wenn wir,
also ich glaube jetzt,
wenn wir da irgendwie uns einen String holen und da dran dann nochmal eine Funktion aufrufen,
dann ist das jetzt nicht so ein großer, grober Verstoß,
wie in den Beispiel unten auf der Folie mit student.getrecord und dann Punkt Axam Entry,
SC2 für 2006 und da auch noch Punkt Ressort,
Ad Ressort.
Das ist ja, da bin ich ja so tief
schon drin in der, in anderen Klassen.
Das ist dann halt schon, das geht dann halt
schon nicht mehr,
Aber klar, aber wenn man die Regeln,
wie sie jetzt da oben stehen, ganz klar anwendet,
aus der theoretischen Sicht, dann würde ich sagen,
dass das das Beispiel, was du geschrieben hast,
mit irgendwas irgendwie ein Getter und da kommt dann irgendwie ein String
raus und da rufe ich dann nochmal eine Methode auf,
könnte bereits das Lauf den Meter verstoßen.
Dafür möchte ich
Also das Law of the Meta jetzt konkret selber,
würde ich jetzt mal behaupten, sagt da jetzt nichts gegen,
wenn diese Referenzen eh schon gehalten werden als Exemplar Variablen.
Also wenn ich diese Kopplung in meiner Klasse eh schon habe,
dann kann ich es ja in der Methode selber nicht mehr schlimmer machen.
Ja, Entschuldigung. Ja,
also ich kann das dann ja, also wenn ich jetzt,
sage ich mal, dieses Studeln.get Record,
also wenn ich alle diese Elemente hier in dieser Anreihung von auf Methoden aufrufen,
wenn ich diese ganzen Elemente bereise,
eh schon als Exemplar Variablen in dieserselben Klasse habe,
dann spricht nach meinem Gefühl zumindest nichts vom Love der Meta dagegen.
Da wäre dann natürlich vielleicht ein bisschen die Frage so,
ja, warum macht man sich die Mühe,
dass hier nochmal alles ranzuholen,
wenn man eh schon direkt die Referenz auf Examen Entry hat
Genau, also die Frage war, wie ist das eigentlich
mit von selbsterzeugten Objekten? Das ist ja bereit,
das ist ja hier über die,
über das dritte Regelwerk hier eindeutig erlaubt,
dass sich an den Objekten,
die ich in M selbst stelle,
sowieso alles dann aufrufen kann
Achso, ja genau, okay, gut, ja,
wenn ich jetzt natürlich versuche, darüber eine Umgehung zu machen.
Das heißt, ich, ich mache jetzt irgendwie sowas wie...
Und ich so, geht's? B und... Und fange
dann halt irgendwie so an wie, hier wird's ja...
Das wäre dann ja natürlich ein,
also das wäre jetzt nicht mehr wirklich abgedeckt, weil,
ja, explizit gesagt wird, dass diese Objekte von M erstellt werden, erzeugt werden müssen.
Das heißt, wenn ich jetzt einfach nur, sag ich mal,
lokale Variablen seklariere und dann halt mit einem Getser die Belege
und dann in der nächsten Zeile dann von der lokalen Variable dann irgendwie so ein Gets C mache,
ne, und dann das als Vokalvariable mache,
dann geht das natürlich nicht.
Deswegen, aber das hat man auch da schon bedacht,
dass man das nicht umgehen kann, indem man halt gesagt hat,
es muss von M erzeugte Objekte sein.
Also alles, was M sowieso erzeugt,
darf er dann
auch benutzen
Da ist jetzt noch die Frage, was wäre,
wenn die klassische Student statisch ist? Ich bin der Meinung,
dass... Ich bin der Meinung, dass das... Also,
es hat ja keinen wirklichen, keine wirkliche Auswirkungen,
weil ich ja trotzdem hier in den Bereich gehe mit,
ich rufe an der statischen Klasse, rufe ich eine Methode auf,
die gibt mir, ob ihnen eine Objektreferenz zurück,
an dieser Objektreferenz rufe ich dann nochmal eine Methode auf,
die gibt mir wieder eine Objektreferenz zurück und dort rufe ich wieder eine Methode auf.
Also, es macht jetzt, also, ob das,
ob jetzt die Ursprungsvariable oder das Ursprungsobjekt,
was ich damit arbeite, ob das jetzt statisch,
ein statisches Objekt ist oder ein normales Objekt ist,
macht keinen Unterschied
Genau, also, also relativ gut gesagt. Also,
alle Methoden, die ich bereits irgendwie als Exemplar variable in meinen Objekt O habe und alle Objekte,
die ich in M selbst erzeuge, kann ich benutzen nach Beleben.
Es geht, also, was halt einfach damit fast,
was halt einfach nicht geht, ist es an meinen Objekten,
die ich habe, ob es,
sei es jetzt Exemplarvariablen oder sei es selbst erstellte Objekte,
dort Methoden aufzurufen,
die mir wieder eine Referenzvariable zurückgeben,
dann an diesen weitere Methoden aufzurufen,
weil ich
dadurch ja meine Koppelung erhöhen würde
Genau, also man kann, also es gibt ja noch
das andere Konzept hier, das ist das Solid-Konzept.
Das heißt, also Solid steht ja für hier Single Responsible,
Principle, Open Close Principle, Lizkov Substitution,
Principle,
Interface Secretation und Dependency Inversion
Und das ist halt auch eine Methode, um nochmal die,
also die Koppelung etwas zu lösen. Also ich habe halt,
also ich versuche halt möglichst schon im Design,
das ist das Single Responsible Ility Principle, die meine Software nach Zuständigkeiten aufzuteilen.
Das heißt, ich habe,
das geht auch so ein bisschen in diese Sache rein mit,
eine Klasse soll eine sinnvolle,
also es spielt so ein bisschen in die Kuriosion rein,
eine Klasse soll
eine logische Aufgabe übernehmen
Ne, in dem Fall zum Beispiel von den Projekten in
der SE2 gibt es halt diese Verleihservice-Klasse, die,
äh, übernimmt halt die logische Aufgabe des Verleihens.
Und, ähm... Genau, und, ähm,
also es ist so ein bisschen,
also es ist so ein bisschen schwierig, ähm,
dass jetzt,
also das ist,
Schwierig zu erkennen, wie gut man damit die los,
also wie gut man damit Kopplung verhindern kann.
Also vieles spielt eigentlich immer darin hinein,
dass ich versuche in der Konzeptionsphase möglichst eindeutige Klassen zu Design,
die halt ihre entsprechenden Sachen machen.
Und eine etwas andere Methode ist natürlich halt auch bestimmte Design-Patterns
noch zu verdenken
Das heißt, eine Möglichkeit wäre es ja natürlich auch noch,
was ja gerade bei UI,
also bei der Entwicklung von grafischen Benutzerauberflächen zur Anwendung kommt,
für lose Kopplung ist es ja mit dem sogenannten Beobachtermuster zu arbeiten.
Also das Beobachtermuster war, wenn wir uns,
wenn man sich das jetzt nochmal anschaut, dass ich mir,
dass ich sage, ich habe hier irgendwie ein Ein Beobachter.
Acht, ja. Und, äh, ein Beobachter,
der halt sagen möchte, okay, ich möchte wissen,
wenn sich irgendwie etwas ändert bei einer Klasse, dass sich darüber informiert werde.
Und die Klasse, wo ich, äh,
die ich halt anschauen muss, muss halt dieses beobachtbar implementieren.
Das ist halt eine Möglichkeit, ein bisschen, äh,
die, eine etwas losere Kopplung zu haben. Und,
äh, der zweite natürlich große Vorteil ist,
wenn man sich das nochmal anschaut mit dem Beobachter und Mutter,
ist natürlich,
ähm,
dass sich dadurch diese sogenannten Zyklen
fern hindern kann
Also wenn, also dieses Problem mit,
wenn ich zwei Klassen habe, die halt,
wo Klasse A,
Sachen von Klasse B auf zugreift und Mothodenaufruf und Klasse B ebenso von Klasse A.
Es lässt sich dann halt diese engere Kopplung und zykische Abhängigkeit
lässt sich dann halt durch dieses Designpattern mit Beobachtermuster auflösen zu
einer etwas loseren Kopplung
Okay. Genau, geerbte Methoden würde ich jetzt tatsächlich
auch dazu sagen, die sind auch Methoden von Objekt O.
Weil dadurch, dass sich diese geerbte Methode aufrufe oder benutze
, erhöhe ich ja nicht
meine Kopplung
Weil diese Kopplung ist ja eh schon da,
weil ich ja, weil ich die Kopplung über die Vererbung
bekommen habe.
Gut, dann gehen wir mal, genau,
also das war es jetzt erstmal mit diesen drei Themenzeilen,
die sehr, sehr häufig, finde ich,
in der Vergangenheit immer zu Fehlern in der Klausur geführt haben.
Und jetzt gehen wir mal kurz,
nehmen wir mal kurz ein bisschen durch.
Was wird euch eigentlich in der Klausur erwarten für Aufgabentypen?
Das heißt, ich versuche euch jetzt ein bisschen,
vielleicht ein bisschen die Angst zu nehmen vor dieser Klausur
Weil ihr müsst dann vielleicht so ein bisschen so einen Kontext zu sagen,
ihr müsst euch vorstellen,
ihr müsst diese Klausur ja in einer gewissen Zeit schaffen,
wenn ich mich recht erinnere, sind es 90 Minuten.
Und in 90 Minuten kann ich jetzt nicht so ein bisschen wie das,
was wir jetzt gemacht haben,
sehr in die Tiefe gehen bei einem Thema oder sonst was.
Oder dass ihr da auch große Textromane schreiben müsst.
Deswegen sind so typische Aufgaben, die ihr in der Klausur
auf euch warten werden, sind die, sind Lückentexte.
Das kann sein, weil ich bin leider nicht in
die Organisation der Klausur mit groß involviert. Deswegen,
es kann auch sein, dass ihr zwei Stunden Zeit habt,
aber meistens sind Klausuren für 90 Minuten konzipiert.
Aber es macht jetzt auch ja jetzt keinen großen Unterschied,
so ob 90 Minuten oder 120 Minuten.
Das Grundprinzip bleibt ja bestehen, die Klausur wird Die Klausur wird
eher breit meistens testen und nicht sehr doll in die Tiefe gehend.
Genau. Und ein Teil davon wird es halt sein,
dass ihr, was ihr auch bereits,
also viele für diese Aufgabentypen werdet ihr so ein bisschen vielleicht wiedererkennen aus den Selbsttests aus dem Nudel.
Das heißt, wir haben halt Lückentexte von Definitionen
Na, saß dann so diese typischen, äh,
Lückentexte, wo es dann darum geht, ähm,
da wird ein Konzept,
wie beispielsweise Law of Demeter beschrieben und es fehlen aber die entsprechenden harten,
sag ich mal, Fachbegriffe.
Und ihr müsst die Fachbegriffe einsetzen können. Das heißt,
das ist dann halt so ein bisschen dieses, äh,
dass ihr halt den sogenannten Recall machen könnt mit,
äh,
Kurt von Konzept
zu Fachbegriffen wiederkommen
Ah, vielen Dank. Okay, also die Klausur geht
anscheinend über 120 Minuten. Ist jetzt natürlich die Frage,
ob das jetzt nur je zeitlich ist oder auch die Aufgaben?
Großartig mehr geworden sind.
Aber genau
Okay. Ja. Ja, also das ist halt auch... Genau. Also falls ihr fragt,
also um das jetzt mal so ein bisschen abzukürzen,
falls ihr weitere Fragen zum Organisatorischen habt, wie die Klausur ablaufen wird,
benutzt am besten im Moodle das Forum für die organisatorischen Fragen.
Ich bin nicht sehr nah am Organisatorischen dran,
um das jetzt sinnvoll beantworten zu können. Und ich glaube,
es ist jetzt wichtiger, dass wir uns weiter konzentrieren auf Das,
was ich vorbereitet habe und welche Fragen ihr dann gleich noch habt.
Und zwar, genau, also was auch gesagt, gerne drankommen können sind,
ist das Erläutern von Konzepten in ein bis zwei Sätzen.
Ja, also das ist dann,
also ich werde gleich auch noch ein Beispiel zu sagen.
Und dann gibt es noch sogenannte Single und Multiple-Choice-Aufgaben, uns Kotvervollständigung.
Und damit ihr so ein bisschen ein Gefühl dafür bekommen könnt,
wie das denn eigentlich so aussieht,
Ein Beispiel für einen Lückentext wäre es dann zu sagen,
ihr bekommt vielleicht ein Parkzeilen, Quelltext oder eine,
oder, genau, also eine von den Möglichkeiten ist halt,
ihr habt eine Zeile Quelltext und soll ich jetzt dazu eine,
diesen Lückentext ausfüllen.
Und genau, also das Beispiel kennen wir ja Ihnen gerade schon aus dem,
aus der Law of the Metafolie, das heißt,
wenn man diesen Lückentext jetzt ausfüllen würde,
dann müsste man da halt schreiben,
dieser Codeausschnitt ist ein Hinweis auf die Verletzung des Laufte Meta,
die Verletzung erhöht sich
die Kopplung im Code
Das heißt, diese Aufgaben sind so ein bisschen daran gedacht,
für euch, diese euch so ein bisschen aufzuwärmen,
um dann, weil ihr da einfach nur diese Fachbegriffe versuchen müsst,
wieder zu erkennen von den entsprechenden Konzepten.
Genau. Ein anderes Beispiel ist es, solche,
wenn einfach mal ganz nach ganz knappen Definitionen gefragt wird,
wie in diesem Beispiel so, was wir,
was sich eigentlich ein Dienstleister von einem Klienten verspricht in dem Vertragsmodell,
was ihr in der voll ist und kennengelernt hat.
Das heißt, im Vertragsmodell ging es ja um Fuhrbedingungen,
die ein Klient erfüllen muss,
damit ein Dienstleister aber arbeitet und dann gibt es Nachbedingungen dieser Dienstleister erfüllen muss,
wenn der Klient sich an die Vorbedingungen gehalten hat.
Und eine etwas Drittes wäre es dann in diesem Beispiel halt auch,
wäre es dann halt auch sogenannte Klassen wie ihren Genau.
Also es geht noch ein bisschen darüber hinaus.
Also er verspricht nicht nur die Dienstleistung bei Einhaltung der Vorbedingungen,
sondern wenn der Dienstleister auch Nachbedingungen definiert. Das heißt,
wenn ich jetzt sage, ich habe wie meinen Dienstleister D,
und der sagt so, halt dieses Ed We Cuire,
Buch, also Dienstleister zum Beispiel verleihen.
Ja, und dann sage ich irgendwie Kunde, Buch,
jetzt einfach mal sehr einfach besprochen.
Und dann kann der Dienstleister halt verlangen, dass das Buch irgendwie im Bestand ist.
Na, also das Buch ist ein Bestand, der Kunde,
der Kunde existiert. Vielleicht auch ist im Bestand. Und
wenn diese Vorbedingungen erfüllt sind, dann kann halt dieser Dienstleister sagen,
dass seine Dienstleistung korrekt ausgeführt worden ist.
Das heißt, das Buch ist dann Kunde verliehen
Also es ist halt, also bei diesen Aufgaben,
also bei diesen Aufgaben ist es halt wichtig, sich ähm,
möglichsten, ähm, sehr klar, äh, nein,
normalerweise, äh, also die Frage ist, ob die,
ob die in natürlicher Sprache geschrieben werden können,
Debi Quires in den Shows, äh,
nein, im Idealfall sollte es in Java Caltex sein,
aber weil es jetzt handschriftlich mit etwas nerviger ist,
Java Quelltext zu schreiben,
habe ich das ein bisschen abgekürzt
Genau. Also wichtig ist bei diesen Fragen,
also wenn es darum geht,
na also was zu so einem Konzept zu beschreiben,
möglichst nahe an den Definitionen zu bleiben und entsprechende Fachwörter zu verwenden.
Das heißt also der Dienstleister verspricht bei Einhaltung der Vorbedingung
die Einhaltung aller Nachbedingungen
Genau, das ist genau. Also es ist halt,
also da ist es halt immer wichtig, dass ihr zeigt,
ihr habt die entsprechenden Fachbegriffe per Rat und könnt sehr konkret benennen,
was er macht. Weil das andere Beispiel mit,
wenn man sich an die Vorbedingungen gehalten wird,
erfüllt er die Dienstleistung, ist halt etwas schwammiger formuliert,
als wenn man wirklich hart sagt,
was wirklich,
also was er wirklich garantiert
Ja, also das ist halt,
also bei diesen Aufgaben ist es halt wichtig,
dass ihr vielleicht ein, zwei Worte mehr schreibt und das sehr,
also zu konkretisieren und dadurch dann die volle Punktzahl für diese Aufgaben zu bekommen.
Genau. Etwas anderes, was ihr in der Klausur erwartet,
wer euch erwartet werden,
sind Single-Choice oder unter Umständen ab und zu auch mal Multiple-Choice,
wobei Multiple-Choice ich jetzt nicht so häufig gesehen habe
Und diese sind meistens mit, sag ich mal, Antworten gepickt,
die, wenn man es nicht genau durchliest, alle irgendwie sinnvoll erscheinen.
Also in diesem Beispiel ist es, ich habe irgendwie eine Klasse B,
die ein direkter Subtyp von Interface A sein soll.
Wie schreibe ich das jetzt in Source Code? Ja,
und diese drei Antworten damit, Klaas B. Extense A,
würden ergeben ja in gewisser Weise Sinn,
wenn der Wenn es nicht ein Subtyp von einem Interface wäre,
sondern für einen Subtyp von einer anderen Klasse,
dann wäre ja da die erste Antwort richtig.
Und in diesem Falle ist die zweite Antwort richtig,
weil hier das wichtige Keyword ist,
dass es von einem Subtyp von der Interface sein soll.
Genau. Genau, die Frage ist, was ist ein
Subtyp nochmal? Also Subtypen ist relativ Also Subtyp ist,
wenn wir uns anschauen, das Gegenteil von Superzügen.
Ja gut, also. Vielleicht ist es ganz wichtig.
Wir schauen uns das erstmal an. Also wir haben ein
Interface, Interface. A. Und eine Klasse B. Klasse B.
Und diese Klasse B sagt jetzt Implements
Ah. Ja, also das, was jetzt halt hier,
wenn wir uns das in diesem Kontext von diesen beiden Sachen anschauen,
sage ich, ist Interface A.
Mein sogenannter Supertyp, weil er in der Hierarchie,
die ich jetzt auf, also in der Klassenhierarchie,
die ich aufbaue, jetzt der Ursprungstyp ist,
und in Java ist ja jede Klasse,
die ich deklariere,
ist ja auch gleichzeitig
ein Datentyp
Daher kommt das jetzt mit dem Wort Typen.
Und die Klasse beziehungsweise Interface,
was dann in der Hierarchie unter dem Interface A steht,
ist dann mein sogenannter Subtyp.
Und jetzt können wir, warte
Genau. Ich kann das auch gleich noch mal in den UML
vor uns zeigen. Okay. Na, also das heißt,
ich habe meinen super Typ und meinen Subtyp. Na,
und wenn ich mir das jetzt irgendwie so als,
ähm, sage ich mal, Hierarchiebaum anschaue,
dann würde das jetzt halt so aussehen.
Und wenn ich jetzt beispielsweise sagen würde, okay,
ich habe jetzt hier noch eine Klasse, Klasse C,
die Extended,
Extended Klasse B,
dann ist Klasse C
ein Subtyp
Ein Subtyp von C. Das heißt,
wenn wir uns das jetzt einfach mal nochmal als OML-Klassendiagramm anschauen würden,
ist es, ich habe hier beispielsweise mein Interface.
Ich mache das mal. Also ich habe hier mein Interface
. Interface A. Das beschreibt hier zum Beispiel irgendwie,
das beschreibt jetzt die Operation A und das Ganze mal ein bisschen vereinfacht zu darzustellen.
Das beschreibt jetzt die A, also B,
Extended in diesem Fall, also Klasse C, Extended B,
weil C, ja, der Subtyp dann von B sein soll.
Also schon so korrekt, wie ich das aufgeschrieben habe
Also habe ich es falsch gesagt. Okay, dann
habe ich es zu außer Versehen falsch gesagt. Genau,
also es geht darum, ich habe... Genau,
ja, also Subtyp, also das kann sehr schnell,
sehr verwirrend werden.
Genau, also wir haben unser Interface,
und jetzt haben wir unsere Klasse B. Und die soll jetzt
von Klasse A, also das Interface A implementieren.
Das heißt, dafür nehmen wir dann die gestrichelte Linie mit
dem nicht ausgefüllten Pfeilkopf
Entschuldigung, ja. Vielen Dank. Genau, es ist natürlich
korrekt. Es ist genau andersrum sein soll. Genau,
und das heißt, damit wird jetzt gesagt,
klasse B soll das Interface A implementieren,
als Unterschluss heißt es natürlich,
also B kann jetzt zum Beispiel noch weitere Methoden sickerieren,
aber was wir,
aber B muss dann halt auch Methode A implementieren,
die halt hier in diesem Interface deklariert ist
Das heißt, wir haben dadurch jetzt diese Beziehung mit B ist ein Subtyp von dem Supertyp A.
Und wenn ich jetzt in diesem Beispiel noch die Klasse C dazu male, zum Beispiel die Methode C hat und diese erbt jetzt davon, das ist dann ja der durchgezogene Strich mit dem geschlossenen Pfeilkopf. Ja,
und wenn ich jetzt das,
um jetzt vielleicht das mal so ein bisschen die Wiederholung von OML komplett zu machen,
wenn ich, wenn jetzt, wenn ich jetzt hier noch meine Klassen,
meine Klasse D habe und E, Und ich möchte,
und ich habe das Klasse C, eine Exemplarvariable,
also dass die Klasse C eine Exemplarvariable von Typ D hat,
dann habe ich ja die sogenannte strukturelle Abhängigkeit in UML,
das ist dann der Durchgezogene,
Strich mit dem offenen Pfeilkopf und wenn ich jetzt in irgendeiner Methode Also jetzt in irgendeine Methode,
das als Parameter benutze, Rückgabetypen oder lokale Variable,
jetzt zum Beispiel E habe,
dann wäre das in diesem Fall der gestrichene,
also der gestrichene Strich, mit dem nicht geschlossenen Pfeilkopf.
Genau. Und also das ist dann,
also das ist dann nochmal so das kleine Recap von,
was sie eigentlich nochmal zu ML wissen müssen.
Also das ist, also so sieht das halt bei Klassendiagrammen
aus und Genau. See und E sind einfach irgendwelche Klassen.
Also da geht es jetzt nur darum,
dass ich nochmal zeigen wollte, wie es eigentlich aussieht,
wenn wir hier mit den durchgestrichenen Fallen,
haben wir die sogenannte strukturelle,
strukturelle Abhängigkeit.
Strukturelle Abhängigkeit,
das heißt beispielsweise Exemplarvariable
Und die Abhängigkeit, die ich halt von C zu E habe,
ist eine sogenannte etwas, einfach nur eine allgemeine Abhängigkeit.
Also das ist dann die allgemeine Abhängigkeit.
Und diese passiert, diese passiert dann,
wenn ich beispielsweise das als Parameter benutze
In einer Methode oder als Rückgabetypen für eine Fohlenmethode benutze.
Oder halt entsprechend eine lokale Variable. Genau, also das ist halt,
also das ist hier, das ist die sogenannte, das ist der Implementationsvererbungsfall.
Implementationsvererbung und hier oben war das die Ist das die Schnittstellenvererbung? Genau,
es lohnt sich vor allem, also es lohnt sich einfach mal,
nochmal diese Pfeilarten so ein bisschen zu verinnerlichen,
wie diese funktionieren und was sie konkret bedeuten,
weil es auch noch ein, also es gibt sogar,
also es gibt noch einen Aufgabentypen,
wo es darum geht, dann solche UML-Diagramme zu vervollständigen.
Also wenn ihr jetzt zum Beispiel Also als Beispiel,
jetzt ist ja jetzt dieses UML-Diagramm,
was ich hier jetzt gerade gezeichnet habe,
würdet ihr dann in der Klausur bekommen,
vollständig ohne Pfeile und in einen Beschreibungstext sind dann diese Abhängigkeiten für euch textuell beschrieben.
Genau. Genau, die Frage ist,
ob Verstöße gegen Demeter aus allgemeinen Abhängungen,
Abhängigkeiten bestehen
Das kann man jetzt in gewisser Weise,
könnte man das sagen, dass das konkret so ist,
weil ich ja,
also der Lore of the Meta schaut sich ja immer an,
wenn ich eine Methode implementiere, in mein Objekt O.
Und das heißt, da habe ich ja nur die Möglichkeit,
lokale Variablen zu machen.
Oder halt Präferenzen aus anderen Methodenaufrufwind zurückzubekommen
Also man kann, also ich glaube,
man kann schon sagen,
dass aus der Verletzung von dem Lore of the Meta
handle ich mir neue allgemeine Abhängigkeiten ein
Genau, also strukturelle Abhängigkeiten wird schwierig, weil man,
ich sag, oh, jetzt muss ich selbst nur überlegen.
Also ich würde jetzt spontan sagen,
dass ich mir dadurch
keine strukturellen Abhängigkeiten einhandle
Weil diese Variable,
also diese Referenzen, die ich dadurch dann ja bekomme,
dann ja keine Exemplarvariablen sind und auch keine Variablen sind,
die, sag ich mal, zwingend notwendig sind,
um diese Klasse zu haben.
Also strukturelle Abhängigkeit ist es ja, wenn diese Abhängigkeit fehlt,
dann kann diese Klasse gar nicht existieren,
weil sie das als Exemplarvariable hat
Also das heißt... Genau,
also strukturelle Abhängigkeiten handle ich mir damit halt nicht ein,
aber wenn ich gegen Love, den Meter verstoße,
handle ich mir halt neue allgemeine Abhängigkeiten ein und erhöhe damit meine Kopplung.
Was man jetzt, was jetzt jemand von euch aber auch
sehr schön geschrieben hat, ist, wichtig dabei ist,
zu sagen, dass diese Beziehung nur einseitig gilt.
Das heißt, nicht jede allgemeine Abhängigkeit, die ich irgendwie habe,
ist auf Grundlage von einem Bruch von der Off-Demeter.
Diese Abhängigkeiten entstehen halt, wie ich auch da unten geschrieben habe,
dass sie aus Parametern Rückgabetypen oder lokalen Variablen,
die ich benutze
Genau, also das, was, ich glaube, das,
was Daniel auch nochmal zusammenfassend geschrieben hat, ich glaube,
das gönnt ihr euch so als Zusammenfassung für, warum es wichtig ist,
dass ihr euch die UNL-File nochmal gut einzuprägen ist,
so als Zusammenfassung dafür zu nehmen.
Genau. Okay
Genau, da gab es dann noch gerade eine Frage bei Solids.
Da muss ich kurz schauen. Da geht es, also bei D
geht es ja um... Oh, wie wichtig ist.
Ich würde jetzt mal behaupten, Solid ist insofern wichtig,
dass ihr verstanden haben müsst, wofür die einzelnen Buchstaben stehen.
Also das heißt, dass ihr halt wisst, was,
also halt hier Single Responsibility Principle,
dass das die Aufteilung oder Zuständigkeiten ist und so weiter und so fort.
Also das ist halt einfach, da müsst ihr euch die
Definition aus der Vorlesung nochmal, aus den Vorlesungsfolien halt anschauen und reinziehen.
Und jetzt bei der Dependency Inversion Principle, also dem D,
Genau. Ich kann das jetzt nicht so konkret beantworten,
ob ihr Ob ihr wirklich konkrete Beispiele geben müsst in der Klausur.
Also ich habe es tatsächlich, glaube ich, noch nie gesehen,
dass sehr in die Tiefe von allen der Prinzipien gegangen ist.
Und also das ist so ein bisschen, also ja,
also wie gesagt,
also wie ihr halt auch schon in meinem Disclaimer gesagt habe,
also wenn es sag ich mal, tiefergehende Fragen gibt zu einzelnen Sachen,
dann sind das meistens die Fragen, die dann sozusagen die,
sag ich mal, restlichen Punkte geben,
um zu da eins zu kommen.
Und ich glaube, da wollen wir uns jetzt nicht
zu doll verstricken in zu tiefen Themen.
Genau. Die Frage, ob ich die Klausur schon gesehen habe,
ich habe ja die konkrete Klausur noch nicht gesehen.
Ich habe aber Entsprechend Altklausuren gesehen und habe auch mit Rücksprache mir,
sage ich mal, eine Liste von typischen Aufgaben geben lassen und Themen,
die in der Klausur drankommen.
Aber die konkrete Klausur habe ich natürlich nicht gesehen.
Das wäre, glaube ich, auch ein bisschen kontraproduktiv,
weil ansonsten würde ich jetzt wahrscheinlich zu sehr auf die Sachen eingehen,
die in der Klausur drankommen werden.
Aber ich weiß grundsätzlich, welche Aufgaben drankommen können und welche
jetzt konkret jetzt wirklich drankommen,
das weiß ich nicht
Genau. Okay, strukturelle Abhängigkeit und... Okay,
das können wir uns gerne mal anschauen an ein Beispiel,
was jetzt
strukturelle und allgemeine
Abhängigkeiten sind
Dazu schauen wir das jetzt uns einfach mal so jetzt in Codeform an.
Natürlich ist das jetzt hier kein Compilierer-Racko. Ja,
aber wenn ich jetzt zum Beispiel sage, okay, ich habe eine... Klasse A.
Die hat eine Methode, die sage ich,
sagen wir jetzt einfach mal, gibt ein... gibt eine Exemplarware,
hat eine Methode von, die eine Intuitur zurückgibt,
sondern ich sage einfach nur... Ah, jetzt an diesem Beispiel.
So, und wenn ich jetzt, jetzt gehe,
sage ich mal, hier als nochmal allgemeine Abhängigkeit,
besteht dann, wenn ich eine Klasse B habe,
wo ich jetzt eine Methode habe,
in der ich jetzt zum Beispiel sage,
also wo ich mir jetzt zum Beispiel ein Exemplar von A
erstelle und jetzt einfach und jetzt irgendwie irgendwas mit diesem Objekt mache,
zum Beispiel.
Also ich breche halt irgendwie etwas. Ja, also ich
breche eine allgemeine Abhängigkeit. Hier kommt die Abhängigkeit darüber,
dass ich in der Methode B mir eine lokale Variable erstelle von Typ A,
diese Initialisiere,
also diese Instanziere mit New A und dann hier zum Beispiel
sage,
object.a und dann hält irgendwie
die Bluthode Aufrufe
Dann gibt es, der zweite Fall ist die, ist ja die sogenannte strukturelle Abhängigkeit.
Das ist, wenn ich jetzt beispielsweise sage,
ich habe eine Public Klasse C. Schön, hier mal.
Genau, ich habe eine Klasse C und die hat jetzt hier oben als private Feldvariable.
Dieses, also als Exemplar war reable, eine Abhängigkeit zu A.
Das ist halt diese strukturelle Abhängigkeit, weil dadurch ist halt das Problem,
ich kann, wenn die Klasse A nicht existent ist,
dann kann diese Klasse nicht existieren.
Wohingegen, wenn ich mir beispielsweise allgemeine Abhängigkeit anschaue,
wäre es ja theoretisch möglich zu sagen,
wenn A noch nicht existent ist,
dass ich dann einfach diese gesamte Methode auskommentiere und zumindest ein Teil der Funktionalität einer Klasse vorhanden ist und funktioniert.
Das ist der Unterschied zwischen struktureller Abhängigkeit und allgemeiner Abhängigkeit.
Genau. Und auf die Frage hin,
ob ihr in der Klausur Kurzsegmente schreiben müsst, da komme ich jetzt zu,
nachdem wir hier Ja, okay, gut.
Dann weine ich direkt wieder in Visuals to You Code gehen.
Also, was euch in der Klausur vorkommen wird,
ist, sage ich mal, zum Teil Lücken programmieren.
Also, wenn wir so komplexere Sachen haben,
wie in diesem Beispiel, wo es darum geht,
eine Equals-Methode zu implementieren, na,
dann erhaltet ihr halt hier diesen Quelltext und müsst dann
die entsprechenden Lückenei ausfüllen
Um halt diese Aufgabe zu lösen. Da ist es dann halt,
also da ist es dann wichtig, dass ihr euch,
dass ihr die so ein bisschen die Hints,
die euch der Lückentext manchmal gibt, sage ich mal,
so ein bisschen zu Herzen nehmt und ein bisschen ausnutzt.
Also wenn halt hier irgendwie gefordert ist, ihr sollt irgendwie etwas mit einer,
mit einem Bezeichner machen und danach kommt ein Plus,
danach kommt ein Plus, genau.
Danach kommt ein Punkt, dann könnt ihr davon ausgehen,
dass das, was jetzt hier in diesen markierten Bereich hinkommen soll,
höchstwahrscheinlich in irgendeiner Art und Weise eine Referenzvariable sein soll,
auf ein Objekt,
an der ihr dann
eine Methode ausführen sollt
Genau. Und in diesem Fall wäre es halt,
könnte man das halt relativ einfach machen,
wenn man würde halt sich anschauen,
okay, wie funktioniert nochmal Equals,
wenn man sich das nochmal so ein bisschen in den Kopf hervorruft,
wie war dann nochmal dieses, sag ich mal,
Muster, nachdem man davor geht?
Man schreibt immer Referenz variable Methode. Also wenn wir das jetzt hier beispielsweise mal ausfüllen,
dann würden wir ja hier sagen, okay,
der erste Schritt Einer der Implementationen einer Equals-Methode ist ja immer die Typ-Abfrage.
Das heißt, ich gucke, ob mein Objekt,
was ich übergeben bekommen habe, eine Instanz von der Klasse Kunde ist,
mit der ich mich vergleichen möchte. Dann kann ich,
was ich dann machen muss, ist der zweite,
also das ist hier in der Schritt 1 einer Equals-Methode,
der Schritt 2, ist es dann die sogenannte Typ-Zusicherung zu machen.
Das heißt, ich muss dann, ich schreibe dann hier
den Den Typen meiner neuen lokalen Variable ich erstellen möchte,
macht dann hier das sogenannte, die Typen Umwandlung.
Damit teile ich Java mit. Das, was jetzt nach diesen Klammern,
also das, was wir jetzt nach den Klammern kommt,
wird von, sollst du ab jetzt so behandeln,
als wäre es vom Typ Kunde.
Und dort kann ich dann sagen, halt mein Objekt reinpacken und
dadurch habe ich dann sozusagen den Schritt zwei meines Equals erfüllt.
Und der Schritt 3 des Equals ist es dann halt, den tatsächlichen Vergleich auszuführen. Das heißt,
in diesem Fall wäre es dann, okay, ich muss,
ich muss beim Kunden sagen, Kunde, Punkt, Gets Name,
weil ich hier unten in dem Quelltext bekomme ich als Synth,
dass es wohl eine Möglichkeit gibt,
auf den Namen zuzugreifen und dass man das über diesen Get
Name machen soll
Also da ist es halt auch wichtig,
dass ihr euch den gesamten Gutschnipsel einmal vollständig durchliest,
um eventuelle Hinweise am Ende oder am Anfang,
möglichst gut zu erkennen.
Das heißt, also es wird von mir erwartet,
dass ich hier kunde.gertname machen will.
Und dann rufe ich an dieser String-Mytho, an diesen String-Objekt.
Natürlich die Klammer nicht vergessen. Genau, ja,
das kann man. Also die Frage ist,
ob man hier nicht eigentlich auch das hier weglassen könnte und
einfach sagen könnte,
kunde unterstrich Name
Das ist in der Theorie möglich,
aber es kann unter Umständen ja sein, dass in dieser,
in diesem Ghetter, der hier benutzt werden soll,
noch irgendwelche sogenannte Post-Processing-Sachen gemacht werden.
Also es wird halt irgendwie noch, also es wird mir
diese Exemplar variable Unterstrich-Name noch irgendwas vorher gemacht oder sowas.
Und man möchte, dass das, also man kann es machen,
aber es ist eigentlich eher nicht so gern gesehen.
Also man benutzt lieber die Ghetter, weil das ist dann ein bisschen eindeutiger,
falls in dem Ghetter noch irgendwelche Logik existiert,
die bevor dieser Name zurückgegeben wird, noch irgendwas mit diesen Namen macht.
Aber das wäre theoretisch, aber ja klar,
es wäre theoretisch. In diesem Fall wäre das möglich,
weil wir die Implementation von Ghettenname nicht wissen.
Genau. Und hier machen wir dann halt,
benutzen wir den Equals-Operator für den String-Vergleich.
Und hier nehmen wir dann von unserer eigenen,
unsere eigenen Exemplar variable oder in diesem Fall können wir auch sagen,
Ghettenname.
Also beides wäre in diesem Falle
auch wieder richtig
Genau, das ist genau, dass das... Genau,
genau, guter Einwand,
also wichtig ist es halt,
wenn ihr so diese Vergleiche macht,
dass ihr halt konsistent bleibt und entweder in diesem Fall unterstrich,
also halt Get-Name benutzt in beiden Fällen oder halt direkt auf
die Exemplarvariable zugreift
Also das jetzt zu vermischen, indem ich jetzt hier schreiben würde,
unter Strichnahme, das wäre halt, das würde ich nicht.
Also das wäre halt, das könnte halt sehr böse enden,
wenn ein Get-Name tatsächlich noch irgendwelche Änderungen an dem Namen macht, wo es das zurückgibt.
Genau. Und hier unten ist es eigentlich dasselbe Spiel dann
halt auch mit dumme Gert-Geburtstag, ist gleich Geburtstag.
Und in diesem Fall Also dieses Beispiel habe ich jetzt so gewählt,
dass man da auch mal zwei verschiedene Vergleiche hat,
weil es sich hier ja um einen primitiven Datentyp handelt,
komme ich halt damit weg, einfach zu sagen, okay,
ich mache den Vergleich mit den Gleichzeichen, anstatt mit der Equals-Methode.
Also das ist etwas, was ihr so ein bisschen,
genau, immer so auf, also das ist halt,
wo ihr halt aufpassen müsst,
wenn es halt um diese Vergleiche geht und Gleichheiten immer schauen,
Hanne, wenn es sich um ein Objekt handelt und manche Objekttypen,
dann immer die Equals-Methode, wenn ihr die Gleichheit haben möchtet und bei primitiven Datentypen könnte es auch über das gleich gleich machen.
Genau, also es wäre theoretisch möglich,
dass in einer späteren Version dann irgendwann gesagt wird,
das Geburtsdatum wird nicht mehr als Interager gespeichert, aber genau,
also vielleicht war jetzt Geburtstag irgendwie jetzt irgendwie eine sehr schlechte Variante,
vielleicht hätte ich das irgendwie Lieblingszahlen nennen müssen oder so,
aber ich glaube, Die Idee dahinter wird so ein bisschen klar,
dass sie halt euch, dass sie halt diese Hinweise,
die euch im Source-Code gegeben werden, den ja davor gesetzt bekommt,
dass sie ja diesen nachgeht und diese verwendet,
um entsprechend die Lücken einsetzen zu können.
Oh ja
, Entschuldigung
Genau, also macht das am besten nicht in der Klausur,
wobei ich leider nicht weiß gerade,
ich könnte aber einfach mal schnell fragen,
ob vergessene Klammern negativ bewertet werden.
Genau, also es ist, naja,
baller mal die Beispielaufgabe für Single Choice
Ja. Genau, also bei diesem,
weil diesen Single-Choice oder Multwitch-Choice-Aufgaben ist etwas,
was ich vielleicht noch als Tipp mitgeben kann,
immer sehr wichtig auf die Formulierung zu achten,
weil gerne mal passiert es auch,
dass dort von Neilungen drin sind.
Also so solche Sachen wie Multiple-Choice,
welche von den folgenden Aussagen gelten nicht für Java.
Und dann stehen da halt so vier Aussagen,
man muss
die falschen Aussagen ankreuzen
Ja. Also, also, sehr häufig wird die Art und Weise,
wie man diese Single oder Multiple-Choice-Aufgaben auszufüllen hat,
wird teilweise von einem Wort,
was in dem Satz drin ist, bestimmt,
ob das eine Verneinung ist oder wie es in diesem Beispiel,
dass es sich um ein Interface handeln soll,
um das Interface A, was von Klasse B implementiert wird.
Genau. Da kam jetzt gerade noch eine Frage,
ob es Abzüge gibt, wenn man was Falsches ankreuzt.
Das ist der, nach meiner Kenntnis ist das der Fall,
wenn es innerhalb einer Aufgabe ist. Das heißt,
wenn ich eine Multiple-Choice-Aufgabe habe und da gibt es jetzt vier Aussagen,
zwei sind davon richtig, zwei davon sind falsch,
wenn ich alle ankreuze, dann habe ich null Punkte,
weil mir halt für die Sachen,
die ich falsch angekreuzt habe,
wieder Punkte für diese Aufgabe abgezogen werden.
Aber wenn ich jetzt bei diesem Multiple-Choice jetzt nur beide falsche Aussagen ankreuze,
dann wird das jetzt nicht von meiner Gesamtpunktzahl abgezogen.
Also, das ist immer,
also die Abzüge bei Multiple-Choice für falsche Kreuze,
die gelten immer nur für die jeweilige Aufgabe,
damit man halt nicht einfach durchgeht und einfach
alles ankreuzen kann
Genau, also eine gute Idee ist es halt immer,
wenn ihr eine Antwort auf eine Multiple-Choice oder Single-Choice-Aufgabe nicht wisst,
erstmal vielleicht die weiteren Aufgaben zu bearbeiten und dann am Schluss euch das nochmal durchzulesen und wenn ihr nichts wisst,
einfach, also bei Single-Choice,
dann einfach Eine von den Antworten ankreuzt mit etwas Glück,
aber es ist die richtige.
Oder ihr könnt noch ein Ausschlussverfahren,
vielleicht sogar ein oder zwei Antworten ausschließen und habt dann halt einfach
nur die Auswahl zwischen zwei und könnt dann eventuell darüber noch Punkte bekommen.
Genau. Ich würde jetzt tatsächlich... Genau. Ich kann leider
die Beispielaufgaben nicht zeigen, weil Ich das nicht darf.
Also ich durfte mir aus den Beispielaufgaben einige rausnehmen. Ich kann mir vorstellen,
dass wahrscheinlich die Aufgaben, die ich jetzt hier behandelt habe,
mit großer Wahrscheinlichkeit nicht in der Klausur drankommen werden.
Weswegen, wenn ich jetzt alle Beispielaufgaben,
die mir gezeigt worden sind, zeigen würde,
dann würde ich halt eine ganze Reihe von Aufgaben aus
den Aufgabenpool rausnehmen leider.
Genau. Bevor, also das werde ich gleich nochmal machen,
aber bevor wir das machen,
es war jetzt eigentlich nochmal eine halbe Stunde so ein bisschen Pause angedacht,
weil Videokonferenzen sind immer anstrengend oder insgesamt sie ja zwei Stunden vor dem Rechner sitzen kann,
eventuell anstrengend sein.
Das heißt, ich würde sagen, wir machen,
nachdem ich das mit dem Hashcoat nochmal gezeigt habe,
dann sagen wir mal, so 20 Minuten in Pause,
um halt einmal Nochmal was trinken,
trinken gehen zu gehen oder sonst was.
Und dann würde ich nochmal eine Stunde oder so mich
euren offenen Fragen widmen und genau.
Und dann sind nochmal so die letzten, sag ich mal,
Unklarheiten vielleicht, weil für euch wichtigen Themen rauszukriegen.
Genau. Genau, also das ist, also das,
was ich vorbereitet habe, das ist schon durch.
Sie liegen auch einigermaßen in der Zeit
mit den Zwischenfragen
Deswegen, ich würde es jetzt einmal nochmal zeigen,
genau, also es wurde ja hier nochmal gefragt,
nachdem zu dem Thema Hashcode,
weil es ist ja in der Java-Dokumentation so vorgeschrieben,
dass wenn man diese Methode Equals hier überschreibt,
dass man dann auch Hashcode überschreiben muss.
Und das Wichtige, was man sich da überlegen muss,
ist halt,
wie kann ich, also erstmal Public,
wenn es jetzt schon tot
Entschuldigung. Genau. Also, das,
was man halt sich hier anschauen muss, ist halt,
wenn ich jetzt Hash-Code überschreibe, dann muss ich mir halt überlegen,
okay, es wird gesagt, dass wenn zwei Objekte laut Equals gleich sind,
müssen sie denselben Hash-Code liefern.
Das heißt, aber umgekehrt muss es nicht heißen,
wenn ein wenn zwei Objekte denselben Hash-Code haben,
müssen sie ja auch E-Code, also halt gleich sein. Das heißt,
in diesem Fall können wir uns theoretisch relativ leicht machen,
weil wir ja eine Exemplarvariabel haben, die den Typ Intiture hat,
dass wir einfach sagen, okay, unsere Implementation für Hash-Code sieht aus,
einfach zum Beispiel diesen Geburtstag, die Geburtstag zu Return,
beziehungsweise das an unseren Ghetter abzugeben.
Das wäre jetzt so, wenn man,
also wenn ich das jetzt implementieren würde, das wäre so die Trivial-Lösung,
Das hat natürlich entsprechende Nachteile, weil wie ihr vielleicht wisst,
noch aus SE1, wenn ich mich recht erinnere,
war das zumindest Thema in der SE1 mal gewesen,
ist es ja so, dieser Hashcode wird in manchen Datenstrukturen,
also zum Beispiel dem Hashset oder der Hashmap verwendet,
um das effizienter abspeichern zu können.
Und der effiziente und wenn man einen effizienten Hashcode haben möchte für diese Datenstrukturen,
da möchte man möglichst, dass sich die Werte,
also der Wertebereich, den diese Methode, Hashcode zurückgibt,
möglichst über den gesamten Wertebereich von Inchitscher streckt.
Wenn wir jetzt aber uns anschauen, ja,
Get Geburtstag, also Geburtstage liegen jetzt relativ nah beieinander,
ist es jetzt, sage ich mal, ungefähr gesehen,
also die Personen, die ich in mein System habe,
wären wahrscheinlich eine Varianz da drin haben von 100 Jahren
Was dann, und das deckt eventuell halt nicht den vollen Wertebereich von Incitia. Das heißt,
vielleicht eine etwas bessere Variante wäre es zu sagen,
okay, ich habe ja einen String,
der mir zurückgegeben wird, hier mit String get Name,
dass ich einfach sage, dass ich das einfach weitergebe.
Das heißt, ich sage, der gelb-name.name und dann
kommt Hashcode. Und dass ich dann sozusagen den Hashcode von
meinem String verwende
Das wäre so eine etwas bessere Variante,
weil die Entwickler, also die, sage ich mal,
die Entwickler von Java haben sehr, sehr viele,
sich sehr, sehr viele Gedanken dazu gemacht,
wie man diesen Hashcode von Strings möglichst effizient für programmiert,
sodass man eine Gleiche,
also sodass man halt die volle Spanne von Inchitsch ausreizt.
Was man jetzt natürlich auch machen könnte,
ist anzufangen irgendwie
das selber
zu machen
Da, also das ist dann so,
also das geht dann so eher in die Richtung des Kreativen,
wo man sich dann Gedanken machen müsste,
wie kann ich aus meinen Zustand von meinen Kunden,
wie kann ich aus diesen Zustanden möglichst guten Hashcore generieren.
Aber das, also ich glaube,
das würde jetzt so ein bisschen zu weit gehen,
weil das dann halt so ein bisschen in Richtung geht,
sich Gedanken zu machen auf dem Papier
Wie erreiche ich durch Addition von Werten,
von deinen Zustandsvariablen oder was auch immer oder Multiplization,
Multiplikation mit Primzahlen oder sonst was zu arbeiten.
Genau. In gewisser, also die Frage ist,
war der Hashcode nicht dazu da, um Jecke zu vergleichen?
In gewisser Weise jein. Also er ist, der Hashcode
wird verwendet, um sozusagen erstmal eine schnelle Entscheidung zu machen.
Also einen schnellen Wert zu bekommen, um ein Objekt zu identifizieren.
Also wenn ich zum Beispiel,
also wenn ihr zum Beispiel so zurückdenkt an zum Beispiel so ein Hash-Set,
das Hash-Set sagt ja aus, dass ich von jedem Objekt immer nur ein Exemplar in diesem Hash-Set drin habe.
Und das Feststells ist halt aufgebaut mit, dass ich halt
Arrays habe. Also ich habe irgendwie so ein Array,
Von 1 bis 100 und in jeden diese L-Rays sind sogenannte,
sind halt, also in diesen, sag ich mal,
Array-Schubladen können dann halt mehrere Objekte drin sein.
Also wenn wir uns das mal anschauen. Na,
also wenn ich... Ja, das heißt,
also Hashcode ist ja dafür gedacht,
wenn ich zum Beispiel so ein Hash-Set habe, einfach dargestellt,
ist ja ein Hashtag nichts anderes, als wenn ich mir angucke,
okay, ich habe hier irgendwie so einen Schrank und ich habe hier so Schubladen.
Und ich, und ich habe hier,
das hier ist zum Beispiel meine Schublade null,
das ist meine Schublade 1, meine Schublade 2. Ah, hier mein schöner Schrank.
So, und wenn ich mir diesen Schrank jetzt ansch,
wenn ich jetzt wissen möchte,
ob ein gewisses Objekt schon bereits in diesem Hash-Set vorhanden ist,
dann nehme ich den Hash-Code.
Also ich möchte jetzt zum Beispiel gucken, so A. Hash-Code
Gib mir dann zum Beispiel irgendwie eine Eins zurück. Ja,
und dadurch weiß jetzt das Hashset okay, das heißt,
ich muss eher in diesen Schrank, den ich habe,
muss ich nur in dieser Schublade Eins jetzt hier,
muss ich die sozusagen aufmachen.
Also das ist dann hier meine Schublade Eins
Und da kann dann zum Beispiel irgendwie A drin sein,
C drin sein, D drin sein.
Also da können dann halt alle Elemente drin sein,
die diesen selben Hashcode haben. Und der Vorteil,
den ich jetzt habe mit diesem Hashcode ist ja,
dass ich nur diese Elemente hier überprüfen muss.
Das heißt, ich gehe dann halt hier rein und sehe,
okay, hier ist das Element hier drin, ist C,
Equals to A, nein, okay.
Ist die Equals zu A, nein.
Ist A, Equals zu A? Ja, okay,
also das Element ist bereits in meinem Hashset vorhanden.
Ja. Und das ist eigentlich der einzige Grund,
warum dieser Hashcode so wichtig ist
Weil dadurch kann halt dieses Hash-Set, was ich hier umhabe,
sehr, sehr effizient arbeiten, weil es halt immer nur ein Subset, also nur eine Teilmenge aller Elemente, die ich in meinen Schrank drin habe, mit der Equels-Methode überprüfen müsste. Ja,
und das ist der Grund, warum in der,
und darauf basieren halt sehr, sehr viele dieser Datenstrukturen,
die wir in Java haben, darauf, dass sie,
dass wenn du Equels überschreibst, du auch Hashcode überschreiben musst,
Na, weil ansonsten funktioniert das halt nicht, weil halt ein Objekt,
was Equal zu allen anderen ist, ne, also,
ne, wenn A. Na, A, Equals,
A, gleich True ist, ne, dann folgt,
dann folgt da draus, dass, äh, A,
also A, 1, Equals A, 2, ist gleich True, dann folgt daraus, dass die Hashcodes, Hashcodes dieselben sein müssen.
Aber das Wichtige ist halt, das ist keine,
das ist keine Be-Dektionales, ähm, dann eine bidirektionale Beziehung.
Genau. Das Beispiel 2, das war zu,
das war das Beispiel, wo ich erklärt hab,
was eigentlich der Unterschied zwischen struktureller und allgemeiner Abhängigkeit ist bei Mumel-Beispiel.
Genau. Und ich würde jetzt sagen,
wir machen so 20 Minuten Pause, das heißt,
wir würden gegen 4.20 Uhr weitermachen,
wo ja dann noch weitere Fragen stellen könnt,
die ich versuche zu eurer Zufriedenheit zu beantworten