width: 900 height: 900 maxScale: 1.5
SE-Tutorium 4 | Mittwoch 16 - 18 Uhr:
anchored to [[191.00_anchor]]
Lernziele:
- Fragen zu HW7 ?
- auf Eintrag im Forum hinweisen (Skript online für DbC!) (https://se.cs.uni-tuebingen.de/teaching/ws23/se/skript/design_by_contract.html)
- DbC wiederholen
- auf Refinement dessen eingehen und diese verstehen
- Anwendung auf Subtypes
- sowie Varianzen betrachten und
- anschließend üben ( am Beispiel verstehen / nutzen)
| Orga | Aktuelle Abgaben
-
HW8 ( allein, Bonus) -> bis zum 28.01.2024
-
HW9 (Gruppen!) -> bis zum 21.01.2024
- Erstellt die Gruppen und Teams!
-
Korrektur für HW7 kommt diese Woche, sorry!
| ORGA | Themen nochmal anschauen?
- Semester neigt sich dem Ende
- –> Sammeln welche Themen nochmal wiederholte werden sollten!
- jede Woche nochmal kurz auf die Inhalte eingehen
note: give them around 2 min -> to start write down a topic from their surveys!
- Side-Effects
- Code Smells
- Interfaces -> Contracts
| ORGA | Fragen zu Hausaufgaben ??
- gibt es Fragen zu den aktuellen Hausaufgaben (HW8,9) ?
note: ask them about the status –> thumbs up or not?!
| heutige Ziele |
- Wiederholung Contracts –> DbC ?
- Pre / Post-Conditions ?
- Warum machen wir das?
- Verbindung zu Interfaces ( und Testing in der aktuellen Vorlesung!?)
- Subtyping
- Variancen
| WDHL | Design by Contract
- Rahmenbedingungen zum Schreiben von Software
- Beziehung zwischen Nutzer*in und Developer*in
[!Question] Welche Dinge beschreiben wir dann in einem solchen Contract?
note: give them around 2 min to think about it?
| WDHL | Design by Contract
- beschreibt also drei Dinge:
- Preconditions -> Voraussetzungen ( )
- State of the world before usage
- Postconditions -> Nachbedingungen ( result is )
- State of the world after usage
- Invarianten –> Zustände, die sich nicht ändern werden -> unchanged … ?
| WDHL | Design By Contract
- ( remember example for traveling from Germany to Taiwan ) link
- PreConditions –> einhalten durch Nutzer*in ( Dev profitiert bzw. kann damit arbeiten)
- PostConditions –> einhalten durch Dev (nutzende profitieren davon!, kann damit arbeiten)
- Bedingen sich also gegenseitig!
| WDHL | Design By Contract
[!Question] Vorteile von Contracts für:
- die Codebase, die wir schreiben?
- Art, wie wir Code schreiben?
- wie Andere damit interagieren können?
note: ask interactively, maybe around 5 min at most?
| WDHL | Design By Contract
- Codebase hat damit klare Definitionen –> Verständlichkeit durch beschreibende Contracts ( Signaturen, Comments o.ä.)
- Assurance / Absicherung, dass es gewollt funktioniert
- auch, weil wir die Contracts dynamisch testen können!
require()
–> PREensuring()
–> POSTassert()
–> INVARIANT
Contract | Refinements
[!Quote] A contract is a valid refinement of another contract, if its preconditions are weakened and its postconditions are strengthened.
–> zwei Stellschrauben für Contracts möglich:
- Weakening Preconditions
- Strengthening Postconditions
- Meist ein Abwägen zwischen:
- Wartbarkeit
- Wiederverwendbarkeit
Contract Refinement | Weaken PreCond
// requires parameter of type Array
// returns true if the given datatype is empty
// true otherwise
def checkIsEmpty(datatype: Array): Bool = {
...
}
[!Question] Wie könnten wir hier die Vorbedingung vereinfachen?
note: -> Prinzipiell ist diese Funktion jetzt nicht soo sinnig konstruiert, weil man das ja je nach Datentyp anders prüft, aber es geht hier um die Idee, dass wir diese Funktion vielleicht auch für mehr Datentypen nutzen können wollen. –> Wir könnten jetzt noch den Eingabewert auf weitere Inhalte erweitern, also folgend:
def checkIsEmpty(datatype: Array | List | String... ): Bool = {
...}
–> hier sieht man auch schon, dass wir für die verschiedenen Implementationen verschieden checken müssen, ob es leer ist. Also wir haben mehr Aifwand es entsprechend zu lösen, quasi
Contract Refinement | Weaken PreCond
- Pre-Condition einfacher setzen, gibt uns einfach mehr Möglichkeiten, die Methode anzuwenden
- etwa eben nicht mehr nur ein Datentyp
- ABER, damit müssen wir mehr bedenken / betrachten
- –> Implementation aufwendiger, weil mehr Cases betrachten
- Grundlegend: “Was ist die Mindestanforderung, die ich als Implementiererin habe?”
- (wir fragen ja nach Inhalten von Nutzer*in, die wir verarbeiten werden!)
Contract Refinement | Strengthen PostCond
- Post-Condition verschärfen –> weniger Zustände werden erlaubt!
- Beschreibt Rückgaben, die von Implementation ausgehen können!
- Nutzer*in erhält stärkere Garantien ( es kann nur noch das und das herauskommen!)
- also einfachere Handhabung mit Ergebnis von der Implementation
- (example: statt 4 Cases, nur 2 betrachten)
Contract | Refinement | Strengthen PostCond
- Beispiel aus Skript:
merge
nimmt zwei sortierte Listen und merged sie zusammen- “If the two given lists are sorted, so is the returned list”
[!Question] was sind die Pre / Post conditions hier?
note: go through this interactively Once we have that How to weaken the pre-conditions?
- we could allow all sorts of inputs instead ( integers !)
- problem with that change –> we may lose the post-cond that its sorted! How to strengthen post-conditions
- garantieren, dass die Werte von Eingabe auch in der Ausgabe sind ( obviously)
- garantieren, dass wir eine sortierte Liste zurückgeben! write it down with the nomenclature we introduced –> mathematical structure basically
| Contract Refinement |
- weitere Ressourcen im Online-Skript https://se.cs.uni-tuebingen.de/teaching/ws23/se/skript/design-by-contract/software-design.html
- weitere Beispiele ( auch ausführlicher erklärt!)
- Inhalte zu Interfaces/Subtyping und mehr dabie
Warum machen wir das?
- Software Design muss abwägen zwischen der Wiederverwendbarkeit und der Wartbarkeit
- Wiederverwendbarbkeit auf Nutzer*innen bezogen –> wie gut kann man Implementation verwenden?
- Wartbarkeit auf Implementiererin bezogen –> wie einfach können wir die Implementation verändern ( Aufwand dabei?)
- Weiterhin –> Verschiedene Pre/Post-Conditions geben Infos über Implementation wieder
- hohe Post-Conditions –> wir können die Implementation nicht so stark ändern!
- niedrige Pre-Conditions –> ev. Hoher Aufwand zu warten note: once again reference skript for more information! Ask for questions too!
Subtyping | Prinzip
- In Sprachen nutzen wir Typen, um ein Datum / einen Wert damit zu beschreiben
- Bool –> True/False
- Array<Int> –> Menge von Werten vom Typ Int
- String –> “…”
- Class X -> Object = X.new() …
- Subtypen sind jetzt Typen, die eine Submenge eines anderen bilden.
- einfache Referenz:
- “NullException” ist ein Subtyp “<:” von “ Exceptions“ in (Java/Scala)
Subtyping | Prinzip
class Item(val productNo: String) {
class Buyable(override val productNo: String, val price: Int) extends Item(productNo) {
class Book(override val productNo: String, ... )extends Buyable(productNo, price)
[!Question] wo finden sich hier Subtypen?
note: its likely obvious but we can see / observe that “Buyable” things are subtypes of “Item” and Books are also subtype of Item and also Buyable -> Transitive behavior just like in math!
ASK: What if we declare a Book and then use it on a method from Item –> because Item is a supertype of Book we are somewhat losing information here. So the methods from “item” are not aware of an isbn being stored and thus we cannot work with it unless an override was given upon extension
Subtyping <-??-> Contracts
- Zusammenhang zwischen Subtypes und Contracts?
- “Subtypen dürfen Verträge der Supertypen nur bestimmt verfeinern/ verändern”:
- Subtyp darf Methoden hinzufügen
- Subtyp darf Pre-Cond von Methoden abschwächen ( warum nicht verstärken?)
- Subtyp darf Post-Cond von Methoden verstärken ( warum nicht abschwächen?)
- Subtyp muss Invarianten beibehalten
Subtyping <-??-> Contracts
![[Pasted image 20240110005304.png]]
note: Wir können hier also weiter runter –> tieferer Baum quasi <– nur noch weiter verfeinern ( bzw Inputs abschwächen), sonst würden die vorherigen Methoden ja nicht mehr funktionieren / passend sein Referenz zum Skript und zum Online-Skript! https://se.cs.uni-tuebingen.de/teaching/ws23/se/skript/design-by-contract/subtyping.html
Varianz |
- Typen kann man gut prüfen ( Compiler, Typ-Annotationen etc)
- sind also Contracts
- ->Eingabe muss Typ X haben
- ->Ausgabe gibt Wert von Typ Y zurück
- geht auch mit first-class-functions –> Funktionen als Argument in Funktion
sortArray(Array,sortingParadigm:function: Int, Int => Bool) = ...
secondSmaller(first,second): Bool = if first > second : true; else false
oder so- Wir können sehr viele Funktionen dieser Form beschreiben!
- Wie wissen wir, ob eine Funktion dann passend ist oder nicht?
Varianz |
- Contracts zur Rettung ( sowie abschwächen / verstärken von Conditions)
- bei einem Subtyp, muss die Post-Condition stärker sein ( also neue Post-Cond alte Post-Cond)
- Post-Conditions nennen wir hier dann covariant
- Subtyp darf Pre-Condition abschwächen (also alte Pre-Cond Post-Cond) ( wir werden größer, müssen aber alles enthalten)
- Pre-Conditions nennen wir hier dann contravariant
–> Es als Mengentheorie betrachten, macht es vielleicht etwas einfacher :)
note: its bit difficult at first, i do have my struggles with that topic too, but its more or less about what type of subsets we allow for output ( postconditions) and which superset we can use ( if they contain the previous set too) etc. Thinking about it
| Übung zu Subtyping | Varianz
[!Task] im REPO: ( ex10-tut4 )
- Repository clonen und lokal mit IDE öffnen :)
- PART 1 gemeinsam durchgehen und betrachten
- Part 2 und 3 selbst durcharbeiten
- gerne Fragen stellen :)
| Feedback | (online) minute paper |
![[Pasted image 20240110124921.png]]
- hab Papier vergessen
- gerne beantworten!
Feedback zur Wiederholung ::
–> Folgend wiederholen /