Ab einer gewissen Größe ist die Komplexität eines Software-Systems von der Entwicklerin nicht mehr vollständig zu erfassen, wenn sie alle Details des Systems berücksichtigen muß. Indem sie sich von Details des Systems löst, also eine grundsätzlichere Sichtweise des Systems und der zugrundeliegenden Struktur anstrebt, kann sie die Komplexität verringern und das System besser verstehen; die Kommunikation über das System ist einfacher. Sie benutzt dazu die Technik der Abstraktion . Abstraktion, so sagt der Duden, ist das Absondern des Allgemeinen vom Einzelnen.
Beispiel: Bei der Entwicklung eines Compilers wird zunächst die grundlegende Struktur definiert, die einzelnen Elemente -- lexikalische Analyse, Syntaxanalyse, Semantikanalyse, Zwischencode- und Code-Erzeugung, eventuelle Code-Optimierungen und die dazu nötige Symboltabellenverwaltung und Fehlerbehandlung. Wie diese Elemente im Detail realisiert sind, wird zunächst nicht berücksichtigt; schließlich sind ja zum Teil mehrere Realisierungsmöglichkeiten vorhanden, die aber an der grundsätzlichen Struktur eines Compilers nichts ändern.
Ein Ansatz zur Abstraktion ist die Modularisierung . Sie dient zur Aufteilung eines komplexen Programms in eine Reihe von einfacheren Unterprogrammen, deren Zusammenwirken die gleiche Funktion erfüllt. Zur Beschreibung der Funktionsweise des Programms können dann die einzelnen Funktionen der Unterprogramme dienen, wobei die Art und Weise, wie das Unterprogramm seine Funktion realisiert (welcher Algorithmus also verwendet wird), zunächst nicht relevant ist.
Die Modularisierung kann, je nach Komplexität der entstehenden Teilfunktionen, fortgesetzt werden, bis die Realisierung trivial ist. Das Gesamtsystem wird also schrittweise verfeinert , eine in der Praxis sehr verbreitete Methode.
Beispiel: Während der lexikalischen Analyse eines Compilerlaufes wird der Eingabetext in einen Strom von Symbolen umgewandelt, die innerhalb der Programmiersprache eine bestimmte Bedeutung haben (Schlüsselworte, Bezeichner, mathematische oder logische Operatoren usw.). Der Text muß gelesen, die Symbole erkannt und in irgendeiner Weise gespeichert werden. Wie diese drei Teilfunktionen Einlesen, Erkennen, Symbol abspeichern realisiert werden, ist zur Beschreibung der Gesamtfunktion ,,lexikalische Analyse`` unwichtig.
Es gibt allerdings noch eine andere Möglichkeit der Abstraktion. Ein Programm besteht -- vereinfacht -- aus Funktionen und Daten. Die Eingabedaten des Programms werden mit Hilfe der Funktionen verarbeitet, dabei werden Ausgabedaten erzeugt. Die Modularisierung betrifft die Funktionen des Programms, die Datenabstraktion die zu manipulierenden Daten. Für die Realisierung des Programms sind zunächst nur die Operationen Operationen, mit denen die Daten manipuliert werden, notwendig; diese Operationen sind also spezielle Hilfsfunktionen, die von allen Funktionen, die auf die Daten in irgendeiner Form zugreifen, benutzt werden können und sollen. Die internen Strukturen der Datenobjekte müssen daher nicht offengelegt werden! Auch die Beschreibung von Daten ist auf diese Weise vollständig durch ihr ,,Verhalten`` möglich, d.h. durch Informationen, auf welche Weise sie manipuliert werden können.
Beispiel: Die Symboltabelle eines Compilers sammelt Informationen über sämtliche Bezeichner des Programms (Variablen, Konstanten, Funktionsnamen). Die Beschreibung der Symboltabelle ist vollständig mit den notwendigen Operationen möglich (z.B. Erzeugung einer leeren Symboltabelle, Eintreten in einen ,,Block`` der Programmiersprache, Verlassen eines Blocks, Eintragen eines Bezeichners, Test auf Existenz eines Bezeichners, Test gewisser Attribute eines Bezeichners). Welche Informationen gesammelt werden müssen, kann aus den erforderlichen Operationen abgeleitet werden.
Wie erläutert, ist die Modularisierung durch schrittweise Verfeinerung eine verbreitete Methode zur Abstraktion. Die Datenabstraktion ist weniger bekannt, nicht zuletzt deshalb, weil viele Programmiersprachen keine Methoden zur Datenabstraktion anbieten.
Guter Programmierstil ist die Beachtung des ,,Geheimnisprinzips``: Auf einer bestimmten Ebene der Entwicklung ist nur das Verhalten der untergeordneten Funktionen und Daten bekannt, nicht aber die Form der Realisierung (ihre Implementation ); zudem ist auch die Verwendung der auf dieser Ebene entwickelten Funktionen in höheren Ebenen nicht bekannt. Beispiel auf der obersten Betrachtungsebene: ein Compiler verarbeitet einen Text in einer Quellsprache und erzeugt einen Text in einer Zielsprache.
Was sind abstrakte Datentypen
Abstrakte Datentypen
Abstrakte Datentypen