Wider die konkret sinkende Produktivität
Die Geschichte der Softwareentwicklung im Allgemeinen ist eine Geschichte steigender Produktivität. Insbesondere seit den 1990ern mit ihren Offensiven an mehreren Fronten - RAD, OOP, Agilität - hat die Branche nochmal einen Sprung gemacht.
Und was ist das Geheimnis hinter diesem Produktivitätszuwachs? Abstraktion.
Abstraction by example
Ständig sind wir dabei, Details zu abstrahieren, um den Umgang damit einfacher zu machen.
Beweisstück 1: Programmiersprachen. Heute wie damals führen Prozessoren Maschinenode aus. Allerdings schreiben wir den schon lange nicht mehr. Zuerst hat uns Assembler über die Details der Maschinencodebitmuster erhoben. Dann kamen erste „richtige“ Programmiersprachen - 3GLs - von Fortran über Pascal bis Java, C#, Python usw. Und in manchen Bereichen wird sogar auf noch höherem Abstraktionsniveau programmiert mit 4GLs mit SQL, LabVIEW oder R. Ganz zu schweigen von noch spezifischeren DSLs wie RegEx oder Zapier.
Beweisstück 2: Frameworks. Bei gegebenen Programmiersprachen wie Ruby oder C# machen es Bibliotheken für spezifische Themengebiete noch einfacher, Code zu schreiben. Nur zwei triviale Beispiele:
- In C# kann ich den Inhalt einer Textdatei mit
File.ReadAllLines(...)
in einem Rutsch zeilenweise in den Speicher laden. Früher war dafür mühsames Hantieren mit file handles nötig. - In C# kann ich den Inhalt einer Textdatei von einem Webserver mit
new WebClient().DownloadString(...)
in einem Rutsch herunterladen. Kein mühsames Hantieren mit Streams mehr nötig.
Die Welt der APIs/Frameworks ist gerade in den letzten Jahren förmlich explodiert. Nichts, wozu es nicht schon eine Lösung gäbe: von Rechtschreibprüfung über Chart-Generierung bis zur emotionalen Analyse von Texten.
Beweisstück 3: Tools. Wie leicht ist es heute, Software zu verwalten, zu prüfen, zu deployen und zu betreiben! Das muss niemand mehr von Hand tun. Mit einem VCS müssen wir uns nicht mehr um die Details der Quelldateiverwaltung in Teams kümmern; mit Testsuites laufen Tests automatisch; mit CI bauen wir Software auf Kopfdruck; und mit einem Service wie Dropstack Vercel ist das Deployment selbst kleinster Funktionseinheiten in die Cloud ein no-brainer.
Robert C. Martin sagt, „Programming is about details“. Da hat er recht. Aber ganz viele Details interessieren uns heute nicht mehr - und deshalb sind wir so produktiv geworden. Wir haben wie „wegabstrahiert“.
Zugegeben, manchmal sind diese Abstraktionen nicht vollständig. Dann beißt uns LOLA, the Law of Leaky Abstraction. Aber allermeistens profitieren wir von Abstraktionen, ohne auch nur darüber nachzudenken.
Abstraktionen sind der Produktivitätshit!
So weit, so gut für die Branche Softwareentwicklung.
Aber wie sieht es innerhalb eines Projektes innerhalb der Branche aus?
Nicht gut, gar nicht gut.
Fehlende Abstraktion in Codebasen
Innerhalb von Softwareprojekten steigt die Produktivität nicht mit der Zeit. Sie steigt sogar nicht nur nicht, sondern sie sinkt. Sie sinkt massiv.
Oder andersherum ausgedrückt: Der Aufwand für weitere Features steigt ständig. Je länger an einem Projekt entwickelt wird, desto schwerer geht es voran.
Nicht umsonst wird über legacy code oder brownfield code oder the big ball of mud gesprochen. Das sind alles abfällige Begriffe für Codebasen, in denen die Produktivität nicht mehr der Hit ist.
Wie kann das aber sein? Wenn man die Branche betrachtet, steigt die Produktivität mit der Zeit; wenn man ein Projekt/Produkt betrachtet, sinkt die Produktivität hingegen? Merkwürdig, oder?
Vielleicht liegt die Erklärung aber gar nicht so fern. Wenn Abstraktion für die Branche der Produktivitätshit ist, in Bezug auf Codebasen die Produktivität jedoch sinkt… vielleicht fehlt dort dann einfach die Hit-Zutat, die Abstraktion.
Ich spekuliere mal: Wenn ein Projekt ebenso konsequent wie die Branche auf Abstraktion setzen würde, dann würde die Produktivität in Bezug auf eine Codebasis nicht so verlässlich sinken, sondern womöglich ebenfalls steigen. Es würde mit der Zeit immer einfacher werden, Funktionalität und Effizienz herzustellen.
Nur ist das nicht die Realität.
Es gibt zwar Mittel zur Abstraktion, allen voran in der Objektorientierung Klassen, Interfaces und sogar Vererbung - doch die werden anscheinend nicht so eingesetzt, dass die Produktivität stetig steigt (oder zumindest nicht fällt).
Irgendetwas fehlt also, etwas noch Grundlegenderes als diese Mittel.
Aus meiner Sicht ist das ein Modell von Software, in dem Abstraktion tatsächlich vorkommt.
Kaum zu glauben, oder? Ich reibe mir auch jeden Tag die Augen. Doch ein Modell, eine Grundvorstellung von Softwarestruktur, in der Abstraktion zentral ist als Mittel der stetigen Vereinfachung, sehe ich nicht.
Man könnte denken, dass das doch die Objektorientierung gewollt hat. Vielleicht. Wenn sie im Sinne von Alan Kay in der Masse angekommen wäre. Aber die de facto mainstream Objektorientierung enthält keine Vorstellung von Abstraktionsebenen, auf denen man nach oben klettern könnte. Und der ewige Wunsch nach Wiederverwendbarkeit ist dafür kein Ersatz.
Die nachgeschobenen Entwurfsmuster füllen die Lücke ebenfalls nicht. Sie abstrahieren zwar ein wenig für konkrete Anwendungsfälle, doch ihnen fehlt jedes Prinzip, jede Vision. In Entwurfsmuster steckt kein Zug hin zu mehr und mehr Abstraktion.
Und auch die Architekturmuster von MVC über Schichtenmodell bis zu den konzentrischen wie Hexagonal Architecture oder Clean Architecture lassen jeden Blick für Abstraktion vermissen.
Das ist womöglich am schwersten zu glauben, aber so ist es: in MVC oder in Clean Architecture sind keine Abstraktionsebenen enthalten. Natürlich ist jedes Modell abstrakter als die Realität. Nur ist Abstraktion deshalb noch kein Bestandteil des Modells.
Ok, das war jetzt abstrakt. Also konkret: Ein Controller in MVC ist nicht abstrakter als ein Model in MVC. Model und View und Controller in MVC sind alle auf demselben Abstraktionsniveau. Zusammen formen sie das Ganze und entsprechen dabei dem SLA Prinzip (Single Level of Abstraction).
Dito bei der Clean Architecture. Entities im Kern ist nicht abstrakter als Controllers in einer Schale drumherum.
Allerdings: Controllers oder Presenters sind abstrakter als die APIs, auf denen sie aufsetzen. Doch dieser Abstraktionshub an der „Membran“ einer Clean Architecture setzt sich nicht nach innen fort. Wieder ist also nichts gewonnen für das konkrete Projekt. Abstraktion passiert vor allem im Außen, bei den Technologien, auf denen eine Software aufsetzt, die nach Clean Architecture strukturiert ist.
Während die Produktivität im Allgemeinen steigt durch Abstraktion, sinkt sie im Konkreten durch die Haftung am Konkreten, durch den Mangel an Abstraktion, weil Ideen fehlen, wie Abstraktion systematisch innerhalb einer Software hergestellt werden könnte.
Stratified Design für systematische Abstraktion
Besonders verwunderlich ist das, weil der Ansatz dafür schon lange existiert. Abelson/Sussman haben ihn Stratified Design genannt. Hier habe ich darüber mal ausführlicher geschrieben.
Alan Kay kennt den Gedanken auch, hat dafür aber das Bild der Sprachen gewählt: Software solle aus Ebenen verschiedener Sprachen aufgebaut sein, deren Abstraktionsgrad schrittweise zunimmt.
Das könnte man als Argument für mehr DSLs auslegen. Für mich muss es aber keine ausgewachsene DSL sein; mir reicht Vokabular bestehend aus Funktionen und Modulen, das allerdings in einer speziellen „Dimension“ integriert wird zu „Sätzen“ auf unterschiedlichen Abstraktionsebenen. Das dahinter stehende Prinzip: IOSP (Integration Operation Segregation Principle).
Wenn Abstraktion der Produktivität innerhalb von Projekten auf die Sprünge helfen soll, braucht es ein Modell von Software, in dem Abstraktion zentral ist. Für mich ist das der Fall, wenn ich an die Softwareentwicklung mit dem IOSP herangehe. Dann ist für mich Stratified Design der Nordstern. Dann baue ich ständig an Abstraktionen auf unterschiedlichen Ebenen; dann spreche ich in meiner Software verschieden konkrete Sprachen: manchmal ist das Vokabular allgemein/umfassend, manchmal konkret/spezifisch.
Titelbild von Deadlyhappen - Eigenes Werk, CC-BY-SA 4.0, Link