Bei der Software-Entwicklung liegt der Fokus oftmals auf der reinen Funktionalität der Software, da der Kunde erwartet, dass die gewünschten Funktionen durch die Software korrekt abgedeckt sind. Neben der Funktionalität dürfen aber die anderen Eigenschaften guter Software nicht vernachlässigt werden: die Möglichkeit, die Software zu warten, zu erweitern und bereitzustellen. Deshalb setzen wir in der Virality bei neuen Projekten vermehrt auf das Clean Architecture Prinzip (Martin, Robert C. Clean Architecture. Pearson, 2017), welches sich vor allem in umfangreichen Projekten bewährt hat.

Details vs. Anwendungslogik
Eine gute Architektur erlaubt es, Änderungen ohne großen Aufwand durchzuführen. Dies wird auch dadurch erreicht, dass Detail-Entscheidungen so spät wie möglich getroffen werden, um bei neuen Anforderungen möglichst flexibel agieren zu können. Diese Details können zum Beispiel die Wahl der Datenbank, die Art der Netzwerk-Kommunikation oder die grafische Benutzeroberfläche sein. Die eigentliche Logik der Anwendung darf zu diesen Details keine Abhängigkeiten haben. In Abbildung 1 sind diese Details in der äußersten Schicht angesiedelt, die schwarzen Pfeile verdeutlichen, dass Abhängigkeiten stets nur von außen (Details) nach innen (Logik) zeigen dürfen. Dadurch kann beispielsweise auch spät in der Entwicklung die Datenbank oder die Benutzeroberfläche ausgewechselt werden, ohne dass die eigentliche Logik der Anwendung angepasst werden muss. Alle Komponenten einer Anwendung, die in der Zukunft voraussichtlich angepasst oder ausgetauscht werden müssen, sollten in dieser äußersten Schicht angesiedelt sein. Dazu gehören beispielsweise Bibliotheken und Frameworks. Verwendet man Framework-spezifischen Code nur in der äußeren Schicht, kann die Logik der Anwendung einfacher auf andere Plattformen portiert werden, da alles in den übrigen Schichten unverändert übernommen werden kann.

(Martin, Robert C. Clean Architecture. Pearson, 2017)

Use Cases
Besonders erwähnenswert ist die Schicht “Use Cases” des Modells, die in der Abbildung als dritte Schicht von außen dargestellt ist. Durch die zentrale Anordnung der Schicht ist bereits klar, dass es hier um Anwendungslogik geht. Bei einem Use Case handelt es sich um eine bestimmte Aktion die meist durch den Nutzer ausgelöst wird. Das kann zum Beispiel bedeuten, dass der Nutzer einen neuen Kontakt in sein Kontaktbuch eingibt und bestätigt. In diesem Fall würde die entsprechende View die eingegebenen Daten an ihren Presenter übergeben und dieser den AddNewContactUseCase starten (statt Use Case wird auch der Begriff “Interactor” verwendet). Der Use Case würde den neuen Kontakt zum Beispiel in die Datenbank schreiben oder über das Netzwerk versenden.

Kontrollfluss
Eine oft gestellte Frage ist, wie man die Abhängigkeiten von inneren zu äußeren Schichten verhindert. Wie kann zum Beispiel der AddNewContactUseCase ein Element in die Datenbank speichern, ohne die Datenbank zu kennen? Dies kann durch Anwendung des Dependency Inversion Principle an allen Stellen, an denen der Kontrollfluss von einer inneren Schicht zu einer äußeren geht, erreicht werden. Das bedeutet, dass auf der zentraleren Schicht ein Interface definiert wird, welches auf der äußeren Schicht implementiert wird. Die zentralere Schicht kommuniziert dann lediglich über dieses Interface mit der äußeren Schicht, wodurch keine Abhängigkeit von innen nach außen besteht.

Abstraktheit
Ein weiteres wichtiges Prinzip ist die Zunahme der Abstraktheit zur Mitte hin: Je weiter man sich in den Schichten nach innen bewegt, desto abstrakter wird der Code. Das bedeutet, dass in der Anwendungslogik deutlich mehr abstrakte Klassen und Interfaces zu finden sind als in den äußeren Bereichen. Hier wiederum sind die meisten Klassen konkrete Implementierungen, die die Anwendungslogik mit der “Außenwelt”, also der Anwendungsumgebung verbinden. Bei der Datenspeicherung wäre zum Beispiel ein Repository-Interface in einer zentralen Schicht angeordnet, während die tatsächliche Kommunikation mit der Datenbank als konkrete Implementierung auf der äußeren Schicht liegt.

Fazit
Die Verwendung von Clean Architecture führt bei uns zu einer besseren Code-Struktur, deutlich effizienteren Arbeitsweise, und generell einer höheren Qualität der Software. Auch neue Kollegen können sich durch die Übersichtlichkeit schnell in Projekte einarbeiten. Außerdem kann auf Änderungswünsche der Kunden schnell reagiert werden, da meist nur wenige Anpassungen nötig sind.

Über den Autor