Mehrschichtige Anwendungen

Access ist – rein architektonisch betrachtet – auf das Anlegen monolithischer Anwendungen mit Objekten mit starker Abhängigkeit ausgelegt. Formulare und Berichte sind starr mit den zu Grunde liegenden Datenherkünften verbunden und der Code liegt jeweils im passenden Formular- oder Berichtsmodul oder, falls nötig, in einem Standard- oder Klassenmodul. Wie man auch mit Access mehrschichtige Anwendungen baut, zeigt dieser Beitrag.

Im Gegensatz zu objektorientierten Programmiersprachen gibt es in Access-Anwendungen keine einzelnen Dateien, die unterschiedliche Klassen repräsentieren, sondern nur eine einzige Datei mit der Endung .mdb, die alle Objekte enthält.

Wenn Sie hier eine mehrschichtige Anwendung bauen möchten und dies von richtigen objektorientierten Programmiersprachen gewohnt sind, müssen Sie von dem Gedanken Abschied nehmen, jede Klasse fein säuberlich in einer eigenen Datei zu speichern.

Davon abgesehen funktioniert das Programmieren mehrschichtiger Anwendungen aber genauso wie in anderen objektorientierten Programmiersprachen – nur dass Sie auf Eigenschaften wie Vererbung und Polymorphie verzichten müssen und alle Klassen in der .mdb-Datei enthalten sind.

Ein Grund, eine mehrschichtige Anwendung zu erstellen, ist die starke Verzahnung von Benutzeroberfläche und Anwendungslogik. Das gilt vor allem für den in Formularen und Berichten enthaltenen Code, der nicht nur die Benutzeroberfläche steuert, sondern auch die Businesslogik und die Funktionen für den Datenzugriff enthält. Letztere sind dabei noch tiefer verborgen, nämlich in den passenden Formular-, Berichts- und Steuerelementeigenschaften, die für die Bindung an die entsprechenden Tabellen und Abfragen sorgen. Teilweise befindet sich die Businesslogik sogar direkt in den Tabellen – etwa in Form der Gültigkeitsregeln und der übrigen Integritätsmechanismen wie der referentiellen Integrität und der darin enthaltenen Lösch- und Aktualisierungsweitergabe.

Wegen dieser Aufteilung kann die Pflege solcher Anwendungen sehr zeitintensiv werden: Wenn Sie etwa eine Meldung, die auf einen falschen Datentyp bei der Eingabe in ein Formularfeld hinweist, ändern oder entfernen möchten, sind Sie unter Umständen lange unterwegs, da sich der Auslöser in verschiedenen Ereignissen des Formulars oder auch im Tabellenentwurf befinden kann.

Ganz klar: Wer eine konsistente Vorgehensweise bei der Programmierung von Anwendungen an den Tag legt, der wird auch genau wissen, wo in seiner Anwendung sich welche Funktionen befinden. Aber erstens kann es ja auch sein, dass sich mal jemand anders um die Wartung oder Weiterentwicklung der Anwendung kümmern muss, und zweitens entwickeln Sie sich selbst ja auch weiter und erkennen nach einer gewissen Zeit die funktionale Struktur früherer Anwendungen nicht mehr wieder. Und Access ist natürlich zunächst einmal dafür ausgelegt, auf schnellstem Wege Anwendungen für den Zugriff auf und die Verwaltung von Daten zu entwickeln. Wenn eine Anwendung allerdings ein gewisses Maß an Komplexität überschritten hat und man für kleine Ônderungen beinahe genauso lange braucht, als wenn man die halbe Anwendung neu programmieren würde, sollte man über alternative Vorgehensweisen nachdenken.

Diese liegen beispielsweise in der Verwendung eines mehrschichtigen Datenmodells. Solche Modelle gibt es in mehreren Varianten mit unterschiedlicher Interpretation.

Im Folgenden lernen Sie ein Modell kennen, das je nach Sichtweise aus drei oder vier Schichten besteht: Der Benutzeroberfläche (GUI-Schicht), der Business-Schicht, der Datenzugriffsschicht und den Daten. Manch einer betrachtet die Datenzugriffsschicht und die Daten als Einheit, andere sehen zwei Schichten darin. Im Rahmen dieses Beitrags werden Datenzugriffsschicht und Daten als zwei Schichten betrachtet.

Beispiel für den mehrschichtigen Datenzugriff

Als Beispiel für den mehrschichtigen Datenzugriff dienen eine Tabelle namens tblPersonal (siehe Bild 1) und ein Formular namens frmPersonal (siehe Bild 2). Dabei verwenden wir aus Gründen der Übersicht nur einige der in der Tabelle enthaltenen Felder.

pic001.tif

Bild 1: Diese Tabelle dient als Datenherkunft des Formulars.

pic002.tif

Bild 2: Das Formular zum Anzeigen der Daten ist ungebunden.

Das Formular ist komplett ungebunden und enthält die folgenden Steuerelemente:

  • cboSchnellsuche: dient der Auswahl von Mitarbeitern
  • txtPersonalID: schreibgeschützt
  • txtVorname, txtNachname, txtPosition, txtAnrede, txtEinstellung: Textfelder der Tabelle
  • cmdOK: Schaltfläche zum Schließen des Formulars und zum Speichern des aktuellen Inhalts
  • cmdLoeschen: Schaltfläche zum Löschen des aktuellen Datensatzes
  • cmdNeu: Schaltfläche zum Anlegen eines neuen Datensatzes

Die GUI-Schicht

Die GUI-Schicht – also die Benutzeroberfläche – bildet für das nachfolgende Beispiel das Formular frmPersonal aus Bild 2. Die GUI-Schicht enthält nur Methoden für den Zugriff auf die Business-Schicht, auf keinen Fall kann sie direkt auf eine der darunter liegenden Schichten zugreifen. Das ist bei herkömmlichen Access-Anwendungen der Fall: Hier werden Datenherkunft und Steuerelemente direkt an die Datenschicht gebunden. Andersherum kann keine der anderen Schichten auf die GUI-Schicht zugreifen – das ist eine der Hauptprämissen bei der Entwicklung mehrschichtiger Anwendungen. Sie minimieren damit die Abhängigkeit, indem Sie dafür sorgen, dass diese lediglich einseitig ist.

Beim hier verwendeten Schichtenmodell greift die GUI-Schicht ausschließlich auf die Objekte der Business-Schicht zu: auf die Datenobjekte mit den anzuzeigenden Informationen und auf das Controller-Objekt, das die Funktionen zum Füllen der Datenobjekte, zum Speichern der per GUI-Schicht geänderten Inhalte der Datenobjekte, zum Speichern neuer Datenobjekte und zum Löschen bestehender Datenobjekte bereitstellt.

Die Business-Schicht

Die Business-Schicht enthält zwei Typen von Objekten: Der erste Typ repräsentiert die in den Datensätzen der Tabellen enthaltenen Daten (Daten-Objekte), der zweite enthält die Steuermechanismen für den Transfer der Daten zwischen der Datenzugriffsschicht und der GUI-Schicht (Controller-Objekte).

Genau genommen ist das nicht ganz richtig: Die Controller-Objekte steuern zwar die Objekte der Datenzugriffsschicht und andere Objekte der Business-Schicht, aber die Kooperation zwischen der GUI-Schicht und den Controller-Objekten geht immer von der GUI-Schicht aus. Wie bereits erwähnt – die oberen Schichten können zwar auf die unteren zugreifen, aber niemals umgekehrt.

Und da auch nie eine Schicht übersprungen werden darf, muss die GUI-Schicht immer über die Business-Schicht auf die Datenzugriffsschicht zugreifen, die dann die gewünschten Daten nach oben reicht.

Wie viele und welche Objekte sich in der Business-Schicht befinden, hängt von der Art der enthaltenen Daten und der Benutzeroberfläche ab. Sie werden vermutlich für jede Tabelle, die objektartige Daten enthält, ein eigenes Objekt erstellen. Außerdem müssen Sie entscheiden, ob Sie ein Controller-Objekt pro Element der Benutzeroberfläche oder vielleicht sogar ein großes Controller-Objekt verwenden. Übersichtlicher dürfte ein Objekt pro Formular sein.

Die Datenzugriffsschicht

Die Datenzugriffsschicht enthält Datenzugriffsobjekte. Zu jedem Datenobjekt gibt es ein Datenzugriffsobjekt, das verschiedene Operationen ausführen kann:

  • Erzeugen eines Datenobjekts auf Basis eines Datensatzes der zu Grunde liegenden Tabelle
  • Erzeugen eines Recordsets mit Datensätzen als Suchergebnis mit vorgegebenen Kriterien
  • Aktualisieren eines Datensatzes in der Datenbank auf Basis der in einem Datenobjekt enthaltenen Daten
  • Anlegen eines neuen Datensatzes in der Datenbank
  • Löschen eines Datensatzes aus der Datenbank

Damit entkoppelt die Datenzugriffsschicht die Business-Schicht von den Daten. Der Vorteil liegt darin, dass Sie ohne Probleme die Datenquelle wechseln können – etwa, um von einem Access-Backend auf einen SQL-Server umzusteigen oder vielleicht sogar um eine XML-Datei als Datenquelle zu verwenden.

Sie müssen lediglich die Klassen der Datenzugriffsschicht anpassen – die GUI-Schicht und die Business-Schicht bleiben von einem Wechsel der Datenquelle unberührt.

Im Beispiel erfahren Sie, wie die fünf Operationen eines Datenzugriffsobjekts aussehen. Man benötigt je ein Datenzugriffsobjekt pro Businessobjekt der Business-Schicht.

Das Beispiel verwendet lediglich ein Datenzugriffsobjekt für den Zugriff auf die Datenbank per DAO. Sie können alternativ ein Datenzugriffsobjekt mit den gleichen Methoden, aber anderen Anweisungen für den Zugriff auf die Daten verwenden, um etwa die ADODB-Bibliothek statt der DAO-Bibliothek zu verwenden. Oder Sie erstellen ein drittes Datenzugriffsobjekt, das den Zugriff auf eine XML-Datei über das mit der Bibliothek MSXML gelieferte Document Object Model ermöglicht. Wenn Sie bezüglich des Datenzugriffs derart flexibel sein möchten, empfiehlt sich die Verwendung einer Schnittstelle.

Die Datenschicht

Die Datenschicht enthält die eigentlichen Daten. Im vorliegenden Beispiel ist das eine Tabelle in einer Access-Datenbank, es kann sich aber auch um eine Tabelle in einer SQL-Server-Datenbank oder um eine XML-Datei handeln.

Diese Flexibilität erhalten Sie durch die Aufteilung der Anwendung auf verschiedene Schichten – um etwa auf eine XML-Datei statt auf eine Access-Datenbank zuzugreifen, müssten Sie nur die Objekte der Datenzugriffsschicht anpassen. Die Benutzeroberfläche und die Business-Schicht bleiben unangetastet.

Beispielanwendung

Nach der Theorie zurück zum Beispiel: Das Formular aus Bild 2 soll nun also über die einzelnen Schichten auf die in der Datenbank gespeicherten Daten zugreifen, diese anzeigen, neue Datensätze anlegen oder bestehende Datensätze ändern oder löschen. Beginnen wir also einfach mal am Anfang: den Zustand beim Öffnen des Formulars.

Person-Objekt erstellen

Während der Arbeit mit dem Formular werden die Daten der Mitarbeiter, wie bereits erwähnt, nicht direkt aus der Tabelle ins Formular transportiert, sondern über ein spezielles Objekt, das im Prinzip mit einem Datensatz einer Tabelle vergleichbar ist, mit dem Unterschied, dass es statt Felder Eigenschaften aufweist und dass Sie seine Methoden selbst definieren können beziehungsweise müssen. Da Sie dieses Objekt auf Basis einer Klasse erzeugen und die Beschreibung dieser Klasse die folgenden Erläuterungen unnötig behindern würde, legen Sie diese Klasse schnell vorab an. Die Klasse heißt clsPerson und enthält den Code aus Listing 1. Dazu gehören lediglich die Membervariablen, die die Eigenschaften speichern, sowie zu jeder Membervariablen eine Property Get– und eine Property Let-Methode. Wenn Sie sich noch nicht mit der Programmierung von Klassen auskennen, finden Sie in [1] weitere Informationen.

Listing 1: Code der Klasse clsPerson

Option Compare Database
Option Explicit
Dim mPersonalID As Long
Dim mVorname As String
Dim mNachname As String
Dim mPosition As String
Dim mAnrede As String
Dim mEinstellung As Date
Public Property Get PersonalID() As Long
    PersonalID = mPersonalID
End Property
Public Property Let PersonalID(lngPersonalID As Long)
    mPersonalID = lngPersonalID
End Property
Public Property Get Vorname() As String
    Vorname = mVorname
End Property
Public Property Let Vorname(strVorname As String)
    mVorname = strVorname
End Property
Public Property Get Nachname() As String
    Nachname = mNachname
End Property
Public Property Let Nachname(strNachname As String)
    mNachname = strNachname
End Property
Public Property Get Position() As String
    Position = mPosition
End Property
Public Property Let Position(strPosition As String)
    mPosition = strPosition
End Property
Public Property Get Anrede() As String
    Anrede = mAnrede
End Property
Public Property Let Anrede(strAnrede As String)
    mAnrede = strAnrede
End Property
Public Property Get Einstellung() As Date
    Einstellung = mEinstellung
End Property
Public Property Let Einstellung(strEinstellung As Date)
    mEinstellung = strEinstellung
End Property

Initialisieren des Formulars

Direkt nach dem Öffnen soll das Formular keinen Datensatz anzeigen. Lediglich das Kombinationsfeld cboSchnellsuche soll alle enthaltenen Personen zur Auswahl anbieten. Das Füllen dieses Steuerelements ist dann auch die erste Funktion, die programmiert und auf mehrere Schichten aufgeteilt werden soll.

Der Beginn sieht unspektakulär aus: Die beim Öffnen des Formulars ausgelöste Routine initialisiert das im Kopf des Moduls deklarierte Controller-Objekt und ruft die Prozedur cboSchnellsucheAktualisieren auf. Das Controller-Objekt befindet sich im Übrigen in einer eigenen Klasse, die Sie weiter unten erstellen. Den Code aus Listing 2 speichern Sie im Klassenmodul des Formulars frmPersonal. Außerdem müssen Sie noch die Eigenschaft Beim Öffnen auf den Wert [Ereignisprozedur] einstellen.

Listing 2: Initialisieren des Formulars

Dim objController As clsController
Private Sub Form_Open(Cancel As Integer)
    Set objController = New clsController
    cboSchnellsucheAktualisieren
End Sub

Die Prozedur cboSchnellsucheAktualisieren soll das Kombinationsfeld mit den in der Tabelle tblPersonal enthaltenen Daten füllen. Unter Access brauchen Sie dafür keine einzige Codezeile, sondern weisen einfach der Eigenschaft Datensatzherkunft eine passende Abfrage zu. Bei der Programmierung einer mehrschichtigen Anwendung wird das Ganze hingegen schon mächtig interessant – Sie füllen dazu zunächst in der Datenzugriffsschicht ein Collection-Objekt, das dann nach oben gereicht und von der GUI-Schicht in das Kombinationsfeld gefüllt wird.

Sie haben das Ende des frei verfügbaren Textes erreicht. Möchten Sie ...

TestzugangOder bist Du bereits Abonnent? Dann logge Dich gleich hier ein. Die Zugangsdaten findest Du entweder in der aktuellen Print-Ausgabe auf Seite U2 oder beim Online-Abo in der E-Mail, die Du als Abonnent regelmäßig erhältst:

Schreibe einen Kommentar