Entwickelt man heute mobile Anwendungen für iOS oder Android, dann heisst es häufig man müsse unbedingt einem bestimmten Architektur-Pattern folgen wie MVVM oder VIPER. Sonst würde sofort die App schlecht werden.
Nun ist es nicht verkehrt gewissen Mustern zu folgen, denn das macht es für andere Entwickler einfach den Code zu verstehen und man hilft natürlich auch sich selbst dabei, das Rad nicht neu zu erfinden.
Das Problem ist aber, dass nicht alle Architektur-Muster gleichermassen geeignet sind. Am wichtigsten ist dabei wohl, dass viele Architektur-Muster für kleine Anwendungen mit 1-2 Entwicklern irgendetwas zwischen Overkill oder sogar Kontraproduktivität sind.
Das beste Beispiel hierfür ist meiner Meinung nach VIPER: Das Akronym steht für View, Interactor, Presenter, Entity, and Routing. Anstatt die Anwendung in drei Kernaufgaben zu spalten wie bei MVC, nämlich in Model, View und Controller, sind es nun fünf.
Das ist nicht per se falsch, aber auch nicht per se richtig.
Zunächst mal sollte man sich daran erinnern, dass das VIPER-Muster aus der Backend-Welt kommt. Aus dem Universum mit Java und C#. Dort sitzen schnell mal 10, 100 oder 1000 Entwickler an einem Produkt. Das wird auch dann nicht besser, wenn ein Backend aus lauter Microservices besteht und somit sauber modularisiert ist. Denn schliesslich will man auch bei einem verteilten, gut modularisierten Backend mit vielen Entwicklern einen Zoo aus zu vielen verschiedenen Sprachen, Mustern und Konzepten vermeiden.
Wenn man also ein grosses Stück Software entwickelt, dann ist ein hoher Grad an Abstraktion und Regeln schwer vermeidbar. Denn die vielen Teams, häufig verteilt über diverse Länder und Zeitzonen oder sogar unterschiedliche Unternehmen und Kulturen (beim Einsatz von externen Dienstleistern) brauchen nun mal etwas mehr Regulation, um gut zusammen zu arbeiten, als ein Team von 1-2 Entwicklern.
Wenn ich nun aber in besagtem kleinen Team bin, vielleicht auch noch in einem Startup, dann habe ich viele Probleme aus der Corporate-lastigen Welt grosser Backends eben nicht.
Alle Teile der App werden ja gerade von einer geringen Anzahl an Entwicklern entwickelt. Diese können sich leicht auf einfache, gemeinsame Muster einigen und häufig Reviews durchführen, so dass der Code gut lesbar und erweiterbar bleibt, selbst wenn er keinem zu komplexen Architektur-Muster folgt.
Häufig hat ein Startup auch weniger Fluktuation als ein Grossunternehmen, sonst macht dieses Startup vermutlich ohnehin Grundlegendes falsch und die Software muss gar keine 5-10 Jahre wartbar bleiben.
Und darüber hinaus ist das VIPER-Pattern optimiert für die typische “Business-Anwendung”. Eine Anwendung, die zwar relativ komplexe Geschäftsregeln und aufwändige Datenmodelle hat, aber nicht unbedingt den Fokus auf besondere Benutzbarkeit, Geschwindigkeit, niedrigen Datenverbrauch oder Stromsparsamkeit legt.
Was also, wenn meine Anwendung gar nicht so ein komplexes Datenmodell hat, von wenigen Entwicklern entwickelt und gewartet wird, dafür aber möglichst sparsam und einfach zu benutzen sein soll.
Ein Beispiel kann hier die Facebook- oder die Revolut-App sein, im Gegensatz zu einer App, die Türen im Büro öffnet.
Meine Philosophie ist hier ein klares Nein!
Eine zu grosse, künstliche Modularisierung nach einem Schema, das mit dem konkreten Anwendungsfall nicht viel zu tun und dann möglicherweise auch noch grundsätzlich zu granular ist, hilft niemandem weiter.
Viele Architekten und Entwickler vergessen, dass Modularisierung zunächst mal Overhead bedeutet, also Geld, Zeit und Nerven kostet. Das muss sich rentieren und sollte nicht aus reiner Prinzipienreiterei erfolgen.
Ein Warnzeichen ist, wenn man viele Klassen hat mit einer einzigen Methode und wenigen Variablen / Eigenschaften. Hier liegt meines Erachtens nach eine klare Fehlinterpretation des “Single Responsibility”-Prinzips vor. Single Responsibility bedeutet nämlich nicht, dass in Wirklichkeit eine Responsibility erstmal auf 5-10 Klassen verteilt wird und schnell die Übersichtlichkeit verloren geht, wie diese miteinander zusammen wirken, um eine Funktionalität zu implementieren.
Wenn ein Architektur-Muster in einem konkreten Fall Übersichtlichkeit, Verständlichkeit oder auch die Nutzung von Tools der IDE behindert, dann stimmt etwas nicht.
Und es ist meines Erachtens nach auch dann meistens nicht zu rechtfertigen, wenn damit die Modularität isoliert betrachtet erhöht wird und beispielsweise der subjektive Eindruck entsteht, man könne so Merge-Konflikten aus dem Weg gehen.
Aber auch hier gilt: Am Schluss lässt sich nur durch Diskussion und Reviews mehrerer Entwickler im konkreten Fall sagen, was nun das Optimum ist.
MVVM ist meistens die bessere Wahl als VIPER, da einfacher und ein guter Kompromiss aus verschiedenen Faktoren.
Zum einen ist MVVM nahe dran an MVC und MVP, den zwei “Standard-Mustern” unter iOS und Android. Somit oktroyiert man also nicht etwas zu Künstliches auf die üblichen Praktiken, die in der Apple- und Google-Welt verbreitet sind.
Auch der Lernaufwand ist geringer für junge Entwickler, die gerade erst angefangen haben, und noch sehr an die vielen Code Samples und Tutorials aus den diversen Online-Kursen und der SDK-Dokumentation gewöhnt sind und vielleicht noch keine Erfahrung in zwei oder mehr Software-Welten haben.
Ausserdem könnte VIPER in 5-10 Jahren schon wieder aus der Mode sein, so wie das immer in der Software-Welt ist, da es eben recht spezifisch ist und selbst erst ein paar Jahre alt ist.
MVC und seine leichten Abwandlungen MVVM und MVP hingegen existieren nun schon seit gut drei Jahrzehnten. In der Informatik ist das eine Ewigkeit und legt nahe, dass diese Muster auch in weiteren 30 Jahren vielleicht noch wohl verstanden sein werden.
Und dann ist nun mal so, dass viele mobile und nicht-mobile Apps gar nicht 10 Jahre lang gewartet werden müssen. Bei einem Prototypen beispielsweise hat der konsequente Einsatz von sonst sinnvollen Mustern häufig keinen Sinn, da ein Grossteil des Codes beim nächsten Wechsel des Geschäftsmodells verworfen werden muss.
Am ehesten sollte man komplexere Muster wie VIPER einsetzen, wenn die Voraussetzungen auch vorhanden sind, die zu deren Entwicklung geführt haben: Wenn ich eine richtig grosse Anwendungen mit vielen Entwicklern über viele Jahre entwickeln und warten möchte und der Businesscase bereits validiert ist.
Insgesamt sind also VIPER und diverse Ungetüme also für die Sonderfälle, die wirklich komplexen Anwendungen vorzubehalten.
Das sind vermutlich 80% der Anwendungen - zum Glück - nicht.
Im Zweifel empfehle ich also bei einfacheren Vorgehensweisen zu bleiben und diese erst dann abstrakter, verteilter und komplizierter zu machen, wenn klar ist, warum das gerechtfertigt ist.