| |
|
SOFTWARE |
|
|
|
|
|
Teilprobleme übersichtlich darzustellen sind. Da für
jeden Programmteil Eingabegrößen, Ausgabegrößen und
der Lösungsweg bereits feststeht - diese sind schon im
Entwurf festgelegt worden -, wird die "trickreiche"
Programmierung weitgehend verhindert.
Durch strukturierte Programmierung allein kann man noch
keine Zuverlässigkeit erreichen. Es ist schließlich
auch möglich, die dümmsten Programme sauber zu
strukturieren. Aber durch die Strukturierung ist es sehr
einfach Prüf- und Testalgorithmen einzufügen. Weiterhin
kann die Datensicherung und der Wiederstart von
Programmen durch definierte Übergänge zwischen den
Programmteilen (Modulschnittstellen) erleichtert werden.
Benutzerfreundlichkeit
Für den gegebenen Benutzerkreis stellt das Programm
keine zu hohen Anforderungen von der Ein- und Ausgabe
her, die Fragen sind dem Benutzer verständlich;
unvollständige Eingaben resultieren in Nachforderungen;
Fehlermeldungen sind im Klartext und geben Hinweise auf
die Behebung des Fehlers (also nicht "ERROR EXIT
05 AT 5476777", sondern "FEHLER IN
UNTERPROGRAMM NULLSTELLE WEGEN DIVISION DURCH 0").
Flexibilität
Wenn sich ein neuer Benutzerwunsch ergibt, so bedeutet
das im allgemeinen eine Änderung im Programm. Bei einem
gut strukturierten Programm beschränkt sich die
Änderungsarbeit meist auf nur wenige Teilprobleme
(Anpaßbarkeit, Adaptibilität). Bei
nicht strukturierten Programmen traten bei den
Änderungen oft Fehler an ganz anderen Stellen im
Programm auf, weil dort beispielsweise Variablen für
einen völlig anderen Zweck verwendet wurden.
Andererseits soll
es möglich sein, ohne große Schwierigkeiten die
Hardware zu wechseln (Übertragbarkeit, Portabilität).
Lesbarkeit
Wenn Sie sich daran gewöhnt haben, die Programme
"von unten nach oben", das heißt, erst den
Anweisungsteil des Hauptprogramms und dann die
Unterprogramme zu lesen, erhalten Sie für jedes
Teilproblem eine kurze Beschreibung, die die Lösung des
Problems in übersichtlicher Form enthält. Für Details
wird auf Unterprogramme verwiesen, die die Teilprobleme
in analoger Weise behandeln. Für die Lesbarkeit von
Programmen ist also entscheidend, daß
- aussagekräftige Namen verwendet werden,
- relativ kurze Unterprogramme und Programmteile
geschrieben werden,
- viele Kommentare im Text stehen und
- jeder Programmteil sauber strukturiert ist
(einrücken, siehe später).
Die Punkte 2 und 4 sind Ergebnisse der strukturierten
Programmierung; Punkte 1 und 3 stellen ein
"ungeschriebenes" Gesetz dar. Lesbarkeit ist Voraussetzung
für Wartbarkeit.!
Effizienz
Die Effizienz kann unter der Strukturierung insofern
leiden, daß C-Programme redundanter sind als z. B. in
Assembler geschriebene und strukturierte Programme
redundanter sind als nicht strukturierte. Gegenüber den
Vorteilen, die sich bei Änderungen ergeben und in Bezug
auf die Sicherheit des Ablaufs bei der Ausführung der
Programme spielen die Effizienzverluste kaum noch eine
Rolle. (Es wird hier von den Problemen bei der
Echtzeitverarbeitung von Daten abgesehen, wo die
Effizienz eine dominierende Rolle spielt.)
Das Programm kann an der benötigten Laufzeit und an den
Speicheranforderungen gemessen werden. Auf dieses
Kriterium darf aber erst dann geachtet werden, wenn eine
fertige Version des Programms vorliegt, die allen
anderen Anforderungen genügt. Erst dann können
zusätzliche Effizienzverbesserungen, ausführlich
erläutert, toleriert werden.
Es ist klar, daß solche Anforderungen besondere Methoden der
Programmentwicklung notwendig machen. Die Programmentwicklung
beginnt nicht mit der Programmierung, sondern, wie bereits unter Problem und Lösungen (6.html) erwähnt, schon lange vorher, die
Programmierung ist eine der letzten Stufen der
Programmentwicklung. Zuerst muß das programmtechnisch zu
lösende Problem genau analysiert werden. Diese Problemanalyse
ist auch wieder in einzelne Phasen unterteilt, die wir im
folgenden kurz umreißen wollen. Zuerst wird die gegebene
Situation genau untersucht, wobei die Wünsche für die EDV und
die Einsatzmöglichkeiten der EDV festgehalten werden
(Istanalyse). Ausgehend von der Beschreibung der Probleme wird
dann eine Beschreibung der Lösungen für den Anwender und eine
Aufgabendefinition für den Hersteller der Software erstellt
(Sollkonzept). Nun wird festgestellt, ob es möglich ist, eine
derartige Aufgabe überhaupt zu lösen (technische
Durchführbarkeit) und ob die gefundenen Lösungen wirtschaftlich
sind (ökonomische Durchführbarkeit). Die optimale
Lösungsmethode wird vervollständigt (Projektplanung).
Der Aufwand der Vorarbeiten zu einem Programm ist natürlich
von der Größe des Projekts abhängig, das Planungsprinzip ist
aber auch auf kleine Programme anwendbar. Auf jeden Fall sollten
die Aufgabenstellung, die Lösungsmethoden, die Benutzerwünsche,
die Qualifikation der Benutzer und die im Rahmen der
Problemanalyse zu Tage getretenen Argumente schriftlich fixiert
werden.
In diesem Kapitel können wir Sie mit theoretischen
Betrachtungen nicht ganz verschonen, aber gerade die in diesem
Kapitel unternommenen Betrachtungen sind sehr wichtig für die
praktische Programmierarbeit.
Es wurden schon kurz Fehler erwähnt, die sich bei der
Erstellung großer Programme einschleichen. Damit Ihnen später
nicht das gleiche passiert, wird Ihnen im folgenden Abschnitt
gezeigt, wie das Problem und nachher das Programm strukturiert
und modularisiert, das heißt in kleinere Teile zerlegt wird. Die
Strukturierung wird von C durch das Sprachkonzept unterstützt
und gefördert. Im Rahmen der Projektplanung wird die Aufgabe des
Programms beschrieben, über die Entwicklung des Programms wollen
wir hier sprechen. Anhand eines Beispielprogramms wird
demonstriert, wie Sie von der Aufgabenstellung durch schrittweise
Verfeinerung des Problems schließlich zu einem fertigen Programm
kommen. Die Vorgehensweise -der schrittweisen Verfeinerung- ist
immer dieselbe, egal wie groß das Programm wird:
Das Problem wird in einzelne Teilprobleme zerlegt. Dies
können Funktionen sein oder aber auch sog. Objekte
(Gegenstände). Die Kunst ist es die Zelegung derart intelligent
zu gestalten, daß die Teilprobleme möglichst nicht voneinander
abhängen (Prinzip der starken lokalen Bindung) und das
Teilproblem in sich alleine -ohne Zuhilfenahme der Lösung
anderer Teilprobleme der gleichen Zerlegungsstufe- zu lösen ist
(Prinzip der möglichst losen Koppelung). Diese so gefundenen
Teilprobleme werden weiter zerlegt (verfeinert) bis die einzelnen
Verfeinerungsstufen so wenig umfangreich sind, daß sie
problemlos programmiert werden können (Top-Down-Design). Diese
Methode sichert sauber strukturierte und verifizierbare Programme
(später: Objekte), wenn Sie die folgenden Grundregeln beachten.
- Jeder Zerlegungsschritt sollte auf einer, höchstens zwei
DIN-A4-Seiten beschrieben werden. Die Beschreibung
besteht aus:
- den erforderlichen Voraussetzungen
- den nachzuprüfenden Anforderungen
- der Zerlegung in Teilprobleme
- einer algorithmischen Beschreibung des
Zusammenhangs der Teilprobleme
- Alle Teilprobleme sollen etwa den gleichen Umfang
besitzen.
- Eine klare Gliederung muß den Überblick garantieren. In
der folgenden Abbildung ist die Zerlegung in Teilprobleme
skizziert. Wie Sie sehen, zeichnet sich eine Struktur von
einzelnen Verfeinerungsstufen oder Schichten ab.
Unter einer solchen Schicht können Sie die
Beschreibung des Problems in einem bestimmten
Abstraktionsgrad verstehen. Sie können sich auch
vorstellen, daß auf jeder Schicht ganz bestimmte,
abstrakte Grundoperationen existieren. Wenn Sie sich zum
Beispiel an den Kreisalgorithmus aus dem ersten Kapitel
zurückerinnern, so existiert in einer Schicht die
Operation der Multiplikation, in der nächstniedrigeren
gibt es die Multiplikation nicht mehr, sondern nur noch
die Addition.
Die Grundoperationen werden von Schicht zu Schicht
nach unten einfacher. Sie bewegen sich so von sehr
abstrakten und komplexen Konstruktionen zu konkreten
Operationen. In der Informatik wird eine Schicht als
abstrakte Maschine aufgefaßt, also als ein gedachter
Computer, der alle Operationen der entsprechenden
Detaillierungsstufe beherrscht. Aus diesem
Gedankenkonzept folgt sofort, daß auch die Verfeinerung
schichtweise geschehen soll. Eine Schicht sollte daher
erst vollständig aufgebaut sein, bevor die nächste
Verfeinerung in Angriff genommen wird. Diese
Vorgehensweise hat einen sehr wesentlichen Vorzug, denn
alle Teilprobleme haben etwa den gleichen
Abstraktionsgrad und ungefähr den gleichen Umfang. Es
kann also nicht vorkommen, daß Sie sich einerseits um
die Optimierung eines Algorithmus bemühen, während Sie
in einem anderen Teilproblem noch nach dem Lösungsweg
suchen. Oder Sie stellen fest, daß ein Teilproblem der
Stufe zwei unlösbar ist, während der Rest bereits
völlig fertig ist.
Jedes Teilproblem hat einen gewissen Abstraktionsgrad, der
für alle Probleme etwa gleich ist. Wenn Sie an die Teilprobleme
gewisse Anforderungen stellen, wird die Korrektheit des Entwurfs
überprüfbar; man sagt, das Programm ist dann verifizierbar. Die
Verifizierbarkeit eines Programms ist wohl die wichtigste Folge
der strukturierten Programmierung. Die Beschreibung eines
Teilproblems besteht aus
- den benötigten Voraussetzungen
- den abzuliefemden Ergebnissen
- dem Algorithmus zur Lösung des Problems auf der Basis von
Grundoperationen und Operationen, die Probleme der
nächstniedrigeren Schicht darstellen.
Aus dieser Beschreibung lassen sich dann die Voraussetzungen
und Anforderungen für die Probleme der nächsten Schicht
definieren.
Ein derart beschriebenes Teilproblem wird Programm-Modul, kurz
Modul genannt. Ein Modul hat also Eingänge (die
Voraussetzungen), Ausgänge (die Ergebnisse) und eine genau
festgelegte Funktion rnit definierten Operationen.
Zum Schluß dieses Abschnitts wollen wir noch einige
Bemerkungen zu den "Programming Standards" machen. Das
sind Vorschriften und Regeln, an die sich alle an einem Projekt
beteiligten Programmierer zu halten haben. Diese Regeln können
Länge und Komplexität von Unterprogrammen betreffen, sie
können Bezeichnungskonventionen oder Schreibweisen betreffen
oder auch Regeln für die Erstellung von Kommentaren sein.
Ein Beispiel für einen einfachen "Programming
Standard" wäre: "Ein Unterprogramm soll höchstens
eine DIN-A4-Seite umfassen. Namen beginnen mit "K-",
falls es sich um Konstante handelt. Zu jedem Unterprogramm wird
im Kommentar am Anfang des Unterprogramms der Verfasser, das
Herstellungsdatum, die Änderungsdaten und eine genaue
Beschreibung der Parameter festgehalten. Jeder Sprung ist
ausführlich zu kommentieren."
Solche Regeln dienen der übersichtlichen Gestaltung von
Programmen und damit auch wieder der Lesbarkeit. In unseren
Beispielen folgen wir auch einem gewissen Standard (wenn auch
nicht sklavisch) durch Einrücken der einzelnen Strukturelemente.
Diese optische Wiederholung der Programmstruktur bringt eine
erhebliche Verbesserung der Übersichtlichkeit und so bessere
Lesbarkeit. Grundgedanke bei der Erstellung der
Einrückungsregeln war, daß Anweisungen, die von anderen
Anweisungen kontrolliert werden, um eine feste Anzahl von Spalten
eingerückt werden.
|
| |
|
|
|