Die Ausgangssituation
In der Softwareentwicklung steht man regelmäßig vor der Situation, dass aus gegebenen Werten Ergebniswerte berechnet werden müssen. Was soll jedoch geschehen, wenn das Ergebnis erneut abgefragt wird? Soll das Ergebnis zwischengespeichert werden? Ist es notwendig, die gesamte Berechnung erneut auszuführen? Müssen vielleicht andere Komponenten über die Ergebnisänderung informiert werden, beispielsweise zur Aktualisierung der Anzeige? Was soll passieren, wenn ein eingegebener Wert in einer von vielen Berechnungen einen Fehler auslöst? Die Liste der möglichen Fragen kann schnell recht umfangreich werden.
Während meiner Überlegungen zu diesem Thema kristallisierten sich fünf konkrete Anforderungen heraus, die von einem Objektmodell unterstützt werden sollten. Diese Anforderungen bezeichne ich – nicht ganz zufällig – als die "Big Calculation Five", denn die im Folgenden dargestellte Komponente zur Erfüllung dieser Anforderungen trug intern den Namen "Business Calculation Foundation" und wird jetzt unter dem Produktnamen CalculationWorks BCF veröffentlicht.
CalculationWorks BCF (im Folgenden nur BCF genannt) ist eine Sammlung von Komponenten und Tools zur Realisierung komplexer wiederkehrender Anforderungen im Zusammenhang mit der Implementierung von Businesslogik. BCF wird von mir für verschiedene Plattformen des .Net-Frameworks entwickelt.
The "Big Calculation Five" – Anforderungen und Umsetzung in BCF
1. Berechnete Spalten & Eigenschaften, Validierungsmeldungen
Die Forderung nach berechneten Spalten/Eigenschaften ist klar und einfach nachvollziehbar. Berechnete Validierungsmeldungen sind eine Erweiterung dieser Forderung.
Häufig werden Benutzereingaben abgelehnt, wenn diese unsinnig oder widersprüchlich sind. Bei unsinnigen Eingaben, beispielsweise die Eingabe eines Textes in ein Datumsfeld, ist es angemessen, diese Eingabe abzuweisen. Bei widersprüchlichen Eingaben ist es jedoch nicht immer angebracht, den Wert abzuweisen, bei dessen Eingabe der Widerspruch offensichtlich wurde. In einer Personalverwaltungs-App wird z.B. zu einem Mitarbeiter als Geburtsjahr 1999 und anschließend als Jahr der Einstellung 1988 eingegeben. Es ist nicht generell davon auszugehen, dass der zuletzt eingegebene Wert fehlerhaft ist. Dem Benutzer sollte daher an beiden Feldern und/oder in einer Fehlerliste eine Meldung angezeigt werden, die auf den Widerspruch hinweist und verschwindet, sobald der Benutzer den Widerspruch auflöst.
BCF bietet die Möglichkeit, ein Funktionsobjekt an einer Spalte zu hinterlegen und diese somit zu einer berechneten Spalte zu machen. BCF-Tabellen können Validierungsobjekte hinzugefügt werden, welche den Funktionsobjekten ähneln. Die Ergebnisse der Validierungen können bestimmten Feldern zugeordnet werden. Eine Liste aller Validierungsmeldungen wird ebenfalls verwaltet.
BCF- Funktionsobjekte verwenden ihre Eigenschaften als Parameter. Durch Zuordnung der Eigenschaften zu Spalten versorgt das BCF-Modell das Funktionsobjekt vor dem Berechnungsaufruf mit den entsprechenden Parametern. Die Zuordnung kann sowohl eine benachbarte Spalte in der gleichen Tabelle als auch eine Spalte in einer anderen Tabelle sein. In letzterem Fall wird einfach der Pfad zur Tabelle in Form von verketteten Relationsnamen angegeben. Es ist unerheblich, ob die zugeordnete Spalte selbst eine berechnete Spalte ist oder nicht. In vielen Fällen ist es logisch, ein Zwischenergebnis in einer Spalte zu halten und in mehreren Berechnungen wieder zu verwenden. Meist übersteigen die Gewinne bei diesem Vorgehen die Kosten, im Hinblick auf die Performance ebenso wie in Bezug auf den Entwicklungs- und Pflegeaufwand.
2. Relationales Modell
Eine naheliegende Anforderung: Sobald die Komplexität eines Objektmodells, die einer einfachen Liste übersteigt, ist es von Vorteil, Verknüpfungen und Verschachtelungen als relationales Modell abzubilden.
Innerhalb eines BCF-Objektmodells können mehrere Tabellen angelegt und über Relationen verknüpft werden.
3. Undo/Redo
Die häufig geäußerte Forderung nach einer Möglichkeit, Benutzereingaben rückgängig zu machen bzw. wiederherstellen zu können, wird ebenso häufig von der ausführenden Seite wegdiskutiert oder gar ignoriert. Der Grund ist, dass die nachträgliche Implementierung aufwendig ist und ein hohes Fehlerrisiko beinhaltet. Betrachtet man von vornherein die Forderung als Kernelement, so lauert die Gefahr, dass sich der gewählte Ansatz als unflexibel erweist und die Implementierung anderer Forderungen unverhältnismäßig erschwert.
BCF hat einen soliden Undo-/Redo-Mechanismus implementiert. Basierend auf den Kompensationsinformationen der Transaktion werden auch berechnete Spalten und Validierungsmeldungen berücksichtigt, ohne dass die Funktionsobjekte erneut ausgewertet werden.
4. Transaktionen
Das zu diesem Thema beliebte Beispiel der Geldüberweisung von einem Konto auf ein anderes verdeutlicht, dass eine Aktion mehrere Datenänderungen beinhalten kann. Diese Änderungen dürfen nur vollständig oder gar nicht ausgeführt werden (Unteilbarkeit). Vor und nach jeder Transaktion muss das Objektmodell in einem konsistenten Zustand sein (Konsistenz).
5. Änderungsbenachrichtigung
Viele Komponenten erwarten Benachrichtigungen über Zustandsänderungen, um effektiv zu funktionieren. Beispielsweise basiert die automatische Aktualisierung der Benutzeroberfläche via Datenbindung von "Windows.Forms" und "WPF" auf Änderungsbenachrichtigung. Zustandsänderungen sollten über Ereignisse publiziert werden.
BCF bietet Änderungsbenachrichtigung für alle Datenänderungen – auch für berechnete Spalten und Validierungsergebnisse.
"Six, Seven, Eight" – weitere Anforderungen
6. Erweiterbarkeit
Bei der Entwicklung von BCF steht die Usability für die Entwickler im Fokus. Je wichtiger ein Gegenstand ist, umso einfacher soll dieser austausch-, erweiter- oder anpassbar sein.
Es gibt keine Beschränkungen bei den verwendeten Datentypen.
Die Programmierung eigener Funktionen und Validierungen ist ohne großen Aufwand möglich.
Für viele Belange gibt es austauschbare Hilfsklassen. Beispielsweise lassen sich Schreibvorgänge abfangen und umleiten (ähnlich Datenbanktriggern) oder eigene Funktionen zur Erzeugung von Standardwerten hinterlegen.
7. Performance
Die weit verbreitete Vorgehensweise, bei Datenänderung sofort die erforderlichen Berechnungen auszuführen, führt bei Transaktionen oft zu vielen überflüssigen Berechnungsaufrufen. BCF verwaltet Datenänderungen selbst und führt die Berechnungen erst am Ende der Transaktion aus. Dadurch werden die unnötigen Berechnungsoperationen ausgelassen. Die Performance erfährt je nach Komplexität eine signifikante Steigerung.
Bei datengebundenen berechneten Objektmodellen entfallen oft 90 bis 99 Prozent der gefühlten Verarbeitungszeit einer Datenänderung auf Anzeigeoperationen. Deshalb wurden in die bindbaren BCF-Objekte Ereignisfilter implementiert, die redundante Änderungsbenachrichtigungen unterdrücken.
BCF wurde optimiert für den Einsatz in Anwendungen und Apps mit Benutzeroberfläche. Daraus ergaben sich folgende Performancestrategien:
- höherer Speicherbedarf, dafür Reduzierung von Rechenzeit
- längere Initialisierungszeit, dafür kürzere Reaktionszeiten bei Datenänderung
8. Testbarkeit
Analog zur Erweiterbarkeit galt bei der Entwicklung von BCF: Je wichtiger ein Gegenstand, umso einfacher soll dieser testbar sein. Beispielsweise können eigene Funktionsklassen ohne Erzeugung eines Objektmodells direkt instanziiert, mit Parametern versorgt und die Berechnung ausgeführt werden.
BCF – Ein Überblick
BCF besteht aus der BCF Library und dem BCF Editor. Die BCF Library enthält die erforderlichen Klassen um anspruchsvolle Business- und View-Models zu betreiben. Der BCF Editor ist das Tool um die Modelle zu erstellen und Programmcode zu generieren.
Die Komponenten
BCF beinhaltet zum Zeitpunkt der Erstellung des Dokumentes die folgenden Elemente:
BCF Library
Die Bibliothek enthält die notwendige Infrastruktur, um Business-Models zur Laufzeit zu erzeugen und zu betreiben.
Endanwendungen mit Windows.Forms-Oberflächen sollten diese Bibliothek verwenden. Damit werden speziell für Windows.Forms bindbare Wrapper-Objekte (View-Models) angeboten.
Endanwendungen mit WPF Oberflächen sollten diese Bibliothek verwenden. Damit werden speziell für WPF bindbare Wrapper-Objekte (View-Models) angeboten.
BCF Editor
Der BCF Editor stellt eine große Erleichterung bei der Entwicklung von Datenmodellen dar. Mit dem BCF Editor können BCF-Datenmodell-Dateien bearbeitet und Programmcode generiert werden. Generiert werden hauptsächlich die typisierten Business- und View-Models. Der Editor unterstützt den Anwender durch Hinweise auf fehlerhafte Angaben und bei der Zuordnung von Funktionsparametern zu Spalten.
Der BCF Editor ist die erste Anwendung, die mit BCF erstellt wurde.
Einsatz von BCF
Mit BCF kann man:
- einfach tabellarische und relationale Datenmodelle erstellen, die schnell und zuverlässig sind
- typisierte Business- und View-Models generieren
- leicht Berechnungen jeder Komplexität implementieren
- einfach Änderungen an der Berechnungslogik umsetzen
- die Berechnung und Validierung vom Datenmodell trennen (zur Verbesserung der Test- und Wiederverwendbarkeit)
- statische und inhaltsbasierende Datenprüfungen implementieren
- Datenänderungen transaktional verarbeiten
- Undo/Redo ohne aufwändige Programmierung implementieren
Fazit
BCF spart Zeit und ermöglicht eine Effizienzsteigerung in der Softwareentwicklung und -pflege für Projekte unterschiedlicher Komplexität. Je komplexer die Abhängigkeiten und Berechnungen in einem Objektmodell sind, desto deutlicher treten die Vorteile der Verwendung von BCF hervor. Die optimalen Einsatzszenarien für BCF sind Anwendungen und Apps mit Benutzeroberfläche. Die exzellente Performance und die große Flexibilität machen BCF zu einem mächtigen Mittel in der Anwendungsentwicklung für das Microsoft .Net Framework.