Vor kurzem habe ich ein Buch mit dem Titel 'Design Rules, Vol. 1: The Power of Modularity' von Carliss Y. Baldwin und Kim B. Clark gelesen. Adrian Colyer hat mich während der hervorragenden AOP-Schulung, die im vorigen Beitrag erwähnt wurde, darauf aufmerksam gemacht.
Der Titel 'Design Rules', beachten Sie den Plural 'Rules', ist so etwas wie eine Fehlbezeichnung. In Wirklichkeit beschreiben die Autoren nur eine einzige Regel, wenn auch eine sehr wichtige. Sie argumentieren, dass die Computerindustrie ihr spektakuläres Wachstum begann, nachdem clevere Ingenieure bei IBM beschlossen hatten, das Design der 360-Familie in eine Reihe von Modulen aufzuteilen, die über Schnittstellen voneinander abhingen.
Die Designer eines solchen Moduls konnten mehr oder weniger tun, was sie wollten, solange sie die Schnittstelle korrekt implementierten. Dies ermöglichte unterschiedliche Implementierungen z.B. des Festplatten-Subsystems und förderte den Wettbewerb und bessere Designs von Subsystemen. Solange eine Implementierung die Schnittstelle respektiert, kann die Implementierung alles sein, auch revolutionäre neue Lösungen. Der Preis, der dafür zu zahlen ist, ist, dass die Änderung einer Schnittstelle kostspielig ist: Die Änderung des Busstandards bei einem PC z.B. würde eine Menge Hardware überflüssig machen und erfordert daher einen hohen technischen Aufwand. Starr definierte Schnittstellen führen zu einer Stabilität, die in Starrheit ausarten kann.
Die Autoren beschreiben keine Methode zur Erstellung eines guten modularen Designs, aber sie bieten eine Prüfung an, mit der Sie herausfinden können, ob Sie in die richtige Richtung gehen. Das Konzept ist das einer Abhängigkeitsmatrix. Jedes Merkmal eines Entwurfs wird sowohl in einer Spalte als auch in einer Zeile am oberen Rand der Matrix aufgeführt. Sie setzen dann ein X an den Schnittpunkt einer Zeile und einer Spalte, wenn das Merkmal in der Zeile von dem Merkmal oben in der Spalte abhängt. Ein Entwurf kann modularisiert werden, wenn es möglich ist, eine Reihe von Merkmalen zu gruppieren, die voneinander abhängen, aber nicht von Merkmalen außerhalb der Gruppe. Diese Eigenschaft ist in einer Matrixform leicht zu erkennen, viel leichter als ich es in Worten beschreiben kann.
Das Buch beschreibt ausführlich zwei Beispiele: die Entwicklung der IBM 360 Familie und die Konzepte der Unix-Implementierung auf einer PDP-11. Ich habe diese Beschreibungen der frühen Computergeschichte sehr gerne gelesen. Zugegeben, die Autoren hätten ihren Standpunkt auch auf 100 statt 483 Seiten vermitteln können, aber wenn man das Buch als Beschreibung der Computergeschichte betrachtet, ist es wirklich gut gelungen.
Die Autoren implizieren, dass man, sobald ein System modularisiert ist, berechnen kann, wie viele verschiedene Implementierungen eines Moduls auf wirtschaftlich sinnvolle Weise ausprobiert werden können. An dieser Stelle verlieren sie mich in Formeln, die zwar unbewiesen bleiben, aber intuitiv sinnvoll sind. Es ist leicht zu erkennen, dass eine Implementierung, solange sie die Regeln der Schnittstelle erfüllt, durch eine andere ersetzt werden kann. Das heißt, Sie können versuchen, eine bessere Version z.B. einer Netzwerkkarte zu finden, solange sie in einen PCI-Steckplatz passt und die Signale auf dem Bus versteht.
Ich glaube, der Modularisierungstrick sollte auch für Software funktionieren. Das Buch konzentriert sich zwar auf Hardware, wo die Vorteile der Modularisierung deutlicher zu Tage treten, aber es ist leicht zu erkennen, dass wir große Probleme in kleinere aufteilen müssen, die unabhängig voneinander gelöst und weiterentwickelt werden können. Genau das habe ich 2005 bei einem Kunden getan. Das System, das sie aufgebaut hatten, war sehr starr geworden, weil jede Änderung das gesamte System auf unvorhersehbare Weise durcheinanderwirbelte. Kundenfunktionen hingen von Produktfunktionen ab und umgekehrt, was Änderungen zu einem echten Vertrauensvorschuss machte. Zunächst zeichneten wir ein Moduldiagramm, d.h. ein einseitiges Linien- und Kästchendiagramm, in dem die Abhängigkeiten zwischen den Hauptkomponenten beschrieben wurden. Zirkuläre Abhängigkeiten waren nicht erlaubt. Dann begannen wir mit der Umstrukturierung des Codes, um die gewünschten Abhängigkeiten zu erfüllen. Vier Entwickler benötigten dafür weniger als sechs Monate. Das Ergebnis war ein System mit Modulen, die unabhängig voneinander geändert werden konnten.
Ich höre einige von Ihnen im Hintergrund 'XML' flüstern, aber wir sind nicht diesen Weg gegangen. Alles, was wir brauchten, waren Java-Schnittstellen: Der Code in einem Modul hängt von den Schnittstellen in anderen Modulen ab, nicht von Implementierungen. Wenn wir wollten, könnten wir direkte Java-Aufrufe durch EJBs oder SOAP-Dienste ersetzen, aber das war nicht nötig, also haben wir es nicht getan.
Das Software-Äquivalent des PC-Busses ist nicht EJB und auch nicht SOAP. Das Software-Äquivalent des PC-Busses ist eine einfache alte Java-Schnittstelle.
Verfasst von

Jan Vermeir
Developing software and infrastructure in teams, doing whatever it takes to get stable, safe and efficient systems in production.
Contact
Let’s discuss how we can support your journey.



