• Keine Ergebnisse gefunden

2.Systematisches Programmieren

N/A
N/A
Protected

Academic year: 2021

Aktie "2.Systematisches Programmieren"

Copied!
20
0
0

Wird geladen.... (Jetzt Volltext ansehen)

Volltext

(1)

Software Engineering II 2. Systematisches Programmieren Martin Glinz Sommersemester 1999 2 - 1

2.Systematisches Programmieren

Inhalt

2.1 Namengebung

2.2 Dokumentieren von Programmen 2.3 Programmstruktur

2.4 Konstruktionsregeln 2.5 Optimierung

2.1 Namengebung

Die Wahl der Namen ist wesentlich für das Verständnis eines Programms:

?? PS_YCRD = PS_XCRD + AD_BRK * AD_BCO

?? y = x + d *b

Was tut die folgende, in MODULA-2 geschriebene Prozedur?

CONST GIGI = 6;

TYPE LOLO = ARRAY [0..GIGI-1] OF CHAR;

PROCEDURE GAGA (VAR GURU: LOLO);

VAR BALA,ZORA:INTEGER;MIMI:CHAR;

BEGIN

BALA := GIGI DIV 2;

FOR ZORA := BALA TO GIGI-1 DO MIMI := GURU[ZORA];

GURU[ZORA] := GURU [GIGI-ZORA-1];

GURU [GIGI-ZORA-1] := MIMI;

END;

END GAGA;

(2)

Software Engineering II 2. Systematisches Programmieren Martin Glinz Sommersemester 1999 2 - 3

Das gleiche Programm mit lesbaren Namen:

CONST

Textlaenge = 6;

TYPE

Zeichenkette = ARRAY [0..Textlaenge-1] OF CHAR;

PROCEDURE Umkehren (VAR Text: Zeichenkette);

(* Kehrt die Reihenfolge der Zeichen im Text um.

Voraussetzung: Text enthält Zeichenkette der Länge Textlaenge.

Ergebniszusicherung: Text[i](neu) = Text[Textlaenge-i-1] für alle 0 <= i <= Textlaenge-1.

*) VAR

Textmitte, Index: INTEGER;

Hilfsplatz: CHAR;

BEGIN (* Umkehren *)

Textmitte := Textlaenge DIV 2;

FOR Index := Textmitte TO Textlaenge-1 DO Hilfsplatz := Text[Index];

Text[Index] := Text [Textlaenge-Index-1];

Text [Textlaenge-Index-1] := Hilfsplatz;

END (* FOR *);

END Umkehren;

Regeln für die Wahl von Namen

Variablennamen bezeichnen ihren Inhalt: NextState, topWindow, brake_coefficient

Prozedur- bzw. Methodennamen bezeichnen ihre Aufgabe: PrintPage, CalculateDelay, Compare_with_limit

Symbolische Konstanten bezeichnen ihren Wert: MaxOpenWindows, DefaultSpeed

Grundtypen werden mit einfachen Namen bezeichnet: File, Table, Speed

Abgeleitete Typen und Komponententypen haben entsprechend zusammengesetzte Namen: SequentialFile, TableIndex, TableValue

Jeder Name hat in seinem Gültigkeitsbereich nur eine Bedeutung

Beispiel: Eine Prozedur berechnet eine Iterationsformel mit einer gegebenen

Schrittweite ∆x. Als Resultate werden das Ergebnis und die Abweichung von einem Referenzwert zurückgegeben.

Es wäre falsch, eine Variable mit dem Namen Delta sowohl für die Schrittweite als

(3)

Software Engineering II 2. Systematisches Programmieren Martin Glinz Sommersemester 1999 2 - 5

Länge von Namen

Grundregel:

Namen mit kleinem Gültigkeitsbereich können kurz sein

Namen mit großem Gültigkeitsbereich müssen selbsterklärend sein

Kurznamen (i, m, y, dx, Rs) demnach nur

für Schleifenindizes in kurzen Schleifen

in einfachen mathematischen Formeln in kurzen Prozeduren / Methoden

Niemals für Prozedur-/Methodennamen oder für Typnamen

Abkürzungen vermeiden: DistanceCounter ist besser als DST_CTR

Groß oder Klein? Zusammen oder getrennt?

Unterschiedliche Konventionen möglich, zum Beispiel:

Jeder Namenbestandteil beginnt mit Großbuchstaben: DefaultInitValue

Typen beginnen immer groß, Variablen immer klein: File (Typ), logFile (Variable)

Namenbestandteile werden durch Unterstreichung getrennt: default_init_value

Sich an die Codierrichtlinien der Organisation, für die man arbeitet, halten

Verwendete Konventionen konsequent durchhalten

(4)

Software Engineering II 2. Systematisches Programmieren Martin Glinz Sommersemester 1999 2 - 7

2.2 Dokumentieren von Programmen

Programmdokumentation ist nicht einfach „Kommentar“

Jedes Stück Code ist dokumentiert

Verwaltungsdokumentation (Autor, Datum,...)

Schnittstellendokumentation (Voraussetzungen, Ergebniszusicherungen, ...)

Deklarationsdokumentation (Bedeutung von Konstanten und Variablen)

Ablaufdokumentation (Verdeutlichen des Algorithmus)

Strukturdokumentation (Statischer Aufbau des Programms; typisch durch Einrücken)

Richtig dokumentieren

Was ist hier falsch? (Beispiele in verschiedenen Programmiersprachen)

if (x > 0) y = sin(x)/x; // negative Werte dürfen nicht bearbeitet werden

u = 2*PI*r; // u = 2πr

i++; // i inkrementieren

WHILE (*t++); /* Ende des Strings suchen. t zeigt danach auf das Byte nach dem String-Terminator */

i := 0; j := 0; c := 0;

REPEAT

IF x[i] = " " THEN INC (c);

ELSE y[j] := x[i]; INC (j); END;

INC (i);

(5)

Software Engineering II 2. Systematisches Programmieren Martin Glinz Sommersemester 1999 2 - 9

Dokumentation und Code müssen übereinstimmen

Kein Nachbeten des Codes

Schlechten Code und Tricks nicht dokumentieren, sondern neu schreiben

Programmstruktur durch Einrücken dokumentieren

Geeignete Namen wählen

Codierrichtlinien beachten

Nicht überdokumentieren

Falscher Code wird durch ausführliche Dokumentation nicht richtig

Beispiel: Ein FORTRAN-Programm (Kernighan, Plauger 1978)

Was ist gut?

Was ist überdokumentiert?

(6)

Software Engineering II 2. Systematisches Programmieren Martin Glinz Sommersemester 1999 2 - 11

2.3 Programmstruktur

2.3.1 Geschlossene Ablaufkonstrukte, GOTO

Alle sequentiellen Programme sind aus den Grundelementen Sequenz, Alternative und Iteration komponierbar (Böhm und Jacopini, 1966)

Jedes Konstrukt ist geschlossen, d.h. es hat genau einen Eintritts- und einen Austrittspunkt

Konstrukte können beliebig aneinandergereiht und verschachtelt werden

“Go To Statement Considered Harmful”

“... we should do (as wise programmers aware of our limitations) our utmost to shorten the

conceptual gap between the static program and the dynamic process, to make the correspondence between the program (spread out in text space) and the process (spread out in time) as trivial as possible.” (Dijkstra 1968)

GOTO bricht bei unbedachter Verwendung die Übereinstimmung zwischen statischer und dynamischer Struktur

GOTO (und Anverwandte, z. B. break in C/C++ und Java) nur unter Erhaltung geschlossener Ablaufkonstrukte

Aber: GOTO-freie Programme sind nicht immer gut strukturierte Programme:

Entscheidend ist, dass die zugrundeliegende Logik klar in Code umgesetzt wird

Manchmal kann ein GOTO ein Programm sogar vereinfachen

(7)

Software Engineering II 2. Systematisches Programmieren Martin Glinz Sommersemester 1999 2 - 13

Beispiel: Vier unterschiedlich strukturierte, funktional äquivalente

1

Programme

// Variante 1: Schlecht strukturiert, aber GOTO-frei int ComputeAResult (int x, int y, int n)

{

boolean a = false, b = false; int z = 0;

for (int i = 1; !a & !b & i <= n; i++) {

a = GetCondition (x, i);

if (!a) b = GetCondition (y, i);

else if (!b) z = 1;

}

if (a) z = Compute (x);

else if (b) z = Compute (y);

else z = Compute (x*y);

return z;

}

1 Faktisch sind die vier Varianten nur unter einer Zusatzbedingung vollständig äquivalent, siehe weiter unten

// Variante 2: Besser strukturiert, aber:

// • komplizierte Schleifenbedingung zur Vermeidung von GOTO // • ineffizient, wenn a und b in allen Schleifendurchläufen falsch sind

// • bei genauem Hinsehen in einem Sonderfall nicht äquivalent mit Variante 1 int ComputeAResult (int x, int y, int n)

{

boolean a = false, b = false; int z = 0;

for (int i = 1; !a & !b & i <= n; i++) {

a = GetCondition (x, i);

if (a) z = Compute (x);

else {

b = GetCondition (y, i);

if (b) z = Compute (y);

else z = Compute (x*y);

} } return z;

}

(8)

Software Engineering II 2. Systematisches Programmieren Martin Glinz Sommersemester 1999 2 - 15

// Variante 3: Effizientere (und wohl auch einfachere) Alternative zu Variante 2, // nach wie vor komplizierte Schleifenbedingung zur Vermeidung von GOTO

int ComputeAResult (int x, int y, int n) {

boolean a = false, b = false; int z = 0;

for (int i = 1; !a & !b & i <= n; i++) {

a = GetCondition (x, i);

b = GetCondition (y, i);

}

if (a) z = Compute (x);

else if (b) z = Compute (y);

else z = Compute (x*y);

return z;

}

Anmerkung: Ein C-Liebhaber würde die Schleife vermutlich so programmieren:

for (int i = 1; !(a = GetCondition (x, i)) & !(b = GetCondition (y, i)) & i <= n; i++);

Was ist das Problem mit diesem Code?

// Variante 4: Die Verwendung von return (d.h. einem GOTO zum Ende der Methode) // ist besser als alle drei GOTO-freien Varianten

int ComputeAResult (int x, int y, int n) {

for (int i = 1; i <= n; i++) {

if (GetCondition (x, i)) return Compute (x);

else if (GetCondition (y, i)) return Compute (y);

}

return Compute (x*y);

}

Hinweis:

In welchem Sonderfall ist Variante 2 nicht funktional äquivalent mit Variante 1?

Wie verhalten sich die Varianten 3 und 4 in diesem Fall?

(9)

Software Engineering II 2. Systematisches Programmieren Martin Glinz Sommersemester 1999 2 - 17

2.3.2 Iteration

DAS PRINZIP DER ITERATION

Wiederholte Ausführung einer Gruppe von Anweisungen in einer Schleife

Vorwärtsberechnung: Resultat wird typisch inkrementell aufgebaut

Schleife muss explizit gesteuert werden: Initialisierung, Abbruchbedingung, Fortschaltung (letzteres nur bei Zählschleifen)

Alle Elemente der Schleifensteuerung sind anfällig auf Fehler KONSTRUKTION KORREKTER SCHLEIFEN

Konstruktion des Schleifenkörpers

Bestimmung einer geeigneten Schleifeninvariante

Schleifeninvariante: Ein Prädikat, das nach jeder Prüfung der Abbruchbedingung wahr ist

Ableitung von Initialisierung, Abbruchbedingung und Fortschaltung aus der Schleifeninvariante

Prüfen, ob die Schleife terminiert

Beispiel: Zu berechnen sei die Summe eines n-elementigen Koeffizientenvektors

• Konstruktionsidee für die Schleife:

double [] vektor; double vektorsumme;

vektorsumme = ?;

for (int i = ?; ? ; ?)

vektorsumme = vektorsumme + vektor[i];

• Schleifeninvariante: vektorsumme =

• Konstruktion von Initialisierung, Abbruchbedingung und Fortschaltung so dass die Invariante wahr ist (und bleibt):

• Fortschaltung: i++

Beweis: Zu Beginn des m-ten Schleifendurchlaufs habe i den Wert p und es gelte vektorsumme = . Berechnet wird im m-ten Schleifendurchlauf mit i = p:

vektorsumme = vektorsumme + vektor[p] = + vektor[p] =

Damit bei der nächsten Prüfung der Abbruchbedingung die Invariante noch gilt, muss i dann den Wert p+1 haben, d.h. i muss im m-ten Durchlauf um 1 erhöht werden.

vektor[k]

k =0

i-1

vektor[k]

k =0

i-1

vektor[k]

k =0

p-1 vektor[k]

k =0

p

(10)

Software Engineering II 2. Systematisches Programmieren Martin Glinz Sommersemester 1999 2 - 19

• Initialisierung: i=0, vektorsumme = 0

Beweis: Nach der ersten Prüfung der Abbruchbedingung muss gelten vektorsumme = = 0. Dies ist bei der üblichen Definition des Summensymbols der Fall: = 0 für alle m < n

Hinweis: Überlegen Sie sich eine andere Initialisierung, welche die Schleifeninvariante ebenfalls erfüllt

• Abbruchbedingung: i < n

Beweis: Beim Schleifenabbruch ist i = n, also vektorsumme = , was genau das gewünschte Resultat ist

• Terminierung:

i wird bei jedem Schleifendurchlauf inkrementiert, n bleibt konstant

⇒ Die Bedingung i < n ist nach endlich vielen Schritten falsch

⇒ Die Schleife terminiert

vektor[k]

k =0

n-1

vektor[k]

k =0

i-1

sk

k =n

m

VERIFIKATION VON SCHLEIFEN

Schleifeninvarianten können auch verwendet werden, um die Korrektheit einer bereits programmierten Schleife zu verifizieren: Sei S eine Schleife und seien

• N ein Prädikat, welches das erwartete Ergebnis von S beschreibt

• V ein Prädikat, das die notwendigen Voraussetzungen für S beschreibt

• b die Abbruchbedingung S

• Inv eine Schleifeninvariante von S

Durch Beweis von (i) V ⇒ Inv (ii) (Inv ∧ ¬b) ⇒ N (iii) S terminiert wird die Korrektheit von S verifiziert

Beispiel: Verifizieren (oder falsifizieren) Sie die Korrektheit folgender Schleife:

double [] vektor; double vektorprodukt;

//ASSERT n > 0 ∧ vektor hat n Komponenten vektorprodukt = vektor [0];

for (int i = 0; i < n ; i++)

(11)

Software Engineering II 2. Systematisches Programmieren Martin Glinz Sommersemester 1999 2 - 21

ABWEISENDE VS. ANNEHMENDE SCHLEIFEN

Abweisende Schleifen (DO-WHILE) prüfen die Abbruchbedingung vor dem Durchlauf durch den Schleifenkörper

Bei a priori nicht erfüllter Schleifenbedingung wird die Schleife nicht durchlaufen

Annehmende Schleifen (REPEAT-UNTIL) prüfen die Abbruchbedingung erst nach dem Durchlauf durch den Schleifenkörper

Unabhängig von der Schleifenbedingung wird der Schleifenkörper mindestens einmal durchlaufen

Falsch, wenn die Schleifenbedingung a priori nicht erfüllt ist

Häufige Fehlerquelle

Abweisende Schleifen sind sicherer als annehmende

Beispiel: Lokalisieren des letzten nicht leeren Zeichens in einer Zeichenkette (in Modula-2) PROCEDURE LokalisiereLetztes (text: ARRAY OF CHAR): INTEGER;

(* Liefert die Position des letzten nicht leeren Zeichens in der Zeichenkette text oder -1, wenn text nur aus Leerzeichen besteht oder gar keine Zeichen enthält

*)

CONST leer = " ";

VAR letztePos: INTEGER;

BEGIN

letztePos := Length (text) - 1;

REPEAT

IF text[letztePos] = leer

THEN letztePos := letztePos - 1;

END (* IF *);

UNTIL (letztePos < 0) OR (text [letztePos] <> leer);

RETURN letztePos;

END LokalisiereLetztes;

Diese Prozedur funktioniert fast immer korrekt. Wann aber versagt sie und warum?

(12)

Software Engineering II 2. Systematisches Programmieren Martin Glinz Sommersemester 1999 2 - 23

2.3.3 Rekursion

DAS PRINZIP DER REKURSION

Mehrfache Ausführung von Anweisungen durch wiederholten Selbstaufruf

Rückwärtsberechnung: Resultat wird durch rekursiven Abstieg gewonnen

Steuerung ist implizit: Nur Reduktion und Verankerung müssen sichergestellt sein

Beispiel: Zu berechnen sei die Summe eines n-elementigen Koeffizientenvektors

• Rekursionsformel:

Mit einer einfachen Substitution (das n-te Element in vektor hat den Index n-1) kann diese Formel direkt programmiert werden:

double Vektorsumme (double [] vektor, int n);

// Berechnet die Summe der Komponenten des Vektors vektor mit n Komponenten int indexDesNten; //Variable programmtechnisch überflüssig; nur zur Verdeutlichung {

indexDesNten = n - 1;

if (n <= 0) return 0;

else return vektor[indexDesNten] + Vektorsumme (vektor, n-1);

x =

Σ

i=1

n

Σ

x

i=1 n-1

x +n

i

i falls n > 0

0 sonst

(13)

Software Engineering II 2. Systematisches Programmieren Martin Glinz Sommersemester 1999 2 - 25

VOR- UND NACHTEILE DER REKURSION

+ Rekursive Lösungen sind einfacher und kürzer als iterative

+ Bei gegebenen Rekursionsformeln ist die Korrektheit viel einfacher zu zeigen als bei Schleifen: Zu verifizieren sind

• die eigentliche Rekursionsformel (reduziert sie korrekt?)

• die Rekursionsverankerung (ist der Startwert korrekt?)

Mehrfachrekursion kann zu Laufzeit- und Speicherplatzproblemen führen Beispiel: Fibonacci-Zahlen fib(1) = fib(2) = 1, fib(n) = fib(n-1) + fib(n-2)

Die Zahl der benötigten Aufrufe zur rekursiven Berechnung von fib (n) wächst mit

wachsendem n stark nichtlinear an (ab n > 3 mehr als fib(n) rekursive Aufrufe), während ein iterativer Algorithmus mit einer Schleife der Länge n auskommt

Für große n ist der rekursive Algorithmus erheblich ineffizienter

Rekursion ist gedanklich schwieriger nachzuvollziehen als Iteration

REKURSION VS. ITERATION

Jede Iteration kann in eine Rekursion transformiert werden und umgekehrt

Die Programmkonstrukte dem Problem anpassen:

Iterativ formulierte Probleme mit Iteration

Rekursiv formulierte Probleme mit Rekursion lösen

Keine Angst vor Rekursion!

(14)

Software Engineering II 2. Systematisches Programmieren Martin Glinz Sommersemester 1999 2 - 27

2.3.4 Fallunterscheidung

Verschachtelte IF-Anweisungen sorgfältig aufbauen

In Verschachtelungen

immer Blockklammern verwenden

IF ohne ELSE-Zweig vermeiden

ELSE IF ist besser als THEN IF

Große Fallunterscheidungen mit SWITCH bzw. CASE-Anweisungen aufbauen

Beispiel: Textcharakteristika ermitteln

String TextCharacteristics (String text, int length, int firstPos, int lastPos);

// PRE

// text Zeichenkette mit n Zeichen

// length Länge der Zeichenkette, d.h. n

// firstPos Index des ersten nicht leeren Zeichens in text // lastPos Index des letzten nicht leeren Zeichens in text

// firstPos und lastPos haben den Wert -1, falls die Zeichenkette leer ist (n=0) oder nur // aus Leerzeichen besteht

//

// POST

// Funktionswert ist ...

// "empty" wenn length = 0

// "oneBlank" wenn length = 1 und nur Leerzeichen // "twoBlanks" wenn length = 2 und nur Leerzeichen // "noText" wenn length > 2 und nur Leerzeichen // "leadingBlanksOnly" wenn firstPos > 0 und lastPos = length-1 // "trailingBlanksOnly" wenn firstPos = 0 und lastPos < length-1

(15)

Software Engineering II 2. Systematisches Programmieren Martin Glinz Sommersemester 1999 2 - 29

{

// Schlechte Struktur if (firstPos = -1)

{

if (length > 0) {

if (length = 1) return "oneBlank";

if (length = 2) return "twoBlanks";

else return "noText";

}

else return "empty";

}

else if (firstPos > 0) {

if (lastPos = length-1) return "leadingBlanksOnly";

else return "leadingAndTrailingBlanks"

}

else if (lastPos < length-1) return "trailingBlanksOnly"

else return "textOnly";

}

Alternative Implementierung der Methode:

{

// Gute Struktur if (length = 0)

{return "empty";}

else if (length = 1 & firstPos = -1) {return "oneBlank";}

else if (length = 2 & firstPos = -1) {return "twoBlanks";}

else if (length > 2 & firstPos = -1) {return "noText";}

else if (firstPos > 0 & lastPos = length-1) {return "leadingBlanksOnly";}

else if (firstPos = 0 & lastPos < length-1) {return "trailingBlanksOnly";}

else if (firstPos > 0 & lastPos < length-1) {return "leadingAndTrailingBlanks";}

else

{return "textOnly";};

}

(16)

Software Engineering II 2. Systematisches Programmieren Martin Glinz Sommersemester 1999 2 - 31

2.3.5 Prozeduren und Methoden

Hierarchie von Abstraktionen in der Strukturierung von Programmen

Maschinenbefehl

Anweisung

Block

Prozedur / Methode

Klasse

Komponente / Modul

Jede Prozedur / Methode realisiert eine Funktion oder in sich geschlossene Teilfunktion

funktionale Kohäsion

Das Strukturierungsmittel für Programmierung im Kleinen

UNTERPROGRAMM – MAKRO – PROZEDUR – METHODE

Unterprogramm

Benanntes, abgegrenztes Programmstück, das unter seinem Namen aufrufbar ist

Beim Aufruf verzweigt die Steuerung zum Unterprogramm und kehrt nach Ausführung des Unterprogramms an die Aufrufstelle zurück

Separater Namensraum und Parameterersetzung

• möglich (FORTRAN, PL/1)

• nicht zwingend (Assemblersprachen, Ur-BASIC, COBOL)

keine Kohäsionsforderungen

Parameterübergabe mit “call by reference”

(17)

Software Engineering II 2. Systematisches Programmieren Martin Glinz Sommersemester 1999 2 - 33

Prozedur

Unterprogramm mit

• eigenem Namensraum und Parameterersetzung

• funktionaler Kohäsion

Aufruf als Anweisung (Anweisungsprozedur; Wertrückgabe über Parameter)

Aufruf in Ausdruck (Funktionsprozedur; Wertrückgabe in Funktionswert)

Statische Bindung an den aufgerufenen Stellen durch Übersetzer

Parameterübergabe mit “call by value”, “call by reference” oder “call by name”

Methode

Wie Prozedur, aber mit dynamischer Bindung an Aufrufer zur Laufzeit

Parameterübergabe teilweise nur mit "call by value"; Referenzierung über Zugriff auf übergebene Objekte (z. B. Java)

Makro

Benanntes, abgegrenztes Programmstück, das unter seinem Namen referenzierbar ist

Bei Referenzierung wird der Makrokörper vom Übersetzer an der Referenzstelle in den Code einkopiert

Parameterersetzung ist möglich

keine Kohäsionsforderungen

Vor allem in maschinennahen Programmiersprachen nützlich

(18)

Software Engineering II 2. Systematisches Programmieren Martin Glinz Sommersemester 1999 2 - 35

2.4 Konstruktion guter Programme

GUT ENTWORFEN

Geeignete, zusammenpassende Algorithmen und Datenstrukturen

Systematischer Entwurf

Sorgfältig

strukturiert: geschlossene Konstrukte, Blockstruktur

und abstrahiert: Prozeduren/Methoden und Parameter im Kleinen, Klassen und Module im Mittleren und Großen

EFFIZIENT UND KORREKT

Entwurf vollständig, korrekt und effizient umgesetzt

Korrektheit durch saubere Konstruktion und durch strenges, argumentativ gestütztes Nachvollziehen zwar nicht bewiesen, aber plausibel dargelegt

LESBAR, VERIFIZIERBAR, ÄNDERBAR

Lesbarkeit vor Schreibeffizienz

Dokumentiert durch Struktur, Namengebung und durch explizite, sorgfältige Dokumentation in Form von Kommentar

Prüfbar und pflegbar

Keine Seiteneffekte oder Tricks

Im Zweifelsfall einfach und direkt

Symbolische Konstanten VERWENDBAR

Schnittstellen definiert und dokumentiert

Angebotene Leistungen

Benötigte Leistungen Dritter

Geregelte Zuständigkeiten und Verantwortlichkeiten

(19)

Software Engineering II 2. Systematisches Programmieren Martin Glinz Sommersemester 1999 2 - 37

SICHER

Defensives Programmieren – “Designed for the unexpected”

Alle möglichen Fehlersituationen erkannt und behandelt, zum Beispiel

• Fehlerhafte Eingabedaten

• Operationen mit ungültigem/undefiniertem Ergebnis

• Nichterfüllung von Aufträgen an Dritte (mit Prozedur / Methodenaufruf)

Vermeidung / zurückhaltende Verwendung / Einkapselung inhärent unsicherer Mittel, zum Beispiel der Bearbeitung von Datenstrukturen mit Zeigern

Vermeidung zweifelhafter Konstrukte

Option zur Prüfung der Voraussetzungen (sollte ausschaltbar sein, da aufwendig)

Alle Voraussetzungen dokumentiert

Verträge eingehalten

Alle Zusicherungen erfüllt

Keine Invarianten verletzt

2.5 Optimierung

Regeln von Jackson:

1. Tu es nicht!

2. Wenn du es dennoch tust oder tun musst, dann tu es später!

Ergänzende Regel von Glinz:

3. Tu es vorher! (Erst denken, dann codieren)

(20)

Software Engineering II 2. Systematisches Programmieren Martin Glinz Sommersemester 1999 2 - 39

Optimieren ist aufwendig, darum

Sich das Optimieren des Codes ersparen durch Wahl guter Datenstrukturen und effizienter Algorithmen (Regel 3)

Code nie auf Verdacht optimieren (Regel 1)

Sondern (Regel 2)

Zuerst messen

Die Flaschenhälse erkennen

Falls nötig, durch gezielte lokale Optimierung die Flaschenhälse beseitigen

Literatur

Berner, S., S. Joos, M. Glinz (1997). Entwicklungsrichtlinien für die Programmiersprache Java.

Informatik/Informatique 4, 3 (Jun 1997). 8-11.

Berner, S., M. Glinz, S. Joos, S. Schett (1998). Java Entwicklungsrichtlinien. Version 2.02. Institut für Informatik, Universität Zürich.

Böhm, C. G. Jacopini (1966). Flow Diagrams, Turing Machines and Languages With Only Two Formation Rules.

Communications of the ACM 9, 5 (May 1966). 366-371.

Dijkstra, E.W. (1968). Go To Statement Considered Harmful. Communications of the ACM 11, 3 (March 1968). 147- 148.

Keller, D. (1990). A Guide to Natural Naming. SIGPLAN Notices 25, 5 (May 1990). 95-102.

Kernighan, B.W., P.J. Plauger (1978). The Elements of Programming Style. New York, etc.: McGraw-Hill

Referenzen

ÄHNLICHE DOKUMENTE

21 Vor dem Schnee ist ihr nicht bange für ihr Haus, denn ihr ganzes Haus ist in Scharlach gekleidet.. 22 Sie macht sich

Ihre Gruppe ist mit Ihrem Text sehr zufrieden, begeistert sich aber eher für einen Ihrer Alternativ-Slogans und gibt Ihnen den Auftrag, sich mit dem Provider auf eine

Seine Präsentation enthält Informationen zum Anwendungsbereich und Inhalt der DSGVO, zu den Ausnahmen für Archivzwecke sowie zu einzelnen Maßnahmen die Archive ergreifen müssen,

§ Wenn wir entscheiden ob eine Aussage falsch oder wahr ist dann müssen wir konservativ sein, d.h..

set( index , value ) replaces value at given index with given value size() returns the number of elements in list. toString() returns a string representation of the list such as

02 BIRCOlight triloc Schlammeimer für Entwässerungsrinnen mit senkrechter Bohrung..

Sollte doch mal ein Beleg verloren gegangen sein, ihr die Zahlung aber bereits via Konto getätigt habt, könnt ihr einen sogenannten Eigenbeleg oder Notbeleg aus- stellen: Ihr

Sofern Sie dieje- nigen Erfahrungen und Beobachtungen, die Sie für eine theoriegestützte Reflexion ausge- wählt haben, noch nicht in Punkt 3 dargestellt haben, sollten Sie diese