Modularität und Liskovsches Prinzip in komplexen Systemen

Seite 3: Austauschbarkeit auf Modulebene

Inhaltsverzeichnis

Package-Struktur eines Projekts

Um auf die Ebene eines Systems zu gelangen, muss man von einzelnen Klassen auf Module umsteigen, die viele Klassen umfassen. Bereits in der Package-Darstellung eines Projekts kann man die Modulstruktur erahnen:

In der Java-Entwicklung hat sich OSGi als Modulsystem mittlerweile durchgesetzt, unter anderem auch deshalb, weil Modularisierung von einer Version des JDKs auf die nächste verschoben wird, sie also nicht Teil des Standards ist. Die Definitionsdatei eines Bundles (Moduls) ist in OSGi zur Beschreibung eines Moduls zu verwenden. Die beiden Klassen werden jeweils in ein Bundle eingefügt. Entscheidend ist, welche Objekte zu importieren und exportieren sind. Die Implementierung der ersten Datenanalysefunktion wird in folgendem Bundle definiert:

Manifest-Version: 1.0 
Bundle-ManifestVersion: 2
Bundle-Name: DataAggregator1
Bundle-SymbolicName:DataAggregator1
Bundle-Version: 1.0.0.qualifier
Bundle-ActivationPolicy: lazy
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Service-Component:OSGI-INF/aggregator-description.xml
Export-Package: arch.dataaggregator1
Import-Package: arch.dataaggregatorinterface,
arch.datasourceinterface,
org.osgi.framework;version="1.3.0"

Die zweite Klasse landet in einem separaten Bundle, sodass sie die Deklaration eines Moduls nur an wenigen Stellen ändert:

Manifest-Version:1.0 
Bundle-ManifestVersion: 2
Bundle-Name:DataAggregator2
Bundle-SymbolicName:DataAggregator2

Bundle-Version: 1.0.0.qualifier
Bundle-ActivationPolicy: lazy
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Service-Component:OSGI-INF/aggregator-description.xml
Export-Package: arch.dataaggregator2
Import-Package: arch.dataaggregatorinterface,
arch.datasourceinterface,
org.osgi.framework;version="1.3.0"

Module folgen der Package-Struktur

Entscheidend ist, dass das Modul dieselben Abhängigkeiten besitzt und dass die Klassen, die exportiert werden (siehe export-packages), durch das implementierte Interface auch dieselbe Schnittstelle nach oben freigeben. Dadurch ist die Ersetzbarkeit der beiden Module gewährleistet. Die Module des Projekts folgen direkt der Package-Struktur:

Genau diese Eigenschaft ist bei der Evolution eines Systems von entscheidender Bedeutung, denn durch die Aufteilung eines Systems in Module können folgende Eigenschaften erreicht werden:

  • Austauschbarkeit von Modulen durch neuere Implementierungen ohne Seiteneffekte auf andere Module (Anwendung des Liskovschen Prinzips).
  • Hinzufügen von neuen Modulen, ohne die bestehenden Implementierungen zu beeinflussen.

Ersetzbarkeit von Modulen

Die folgende Abbildung beschreibt diese Ersetzbarkeit durch eine Entkopplung der Module über Schnittstellen.