Inhalt
|
Anforderung
Was soll der Baustein tun?
Ein Problem aus dem Projektalltag: Anforderungen hatten sich geändert mit der Folge, dass Meldungen zum selben Ereignis zweimal gesendet werden konnten - und dieses Verhalten war unerwünscht.
Meldungen sollten daher eine kurze Zeit aufbewahrt werden, um überprüfen zu können, ob eine Meldung zu einem Ereignis bereits verschickt worden ist.
Ein geflügeltes Wort im Projektalltag war minimal invasiv, was heißen soll, Änderungen seien so vorzunehmen, dass Seiteneffekte möglichst ausgeschlossen werden können. Da liegt ein modularer generischer Baustein nahe, der außerhalb des Softwaresystems entwickelt und und dessen Ablauflogik auch außerhalb des Softwaresystems getestet werden kann.
Entwurf
Was leistet Ada für den Entwurf?
Was muss ich wissen? Ich benötige einen generischen Datentyp Item_Type (Zeile 5), dessen Elemente gepuffert werden sollen, seine Struktur ist im wesentlichen unerheblich - aber ich muss überprüfen können, ob zwei Elemente des Datentyps 'gleich' (Are_Equal, Zeile 10) sind. Und der Datentyp muss Zeitinformationen tragen (Get_Time_Stamp, Zeile 12), denn eine Meldung soll ja nur eine gewisse Zeit (Storage_Duration, Zeile 8) aufbewahrt werden.
Das Paket kommt also mit zwei generischen Funktionen daher (Zeilen 10, 12), ich muss nur ihre Schnittstellen kennen, ihre Implementierung ist unerheblich. Das "is <>" hier weist den Compiler an, bei der Ausprägung des generischen Paketes selbst nach diesen Funktionen zu suchen.
Die Schnittstelle des generischen Pakets
Anwendungsschnittstelle
Die Anwendungschnittstelle weist zwei Routinen auf, mit der Prozedur Add (Zeile 16) schiebe ich ein Element in den Puffer und mit der Funktion Already_Handled (Zeile 18) kann überprüft werden, ob ein Element schon im Puffer vorhanden ist.
Die Ausnahme No_Space_To_Store_Item (Zeile 20) ist eher ein Testhilfsmittel, diese Ausnahme wird ausgelöst, wenn der Puffer voll ist, die zugeordnete Meldung wird in der Implementierung schlicht verworfen.
Implementierung
Was leistet Ada für die Implementierung?
Als Puffer verwende ich eine Booch-Komponente, die die gespeicherten Einträge gleich nach dem Zeitstempel sortiert. Der Zugriff auf den Puffer wird über ein geschütztes Objekt ('protected object') namens Controller (Zeile 25) gesteuert.
Die Schnittstelle des Controllers weist fünf Routinen auf, darunter ist der bewachte Eingang Get_Next_To_Purge (Zeile 31); ist der Puffer leer, muss der Aufrufer dieses Eingangs solange warten, bis ein Eintrag da ist, notiert durch den Wächter des Eingangs (Zeile 36).
Der verwendete Puffer The_Items (Zeile 34) steht im privaten Teil der Objektspezifikation.
Das geschütze Objekt namens Controller
die Schnittstelle
Die Implementierung des Eingangs 'Get_Next_To_Purge' ist kurz und knapp. Der Eingangsaufrufer bleibt wie gesagt solange blockiert, bis der Wächter hinter dem Schlüsselwort when (Zeile 70) den Wert True angenommen hat.
Die Implementierung des Eingangs
'Get_Next_To_Purge'
Die Implementierung der Funktion Already_Handled verwendet die generische Funktion Are_Equal (Zeile 85).
Die Implementierung der Funktion
'Already_Handled'
Den aktiven Teil unseres Moduls übernimmt ein Taskobjekt namens Timed_Purger, dessen Rumpf aus einer Schleife besteht, in der zunächst das älteste Element aus dem Puffer entnommen wird (Zeile 134), dann wird die verbleibende Wartezeit berechnet (Zeile 136), um schließlich zu warten, bis das Element gelöscht werden kann (Zeile 140).
Die Implementierung des Taskobjektes
'Timed_Purger'
Test
Der erste Schritt zum Test
Um das generische Paket testen zu können, müssen für den aktuellen Datentyp (Zeilen 11-14) die generischen Routinen bereitgestellt werden (Zeilen 16-19, 21-25).
Die Ausprägung oder Instantiierung wird in den Zeilen 35-38 vorgenommen.
Die Ausprägung des generischen Paketes
Quellcode
Hinweis: Die Zeilennummern stimmen nicht unbedingt mit denen in den obigen Code-Ausschnitten überein.
• Der Quellcode, gezippt Mein GNAT-Projekt zum Weitermachen
Ada-Compiler
• GNAT-Ada-Compiler von AdaCore
Literatur
Das gute, alte Buch
John Barnes
Programming in Ada 2005
Addison-Wesley, 2006
Alan Burns, Andy Wellings
Concurrent and Real-Time Programming in Ada 2005
Cambridge University Press, 2007
Norman H. Cohen
Ada as a second language
- based on Ada 95
The McGraw-Hill Companies, 1996