Wie behindert eine hohe Komplexität in Controllern die Wiederverwendbarkeit von Programmcode?

Melden

Eine hohe Komplexität in Controllern (oft als „Fat Controller“ bezeichnet) ist eines der häufigsten Hindernisse für die Wiederverwendbarkeit von Programmcode. In der Softwarearchitektur (insbesondere im MVC-Muster) sollte ein Controller lediglich die Anfrage entgegennehmen, die Logik delegieren und die Antwort zurückgeben.

Wenn Controller jedoch zu komplex werden, entstehen folgende Probleme, die eine Wiederverwendung verhindern:

1. Vermischung von Geschäftslogik und Infrastruktur

Wenn die eigentliche Berechnungslogik oder Entscheidungslogik direkt im Controller steht, ist sie untrennbar mit der Web-Infrastruktur verbunden.

  • Das Problem: Möchte man dieselbe Logik an einer anderen Stelle nutzen (z. B. in einem zeitgesteuerten Background-Job, einer Konsolenanwendung/CLI oder einer mobilen API), müsste man den Controller instanziieren oder die Logik kopieren.
  • Die Folge: Code-Duplizierung statt Wiederverwendung.

2. Kopplung an spezifische Request/Response-Objekte

Komplexe Controller arbeiten oft direkt mit Objekten des Web-Frameworks (z. B. HttpRequest, HttpContext oder Session).

  • Das Problem: Diese Objekte existieren nur im Kontext eines HTTP-Aufrufs. Wenn die Logik tief im Controller vergraben ist, kann sie nicht einfach in einer anderen Umgebung aufgerufen werden, die diese spezifischen Objekte nicht kennt.
  • Die Folge: Die Logik ist „gefangen“ im Web-Framework.

3. Verletzung des Single Responsibility Principle (SRP)

Ein komplexer Controller übernimmt oft zu viele Aufgaben: Validierung, Autorisierung, Datenbankzugriffe, Logging und Geschäftslogik.

  • Das Problem: Wenn man nur einen kleinen Teil dieser Funktionalität an anderer Stelle benötigt, kann man den Controller nicht nutzen, ohne den gesamten anderen „Ballast“ mitzuschleppen.
  • Die Folge: Der Code ist zu monolithisch, um in kleinen, modularen Stücken wiederverwendet zu werden.

4. Schwierige Testbarkeit (Unit Testing)

Hohe Komplexität bedeutet meist viele Abhängigkeiten und verzweigte Logikpfade.

  • Das Problem: Um einen komplexen Controller in einem Test aufzurufen, müssen extrem viele Abhängigkeiten (Datenbanken, HTTP-Kontexte, Authentifizierungs-Mocks) vorbereitet werden.
  • Die Folge: Da der Code schwer zu testen ist, scheuen sich Entwickler davor, ihn in anderen Projekten oder Modulen wiederzuverwenden, da die Stabilität nicht garantiert werden kann.

5. „Abhängigkeits-Hölle“ (Dependency Bloat)

Je mehr ein Controller tut, desto mehr Dienste muss er per Dependency Injection (DI) einbinden.

  • Das Problem: Ein Controller, der 10 verschiedene Services injiziert bekommt, ist schwer wiederzuverwenden, weil jedes Mal alle 10 Abhängigkeiten aufgelöst werden müssen, selbst wenn man nur eine einzige Methode des Controllers nutzen wollte.

Die Lösung: Thin Controllers & Service Layer

Um die Wiederverwendbarkeit zu erhöhen, wird das Prinzip der „Thin Controllers“ angewandt:

  1. Service Layer: Die gesamte Geschäftslogik wird in separate Klassen (Services) ausgelagert. Diese sind unabhängig vom Web-Framework.
  2. Domain Models: Datenverarbeitung findet in reinen Datenklassen oder Domain-Objekten statt.
  3. Controller als Vermittler: Der Controller nimmt nur die Daten entgegen, ruft einen Service auf und gibt das Ergebnis zurück.

Vorteil: Die Logik im Service kann nun problemlos von überall aufgerufen werden – vom Web-Controller, von einem Terminal-Befehl oder von einem anderen Modul aus. Der Code ist nun echt wiederverwendbar.