252-0027
Einführung in die Programmierung I 10.0 Systematisches Programmieren
Thomas R. Gross
Department Informatik ETH Zürich
Copyright (c) Pearson 2013 and Thomas Gross 2016 All rights reserved.
Uebersicht
§ 10.0 Beispiel
§ Java und Speicher Modell
§ 10.1 Darstellung von Variablen und Objekten
§ 10.2 Assertions
§ 10.3 Preconditions und Postconditions
2
(Logische) Aussagen
§ Aussage ("assertion"): Eine Behauptung die entweder wahr oder falsch ist.
§ Wir fragen dann oft "Ist die Aussage wahr"?
§ Beispiele:
§ x ≥ 0 (hängt von x ab)
§ Zürich ist ein Kanton der Schweiz
§ Maseru ist die Hauptstadt Lesothos
§ 11 ist eine Primzahl
§ 120 ist kleiner als 11
§ x geteilt durch 2 ergibt 8 (hängt von x ab) 63
(Logische) Aussagen
§ Nicht alle Aussagen sind wahr
§ Für einige Aussagen können wir vielleicht nicht sofort entscheiden ob sie wahr oder falsch sind
§ Wichtig ist dass es Sinn macht zu fragen, ob die Aussage wahr oder falsch ist
§ Logisch heisst hier: im Sinne der klassischen Logik
64
66
Aussagen und Programme
§ Wir können Aussagen über das Programm machen und fragen ob sie an bestimmten Stellen wahr sind.
§ Gültige Antworten sind IMMER, NIE, oderr MANCHMAL.
System.out.print("Type a nonnegative number: ");
double number = console.nextDouble();
// Point A: is number < 0.0 here?
while (number < 0.0) {
// Point B: is number < 0.0 here?
System.out.print("Negative; try again: ");
number = console.nextDouble();
// Point C: is number < 0.0 here?
}
// Point D: is number < 0.0 here?
(MANCHMAL) (IMMER)
(MANCHMAL) (NIE)
Mit Aussagen arbeiten …
§ Direkt nachdem eine Variable initialisiert wurde, ist ihr Wert bekannt: int x = 3;
// is x > 0? IMMER
§ Ueber die Werte von Parametern wissen wir i.A. nichts:
public static void mystery(int a, int b) { // is a == 10? MANCHMAL
§ Innerhalb eines if , while , usw. wissen wir evtl. etwas:
public static void mystery(int a, int b) { if (a < 0) {
// is a == 10? NIE } ...
}
Aussagen und Schleifen
§ Zu Beginn des Rumpfes einer Schleife muss der Test true , ergeben haben:
while (y < 10) {
// is y < 10? IMMER ...
}
§ Direkt nach einer Schleife muss der Test false sein:
while (y < 10) { ...
}
// is y < 10? NIE
Aussagen und Schleifen
§ Im Rumpf einer Schleife kann der Test false ergeben:
while (y < 10) { y++;
// is y < 10? MANCHMAL }
72
"Manchmal"
§ Verschiedene Aktivitäten können dazu führen, dass der Wert einer Variable unbekannt ist (diese führen dann zu
"MANCHMAL" Antworten):
§ Eingabe von Scanner lesen
§ Lesen einer Zahl von einem Random Objekt
§ Uebergabe eines Parameters
§ Wenn für eine Stelle im Programm sowohl die Antwort ”ja"
also auch "nein" möglich ist, dann ist die richtige Antwort
"manchmal".
§ Wenn man sich nicht sicher ist dann ist "Manchmal" eine gute Vermutung
Beispiel 1
public static void mystery(int x, int y) { int z = 0;
// Point A
while (x >= y) { // Point B x = x - y;
z++;
if (x != y) { // Point C z = z * 2;
}
// Point D }
// Point E
System.out.println(z);
}
x < y x == y z == 0
Point A Point B Point C Point D Point E
MANCHMAL MANCHMAL IMMER NIE MANCHMAL MANCHMAL
MANCHMAL NIE NIE
MANCHMAL MANCHMAL NIE
IMMER NIE MANCHMAL
Welche Aussagen sind an diesen Stellen wahr?
Möglich sind IMMER, NIE oder MANCHMAL.
75
Beispiel 2
public static int mystery(Scanner console) { int prev = 0;
int count = 0;
int next = console.nextInt();
// Point A
while (next != 0) { // Point B
if (next == prev) { // Point C
count++;
}
prev = next;
next = console.nextInt();
// Point D }
// Point E return count;
}
next == 0 prev == 0 next == prev
Point A Point B Point C Point D Point E
MANCHMAL IMMER MANCHMAL
NIE MANCHMAL MANCHMAL
NIE NIE IMMER
MANCHMAL NIE MANCHMAL
IMMER MANCHMAL MANCHMAL
Welche Aussagen sind an diesen Stellen wahr?
Möglich sind IMMER, NIE oder MANCHMAL.
Beispiel 3
// Assumes y >= 0, and returns x^y public static int pow(int x, int y) {
int prod = 1;
// Point A
while (y > 0) { // Point B
if (y % 2 == 0) { // Point C x = x * x;
y = y / 2;
// Point D } else {
// Point E
prod = prod * x;
y--;
// Point F }
}
// Point G return prod;
}
y > 0 y % 2 == 0
Point A Point B Point C Point D Point E Point F Point G
Welche Aussagen sind an diesen Stellen wahr?
Möglich sind IMMER, NIE oder MANCHMAL.
y > 0 y % 2 == 0
Point A MANCHMAL MANCHMAL
Point B IMMER MANCHMAL
Point C IMMER IMMER
Point D IMMER MANCHMAL
Point E IMMER NIE
Point F MANCHMAL IMMER
Point G NIE IMMER
Uebersicht
§ 10.0 Beispiel
§ 10.1 Darstellung von Variablen und Objekten
§ 10.2 Assertions
§ 10.3 Preconditions und Postconditions
2
Ziel: Aussagen über ein Programm herleiten
§ Welche Aussagen gelten (an einer Stelle) im Programm?
§ Ggf. was für Annahmen sind nötig, dass die Aussage wahr ist
§ Warum?
§ Finden "interessanter" Fälle für Test
§ Erstellen der Bedingungen, die Klienten erfüllen müssen
§ Behandeln von Sonderfällen in einer Methode
§ Wenn die Liste am Anfang leer ist, dann muss das 1. Element auf diese Weise eingefügt werden.
3
Hoare Logik
§ Tony Hoare entwickelte in den (19)70gern einen Ansatz wie man über Programme logische Schlüsse ziehen kann.
§ Am Anfang betrachten wir nur Zuweisungen, If-Statements, Schleifen und Variable
§ Fürs erste keine Objekte und Methoden
§ Schritt 1: Vorwärts und rückwärts schliessen
§ Schritt 2: Genauere Definition von Aussagen, Vor- und Nachbedingungen
§ Erstmal ohne Schleifen
4Warum
§ Ziel ist es, dass Sie für ein einfaches Programm genau argumentieren können.
§ In der täglichen Programmentwicklung genügt es oft, weniger detailliert zu argumentieren als es die Hoare Logik erforderlich macht.
§ Für einfache Programme ist dieser Ansatz zu aufwändig.
§ Für realistische Progamme wird der Ansatz schnell kompliziert.
§ Wir haben immer noch kein gutes Modell für Objekte und Parallelismus. Aliasing ist eine Herausforderung.
§ Aber manchmal hilft der Ansatz (siehe Fencepost Probleme) 5
§ Aber eine gute Schulung, systematisch zu programmieren
§ Wir können über Zustände (der Ausführung) eines Programms (und später auch eines Objekts) schlussfolgern
§ Wir können den Effekt eines Programms beschreiben
§ Wir können definieren was es heisst dass eine Aussage “weaker”
(schwächer) oder “stronger” (stärker) ist.
§ Wichtig für die Definition von Schnittstellen (zwischen Modulen)
wenn wir entscheiden müssen welche Bedingungen erfüllt sein
müssen (um eine Methode aufzurufen).
6Beispiel
§ Wie finden wir Aussagen für Stellen im Programm
§ Uns interessieren nicht irgendwelche Aussagen sondern solche, die das Verhalten der Ausführung beschreiben
7
Beispiel
§ Vorwärts schliessen
§ Vom Zustand vor der Ausführung eines Programm(segments)
§ Nehmen wir an wir wissen (oder vermuten) w > 0 // w > 0
x = 17;
//
y = 42;
//
z = w + x + y;
// 8
Beispiel
§ Vorwärts schliessen
§ Vom Zustand vor der Ausführung eines Programm(segments)
§ Nehmen wir an wir wissen (oder vermuten) w > 0 // w > 0
x = 17;
// w > 0 ∧ x == 17 y = 42;
// w > 0 ∧ x == 17 ∧ y == 42 z = w + x + y;
// w > 0 ∧ x == 17 ∧ y == 42 ∧ z > 59
§ Jetzt wissen wir einiges mehr über das Programm, u.a.
z > 599Beispiel
§ Rückwärts schliessen:
§ Nehmen wir an wir wollen dass z nach Ausführung negativ ist //
x = 17;
//
y = 42;
//
z = w + x + y;
// z < 0
10
Beispiel
§ Rückwärts schliessen:
§ Nehmen wir an wir wollen dass z nach Ausführung negativ ist // w + 17 + 42 < 0
x = 17;
// w + x + 42 < 0 y = 42;
// w + x + y < 0 z = w + x + y;
// z < 0
§ Dann müssen wir wissen (oder vermuten) dass vor der Ausführung gilt: w < -59
§ Notwendig und hinreichend 11
Vorwärts vs Rückwärts, Teil 1
§ Vorwärts schliessen:
§ Bestimmt was sich aus den ursprünglichen Annahmen herleiten lässt.
§ Sehr praktisch wenn eine Invariante gelten soll
§ Rückwärts schliessen:
§ Bestimmt hinreichende Bedingungen die ein gegebenes Ergebnis garantieren
§ Wenn das Ergebniss erwünscht ist, dann folgt aus den Bedingungen die Korrektheit.
§ Ist das Ergebniss unerwünscht, dann reichen die Bedingungen um einen Bug zu generieren
12
Vorwärts vs Rückwärts, Teil 2
§ Vorwärts schliessen:
§ Simuliert de Ausführung des Programms (für viele “Inputs”
“gleichzeitig”)
§ Oft leicht zu verstehen, erscheint “natürlich”
§ Aber führt dazu dass (viele) Details festgehalten werden, die letztlich irrelevant sind.
13
Vorwärts vs Rückwärts, Teil 3
§ Rückwärts schliessen:
§ Oft von grossem praktischen Nutzen: Sie müssen verstehen (oder festhalten) was jede Anweisung zum Erreichen eines bestimmten Zustandes beiträgt.
§ Ein Programm(segment) ”rückwärts” zu lesen erfordert Uebung aber führt zu einer neuen Sicht auf ein Programm.
14
If-Statement Muster
// initial assumptions if(…) {
// also know test evaluated to true } else {
// also know test evaluated to false }
// either branch could have executed
15
Terminologie
§ Die Annahme (Aussage), die vor der Ausführung eines Programmsegments gilt, ist die Precondition.
§ Die Aussage, die nach der Ausführung gilt (unter der Annahme dass die Aussage davor gültig ist), ist die Postcondition.
16
Grundidee(n)
1. Die Precondition für the then-part und den else-part (eines if- Statements) beinhaltet das Ergebnis des Tests.
2. Die Postcondition nach dem If-Statement ist die Disjunktion (“oder”) der Postconditions des then- und else-parts.
17
Beispiel (Vorwärts)
Nehmen wir an x >= 0 // x >= 0
z = 0;
// x >= 0 ∧ z == 0 if (x != 0) {
// x >= 0 ∧ z == 0 ∧ x != 0 (also x > 0) z = x;
// … ∧ z > 0 } else {
// x >= 0 ∧ z == 0 ∧ !(x != 0) (also x == 0) z = x + 1;
// … ∧ z == 1 }
// ( … ∧ z > 0) ∨ (… ∧ z == 1) (also z > 0) 18
20
Mehr Terminologie
§ Aussagen (Pre/Postconditions) sind logische Ausdrücke die sich auf den Zustand (der Ausführung) eines Programms
beziehen.
§ Der Zustand eines Programms ist sichtbar durch die Namen der Variablen (und jede Variable liefert ihren Wert)
§ Die Variablennamen können in (logischen) Ausdrücken verwendet werden – solange die Ausdrücke keine Nebenwirkungen (“no side- effects”) haben
21
23