Century Support Teil 4: Mit Transformationen Generationen überbrücken
Dieser Gastartikel von Carsten Pitz ist der vierte Teil zum Thema Langzeitunterstützung. Im ersten Teil schildert Carsten die Entwicklung eines Dokumentationssystems, im zweiten Teil, wie der falsche Start schnell zu Problemen führen kann.Im dritten Teil ging es um die menschlichen Aspekte.
In diesem Teil geht es nun um ein konkretes Konzept, die Transformation.
Gastbeitrag von Carsten Pitz
Dieser und der folgende Teil sind wieder technisch geprägt. Der letzte Teil wird das Thema Dokumentation behandeln und ist eher nicht-technisch.
Wir hatten bereits im Teil 2 im Abschnitt „Ein erstes Review“ bemerkt, dass aufgrund nicht voraussehbarer Technologiewandel eine Anwendungsarchitektur kein Garant für einen 100+ Jahre Produktsupport darstellt. Dennoch halte ich – als Architekt aus Leidenschaft – eine Anwendungsarchitektur für sinnvoll. Wir werden im Verlauf dieses Artikels verstehen, eine Anwendungsarchitektur ist nicht bloß sinnvoll, sondern für einen 100+ Jahre Produktsupport notwendig.
Eine Anwendungsarchitektur ist für einen 100+ Jahre Produktsupport notwendig
Twittern
Wie eine Anwendungsarchitektur beschaffen sein muss um einen 100+ Jahre Produktsupport zu unterstützen erarbeiten wir uns jetzt.
Transformation
Ein Wandel ist eine Transformation von einen bestehenden in einen neuen Zustand. So abstrakt dies zunächst klingt, so ist die Transformierbarkeit der Anwendung aus meiner Sicht der wesentliche Schlüssel, einen 100+ Jahre Produktsupport zu ermöglichen.
Aber was macht eine Anwendung transformierbar? Zunächst ein kleiner Ausflug: Ich habe den Begriff Transformation bewusst gewählt, da dieser ein in der Mathematik ein geläufiger Begriff ist. In der Mathematik bildet eine Transformation eine Darstellung eines Sachverhalts in eine andere Darstellung ab.
Als Beispiel zerlegt die Fourier Transformation kontinuierliche, aperiodische Signale in ein kontinuierliches Spektrum. Aus einer Darstellung als Funktion der Zeit oder des Orts wird eine Darstellung als Funktion der Frequenz respektive der Ortsfrequenz.
Nett, aber wie hilft uns dieser Ausflug weiter? Aus der Mathematik können wir die Anforderungen an ein transformierbares Etwas ableiten. Wir benötigen eine formale Darstellung für das transformierbare Etwas, auf die eine Transformationsvorschrift angewendet werden kann.
In unserem Kontext ist dies die Anwendungsarchitektur, aus der wir sowohl (1) die Anwendung selbst, als auch (2) eine Folgearchitektur durch Transformationsvorschriften generieren können.
MDSE, in medias res
Und schwupps wir sind plötzlich mitten im MDSE (Model Driven Systems Engineering). Die Transformation 1 ist eine struktur-erhaltende Transformation und die Transformation 2 ist eine struktur-ändernde Transformation. Und plötzlich sind wir so richtig in medias res beim MDSE.
Über Struktur
In der Diskussion mit Michael Jastram wurde schnell klar, dass wir verschiedene Ansichten darüber haben, was Struktur ist. Daher eine kurze Erläuterung über meine Sicht auf den Begriff Struktur.
Für mich beschreibt die Struktur den Schnitt des Verhaltens in funktionale Einheiten als auch die Zuordnung von Zustand zu Verhalten. Dies klingt erst einmal äußerst komplex, ist es aber nicht.
Zum Schnitt des Verhaltens in funktionale Einheiten gibt es verschiedene Vorgehensweisen, welche sich in top-down, bottom-up und hybriden Vorgehen klassifizieren lassen. Ein top-down Vorgehen (z.B. FAST (Function Analysis System Technique)) führt in aller Regel zu einem anderen Schnitt als ein bottom-up Vorgehen (z.B. SOA (Service Oriented Architecture) oder auch das übliche Vorgehen bei der Entwicklung von HW für Steuerrechner aus vorgegebenen Bauelementen wie MCUs, Switches, PHYs, etc). Während bei einem top-down Ansatz der Aufbruch fortlaufend, hierarchisch verfeinert wird, wird beim bottom-up Ansatz ein System aus als existierend angenommenen (Teil-)Systemen zusammengesetzt. Eine Metrik, die meiner Erfahrung nach sich bei beiden Vorgehen extrem unterscheidet, ist die funktionale Redundanz. Aber auch der Relationsgraph zwischen den Entitäten ist grundsätzlich verschieden. Eine strikte hierarchische Verfeinerung führt stets zu einem Baum. Eine Synthese führt hingegen zu einer Überlagerung von Bäumen, zu einem Wald. Zudem ist der resultierende Grad der Knoten bei einer Synthese zumeist größer als bei der Zerlegung.
In der klassischen, prozeduralen Programmierung (z.B. BASIC oder FORTRAN 77) wird der gesamte Systemzustand in globalen Variablen verwaltet. Mit Einführung des Modulkonzepts (z.B. Modula2 oder FORTRAN90) konnten Modulen Teile des Systemzustands zugeordnet werden. Eine weitere Evolutionsstufe ist die Objektorientierung, hier bilden Objekte Entitäten, welche Zustand und Verhalten kapseln. Ein – aus meiner Sicht – wesentlicher Unterschied bei der Zuordnung von Zustand zu Verhalten bei Objektorientierung gegenüber der klassischen, strukturierten Programmierung und dem Modulkonzept ist, dass bei Objektorientierung zur Laufzeit aus einer Klasse (= Schablone) mehrere Objekte (= Instanzen) instantiiert werden können. Jedes Objekt kapselt einen Teil des Gesamtzustands.
Als kleine Anmerkung: Kapseln des Teilzustands impliziert hierbei insbesondere auch: schützt den Teilzustand vor externer Änderung. Die Objektorientierung bietet somit einen impliziten „Speicherschutz“ und damit ein Mittel Interferenzfreiheit über das Design sicherzustellen. Dies ist unabhängig davon ob aus dem objekt-orientierten Designmodell eine Realisierung als, in C++ oder auch MISRA C kodierte Software oder als, in VHDL spezifizierten ASIC erstellt wird. Wird nach VHDL transformiert, muss als einzige Einschränkung die Instanziierung der Objekte statisch sein. Da HW eh statisch ist, ist dies in der Praxis stets gegeben.
Wesentlich für die Struktur ist auch bei der Zuordnung von Zustand zu Verhalten, dass sich die Beziehungsgraphen grundlegend unterscheiden.
Beide Aspekte, der Schnitt des Verhaltens in funktionale Einheiten und die Zuordnung von Zustand zu Verhalten bestimmen die Entitäten, aus denen sich das System zusammensetzt als auch die Relationen zwischen diesen Entitäten. Dies ist für mich die Struktur eines Systems.
Die Struktur des Systems hat Auswirkungen auf die Arbeitsteilung im Entwicklungsteam, Konfigurationsmanagement, Methoden zur Fehlerisolation, etc. Aber dies ist eher eine Idee für einen getrennten Artikel.
Über Transformation
Wie der Begriff Struktur ist auch, wie Diskussionen ergaben der Begriff Transformation näher zu erläutern. Eine Transformation im Sinne dieser Artikelreihe ist eine Rechenvorschrift, mit welcher ein Modell in eine andere Darstellung umwandelt wird. Betrachten wir als Beispiel für eine Transformation eine einfache Summenbildung: aus einer Instanz eines (Daten-)Modells, das mehrere Zahlenwerte enthält wird eine Instanz eines (Daten-)Modells erzeugt, das genau einen Zahlenwert, die Summe enthält. Aus der Summe können wir nicht auf die Summanden zurück schließen. Diese Transformation ist entsprechend nicht umkehrbar.
Ein komplexeres Beispiel: Wir haben zwei Roboterarme mit einer unterschiedlichen Anzahl von Freiheitsgraden. Wir müssen einer Trajektorie folgen, der beide Roboterarme folgen können. Der Bewegungsablauf des Roboterarms mit weniger Freiheitsgraden kann in einen Bewegungsablauf des Roboterarms mit mehr Freiheitsgraden transformiert werden. Diese Transformation ist jedoch nicht eindeutig. Der Roboterarm mit mehr Freiheitsgraden hat mehrere Möglichkeiten der Trajektorie zu folgen. Dies gilt nicht nur für Bewegungsmodelle, sondern für Modelle allgemein. Entsprechend kann nicht von einem, aus einem Modell höheren Freiheitsgrades durch eine Transformation abgeleiteten Modell auf das zugrundeliegende (Quell-)Modell höheren Freiheitsgrades geschlossen werden.
Bei im Kontext MDSE (MDA) relevanten Modellen hat ein abstrakteres Modell mehr Freiheitsgrade als ein konkreteres Modell. Das Blockschaltbild eines Steuerrechners ist abstrakter als das Schaltplan (Schematics). Nehmen wir an, wir haben einen Steuerrechner mit zwei MCUs mit konfigurierbaren Pins. Laut Blockschaltbild kommunizieren beide MCUs via SPI. Diese Information ist aus dem Schaltplan (Schematics) nicht rekonstruierbar. Im Schaltplan (Schematics) sind nur Verbindungen zwischen Pins enthalten. Ob über diese Verbindungen SPI oder MII oder I²C realisiert wird, ist nicht ersichtlich.
Dies zeigt eine weitere Eigenschaft der im Kontext MDSE (MDA) verwendeten Transformationen. Diese Transformationen können zum Teil vorhandene Informationen nicht erhalten, können somit verlustbehaftet sein.
Die im Kontext MDSE (MDA) verwendeten Transformationen bilden grundsätzlich ein abstrakteres Modell in eine konkretere Darstellung ab und können zudem verlustbehaftet sein. Entsprechend sind diese Transformationen nicht umkehrbar.
M2T & M2M
Im Kontext MDSE (MDA) wird häufig von M2T (model to text) und M2M (model to model) Transformationen gesprochen. Diese Klassifikation ist jedoch rein technisch. M2T bzw. M2M sagen ausschließlich aus, ob das Resultat ein Text oder eine Modellrepräsention (z.B. MOF) ist. So kann ein Modell mittels einer M2T Transformation in einen Text transformiert werden, welcher ein strukturell geändertes Modell im XMI-Format repräsentiert. Diese M2T Transformation transformiert ein Modell in ein strukturell geändertes Modell.
… und zurück
Aber keine Angst, auch wenn MDSE eine steile Lernkurve hat, ist MDSE durchaus beherrschbar wenn ein paar einfache Grundregeln beachtet werden.
Noch ein Beispiel
Bevor wir zu den Grundregeln kommen ein wenig Motivation für MDSE. Vor etwa 15 Jahren gab es einen tiefgreifenden Wandel in der Entwicklung von Geschäftsanwendungen. Für neue Projekte wurde nicht mehr die Programmiersprache COBOL sondern die Programmiersprache Java verwendet. Eine Folge war, die Programmiersprache COBOL wurde weniger und weniger populär und entsprechend wenige lernten die Programmiersprache COBOL. Gut mag man denken, dann benötige ich bloß eine handvoll Personen, die sowohl COBOL als auch Java kennen und einen Java Code Generator für einen COBOL Compiler programmieren. Dieser COBOL Compiler erzeugt statt Object Code Java Code. Ach ja, die COBOL Quelltext-Kommentare sollte dieser Compiler natürlich auch noch in Java Quelltext-Kommentare umwandeln. Ein solcher COBOL Compiler ist wahrlich kein Hexenwerk und entsprechend gibt es etliche derartige Compiler (bspw. OpenCobol2Java). Einen Aspekt haben die zahlreichen Entwickler dieser COBOL Compiler jedoch vergessen. Deshalb werden mittlerweile von Einigen andere Vorgehen propagiert.
Welcher Aspekt wurde vergessen?
Mit der Programmiersprache hat sich auch die Methodik der Softwareentwicklung gewandelt. Waren COBOL Codes gemäß der Methode der strukturierten Programmierung nach Michael A. Jackson strukturiert, werden Java Codes gemäß der Methode der objekt-orientierten Programmierung (OOP) strukturiert. Die gewandelten COBOL Codes waren zwar Java Codes aber dennoch aufgrund der vollkommen unterschiedlichen Struktur für Java Entwickler zunächst schwer verständlich und somit erst nach einer Umgewöhnung wartbar. Dieser Aspekt macht diesen Weg nicht zu einem favorisierten.
Aber was ist die Struktur eines Quelltextes?
Die Struktur des Quelltextes ist schlicht und einfach die Struktur der Architektur des Quelltextes.
Was machen struktur-ändernde Transformationen?
Entsprechend müssen auch struktur-ändernde Transformationen beachtet werden. Struktur-ändernde Transformationen transformieren die Struktur und somit die Architektur. Struktur-ändernde Transformationen ändern die Struktur wie beim zuvor als Beispiel erwähnten Wandel beispielsweise von strukturierter Programmierung hin zur objekt-orientierten Programmierung (OOP).
Die struktur-erhaltenden Transformationen transformieren hingegen die Darstellung. Aus der Darstellung in einer Modellnotation (z.B. UML/SysML) wird eine Darstellung in einer i.d.R. höheren Programmiersprache (z.B. Java). Die Struktur, die Architektur ändert sich bei struktur-erhaltenden Transformationen nicht. Jedoch können struktur-erhaltende Transformationen Inhalte hinzufügen.
Im Vorgriff auf den letzten Teil können struktur-erhaltenden Transformationen auch verwendet werden, um aus den Modellen Dokumentation zu generieren. Und zwar sowohl Dokumentation für Entwickler als auch Dokumentation für Anwender. Beim Generieren von Dokumenten ergänzen struktur-erhaltende Transformationen z.B. das Format (Layout), Überschriften oder Inhaltsverzeichnisse.
Entwurfsmuster & Architektur
Um die Struktur eines Quelltextes zu ändern müssen zuvor die verwendeten Entwurfsmuster aus dem Quelltext bestimmt werden. Dies ist zwar prinzipiell möglich, artet aber zur Sisyphusarbeit aufgrund unterschiedlicher Realisierungen ein und des selben Entwurfsmusters durch verschiedene Entwickler oder gar des selben Entwicklers aus.
Die Architektur muss jedes Entwurfsmuster als einzelne, wiederverwendbare Meta-Architektur definieren und ausschließlich bei Anwendung von Entwurfsmuster auf die jeweils zugehörige Meta-Architektur verweisen.
Meta-Architektur
Im Vorgriff eine kurze Erklärung, weshalb ich Entwurfsmuster als Meta-Architekturen abbilde. UML definiert die vier Meta-Ebenen M0 bis M3. Beginnend mit der Realität als M0, über das Modell dieser Realität als M1, dem, zur Modellierung des Modells dieser Realität zugrunde liegende Meta-Modell (z.B. UML) als M2 und schließlich das dem Meta-Modell zugrunde liegende Meta-Meta-Modell, das MOF als M3.
Falls das UML Werkzeug dies unterstützt, ist mein favorisiertes Vorgehen das Meta-Modell um die Design-Pattern zu erweitern. Hierzu bevorzuge ich ein UML Werkzeug mit einen UML 2.x Profilmechanismus inklusive vollständiger OCL Unterstützung. Dies bietet jedoch kein mir bekanntes kommerzielles UML Werkzeug. Entsprechend muss hierzu bei allen mir bekannten, kommerziellen UML Werkzeugen gegen das jeweilige proprietäre interne Datenmodell programmiert werden. Dies ist zum Einen deutlich aufwändiger, zum Anderen ist dieses Vorgehen hochgradig Produkt-spezifisch.
In Einklang mit der UML Spezifikation nenne ich daher die Abbildung der Entwurfsmuster Meta-Architekturen.
MDSE zahlt sich aus
Zumindest gilt diese Aussage im Kontext Century Support. Aus einem geeignet aufgebauten Modell kann mit struktur-erhaltenden Transformationen
- der Quelltext,
- die Entwicklerdokumentation und
- die Anwenderdokumentation
und mit einer struktur-ändernden Transformation
- das Modell in eine neue Struktur generiert werden.
Ich glaube dies ist Anreiz genug um den MDSE Weg zu verfolgen.
Die Grundregeln
Die folgenden drei Grundregeln sind im Sinne des gesunden Menschenverstands Grundregeln für das Systems Engineering unabhängig von der verwendeten Methode.
Erläuterung & Rationale: Der Titel ist frei nach Albert Einstein. Je einfacher eine Architektur ist, je einfacher ist die Architektur transformierbar. Die Architektur muss jedoch ihren Zweck erfüllen, insbesondere in sich abgeschlossen sein. Entsprechend darf die Architektur nicht einfacher sein.
Erläuterung & Rationale: Ein und die selbe Problemstellung soll innerhalb eines Modells stets mit ein und der selben Problemlösung gelöst werden.
Diese Grundregel ist jedoch nicht auf Entwurfsmuster beschränkt. Auch sollte als weiteres Beispiel auch die Gruppierung von Eingangsdaten immer nach dem selben Regelwerk durchgeführt werden.
Hierdurch wird nur eine Transformationsvorschrift für die Transformation von gruppierten Eingangsdaten benötigt.
Ein weiterer Vorteil ist das durch die immer gleichen Strukturen auch das generierte Artefakt immer gleichartig ist. Beim Beispiel Eingangsdaten wären somit hieraus generierte Eingabemasken immer gleich aufgebaut. Damit wird die Lernphase von Anwendern reduziert und Fehlbedienungen vermieden.
Zudem muss falls eine Realisierung aufgrund eines Fehlers oder unzureichender Performance angepasst werden muss, nur eine Transformationsvorschrift geändert werden.
Erläuterung & Rationale: Ganz einfach: Garbage in, Garbage out!
Was muss transformiert werden?
Nur das Modell (zu dem auch die Schnittstellen gehören) muss transformiert werden. Das Modell enthält die notwendige Information. Die Transformation in ein Modell der nächsten Generation findet über eine Transformationsvorschrift statt. Doch wo soll diese herkommen? Die Transformationsvorschrift für die Transformation unseres Modells in das Modell unserer Nachfolger gibt es ja noch gar nicht
Unserer Nachfolger der nächsten Generation definiert die Ziele, die Anforderungen und die Struktur für das Modell der nächsten Generation. Wir kennen nicht die Ziele, sprich die Anforderungen, geschweige kennen wir die Struktur des Modells der nächsten Generation.
Wir brauchen also einen anderen Ansatz.
Das Transformationsziel: Modell der nächsten Generation
Aber wozu auch müssen wir die Anforderungen des Modells der nächsten Generation wissen? Wir müssen lediglich die Transformation ermöglichen, indem wir strikt die drei Grundregeln einhalten.
Was das bedeutet, wird im nächsten Teil behandelt.