Wird Code nach dem Prinzip der gegenseitigen Nichtbeachtung erstellt, so ist er so unabhängig wie möglich. Dadurch lässt er sich leichter verstehen und auch verändern. Bei der Entwicklung der Softwarelösungen unserer Kunden achten wir besonders darauf, dass unsere auch Lösungen langfristig weiterentwicklungsfähig bleiben.
Hier habe ich gezeigt, wie ich derzeit versuche Software aufzubauen. Dazu verwende ich Flow-Design. Und das nun seit vielen Jahren. Beim ersten Betrachten dachte ich, dass es sich hierbei nur um eine Variante der strukturierten Analyse handelt. Steht doch bei beiden der Datenfluss und die Zerlegung in kleinere Teile im Vordergrund, aber bei Flow-Design geht es vor allem um das Thema Evolvierbarkeit.
Das Fundament auf dem Flow-Design aufbaut, ist das „Prinzip der gegenseitigen Nichtbeachtung“ (Principle of Mutual Oblivion), auch PoMO genannt. Dieses Prinzip wurde von Ralf Westphal geprägt. Im Grunde bedeutet das nichts anderes, als dass sich die einzelnen Komponenten einer Software nicht kennen dürfen. Der Begriff Komponente ist dabei nicht ganz passend, kann es sich dabei je nach Granularität um Methoden, Objekte/Klassen, Prozesse usw. handeln. Aus diesem Grund eignet sich der Begriff Funktionseinheit, um zu zeigen, dass da drin etwas passiert, ohne die Größe der Einheiten festzulegen. Natürlich ist das Ganze erst mal nichts Neues, wissen wir doch schon lange, dass jede Form von Abhängigkeit der Evolvierbarkeit von Software schadet.
Ansätze zum modularen Zerlegen von Software gibt es schon lange. Meist mit dem Ziel Software flexibel zusammenzubauen oder Teile wiederzuverwenden. Gerne wird hier eine Analogie in anderen Bereichen (z.B. dem Maschinenbau) gesucht. Auch, wenn es in der materiellen Technik keine zur Software vergleichbaren Abhängigkeiten gibt. Als Beispiel werden gerne Lego-Bausteine genannt oder andere technische Dinge wie eine Zündkerze. Denn eine Zündkerze hat keine Ahnung von einem Motor. Sie weiß auch nicht, dass sie in einem Motor verbaut ist. Genauso hat der Motor keine Ahnung davon ob dieser wirklich in einem Auto verbaut ist. Denn er dreht genauso, wenn er auf einem Prüfstand betrieben wird.
Für mich persönlich ist derzeit das beste Beispiel eine Produktionslinie. Eine solche Produktionslinie besteht aus vielen Stationen. An jeder dieser Stationen wird irgendetwas getan. Geschraubt, Lackiert, Gebohrt, Geschweißt etc. Und am Ende purzelt ein fertiges Produkt raus. Das viele verschiedene Stationen durchlaufen hat.
Genauso ist es auch bei PoMO. Funktionseinheiten leisten jeweils etwas, kennen sich aber nicht untereinander. Der Unterschied zu vielen anderen Ansätzen liegt hierbei in der Radikalität wie dies eingefordert wird. So geht PoMO z. B. viel weiter als es das Dependency Inversion Principle fordert. Denn selbst wenn wir statische Abhängigkeiten durch IoC auflösen, so sind diese zur Laufzeit immer noch vorhanden. Funktionseinheiten nach PoMO dürfen sich hingegen auch zur Laufzeit nicht kennen.
Eine Umsetzung nach PoMO variiert je nach verwendeter Programmiersprache. Je nach Sprache kann die Radikalität von PoMO dann ggf. auch nicht voll eingehalten werden. Grundlegend gilt dabei aber immer, dass Daten nur noch unidirektional fließen dürfen. Eine einfache Lösung die PoMO befolgt, habe ich neulich gezeigt. Dort habe ich auf klassische Methodenaufrufe mit Übergabeparameter und Rückgabewerte gesetzt. Was zeigt, dass auch mit einfachen Mitteln das Prinzip der gegenseitigen Nichtbeachtung umgesetzt werden kann.
Auch wenn es die einzelnen Funktionseinheiten selbst nicht interessiert wie diese nachher zusammengesetzt werden, so bleibt dennoch die Frage wie das Zusammenbauen nachher funktionieren sollen. Denn nur wenn diese zusammengesetzt werden, können diese auch etwas Größeres erfüllen. Dafür benötigt es dann einen Kontext der vorgibt wie die Schnittstellen der Funktionseinheiten aussehen müssen, damit diese nachher auch zusammenpassen. Beim Zusammensetzen selbst hilft ein weiteres Prinzip, nämlich das Integration Operation Segregation Principle. Welches ich in meinem nächsten Post etwas näher beleuchten werde.
Anmerkung: Bei diesem Text handelt es sich um einen überarbeiteten Repost eines alten Blog-Artikels aus 2015 von mir.