Schichtenarchitektur

Schichtenarchitekturen sind in der Softwareentwicklung unentbehrlich bei der Entwicklung von Systemen. Sie fördern Wartbarkeit und Wiederverwendbarkeit der Programme, und sie sind eine gute Grundlage für arbeitsteiliges Entwickeln.

 

Die klassische Schichtenaufteilung besteht aus drei Schichten:

 

  • der Benutzeroberfläche bzw.  Benutzerführung,
  • einer „logischen Schicht“ für den Verarbeitungskern, 
  • einer Datenbankzugriffsschicht.

 

Bei komplexen Systemen kann jede dieser drei Schichten selbst wieder in Schichten aufgeteilt sein. Kleine Anwendungen ohne Datenbankzugriff sollten zumindest zwei Schichten besitzen, die Benutzerführung und die logische Schicht.

 

Eine Schichtenarchitektur bildet stets eine Zugriffshierarchie. Jede Schicht kann nur auf darunter liegende Schichten zugreifen, niemals auf eine darüber liegende. Zugriffe auf Einheiten innerhalb derselben Schicht sind erlaubt.

 

Eine wichtige Konsequenz der Schichtenbildung ist die Trennung von Benutzerführung und Programmlogik, da diese verschiedenen Schichten angehören. Auf diese Weise kann man die Benutzerführung ändern, ohne den Programmkern anzutasten, und umgekehrt.

 

Wir betrachten eine zweischichtige Anwendung ohne Datenbankzugriff. Das Programm erlaubt dem Benutzer, eine natürliche Zahl n zwischen 1 und 1 Million in die unten stehende Maske einzugeben. Nachdem der Benutzer die Schaltfläche <Start> gedrückt hat, werden n Zufallszahlen in die zweite Spalte des Arbeitsblatts „Tabelle1“ ausgegeben.

 

 

Die obere der beiden Schichten besteht aus dem Formular (der Maske) ZufallszahlenForm und seinem Modul. Dabei steuert das Formularmodul nicht nur die Eingaben des Benutzers in das Formular, sondern auch die Ausgaben des Programms in das Tabellenblatt, das hier auch zur Benutzeroberfläche gehört.

 

Die zweite Schicht besteht aus zwei Moduln. Davon enthält das eine, HR (für Hilfsroutinen), Funktionen, welche häufig in allen möglichen Anwendungen gebraucht werden. Hier sind es Funktionen, welche bei der Validierung helfen. Das zweite Modul dieser Schicht (Zufall) enthält den Kern der Verarbeitung: es produziert die Zufallszahlen.

 

 

Beachten Sie, dass das Modul Zufall der zweiten Schicht die Zahlen nicht direkt in das Tabellenblatt schreibt. Dies wäre ein eklatanter Verstoß gegen das Schichtenprinzip, denn das Tabellenblatt gehört zur Benutzeroberfläche. Stattdessen liefert Modul Zufall ein Array mit den Zufallszahlen an die auftraggebende Einheit, das Formularmodul ZufallszahlenForm. Das Formularmodul ist damit das einzige Modul in der Anwendung, das Ein- und Ausgaben vollzieht. Die Trennung zwi­schen Programmlogik einerseits, Ein- und Ausgabe andererseits ist perfekt.

 

Wir betrachten zunächst das Formularmodul. Die Ereignisprozedur StartBtn_Click leert zunächst das Arbeitsblatt, in das die Zufallszahlen geschrieben werden sollen. Dann bezieht es die Zufallszahlen aus dem Modul Zufall durch Aufruf der Funktion ZufallszahlenErzeugen. Wie weiter unten noch genauer gezeigt wird, liefert diese Funktion die Zahlen in einem (formal) zweidimensionalen Array von n Zeilen und einer Spalte (!). Der Grund für dieses Vor­gehen ist in einer Excel-Eigenheit zu sehen. Ein zweidimensionales Array können wir einem Arbeits­blattbereich in einer einzigen Anweisung zuweisen, bei einem eindimensionalen wäre dies nur beschränkt möglich.

 

'Formularmodul ZufallszahlenForm

'===============================

 

'Aktionen nach Anklicken des Buttons <Start>

'===========================================

Private Sub StartBtn_Click()

    Dim n As Long

    Dim r() As Double

    If ValidierungOK Then

        n = CLng(Me.AnzahlTBx.Text)

        Worksheets("Tabelle1").Cells.Clear

        r = Zufall.ZufallszahlenErzeugen(n)

        Worksheets("Tabelle1").Range("B1:B" & n) = r

    End If

End Sub

 

Die Funktion ValidierungOK hilft bei der Validierung der Eingaben. Sie bedient sich dabei einer Funktion aus dem Modul HR der zweiten Schicht:

 

'prüft die Eingaben

'==================

Public Function ValidierungOK() As Boolean

    If HR.istNatuerlicheZahl(AnzahlTBx.Text) Then

       If CLng(Me.AnzahlTBx.Text) <= 1000000 Then

          ValidierungOK = True

       Else

          ValidierungOK = False

       End If

    Else

       ValidierungOK = False

    End If

    If Not ValidierungOK Then

         MsgBox "nur ganze Zahlen von 1 bis 1 Million eingeben!"

         Me.AnzahlTBx.SetFocus

    End If

End Function

 


Das Kernmodul Zufall besteht nur aus der Funktion ZufallszahlenErzeugen. Sie liefert ein formal zweidimensionales Array mit den gewünschten Zufallszahlen.

 

'Modul Zufall

'=============

 

Option Explicit

 

'erzeugt ein eindimensionales Array mit n Zufallszahlen

'der Index läuft von 1 bis n

'======================================================

Public Function ZufallszahlenErzeugen(ByVal n As Long) As Double()

    Dim i As Long

    Dim z() As Double

    ReDim z(1 To n, 1 to 1)

    For i = 1 To n

        z(i, 1) = Rnd

    Next i

    ZufallszahlenErzeugen = z

End Function

 

 

Das Modul HR mit den Hilfsroutinen enthält hier der Einfachheit halber nur die beiden Funktionen, welche in der Anwendung gebraucht werden. Die Funktion istGanzzahl prüft, ob der übergebene Wert aus einer Zeichenfolge besteht, welche einen ganze Zahl repräsentiert. Die Funktion istNatuerlicheZahl arbeitet analog und greift dabei auf die Funktion istGanzzahl zurück.

 

'ermittelt für den Wert z, ob er einer Ganzzahl entspricht;

'z kann auch ein String sein

'================================================

Public Function istGanzzahl(ByVal z As Variant) As Boolean

    If Not IsNumeric(z) Then

        istGanzzahl = False

    Else

        If z - Int(z) = 0 Then

            istGanzzahl = True

        Else

            istGanzzahl = False

        End If

    End If

End Function

 

 

'ermittelt für den Wert z, ob er einer natürlichen Zahl entspricht;

'z kann auch ein String sein

'====================================================

Public Function istNatuerlicheZahl(ByVal z As Variant) As Boolean

    If Not istGanzzahl(z) Then

        istNatuerlicheZahl = False

        Exit Function

    End If

    istNatuerlicheZahl = CLng(z) > 0

End Function