Erfahrungen mit dem objektorientierten Datenbanksystem O2

Jutta Göers, Fachbereich Mathematik/Informatik, Universität Osnabrück

Objektorientierte Systeme, speziell auch Datenbanksysteme (OODBS), sind heute in aller Munde. Man fragt sich, ob es sich lohnt, vom ``altbewährten'' Relationalen Datenbanksystem auf ein objektorientiertes umzusteigen, und welches der am Markt angebotenen das geeignetste ist. Letztere Frage kann einem erst der praktische Einsatz des Systems beantworten. Der vorliegende Artikel beschreibt die Erwartungen und Erfahrungen, die an der Universität Osnabrück mit dem OODBS O2 gemacht wurden.

gc

Das objektorientierte Datenbanksystem O2 und sein gleichnamiges Datenmodell wurden urspünglich vom Altar Research Konsortium konzipiert, welchem INRIA , Siemens-Nixdorf, Bull, CNRS und die Universität Paris angehören. In einem Fünfjahres-Projekt, von 1986 bis 1991, wurde dann das O2-System entwickelt. Ende 1990 wurde die Firma O2 Technology gegründet, welche heute das System kommerziell vertreibt.

Einige der Wissenschaftler, die an der Entwicklung von O2 beteiligt waren, gehören zu den Autoren des MANIFESTO s [1]. Diese Abhandlung beschreibt die Bestandteile eines objektorientierten Datenbanksystems, wobei die Bestandteile in unbedingt notwendige, strittige, optionale und offene gegliedert sind.

So ist der Anspruch, den man als Benutzer an das O2-System stellt, natürlich hoch: Man erwartet, daß alle (nach dem MANIFESTO ) unbedingt notwendigen Eigenschaften in O2 realisiert sind, die strittigen ebenfalls, und von den optionalen möglichst viele. Um es vorwegzunehmen: Die meisten Bestandteile sind wie erhofft in O2 realisiert, nur nicht immer so, wie man es erwartet ...

Nach allgemeinen Hinweisen zur Installation und zum Start von O2 werden wir die erwarteten Eigenschaften und ihre Realisierung näher betrachten.

Am Anfang war die Installation

Die Installation von O2 ist kurz und einfach. Nach dem Herunterladen und Auspacken vom Band muß (leider von Hand) pro Lizenz ein Schlüssel in eine .KEYS-Datei eingetragen werden. Diese Schlüssel sind vorher bei O2 Technology unter Angabe der Rechner, die als O2-Server fungieren sollen, anzufordern. Die gekauften Lizenzen können beliebig auf Server und Clients verteilt werden.

Dieses, und die Tatsache, daß man die Server-Client-Aufteilung unter Anforderung neuer Schlüssel schnell ändern kann, ist für unseren bisherigen Einsatz von O2, nämlich der gleichzeitigen Entwicklung vieler kleiner Projekte, sehr zum Vorteil gewesen. Es stellte sich nämlich heraus, daß bei einem Server mit vielen Clients auf letzteren nicht gleichzeitig neue Schemadefinitionen stattfinden konnten, da sie sich gegenseitig gemeinsame Daten(bereiche) sperrten. So arbeitete jedes Projekt auf einem eigenen O2-Server.

Nachdem man einige Umgebungsvariablen gesetzt und eine Initialisierungsroutine durchlaufen hat, kann man O2 schon mit einem Demo-System starten. Für (spätere) eigene Systeme muß jeweils ein selbst zu vergebender Systemname in einer systems-Datei bekanntgemacht werden. In dieser Datei gibt man zu jedem System beispielsweise auch an, wieviel Platz für die Log-Datei oder temporär für große Transaktionen reserviert werden soll. Begrenzt man hier den Platz für die eigentlichen Anwendungsdaten nicht, so stehen bis zu 80 % des freien Speicherplatzes zur Verfügung. In systems regelt man ebenfalls, ob gleichzeitiger Zugriff mehrerer Benutzer erlaubt ist und ob Abort und Recovery möglich sind.

Nun kann man O2 auch mit eigenen Systemen starten ...

Die ``12 Gebote''

Im folgenden wollen wir die unbedingt notwendigen Eigenschaften, im MANIFESTO als Gebote formuliert, näher betrachten:

Thou shalt support complex objects

-- an dieses grundlegende Gebot hält sich O2 natürlich. Neben den bekannten atomaren Typen integer, char, boolean und real stellt O2 strings und bits (Bitstring mit beliebigen Byte-Inhalten) zur Verfügung. An komplexen Typen findet der Benutzer tuple, list, set und unique set, die sich beliebig schachteln lassen. Sehr hilfreich sind einige vordefinierte Klassen, die vom O2-Kit angeboten werden und wie Typen benutzt werden können: Date, Text, Bitmap, Image und weitere zur Definition eigener Dialogboxen. Zu diesen Klassen gibt es gleich eine ganze Reihe von Methoden (zum Beispiel add_days(Tagesanzahl), diff(Datum) bei der Klasse Date), die einen vernünftigen Einsatz ermöglichen und erleichtern.

Thou shalt support object identity

-- eine Eigenschaft, die objektorientierte Systeme auszeichnet. Objektidentität kann über einen logischen oder einen pysikalischen Identifikator realisiert werden. O2 hat sich für die (zugriffs)effizientere Lösung entschieden: Der Objektidentifikator ist eine pysikalische Referenz auf den Speicherbereich des Objekts. Wird ein Objekt (später) an anderer Stelle im Speicher abgelegt, so verweist ein Zeiger vom ursprünglichen Speicherbereich auf den neuen Aufenthaltsort. Dieser Zeiger wird, wenn nötig, aktualisiert, so daß ein Zugriff auf ein Objekt maximal 2 Plattenzugriffe benötigt: einen auf den (ursprünglichen) Speicherbereich und evtl. einen zweiten zum Durchgreifen auf das Objekt.

Thou shalt encapsulate thine objects

-- wer nicht will, muß es aber nicht. In O2 kann man selbst entscheiden, ob man nur über Methoden auf Objekte zugreifen läßt oder direkten Zugriff auf Attribute erlauben will. Letzteres ist möglich, indem man public (les- und schreibbare) oder read-only-Attribute definiert. Zum Glück ist die Voreinstellung private, sonst gäbe es manche Überraschungen ...

Thou shalt support types or classes

-- O2 unterstützt gleich beides. Mit

o2 Person p;
o2 type (Person) q;

wird eine Variable p für ein Objekt der Klasse Person definiert und eine Variable q für einen Wert (Instanz eines Typs), der dieselbe Struktur hat wie Personenobjekte. Typen werden bei Klassendefinitionen und Methodenspezifikationen ebenso benutzt wie zur Definition von Variablen. Ihre Instanzen haben aber im Gegensatz zu Objekten zum Beispiel keine Identität.

Thy classes or types shall inherit from their ancestors

-- in O2 gilt dies gleichermaßen für Typen und Klassen. Der Subtyp bzw. die Subklasse kann dabei dieselben Attribute, mehr Attribute oder bei einzelnen Attributen speziellere Attributtypen haben. Subklassen können auch weitere Methoden besitzen und geerbte überschreiben:

class Person
type tuple(nachname: string;
           vorname:  string;
           alter:    integer;
           photo:    Bitmap;
          )
method zeige-photo
end

class Angestellter
       inherit Person
type tuple(position:  string;
           gehalt:    real;
          )
method erhoehe-gehalt,
       zeige-photo
end

Mehrere Vaterklassen sind in O2 erlaubt, wir werden Mehrfachvererbung aber erst später betrachten.

Thou shalt not bind prematurely

-- tut O2 auch nicht, sondern immer erst zur Laufzeit. Erst dann wird bei gleichnamigen Methoden entschieden, welche denn nun ausgeführt werden soll: die Implementierung von zeige-photo der Klasse Angestellter oder der Klasse Person. Soll für einen Angestellten myang bewußt die Implementierung der Klasse Person ausgeführt werden, so kann dies über

myang->Person@zeige-photo

realisiert werden.

Thou shalt be computationally complete

-- ein wirklich nicht leicht zu erfüllendes Gebot. Damit ein System abgeschlossen bzgl. aller Berechnungen ist, müßte das Ergebnis einer jeden Datenbankoperation eine gültige Datenbankinstanz sein, und alle Operationen dürften beliebig geschachtelt werden. Die allseits bekannte Sprache SQL ist damit nicht ``computationally complete''.

Die Anfragesprache O2SQL ist allerdings erheblich mächtiger als SQL . So sind geschachtelte SELECT-FROM-WHERE-Statements nicht nur im WHERE-Teil möglich, sondern auch im SELECT- und FROM-Teil erlaubt. Das Ergebnis einer Anfrage ist (fast) immer eine Menge, zum Beispiel eine Menge von Objekten, von Werten oder von Tupeln. Nur bei Anfragen, in denen eine Sortierung vorgenommen wird, erhält man als Ergebnis eine Liste. Entsprechend sind auf Anfrageergebnisse auch ``nur'' diejenigen Operationen anwendbar, die auf dem entsprechenden Typ (Menge oder Liste) definiert sind.

Folgende (wenn auch wenig sinnvolle) Anfrage gibt ein Tupel mit Vor- und Nachnamen desjenigen Mitarbeiters aus, der den lexikographisch kleinsten Vornamen hat:

first(
select(tuple(v: p.vorname,
             n: p.nachname))
from p in (
  sort c in Mitarbeiter
  by c.vorname)
)

Thou shalt be extensible

-- dies versucht O2 insofern zu sein, als daß man aus den vordefinierten Typen eigene, beliebig komplexe Typen zusammensetzen und sie mittels

create type neuer_name:
     komplexer_typ

benennen kann. Dieser neue Typ kann dann wie alle vordefinierten Typen verwendet werden. Mittels

delete type neuer_name

kann der Typname wieder entfernt werden, der Typ allerdings, der ja eventuell schon zur Konstruktion weiterer Typen eingesetzt wurde, bleibt bestehen.

Thou shalt remember thy data

-- es wäre auch schade, wenn dies nicht der Fall wäre. In O2 macht man Objekte und Werte persistent, indem man sie benennt. Nur benannte Objekte (das können ja auch Mengen von Objekten sein) und benannte Werte überleben den erfolgreichen Abschluß einer Transaktion. Sollen zum Beispiel alle Mitarbeiter einer Firma persistent gespeichert werden, so definiert man

name Mitarbeiter:
     set(Angestellter);

und fügt einen neuen Mitarbeiter durch folgende Anweisungen ein:

o2 Angestellter a=
     new Angestellter;
a->nachname="Hurtig";
a->vorname="Hermann";
a->alter=35;
a->photo=photo_hermann;
a->position="Kurier";
a->gehalt=4050.0;

Mitarbeiter +=set(a);

In der letzten Anweisung findet eine Mengenvereinigung statt: Der Mitarbeitermenge wird eine Menge mit einem Element, nämlich dem neuen Mitarbeiter, hinzugefügt.

Da O2 mit O2Look auch eine graphische Benutzerschnittstelle bietet, kann das Anlegen neuer (persistenter) Objekte mit der vordefinierten Methode edit auch erheblich benutzerfreundlicher durchgeführt werden. Führt man

o2 Angestellter a=
     new Angestellter;
if (a->edit == SAVE)
     Mitarbeiter +=set(a);

als Transaktion aus, so erhält man zum Einfügen neuer Mitarbeiter das in Abbildung 1 gezeigte Eingabefenster.

Abbildung 1: Eingabefenster für neue Objekte der Klasse Mitarbeiter

Thou shalt manage very large databases

-- zum Bewältigen sind Hilfen erlaubt. So kann der Systemadministrator über Umgebungsvariablen Einfluß darauf nehmen, wieviel Speicher dem O2-Serverprogramm oder den Benutzern bei ihren Anwendungen als Puffer zur Verfügung steht. Voreingestellt ist ein Puffer von 2 MByte, der aber bei großen Datenbanken zu knapp wird.

Der Benutzer selbst kann über (auch mehrfache) Indexvergabe das Antwortzeitverhalten für Standardanfragen beeinflussen, ein Vorteil, der sich besonders bei großen Datenmengen bemerkbar macht. Wird auf die Mitarbeiter zum Beispiel meist über ihren Nachnamen zugegriffen, so erzeugt man mit

create index Mitarbeiter
    on nachname

einen passenden Index. Das Schlüsselattribut muß immer ein Tupelattribut sein, kann aber beliebig tief in der Struktur der Objekte ``versteckt'' sein.

Thou shalt accept concurrent users

-- das möchte und macht O2 auch, nur nicht immer zur Zufriedenheit der Benutzer. Arbeiten mehrere Benutzer auf dem gleichen Datenbankserver, so ist ein vernünftiges Arbeiten nur möglich, wenn sie ihre Schemata zu unterschiedlichen Zeiten angelegt haben -- und damit die Schemainformation auf unterschiedlichen Seiten abgelegt ist. Ein gleichzeitiges Anlegen mehrerer Schemata führt zu der Situation, daß ein Benutzer (der schnellste) Seiten sperrt und die anderen warten müssen, bis er seine Transaktion (mit commit) beendet hat, um dann möglichst am schnellsten zu sein. Hier ist O2 auf jeden Fall gefordert, Abhilfe zu schaffen!

Thou shalt recover from hardware and software failures

-- sonst könnte man Probleme bekommen. In O2 läßt sich für jedes O2-System in der systems-Datei bestimmen, ob Multiuserbetrieb, Rollbacks und Recovery unterstützt werden sollen. Für Recovery wird das sog. ``write ahead logging'' eingesetzt, wobei im Log-Volume für jedes Objekt ein ``Redo-Log'' mitgeschrieben wird. Nach einem Crash wird dann über das Rollback der Zustand vom letzten commit wiederhergestellt.

Thou shalt have a simple way of querying data

-- denn manchmal muß es schnell gehen. O2 bietet verschiedene Wege zu Ad-hoc-Anfragen. Hat man O2 im Textmodus, also ohne graphische Benutzerschnittstelle, gestartet, so schaltet man mittels query in die O2SQL-Anfrageshell und kann dort seine SQL -Anfrage eingeben. Im Graphikmodus kann man mit Hilfe des O2-Shell-Buttons ebenfalls in die in Abbildung 2 gezeigte O2-Shell wechseln.

Abbildung 2: O2-Shell-Editor der graphischen Oberfläche

Im Shell-Editor wird dann die Ad-hoc-Anfrage eingegeben und unter dem Menüpunkt Query gestartet. Der Benutzer hat dabei noch die Auswahl, ob das Ergebnis textuell (im Output-Feld) oder graphisch dargestellt werden soll.

Strittige Eigenschaften

Betrachten wir nun die strittigen Eigenschaften, die (leider) nicht mehr als Gebote im MANIFESTO formuliert sind.

Sichtdefinition

-- ein Konzept, welches implizit unterstützt wird. So kann man zum einen eine private (Basis-) Klasse anlegen und von ihr Sohnklassen ableiten, die jeweils unterschiedliche öffentliche Methoden haben und damit unterschiedliche Sichten auf die Basisklasse ermöglichen. Zum anderen lassen sich Sichten (als virtuelle Instanzen) durch Anfrageausdrücke generieren. Dem Benutzer wird dann nicht die Originalklasse, sondern nur das Anfrageergebnis zur Verfügung gestellt.

Die folgende Anfrage liefert eine Teilmenge aller Mitarbeiter, die als eingeschränkte Sicht dem Benutzer zur Verfügung gestellt werden kann:

o2 set(Angestellter) teilmenge;
o2 real money=3000.0;

o2query(teilmenge,
        "select t
         from t in Mitarbeiter
         where t.gehalt < $1",
        money);

Datenbankentwurfswerkzeuge

-- stellen ein sehr hilfreiches Konzept dar. O2 unterstützt den Benutzer beim Entwurf mit einer recht intuitiven Benutzerschnittstelle namens O2Tools.

Abbildung 3: Startfenster der graphischen Oberfläche von O2

Unter dem Startfenster von O2, welches in Abbildung 3 gezeigt ist, findet man Fenster zum Anlegen und Ändern von Schemata, Klassen, Methoden, Applikationen und vieles mehr. Nur an wenigen Stellen sucht der Benutzer dieser graphischen Schnittstelle etwas länger, bis er gefunden hat, wo man ``Details'' einstellen kann (zum Beispiel, daß ein Programm eine Transaktion sein soll). Die angelegten Klassen und Methoden werden automatisch auf Korrektheit bzgl. des Datenmodells untersucht. Leider sind die Fehlermeldungen oft nicht sehr aussagekräftig und damit wenig hilfreich.

Hat man ein paar Klassen und eine kleine Applikation entwickelt, so kann man sie gleich von der graphischen Benutzerschnittstelle aus testen. Nach Ablauf der Applikation kommt die graphische Entwicklungsumgebung wieder hoch. Hatte der Entwickler zuvor Fenstereinstellungen geändert, so sind diese leider verlorengegangen. Vielleicht ist O2Tools in einer nächsten O2-Version ja weniger vergeßlich ...

Integritätsbedingungen

-- sind in relationalen Datenbanken unverzichtbar. In objektorientierten Modellen sind einige Integritätsbedingungen (zum Beispiel Kardinalitäten, Fremdschlüssel) schon in den Konzepten verankert oder überflüssig. Andere Integritätsbedingungen, wie zum Beispiel benutzersichtbare Schlüssel, könnten auch in objektorientierten Datenbanksystemen hilfreich sein, werden aber von O2 (wie von den meisten OODBS ) nicht unterstützt. Allgemeine Integritätsbedingungen, die man durch entsprechende Anweisungen in Methoden oder Transaktionen implementiert, kann man natürlich auch in O2 formulieren.

Schema-Evolution

-- ist für manche Anwendungen zur Laufzeit einfach notwendig. O2 ermöglicht Schemaänderungen durch sein Meta Schema. Importiert man sich dieses Meta Schema mit den Klassen Meta, Meta_definition, Meta_class, Meta_type und weiteren, so kann man zur Laufzeit Typinformationen über Objekte abfragen und mit der Methode command ein beliebiges O2-Kommando (zum Beispiel create class amp;...) absetzen:

Schema = new Meta;
if (
  Schema->definition("Student")
  == nil)
   /* Klasse nicht definiert */
{
  erg = Schema->command(
   "create class Student
    inherit Person
    type tuple(matnr: integer;
               fach:  string;
               gehalt: real; )
     end");

  if (erg!=0) {
    display("Fehler ...");
    abort;
  }
}

Zum Meta Schema sind in O2 neben definition und command viele hilfreiche Methoden definiert. Leider lassen sich Applikationen, die auf dem Meta Schema arbeiten, nicht von O2Tools aus testen, sondern sind nur über die alphanumerische Schnittstelle aufrufbar.

Optionale Eigenschaften

Mehrfachvererbung

-- wird natürlich auch von O2 unterstützt. Dazu werden bei der Klassendefinition beide Vaterklassen angegeben:

create class
     Hilfswissenschaftler
inherit Student,Angestellter
type tuple (stunden: integer;
            aufgabe: Text; )

Probleme bereitet die Mehrfachvererbung dann, wenn beide Vaterklassen gleichnamige Attribute oder Methoden haben. Welche von beiden soll nun für die gemeinsame Sohnklasse gelten? O2 löst das Problem folgendermaßen: Haben beide Vaterklassen keinen gemeinsamen Vorfahren, so werden die gleichnamigen Attribute/ Methoden in den Vaterklassen umbenannt. Damit erbt die Sohnklasse beide Attribute/Methoden. Haben die Vaterklassen jedoch einen gemeinsamen Vorfahren, so wird jeweils das gleichnamige Attribut (Methode) um den Namen der (Vater)Klasse erweitert. Beide Attribute/Methoden werden dann dem gemeinsamen Sohn vererbt.

Im obigen Beispiel des Hilfswissenschaftlers erbt dieser von Angestellter und von Student das Attribut gehalt. Da Angestellter und Student eine gemeinsame Vaterklasse haben, heißen die geerbten Attribute bei Hilfswissenschaftler gehalt__Angestellter und gehalt__Student.

Der Datenbank-Designer hat schließlich noch die Möglichkeit, mittels rename attribute/method die geerbten Eigenschaften umzubenennen.

Ein Sonderfall liegt vor, wenn nicht nur beide Vaterklassen, sondern auch deren gemeinsamer Vorfahr eine Methode gleichen Namens haben. Wurde diese Methode von beiden Vaterklassen überschrieben, so darf in O2 keine gemeinsame Sohnklasse angelegt werden. Hat nur eine Vaterklasse die Methode überschrieben, so muß auch die Sohnklasse die Methode überschreiben.

Typüberprüfung

-- je mehr, je besser. O2 nutzt einen statischen Typchecker, um Fehler bei Operationen auf Objekten oder Werten, die nicht in einer Vererbungsbeziehung stehen, zu entdecken. Bei Objekten aus Klassen, die in eine Klassenhierarchie eingebunden sind, können nur zur Laufzeit Typüberprüfungen durchgeführt werden. Wie streng diese Typüberprüfungen überhaupt sein können, hängt von der Sprache ab, in der die Anwendung implementiert ist. O2 bietet momentan mit O2C eine C- und eine C++-Spracherweiterung an.

Verteilung von Daten

-- ist bei sehr großen Anwendungen und Datenmengen ganz hilfreich. O2 unterscheidet zwischen dem schema und der base. Im schema sind alle Klassendefinitionen gesammelt. Die base enthält alle Objekte, also Instanzen der Klassen. Jede base ist einem schema zugeordnet, es kann aber beliebig viele schemata und damit auch bases geben.

Zur Verteilung von Daten unterscheidet O2 zwischen horizontaler und vertikaler Partitionierung. Durch horizontale Partitionierung können einem schema beliebig viele bases zugeordnet sein, die jeweils auch einige Objekte derselben Klasse beinhalten können. Physikalisch können diese Objekte getrennt gespeichert werden, indem man die bases unterschiedlichen volumes zuordnet, die physikalisch UNIX -Dateien entsprechen.

Die vertikale Partitionierung erlaubt dem Datenbank-Designer, ein Anwendungsschema auf mehrere schemata zu verteilen und wenn nötig Schemadefinitionen aus dem einen schema in das andere zu importieren. Mit dieser Technik des Importierens kann jeder Designer auch auf die vordefinierten Klassen des schemas O2Kit zugreifen.

Entwurfstransaktionen

-- können kurz, aber bei Non-Standard-Anwendungen auch sehr lang sein. In O2 ist eine Transaktion eine Menge von zusammengehörigen Operationen auf der Datenbank, die der ACID -Eigenschaft (Atomicity, Consistency, Isolation, Duration) genügt. Wird eine Transaktion zum Beispiel durch einen Hardwarefehler unterbrochen, so werden die bereits ausgeführten Operationen der Transaktion wieder rückgängig gemacht (Rollback) und so ein konsistenter Datenbankzustand wiederhergestellt.

Eine O2-Applikation stellt immer eine (read-only) Transaktion dar. Innerhalb der Applikationen können aber weitere (read-write) Transaktionen definiert werden. Dazu gibt es zwei Möglichkeiten. Zum einen kann im Applikationscode der Befehl transaction gegeben werden, wodurch eine neue (read-write) Transaktion gestartet wird. Diese umfaßt alle Operationen bis zum nächsten validate-Befehl. Zum anderen kann eine Transaktion als ``eigenständige Einheit'' über

transaction body {
      ...
      ...
      return;
      ...
}

definiert und innerhalb von Applikationen aufgerufen werden. Eine Validierung findet beim Rücksprung an das aufrufende Programm automatisch statt.

Die einzige Ausnahme bildet hier der Aufruf der Transaktion innerhalb einer anderen Transaktion: In diesem Fall findet die Validierung erst am Ende der aufrufenden Transaktion statt. O2 behauptet von sich selbst, daß nur diejenigen Objekte bei einer read-write Transaktion gesperrt werden, die in irgendeiner Form in den Operationen der Transaktion vorkommen. Im Einsatz entstand jedoch eher der Eindruck, daß die Seiten, auf denen diese Objekte zu finden sind, komplett gesperrt werden.

Versionierungsmechanismen

-- sind ebenfalls für Non-Standard-Anwendungen hilfreich. In O2 findet man Versionen auf zwei Ebenen: bei Methoden, Applikationen, Transaktionen oder Funktionen und auf höherer Ebene bei den Datenbankschemata und Instanzen.

Von jeder Methode, Applikation etc. kann es mehrere Versionen geben. Ausgeführt wird beim Aufruf jeweils diejenige Methode, die zuletzt übersetzt wurde. Jeder Version kann ein eigener Name gegeben werden. Über diesen Namen kann man zwar die entsprechende Implementierung editieren oder drucken, leider aber nicht ausführen -- dazu ist ein erneutes Kompilieren notwendig. Das Kompilieren muß aber nicht in der Entwicklungsumgebung stattfinden, sondern kann über

method body methoden_name
      version versions_name
/* bei Methoden */

innerhalb der umgebenden Transaktion geschehen.

Will man bei einer bereits mit Objekten gefüllten Datenbank einer Klasse, und damit allen ihren Objekten, ein weiteres Attribut hinzufügen, so muß man eine neue Datenbankversion aufbauen. Neue Datenbankversionen erzeugt man, indem man ein neues schema anlegt, die Klassendefinitionen der alten Version importiert und diejenigen Klassen, die von der Änderung betroffen sind, umbenennt. Danach kann man die Objekte der ``alten'' Klassen in die neuen Klassen übertragen und ihnen dabei die fehlenden Attributwerte mitgeben. Da hierbei neue Objekte (mit neuer Identität) entstehen, müssen noch die Referenzen auf diese Objekte angepaßt werden.

Darüber hinaus gibt es in O2 leider keine Möglichkeit, in einer Datenbank mehrere Objektversionen (evtl. noch mit Versionshistorie) zu halten.

Fazit

Neben den oben näher untersuchten unbedingt notwendigen, strittigen und optionalen Bestandteilen gibt es noch offene. Zu diesen zählen unter anderem das zugrundeliegende Programmierparadigma, Möglichkeiten der Objektdarstellung und die Gleichförmigkeit. Da bei den offenen Bestandteilen nichts zwingend gefordert wird, wollen wir sie nicht weiter betrachten.

Läßt man die untersuchten Bestandteile noch einmal Revue passieren, so werden die meisten von gc recht gut realisiert. Aus Sicht des gc zugrundeliegenden Datenmodells steht also der Wahl von gc als Datenbanksystem nichts im Wege. Mehrwöchiges praktisches Arbeiten mit dem gc-System hat jedoch einige kleinere und größere Mängel zutage gebracht. Die schwerwiegendsten dabei sind die sich gleichzeitig blockierenden Projektstarts (Entwürfe von Anwendungsschemata) und die oft unverständlichen Fehlermeldungen und Abstürze des Compilers beim Kompilieren von Applikationen. Weitere Mängel finden sich zum Beispiel in der Implementierung der vordefinierten Dialogbox-Klasse und vordefinierter Methoden. Etwas hinderlich ist auch, daß die Dokumentation nicht immer mit der aktuellen gc-Version übereinstimmt.

Wenn gc erst einmal diese ``Kinderkrankheiten'' überwunden hat, kann es sich zu einem wirklich guten objektorientierten Datenbanksystem entwicklen.

Literatur

  1. M. Atkinson, F. Bancilhon, D. DeWitt, K. Dittrich, D. Maier, S. Zdonik ``The object-oriented database manifesto'' Proceedings of the first international DOOD Conference, 1990.