Prinzipien der Softwareentwicklung

Werbung
Prinzipien der Softwareentwicklung
Programmieren ist eine Kunst, aber es gibt eine Reihe
von Regeln, die dabei beachtet werden müssen:
Prinzip der Striktheit
Prinzip der Strukturierung
Prinzip der Abstraktion
Prinzip der Lokalität und Geheimhaltung
Prinzip der Annahme der Änderungsnotwendigkeit
. – p.1/19
Striktheit
Striktheit ist u.a. bei folgenden Aufgaben ein Muß:
Zielsetzung (was soll das Programm leisten)
Dokumentation von Beginn des Projekts an
Entwurf (Überlegungen zum Algorithmus)
Umsetzung in Programmcode
. – p.2/19
Strukturierung
Beim Programmentwurf ist zu beachten:
Das Programm muß robust gegenüber falscher
Eingaben und Laufzeitfehlern sein.
Die Ergebnisse müssen nachweisbar korrekt sein.
Der Code muß übersichtlich und erweiterbar sein.
Der Ressourcenverbrauch (Speicheraufwand) muß
minimiert und die Performance optimiert werden.
Dabei treten häufig Zwiespälte auf:
Performance ↔ Erweiterbarkeit
Resourcenverbrauch ↔ Performance
. – p.3/19
Abstraktion
Trennung von wichtigen und unwichtigen Merkmalen zum
Zweck der “Wegabstraktion” der letzteren ermöglicht
Vereinfachungen des Algorithmus
Reduzierung der Entwicklungszeit
Erweiterung des Anwendungsbereiches
Erhöhung der Leistungsfähigkeit
Beispiel: Es soll ein Modell eines Kanals erstellt werden
wichtig
unwichtig
- Fließgeschwindigkeit
- Insekten/Blätter auf der
- Form der Kanalbegrenzung
Wasseroberfläche
- Hindernisse (Brücken)
- Wassertemperatur
. – p.4/19
Lokalität und Geheimhaltung
Lokalität
Funktionen greifen – soweit möglich – nur auf die
mit ihnen verbundenen Daten zu, so daß keine
unkontrollierbaren Seiteneffekte auftreten.
Geheimhaltung
Funktionen zeigen ihre internen Daten nicht nach
außen. Dann können lokale Variablen auch nicht von
außen unabsichtlich geändert werden.
Interner Aufbau von Funktionen ist nach außen nicht
erkennbar. Wird der interne Aufbau einer Funktion
nachträglich verändert / verbessert, beeinträchtigt
dies das restliche Programm nicht.
. – p.5/19
Änderungsnotwendigkeit
In der Regel unterliegt ein Softwareprodukt einer stetigen
Veränderung mit dem Ziel
... erkannte Fehler zu korrigieren.
... bestehende Software-Routinen in Bezug auf ihr
Laufzeitverhalten zu optimieren.
... neue Module zu schreiben, um das Programm
mit zusätzlichen Möglichkeiten zu erweitern.
Denn: Softwareentwicklung ist kein typischer
Fertigungsprozeß, sonder verläuft zyklisch!
Dieser Zyklus ist meistens nicht endlich ;-)
. – p.6/19
Strukturiertes Programmieren
Tipps zur Entwurfsphase:
Der Übersichtlichkeit halber sollte der erste Entwurf als
Flußdiagramm oder als Pseudocode geschrieben werden.
Der Entwurf soll (evtl. von Kollegen) kritisch bewertet
und im weiteren Verlauf ggf. nachgebessert werden.
Es muß überlegt werden, welche Datenstrukturen für die
konkrete Problemstellung am besten geeignet sind.
Das Softwareprodukt sollte modular aus Unterroutinen
aufgebaut werden, die kleine Teilprobleme lösen.
Literaturrecherchen und Internetsuche nach passenden
Algorithmen/Software-Komponenten zahlen sich aus.
. – p.7/19
Strukturiertes Programmieren
Tipps zur Entwicklungsphase:
Der Code sollte strikt dem Entwurf entsprechen. Falls
dieser nicht zu realisieren ist, muß unbedingt der
Entwurf überarbeitet werden.
Das Programm sollte möglichst lesbar und verständlich
sein (auch nach mehreren Jahren sollte man noch in
der Lage sein zu verstehen, was der Code macht.)
Programmierarbeiten sind schrittweise durchzuführen,
so daß jeder Teil einzeln getestet werden kann.
Es sollte auf bestehende (bewährte) Algorithmen und
Softwarebibliotheken zurückgegriffen werden.
Defensives Programmieren
erspart oft die Fehlersuche.
. – p.8/19
Programmieren mit MATLAB
Modularität und Performance: schrittweiser Aufbau aus
Unterroutinen für Teilaufgaben mit Verwendung von
optimalen Datenstrukturen und Speicherzugriffen
Vorbelegung/Initialisierung von großen Matrizen
Vektorisierung und matrixorientierter Programmierung
laufzeitoptimierten MATLAB-Funktionen und -Toolboxen
effizienter Programmsteuerung (Schleifen nur dort
einsetzen, wo sie zwingend notwendig sind)
Ressourcenverbrauch: Minimierung des erforderlichen
Speicheraufwandes mit allen Mitteln!
. – p.9/19
Programmieren mit MATLAB
Sicherheit: Vermeidung von Programmabstürzen und
falschen Ergebnissen durch ...
Überprüfung von Ein- und Ausgabeparametern
Abfangen von Fehlern, die während der Rechnung
auftreten können, mit Hilfe von try/catch
eindeutige Namensgebung und – sofern möglich –
keine Verwendung von globalen Variablen
Sonstige Anforderungen:
Benutzerfreundlichkeit (Hilfe, Dokumentation, GUI)
Lesbarkeit (Kommentare, Leerzeichen, Einrückung)
Orientierung beim Programmieren an den gängigen
Richtlinien zum Layout von M-Files
. – p.10/19
Struktur von M-Files
Ein M-File soll folgende Informationen enthalten:
Name und Typ (Skript oder Funktion)
H1-Zeile mit einer Kurzbeschreibung
Informationen zur Syntax, ggf. Beispiele
Beschreibung von Ein- und Ausgabeparametern
Default-Einstellungen für evtl. fehlende Daten
Gültigkeitsbereich, bekannte Einschränkungen
Liste von Unterroutinen, die aufgerufen werden
Autor(en), Version, Datum der letzten Änderung
Ausführliche Kommentare im Quelltext!!!
. – p.11/19
Kommentare im Quelltext
Kommentare müssen während des Programmierens
geschrieben werden, nicht danach
Quelltext und Kommentare müssen übereinstimmen.
Darauf ist besonders bei Modifikationen zu achten
Kommentare sollten kurz, verständlich und lesbar sein
(mit Leerzeichen, Großbuchstaben, Einrückung)
Ausdrücke wie A+B benötigen keine nähere Erklärung!
Jeder Kommentar im Quelltext muß zählen
Ein schlecht konzipierter oder fehlerhafter Code kann
nicht allein durch Kommentare verbessert werden ;-)
Ein übersichtlicher Code mit Kommentaren kann von
vielen Leuten benutzt und ggf. ausgebaut werden
. – p.12/19
Namensgebung und Performance
Variablennamen sollten aussagekräftig sein, d.h. in der
Regel aus mehr als einem Buchstaben bestehen.
Variablen können durch einheitliche Namensgebung
sowie Groß- und Kleinschreibung strukturiert werden.
Namen aus dem MATLAB-Vokabular sollten nicht für
eigene Variablen und Funktionen verwendet werden
Funktionen werden schneller ausgeführt als Skripte
Zeiten werden mit tic/toc bzw. cputime gemessen
Mit Hilfe des Profilers findet man rechenzeitintensive
Programmteile, die optimiert werden müssen
Nicht bzw. schlecht vektorisierbare Algorithmen können
als MEX-Files in Fortran oder C implementiert werden
. – p.13/19
Speicherverwaltung in MATLAB
Dynamische Vergrößerung von Matrizen ist untersagt;
diese sollten mit zeros oder ones vorbelegt werden
Dünnbesetzte Matrizen sollten als solche behandelt
werden, um den Speicheraufwand zu reduzieren
Aufgrund der komprimierten Darstellung von sparse
Matrizen ist der Zugriff auf ihre Elemente langsamer
MATLAB speichert die Elemente eines Spaltenvektors
hintereinander ab, so daß ein sehr schneller Zugriff
möglich ist. Zeilenvektoren werden nicht hintereinander
abgespeichert, so daß für jeden Eintrag eine
kostspielige Indexberechnung notwendig ist.
Variablen, die nicht mehr gebraucht werden, sind mit
dem Befehl clear aus dem Workspace zu löschen
. – p.14/19
Flexibilität und Sicherheit
Funktionen lassen optionale Parameter und variable
Parameterlisten varargin bzw. varargout zu
Die Parameterzahl für den aktuellen Funktionsaufruf
läßt sich mit nargin bzw. nargout feststellen
Funktionen können so geschrieben werden, daß sie
sowohl Zeilen- als auch Spaltenvektoren als Parameter
akzeptieren: x=x(:) bzw. x=x(:).’
Kommandos wie eval und feval bieten eine große
Flexibilität erschweren aber die Fehlersuche
Voraussehbare Laufzeitfehler lassen sich durch evtl.
geschachtelte try/catch Blöcke abfangen
Der MATLAB-Debugger ermöglicht eine schrittweise
Programmanalyse und erleichtert die Fehlersuche
. – p.15/19
Fehlersuche: logische Fehler
Der Interpreter von MATLAB ist nur in der Lage,
syntaktische Fehler zu finden. Inhaltliche Fehler muß der
Programmierer selbst erkennen und beseitigen.
Bei einer if-Anweisung kann die falsche Verzweigung
gewählt werden
if x < 0
y = sqrt(x);
else
warning(’x darf nicht negativ sein.’);
end
Bei der Betrachtung von mehreren Bedingungen muß
auf die logische Hierarchie geachtet werden
(y =0 | z =0) & x>=0 (help precedence)
. – p.16/19
Fehlersuche: Schleifen
Falsche Initialisierung der Iterationsvariablen bzw. des
logischen Ausdruckes bei while-Schleifen
Fehlende oder nicht erfüllbare Abbruchbedingung
(keine Erhöhung des Zählers) bei while-Schleifen
while n<100
...
n=n+1 % Darf nicht fehlen
end
Falsche Anzahl der Schleifendurchläufe, Schrittweite
oder Zählrichtung (aufwärts, abwärts) bei for-Schleifen
Falsche Anwendung von Kommandos break und
continue, insbesondere bei geschachtelten Schleifen
. – p.17/19
Fehlersuche: Matrixoperationen
Benutzung von mehrdimensionalen Feldern ohne
Überprüfung ihrer tatsächlichen Dimension, z.B.
ein Funktionsaufruf mit einem Skalar anstelle einer
Matrix, die als Eingabeparameter erwartet wird.
Zugriff auf Feldeinträge, die außerhalb der zulässigen
Dimensionen liegen.
v=[1;2;3];
c=v(4);
??? Index exceeds matrix dimensions.
Verwechslung von Zeilen- und Spaltenvektoren
Falsche logische Indizierung für Teilmatrizen
Fehlerhafte Ein- und Ausgabe von Daten
. – p.18/19
Testaufgabe “Ringelwurm”
Die Dermatophytose (Ringelwurmkrankheit) ist eine durch
Pilzinfektion hervorgerufene Hautkrankheit. Der Verlauf
einer Infektion läßt sich folgendermaßen modellieren:
Ein Hautareal wird durch eine n × m-Matrix symbolisiert, jeder
Matrixeintrag ist eine Hautzelle. In einem Zeitschritt kann jede infizierte
Hautzelle eine der acht Nachbarzellen mit Wahrscheinlichkeit p ∈ ] 0, 1 [
infizieren. Nach i Zeitschritten wird eine infizierte Zelle wieder gesund;
sie ist dann immun für j weitere Zeitschritte.
Aufgabenstellung: Schreiben Sie eine MATLAB-Funktion,
die auf den Parametern n, m, p, i, j eine Infektion simuliert,
die mit einer infizierten Zelle in der Mitte der Matrix beginnt.
Idee und Implementierung: Prof. Dr. Jörg Fliege
. – p.19/19
Herunterladen