© deomis/Shutterstock.com
Bindings im Detail – Teil 1

Kurz angebunden – mit UWP und WinUI


Applikationen werden in Schichten aufgetrennt. Nur so lassen sie sich langfristig warten, funktionell erweitern und fortlaufend testen. Die Verbindung zwischen User Interface und Logik erfolgt im Umfeld von Microsoft-Apps mittels Bindings. Wir lernen hier Varianten und den Praxiseinsatz der Datenbindung in XAML kennen.

Das User Interface (UI) ist nach Möglichkeit nur lose an die Logik einer Anwendung zu koppeln. Damit verfolgt man das Ziel, die Schichten auf technischer Ebene zu trennen, denn umfassende Anwendungen muss man in Einheiten und Bereiche aufteilen, um die dabei entstehende Komplexität in den Griff zu bekommen. Packt man dagegen alle Elemente einer Applikation in einen „Topf“, d. h., trennt man sie nicht in Schichten auf, führt das zu den allseits bekannten monolithischen Anwendungssystemen, die insbesondere die folgenden Nachteile aufweisen:

  • Das Softwaresystem ist komplex. Die fehlende Aufteilung in Einzelmodule führt dazu, dass die Komplexität nicht reduziert wird.

  • Wartung und Fehlerbereinigung stellen sich als sehr schwierig dar. Es gelingt nicht, einzelne Teile der Anwendung gegen neuere Technologien auszutauschen, ohne dass es direkte Einflüsse auf andere Bestandteile der Software hat. Anpassungen an einer Stelle im Quellcode lösen eine Kette von notwendigen Folgeanpassungen aus.

  • Die Wiederverwendung einzelner Softwarekomponenten ist bei einem komplizierten monolithischen Gesamtsystem ausgeschlossen. Wir können eine einmal erarbeitete Lösung nicht für eine ähnliche Problemstellung wiederverwenden, sondern müssen jedes Mal von vorn beginnen.

  • Erweiterbarkeit und Skalierbarkeit sind nahezu ausgeschlossen bzw. stark eingeschränkt.

Ein typisches und schon seit sehr langer Zeit verwendetes Architekturmuster ist die Aufsplittung in die drei typischen Schichten User Interface, Fachkonzeptschicht (Business Layer) und Datenhaltungsschicht. Wird es komplizierter, können wir eine weitere Trennung der Schichten vornehmen, beispielsweise in eine sogenannte Mehr-Schichten-Architektur. Hier haben die Schichten zum Beispiel die folgenden Aufgaben (Abb. 1):

  • Präsentation: Dateneingabe und Datenausgabe

  • Applikation: Koordination von Workflows, Transformation von Daten

  • Fachkonzept: Umsetzung der fachlichen Anforderungen

  • Businessinfrastruktur: grundlegende, allgemein verwendbare fachliche Funktionen

  • Technische Services: höhere technische Dienste wie persistente Speicherung und Datensicherheit

  • Basisdienste: niedrigere technische Dienste wie Threadverwaltung, Datenbank und Netzwerk

Eine solche Aufteilung ist kein Muss, es handelt sich vielmehr um Vorschläge bzw. bewährte Architekturmuster (Pattern). Die konkrete Wahl der Architektur ist selbstverständlich dem Entwickler (Architekten, Team) überlassen und muss auf das Projekt abgestimmt werden.

krypczyk_bindings_teil1_1.tif_fmt1.jpgAbb. 1: Drei- und Mehr-Schichten-Architektur einer Anwendung [1]

Architekturprinzipien

Eine gute und durchdachte Architektur sollte bestimmten Handlungsmustern, den sogenannten Architekturprinzipien, folgen. Diese Architekturprinzipien sind allgemeingültig, d. h., man kann sie auf die unterschiedlichsten Arten von Softwaresystemen anwenden. Sehen wir uns die wichtigsten Prinzipien an:

  • Klare Struktur und Abstraktion: Das Ziel einer Softwarearchitektur ist es, die hohe Komplexität von umfassenden IT-Systemen zu reduzieren. Damit das gelingt, muss die Architektur eine klare und einfach zu durchschauende Struktur schaffen. Abstraktion besagt, dass man auf die Abbildung unnötiger Details während des Entwurfs der Architektur zu Gunsten der Übersichtlichkeit bewusst verzichtet. Ein Beispiel: Beim Entwurf eines Bestellsystems sollte man bereits zu Beginn die einzelnen Programmbestandteile identifizieren, zum Beispiel die Kundenverwaltung, die Artikelverwaltung und das Management der Bestellungen. Der Aufbau der Komponenten im Detail bleibt zunächst im Verborgenen.

  • Konzeptionelle Integrität: Hiermit ist Einheitlichkeit gemeint. Die getroffenen Architekturentscheidungen sollten über das gesamte System beibehalten werden. So sollten beispielsweise die Schnittstellen zwischen den Komponenten alle einheitlich aufgebaut sein. Das stellt sicher, dass sich Außenstehende in die Funktionsweise des Systems in akzeptabler Zeit einarbeiten können, weil sie auf diese Weise Muster erkennen können und nicht bei der Inspektion einer jeden Funktion überrascht werden. Auch für uns Entwickler ist Einheitlichkeit eine wichtige Handlungsmaxime. Nur so haben wir die Chance, unseren Quellcode und das Gesamtsystem auch nach längeren Pausen noch zu verstehen. Ein Beispiel: Die Schnittstellen der Kundenverwaltung, der Artikelverwaltung und des Bestellsystems sollten gleich konstruiert sein. Weiß man also, wie man einen neuen Kunden hinzufügt, kennt man auch die Logik, wie ein neuer Artikel hinzugefügt werden kann.

  • Modularisierung und Trennung von Zuständigkeiten: Dieses Prinzip besagt, dass jede Komponente der Architektur nur für eine Aufgabe oder einen Aufgabenkomplex verantwortlich ist. Da die Zuständigkeiten klar voneinander abgegrenzt sind, ergibt sich daraus eine modulare Architektur. Natürlich ist auch die Zerlegung des Gesamtsystems in einzelne Module mit Augenmaß zu betreiben, um eine Fragmentierung zu vermeiden. Ein Modul soll zwar grundsätzlich nur eine Aufgabe ausführen, aber diese vollständig. Ein Beispiel: Das Teilsystem Kundenverwaltung ist auch wirklich nur für die Verwaltung der Kunden zuständig. Andere Informationen zum Kunden, wie dessen Bestellungen, werden nicht hier verwaltet, sondern in einem anderen Teilsystem.

  • Bindung und Kopplung: Die Bindung (Cohesion) innerhalb einer Systemkomponente und die Kopplung (Coupling) der Systemkomponenten untereinander bestimmen die Struktur eines Softwaresystems. Dabei sollten die Beziehungen zwischen den Elementen der Systemkomponenten möglichst intensiv sein. Dagegen sollte die Kopplung der Systemkomponenten untereinander möglichst gering sein. Mit anderen Worten: Alle Funktionen innerhalb eines Moduls sollten der Erfüllung einer Aufgabe dienen. Unterschiedliche Module sollten dagegen unterschiedliche Aufgaben haben. Mit einer hohen Bindung innerhalb der Komponenten und einer losen Kopplung zwischen den Komponenten schafft man die Voraussetzungen für eine Wiederverwendung der Komponenten und für eine leichtere Wartung des Gesamtsystems. Beispielsweise ist es nur so möglich, eine Komponente gegen eine neuere Version mit verbesserter Leistung auszutauschen, ohne dass weitere Änderungen am Gesamtsystem durchgeführt werden müssen. Ebenso können Komponenten eines Systems in einem anderen System ohne Anpassungen wiederverwendet werden. Ein Beispiel: Die Teilsysteme Kunden- und Artikelverwaltung sind unabhängig voneinander und nur über das Bestellmanagement verbunden. Möchte man Änderungen an der Kundenverwaltung durchführen, beispielsweise weil es notwendig ist, neue Datenfelder aufzunehmen, dann hat das keine Auswirkungen auf den Rest des Systems.

Kopplung und Bindung sind wichtige Merkmale einer Softwarearchitektur. Weitere Informationen bietet der Infokasten „Kopplung und Bindung“.

Kopplung und Bindung

Eine geringe Bindung innerhalb der einzelnen Module führt dazu, dass viele Beziehungen zwischen den Modulen vorherrschen. Gewissermaßen hängt bei einer solchen Konstruktion jedes Modul von jedem anderen Modul ab. Man kann in diesem Fall kein Modul ohne Nebenwirkungen austauschen oder anpassen. Typisch ist zum Beispiel eine (zu) enge Verzahnung des UI mit der Fachlogik. Das passiert u. a. dann, wenn ein Großteil der Logik direkt in den Dateien (Code-behind) der UI-Definition codiert wird. Ohne zusätzliche Aufwendungen war das bei Windows Forms kaum anders möglich. Innerhalb eines Moduls hängen dagegen die...

Neugierig geworden? Wir haben diese Angebote für dich:

Angebote für Gewinner-Teams

Wir bieten Lizenz-Lösungen für Teams jeder Größe: Finden Sie heraus, welche Lösung am besten zu Ihnen passt.

Das Library-Modell:
IP-Zugang

Das Company-Modell:
Domain-Zugang