7. Programmeinheiten | ||||||
|
||||||
7.11.3 Kind-Pakete
Syntaktisch wird ein Paket zu einem Kind-Paket erklärt, indem der Name des Kind-Pakets mittels "." (Punkt) an den Namen des bereits existierenden Vater-Pakets angefügt wird.
Applikationen lassen sich oft in logische Einheiten unterteilen, die zusammen eine gemeinsamen Aufgabe lösen. Können diese logischen Einheiten (unter Beibehaltung der logischen Struktur) auch in programmiertechnische Einheiten überführt werden, so vereinfacht sich das Erstellen komplexer und umfangreicher Applikationen. Ada bietet die Möglichkeit, solche logischen Einheiten in eigenständigen Paketen mittels des Konzeptes von sogenannten Kind-Paketen zusammenzufassen. So bleibt der Zusammenhang gewahrt bei gleichzeitigem Zugriff aller Kind-Pakete untereinander. Das Ergebnis sind hierarchische Bibliotheken. Das Paket an oberster Stelle der Hierarchie wird Vater oder auch Wurzelpaket genannt, untergeordnete Pakete, Kind-Pakete und Kind-Pakete untereinander werden Geschwister-Pakete genannt. Insgesamt ergibt sich eine Hierarchie von Paketen, kurz Pakethierarchie. Vorhandene Applikationen, die nicht verändert werden sollen oder nicht verändert werden können, lassen sich durch Anfügen von Kind-Paketen erweitern. Solche Erweiterungen beeinträchtigen die Zuverlässigkeit der vorhandenen Applikation nicht, nur ihr Funktionsumfang wird vergrößert. Pflege und Änderung lassen sich so mit geringerem Aufwand betreiben. Der entscheidende Vorteil bei diesem Konzept ist, daß das Kind-Paket vollen Zugriff auf den privaten Teil der Spezifikation seines Vaters hat. Dieser Zugriff ist allerdings so eingeschränkt, daß das Kind-Paket weder direkt noch indirekt den privaten Teil seines Vaters offenlegen kann. Kind-Pakete erlauben es, Applikationen - a priori (von vornherein) zu strukturieren und - a posteriori (im nachhinein) wiederzuverwenden. Die a priori - Strukturierung Applikationen zeichnen sich oft durch eine Vielzahl von logisch unterschiedlichen Sub-komponenten aus, die in ihrer Gesamtheit die Implementierung bilden. Diese Subkomponenten gruppieren Funktionen und Prozeduren, so daß sich die Struktur der Applikation einfacher überblicken läßt. In Ada lassen sich solche Subkomponenten mittels Kind-Paketen verwirklichen. Beispiel: Ein gerichteter Graph besteht aus Ecken und Kanten. Die Kanten weisen von einer Ecke zu einer anderen. Ein solcher gerichteter Graph kann in folgende Pakete zerlegt werden:
Beide Kind-Pakete haben Zugriff auf den privaten Teil der Spezifikation von "gerichter_graph" und damit auf die Implementierung der als privat deklarierten Typen "graph", "ecke" und "kante". Für diese Implementierung eines gerichteten Graphen soll keine Ecke als erste ausgezeichnet sein, wichtig ist nur, daß mit den Iteratoren alle Ecken und Kanten angesteuert werden. Daher ist auch der Parametermodus "in out", denn der Graph muß sich merken, welche Ecke die letzte war bzw. welche schon ausgegeben wurden. Die a priori - Addition Das in "A-priori-Strukturierung" angegebene Beispiel eines gerichteten Graphen führt nur die Basisfunktionen und -prozeduren auf, die notwendig sind, um auf den drei privaten Typen "graph", "ecke" und "kante" zu operieren. Für bestimmte Anforderungen an gerichtete Graphen können allerdings weitere Funktionen notwendig werden, je nachdem, was mittels eines gerichteten Graphen realisiert werden soll. Diese können durch einfaches Hinzufügen weiterer Kind-Pakete implementiert werden. Beispiel: Für zwei Ecken aus einem gerichteten Graphen ist nicht unerheblich zu wissen, welches der kürzeste bzw. längste Weg (ohne eine Ecke doppelt zu enthalten) von einer Ecke zu einer anderen ist. Für das Versenden von Briefen oder Paketen sind kürzeste Wege sinnvoll. Bei anderen Anwendungen ist wichtig zu wissen, (gleichgültig welchen Weg die Nachricht -durch den Graphen nimmt- nimmt), über wieviele Ecken die Nachricht maximal laufen kann. Das bestimmt die maximale Verweildauer einer Nachricht. Dazu muß die Anzahl der Ecken des längsten Weges bestimmt werden. Solche Anforderungen lassen sich mittels Kind-Paketen an bestehende Pakete anfügen, ohne daß diese verändert und damit wieder getestet werden müssen. Das bestehende Paket benötigt keine Informationen (es braucht nicht verändert zu werden) über das Kind-Paket. Das bestehende Paket "weiß" überhaupt nicht, daß ein Paket als Kind-Paket angefügt wird. Es kann auch weiterhin für sich alleine genutzt werden.
In diesem Beispiel wird nicht berücksichtigt, daß es mehrere kürzeste bzw. längste Wege geben kann. Es sei ausreichend, einen zu kennen. Natürlich ist es auch möglich, schon bestehende Kind-Pakete zu erweitern. Beispiel: Die Frage, ob ein Graph einen anderen als Subgraph enthält, kann durch ein Kind-Paket zu "gerichteter_graph.selektoren" beantwortet werden.
Das Kind-Paket "gerichteter_graph.selektoren.sub_graph" erweitert das Paket, das die Selektoren enthält, um eine weitere Funktion. Dabei ist es unwesentlich, daß das Selektoren-Paket selber ein Kind-Paket ist. Das Paket "...sub_graph" hat wie sein Vater vollen Zugriff auf die privaten Typen des Wurzelpaketes "gerichteter_graph". Um zu verhindern, daß durch Kind-Pakete der private Teil des Vater-Pakets offengelegt werden kann, sind folgende Zugriffe nicht erlaubt:
Ein Kind-Paket benötigt keine "With"-Klausel, damit das Vater-Paket für das Kind-Paket sichtbar ist. Diese Sichtbarkeit ist implizit gegeben. Ebenso gilt, daß, wenn ein Kind-Paket z. B. einem Unterprogramm bekannt gemacht wird, dieses Unterprogramm damit Zugriff auf die Spezifikation des Vater-Pakets erhält. Wird dem Unter-programm aber das Vater-Paket bekannt gemacht, so hat das Unterprogramm damit keinen Zugriff auf die Spezifikationen von Kind-Paketen. Die Verwendung von "use" für Kind-Pakete, um z. B. einem Unterprogramm direkten Zugriff auf alle Operatoren zu ermöglichen, impliziert nicht den direkten Zugriff auf die des Vater-Pakets. Das Vater-Paket müßte zusätzlich mit "use" aufgeführt werden. Die erlaubten bzw. möglichen Zugriffe lassen sich durch die Vorstellung erklären, daß alle Kind-Spezifikationen Teil der Spezifikation ihres Vaters wie auch die Kind-Rümpfe Teile des Vater-Rumpfes sind. Kind-Pakete können als privat deklariert werden. Für private Kind-Pakete gilt:
Beispiel: Abhängig von der Implementierung eines Graphen ("A-priori-Strukturierung", Paket "gerichteter_graph") kann ein privates Paket Unterprogramme zur Verfügung stellen, die auf zusätzlichen Typen operieren. Denn ein Paket "gerichteter_graph" wird auf Typen (z. B. Mengentypen als Container für Ecken und Kanten) aufsetzen, die von anderen Paketen zur Verfügung gestellt werden. Diese sollten, um sie austauschbar zu halten, möglichst geringen Einfluß auf die Implementierung des gerichteten Graphen selber nehmen.
Das Schlüsselwort "private" verhindert den Zugriff von außen auf die Spezifikation. Alle Geschwister haben dagegen freien Zugriff. |
||||||
|