Was ist Modularität? (Angewandte Modularität, Teil 1)

Was ist Modularität?

Dieser Blog ist der erste einer Serie zum Thema „Angewandte Modularität„. Die ersten drei Blogs dieser Serie haben zwar theoretischen Charakter, bereiten aber mehrere Blogs vor, in denen Modularität in sehr praktischer Form (u.a. OSGi, Micro-Services, Modulkonzept von Java 9) vorgestellt wird. Durch Vergleiche dieser verschiedenen Ansätze, modulare Software zu entwickeln, werden dann Gemeinsamkeiten und Unterschiede sowie Vor- und Nachteile dieser Ansätze deutlich.

Modularität bedeutet grundsätzlich das Aufteilen eines Ganzen in Teile. Dies geschieht zum Zweck, eine bessere Übersicht über das Ganze zu gewinnen und zu bewahren. Diese Idee wurde bereits vor vielen hundert Jahren in die berühmten Worte gefasst „teile und herrsche“ und wurde im politischen Sinne bereits bei den alten Römern intensiv praktiziert. Für uns Softwareentwickler bedeutet das: Untergliedere ein Softwaresystem so in Teile, dass das System wartbar wird und auch dann bleibt, wenn es noch komplexer wird. Die Wartbarkeit einer Software steht auf drei Säulen: Verständlichkeit, Änderbarkeit und Testbarkeit. Steht eine dieser Säulen nicht sicher, ist die Wartbarkeit und damit die Software selbst gefährdet (siehe auch http://clean-coding-cosmos.de/der-entwicklerkosmos/cleancoding1).

Software hat zwei sehr unterschiedliche Erscheinungsformen. Zum einen den Quellcode, den Softwareentwickler in ihrer Entwicklungsumgebung bearbeiten, und zum anderen die Programmpakete, wie sie zur Installation oder zum Deployment auf einem Zielsystem benötigt werden (die Deployment-Units, in Java typischerweise Artefakte wie EAR-, WAR- und JAR-Dateien). Beim Quellcode hat die Clean Code Bewegung mit den Prinzipien Separation of Concern, Single Responsibility and Interface Segregation Principle das Konzept „teile und herrsche“ propagiert (siehe auch http://clean-coding-cosmos.de/die-ccd-regeln). Dementsprechend sind Java-Entwickler gewohnt den Quellcode in folgende Strukturen zu unterteilen:

  1. Programmzeile / Anweisung
  2. Code Block aus mehreren Anweisungen
  3. Methoden
  4. Klassen
  5. Packages

Jeder dieser Strukturen stellt eine Ebene dar, in welcher der Quellcode unterteilt werden kann und die ineinander geschachtelt werden können. Ähnliche Strukturen auf einer höheren Ebene finden sich bei den Deployment-Units:

  1. Technische Module
  2. Geschäftskomponenten
  3. Subsysteme
  4. Systeme
  5. System-Cluster

Manche dieser höheren Ebenen lassen sich schachteln wie Quellcode. So kann z.B. eine EAR-Datei verschiedene WAR-Dateien beinhalten und eine WAR-Datei verschiedene JAR-Dateien. Für eine ganzheitliche Anwendung von Modularität lassen sich all diese zehn Strukturebenen nicht nur theoretisch unterscheiden, sondern in der Praxis auch wirklich nutzen, um Software zu modularisieren. Diese zehn Struktur- oder Granularitätsebenen lassen sich sehr gut in drei Hauptebenen unterteilen:

 


Ob ein großes Stück Software (eine Deployment-Unit) ein System oder Subsystem darstellt, hängt immer vom Kontext ab. Betrachtet man das Große und Ganze macht es Sinn, eine Deployment-Unit (z.B. ein WAR file) als Subsystem zu bezeichnen, um es als Teil des Ganzen zu charakterisieren. Betrachtet man ein Detail innerhalb einer Deployment-Unit, dann macht es Sinn die gleiche Deployment-Unit als System zu betrachten, um sich besser auf das Detail fokussieren zu können.

Und welchen Sinn macht es, zwischen Geschäftskomponenten und technischen Modulen zu unterscheiden? An Software werden sowohl funktionale (laden, anzeigen, ändern, speichern) als auch nicht-funktionale (Performance, Security) Anforderungen gestellt. Wenn Software jetzt in Teile gegliedert wird, gelten die nicht-funktionalen Anforderungen natürlich für alle funktionalen. Lösungen für die nicht-funktionalen Anforderungen werden sinnvollerweise in kleine spezielle Artefakte (technische Module) gepackt, die überall, wo diese Anforderungen benötigt werden, eingesetzt werden können. Diese kleineren Artefakte sind also auf Wiederverwertbarkeit ausgelegt – während die großen Artefakte, die typischerweise funktionale Anforderungen implementieren, das sehr häufig nicht sind. Es gibt z.B. nur eine Geschäftskomponente „Auftragserfassung“ im ganzen Softwaresystem, die aber die gleiche Security benutzt wie die Geschäftskomponente „Abrechnung“.

Ich vergleiche Software gerne mit einem Lehrbuch. Ein Lehrbuch besteht aus Hauptkapiteln, Unterkapiteln, großen und kleinen Absätzen sowie Sätzen. Außerdem können mehrere Lehrbücher zum gleichen Thema zu einer Serie zusammengefasst sein. Im Grunde gilt gleiches für die Software, wobei ein einzelner Satz eine Anweisung darstellt, Absätze stellen Methoden und Codeblöcke dar, Klassen sind Kapitel ohne Unterkapitel und Packages solche mit Unterkapiteln. Außerdem können mehrere Softwaresysteme einen Cluster bilden genauso wie mehrere Lehrbücher eine Serie. Je kleiner diese Strukturebenen geschnitten sind und je präziser jede einzelne Einheit in den verschiedenen Ebenen benannt wurde (aussagekräftige Bezeichner!), desto verständlicher, änderbarer und testbarer wird die Software.


Dieser Blog hat das Ziel, deutlich zu machen, was Modularität in der Welt der Softwareentwicklung bedeutet. Der nächste Blog wird auf die Vor- und Nachteile bzw. die Kosten und Nutzen von Modularität eingehen und der übernächste Blog wird sich dann mit den Mitteln beschäftigen, die zur Verfügung stehen, um modulare Software zu bauen. Die Blogs, die dann zum Thema folgen, wenden sich dann der Praxis zu. Mehr Details zum Thema finden sich auch unter https://leanpub.com/applied-modularity.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.