1 / 24

Robustheit

Seminar aus Softwareentwicklung: Programmierstile. Robustheit. Christian Zeilinger ch.zeilinger@gmx.at. Übersicht. Einführung und Beispiele von Softwarefehler Was bedeutet „Defensives Programmieren“ Design by Contract Erfolgreiches Verwalten von Resourcen Self-Describing Data

sanjiv
Download Presentation

Robustheit

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Seminar aus Softwareentwicklung: Programmierstile Robustheit Christian Zeilinger ch.zeilinger@gmx.at

  2. Übersicht • Einführung und Beispiele von Softwarefehler • Was bedeutet „Defensives Programmieren“ • Design by Contract • Erfolgreiches Verwalten von Resourcen • Self-Describing Data • Die Kunst des Testens Robustheit, Christian Zeilinger (ch.zeilinger@gmx.at) Folie 2/23

  3. ! ! Einführung Leider Tatsache: Es gibt keine perfekte Software! Also, was tun? Sich damit abfinden, oder gar verzweifeln? Robustheit, Christian Zeilinger (ch.zeilinger@gmx.at) Folie 3/23

  4. SO NICHT!!! Die schlimmsten Softwarefehler • 1985: Software-Fehler in einem Röntgenapparat • 1996: Explosion der Ariane 5 am 4. Juni • 1999: Verglühen eines Mars Climate Orbiters • Rechtzeitig gefundener Fehler: F-16 T+36: Fehler im Inertial Reference System Hauptcomputer weist Triebwerke an, eine große Korrektur durchzuführen Rakete bricht aufgrund aerodynamischer Kräfte auseinander (Selbstzerstörung) Robustheit, Christian Zeilinger (ch.zeilinger@gmx.at) Folie 4/23

  5. Defensives Programmieren Definition Robustheit: Fähigkeit von Softwaresystemen, auch unter außergewöhnlichen Bedingungen zu funktionieren Defensiv zu programmieren bedeutet, die Programme in Hinblick auf Robustheit zu gestalten Deshalb: Alle Annahme über Eingaben, Systemzustände usw. prüfen und bei Fehlern handeln (Assertions, Exceptions,…) Zum Beispiel: „Die Variable x muss hier positiv sein“ „Dieser Zeiger darf hier (eigentlich) nicht NULL sein“ Robustheit, Christian Zeilinger (ch.zeilinger@gmx.at) Folie 5/23

  6. Design by Contract • Bedingungen, die gelten müssen, damit ein System funktionieren kann • Beispiel im realen Leben: Paketzustelldienst Bedingungen der Zustellfirma: • maximale Größe und Gewicht des Paketes • Bezahlung der Dienstleistung im Voraus Bedingungen von Seiten des Klienten: • Sorgfältiger Umgang mit der Fracht (keine Beschädigungen,…) • Ankunft des Gutes am gewünschten Zielort innerhalb einer gewissen Zeitspanne Robustheit, Christian Zeilinger (ch.zeilinger@gmx.at) Folie 6/23

  7. Design by Contract • Preconditions Bedingungen, die gelten müssen, damit eine Methode (Komponente) ausgeführt werden kann • Postconditions Bedingungen, die nach dem Ausführen einer Methode gelten müssen (impliziert auch Resultate) • Invarianten Bedingungen, die aus Sicht des Rufers immer erfüllt sein müssen Beispiele: Class-Invarianten, Loop-Invarianten „Lazy Code“ Robustheit, Christian Zeilinger (ch.zeilinger@gmx.at) Folie 7/23

  8. Design by Contract /* class invariant: * count enspricht der Anzahl der gesetzten Integer-Werte array ist ein Feld von Werten * die gesetzt werden können, wobei jeder noch nicht gesetzter Wert -1 entspricht. */ public class IntegerArray { ………………… public int Max { get { int max = -1; /* Loop-Invariante: * Vor jedem Durchlauf gilt: max = max(array[0:i-1]) (auch nach dem Ende der Schleife)*/ for(int i=0; i < array.Length; i++) if(array[i] > max) max = array[i]; return max; } } public int this[int index] { get { return array[index]; } // Precondition: 0 <= index < size set { array[index] = value; /* Nach der Ausführung dieser Anweisung ist die Klasseninvariante * verletzt, da count ungleich der der Anzahl der gesetzten Werte*/ count++; //Erst jetzt gilt die Klasseninvariante wieder } // Postcondition: Wert gesetzt } …………………… } Robustheit, Christian Zeilinger (ch.zeilinger@gmx.at) Folie 8/23

  9. Design by Contract Überprüfung der Kontrakte • Mit Hilfe von Tools Tool für Java: iContract (im Kommentar: @pre, @post, @invariant) • Assertionen Methodenaufruf mit Übergabe der Bedingung - Beispiel: assert(x > 0); Bedingung erfüllt: okay Bedingung verletzt: Fehler -> Programmabbruch • Exceptions Sprachliche Unterstützung, um mit einfachen Mitteln: • dem Rufer einen Ausnahmefall mitzuteilen (throw) • ein (kollektives) Errorhandling zu bewerkstelligen (try …… catch) Robustheit, Christian Zeilinger (ch.zeilinger@gmx.at) Folie 9/23

  10. Design by Contract Assertions using System.Diagnostics.Debug; public class IntegerArray { ………………… public int this[int index] { get { Debug.Assert(index >0 && index < array.Length);//Prüfung der Precondition return array[index]; } set { Debug.Assert(index >0 && index < array.Length);//Prüfung der Precondition array[index] = value; count++; } } public IntegerArray(int size) { Debug.Assert(size > 0);//Prüfung der Precondition array = new int[size]; for(int i=0; i<size; i++) array[i] = -1; } } Robustheit, Christian Zeilinger (ch.zeilinger@gmx.at) Folie 10/23

  11. Design by Contract Exceptions #include <stdio.h> //without Exceptions int main() { int xMin, xMax, yMin, yMax, error = 0; FILE *file = fopen("file.cfg", "rb"); if (f != NULL) { error = 1; } else if(xMin = fgetc(file) == EOF) { error = 1; } else if(xMax = fgetc(file) == EOF) { error = 1; } else if(yMin = fgetc(file) == EOF) { error = 1; } else if(yMax = fgetc(file) == EOF) { error = 1; return -1; } if (error == 0) { printf("%d,%d,%d,%d", xMin,xMax,yMin,yMax); } else printf("Error reading file.cfg"); fclose(file); } using System; //using Exceptions using System.IO; class Test { static void Main() { int xMin, xMax, yMin, yMax; try { FileStream str = new FileStream("file.cfg", FileMode.Open); xMin = str.ReadByte(); xMax = str.ReadByte(); yMin = str.ReadByte(); yMax = str.ReadByte(); Console.WriteLine("{0},{1},{2},{3}", xMin,xMax,yMin,yMax); } catch(IOException) { Console.WriteLine("Error reading file.cfg"); } finally { //Code der in jedem Fall ausgeführt wird str.Close(); } } } Robustheit, Christian Zeilinger (ch.zeilinger@gmx.at) Folie 11/23

  12. Resource-Balancing • Hauptspeicher, Threads, Dateien, Timer,… sind limitiert • Verhaltensmuster: allocate – use – deallocate using System.IO; class Budget { FileStream fileStr = null; void ReadBudget(string fileName, out int budget) { fileStr = new FileStream(fileName, FileMode.Open, FileAccess.ReadWrite); budget = (new BinaryReader(fileStr)).ReadInt32(); } void WriteBudget(int budget) { fileStr.Seek(0, SeekOrigin.Begin); (new BinaryWriter(fileStr)).Write(budget); fileStr.Close(); } public virtualint Update(string fileName, int newBudget) { int oldBudget; ReadBudget(fileName, out oldBudget); //Altes auslesen WriteBudget(newBudget); //Neues schreiben return newBudget; } } class NewBudget : Budget { public override int Update(string fileName, int newBudget) { int oldBudget; ReadBudget(fileName, out oldBudget); if (newBudget > 0) { //nur mit positiven neuem Budget überschreiben! WriteBudget(newBudget); return newBudget; } return oldBudget; } } Robustheit, Christian Zeilinger (ch.zeilinger@gmx.at) Folie 12/23

  13. Resource-Balancing Finish What You Start! using System.IO; class Budget { protected void ReadBudget(FileStream fileStr, out int budget) { budget = (new BinaryReader(fileStr)).ReadInt32(); } protected void WriteBudget(FileStream fileStr, int budget) { fileStr.Seek(0, SeekOrigin.Begin); (new BinaryWriter(fileStr)).Write(budget); } public virtual int Update(string fileName, int newBudget) { int budget; FileStream fileStr = new FileStream(fileName, FileMode.Open, FileAccess.ReadWrite); ReadBudget(fileStr, out budget); //Altes Budget auslesen if (newBudget > 0) { WriteBudget(fileStr, newBudget); //eventuell mit neuem Budget überschreiben budget = newBudget; } fileStr.Close(); return budget; } } Robustheit, Christian Zeilinger (ch.zeilinger@gmx.at) Folie 13/23

  14. Self-Describing Data Problem: Mysteriöse Daten! Linux-Verzeichnisausgabe mittels „dir“: total 44-rw-r--r--   1 pr17     pr          4810 Dec  4 14:37 ETRC-rw-r--r--   1 pr17     pr          4810 Dec  4 14:36 ETRC.BAKdrwxr-xr-x   2 root     root         512 Oct 24  2001 TT_DB-rw-r--r--   1 pr17     pr             0 Dec  4 17:02 out.txtdrwxr-xr-x   3 pr17     pr           512 Dec  4 14:19 rounddrwxr-xr-x   2 pr17     pr           512 Nov  7 15:12 testdrwxr-xr-x   2 pr17     pr           512 Dec  4 14:25 traces1drwxr-xr-x   2 pr17     pr           512 Dec  4 14:29 traces2drwxr-xr-x   2 pr17     pr           512 Dec  4 14:33 traces3drwxr-xr-x   2 pr17     pr           512 Nov 12 17:35 ueb13drwxr-xr-x   2 pr17     pr           512 Nov 20 16:51 ueb24drwxr-xr-x   2 pr17     pr           512 Dec  3 15:35 ueb32drwxr-xr-x   2 pr17     pr           512 Dec  3 17:43 ueb33drwxr-xr-x   2 pr17     pr           512 Dec  4 12:30 ueb42drwxr-xr-x   3 pr17     pr           512 Dec  4 12:17 ueb43 ??? Kundendaten: Hans Maier, 03/04/1976, 02/07/2001, 01/12/2002, 20 Christoph Huber, 01/02/1979, 01/01/2000, 11/02/2002, 10 Hannes Dorfer, 09/09/1958, 01/01/2000, 01/01/2002, 5 Linux-Prozessübersicht mittels: ps –ef | grep pr17 pr17 26763     1  0 17:00:58 ?        0:00 /system/apps/gup/bin/lamd -H 140.78.91.1 -P 59246 -n 0 -o 0pr17 26809 26739  0 17:04:16 pts/2    0:00 -tcshpr17 26802 26801  0 17:03:19 ?        0:00 /usr/local/bin/tcsh -c sftp-serverpr17 26739 26737  0 17:00:48 pts/2    0:00 -tcshpr17 26804 26802  0 17:03:19 ?        0:00 sftp-server Robustheit, Christian Zeilinger (ch.zeilinger@gmx.at) Folie 14/23

  15. Self-Describing Data • Name-Value Pairs: Daten + Schema Beispiel: Kundendaten %name „Hans Maier“ %birthday „03/04/1976“ %firstTransaction „02/07/2001“ %discountStartDate „01/12/2002“ %discountPercent 20 %name „Christoph Huber“ ……… Speichereffizienz? Robustheit, Christian Zeilinger (ch.zeilinger@gmx.at) Folie 15/23

  16. Self-Describing Data • Komprimierte Speicherung von Name-Value Pairs Beispiel: Kundendaten naHans Maier|bi03/04/1976|ft02/07/2001|ds01/12/2002|di20 naChristoph Huber| ......... Zusatzinformationen in einem Data Dictionary: ABBREVIATION NAME UNIT na name text bi birthday date ft firstTransaction date ds discountStartDate date di discount percent • Herkunft der Daten und Geschichte von Veränderungen Wer? Wann? Wieso? Robustheit, Christian Zeilinger (ch.zeilinger@gmx.at) Folie 16/23

  17. Self-Describing Data • Name-Value Pairs in der Programmierung Bsp.:AddProduct(1001, „C# and .NET Reference“, 5, 29.90, 20, 10); Was bedeuten die einzelnen Werte? • Programmierdisziplin (Kommentare): AddProduct( 1001, //Produktnummer „C# and .NET Reference“, //Bezeichnung 5, //Stückzahl 29.90, //Verkaufspreis netto 20, //Mehrwertsteuer (in %) 10); //maximaler Rabatt • Sprachliche Unterstützung AddProduct(pNr = 1001, name = „C# and .NET Reference“, count = 5, price = 29.90, MWSt = 20, discount = 10); Robustheit, Christian Zeilinger (ch.zeilinger@gmx.at) Folie 17/23

  18. Die Kunst des Testens • Fehler gefunden -> Test war erfolgreich • Ging alles gut -> Erfolgloser Test Testen bedeutet: Ein Programm mit der Absicht auszuführen, Fehler zu finden! Testen kann NICHT zeigen, dass ein Programm fehlerfrei ist. Robustheit, Christian Zeilinger (ch.zeilinger@gmx.at) Folie 18/23

  19. Die Kunst des Testens Teste während der Codeerstellung • Testen im Software-Lebenszyklus • Test der Spezifikation • Modultest • Integrationstest • Systemtest • Abnahmetest • Systematisch Testen • inkrementelles Testen • beginnend mit den einfachen und grundlegenden Teilen • Welchen Output erwartet man sich? • Vergleich verschiedener Implementierungen • Coverage? Robustheit, Christian Zeilinger (ch.zeilinger@gmx.at) Folie 19/23

  20. Die Kunst des Testens White-Box-Testing vs. Black-Box-Testing ? ? Robustheit, Christian Zeilinger (ch.zeilinger@gmx.at) Folie 20/23

  21. Die Kunst des Testens • Abklären, was getestet werden soll z.B.: Methode: String ToUpperCase(String str, int startIndex, boolean unicode); • Wahl geeigneter Inputs • Äquivalenzklassen str: null, im ASCII-Code, im Unicode; unicode: true, false startIndex < 0, 0 <= startIndex < N, startIndex >=N • Randbereiche startIndex: -1, 0, 1, N-2, N-1, N; str: null, 1-Zeichen, 2-Z., N-Zeichen • Reduktion der Testeingaben „unmögliche“ Kombinationen: str.length == 0 und unicode == true nur für einen Parameter eine ungültige Äquivalenzklasse wählen • Festlegen der erwarteten Ausgabe • Durchführen des Test • Vergleich der Ausgabe mit der erwarteten Robustheit, Christian Zeilinger (ch.zeilinger@gmx.at) Folie 21/23

  22. Die Kunst des Testens • Testautomation • Code-Review • Erzeugung von Eingabewerten • Generische Daten • Intelligente Daten • Stress-Tests • Regressionstesten • Testabbruch • wenn bestimmte Anzahl von Fehlern entdeckt wurde • 1 Fehler / 10-25 Anweisungen • Es bleiben immer Restfehler!!! • wenn bei gleichmäßiger Testanstrengung die Fehlerentdeckungsrate deutlich abnimmt Robustheit, Christian Zeilinger (ch.zeilinger@gmx.at) Folie 22/23

  23. Zusammenfassung • Defensives Programmieren steigert die Robustheit von Softwareprodukten • Design by Contract trifft Aussagen über notwendige Bedingungen zur Ausführung von Software • Korrektes Resource-Balancing ist von hoher Notwendigkeit • Selbstbeschreibende Daten helfen bei der Analyse und tragen zum allgemeinen Verständnis bei • Ausreichende Tests sind der Schlüssel zu robusten Programmen Robustheit, Christian Zeilinger (ch.zeilinger@gmx.at) Folie 23/23

  24. Danke für die Aufmerksamkeit!

More Related