Action Domain Responder Pattern

Action–Domain–Responder Pattern

vg

Das Action Domain Responder Pattern (ADR) ist ein Software-Design-Muster, das vor allem im Bereich der Webentwicklung verwendet wird. Es wurde von Jonathan Rasmusson eingeführt und dient dazu, die Struktur und Trennung von Verantwortlichkeiten in Webanwendungen zu verbessern. Dieses Muster ist eine Alternative zum klassischen Model-View-Controller (MVC)-Muster, das in vielen Webanwendungen verwendet wird.

Das ADR-Muster konzentriert sich auf die Aufteilung der Anwendung in drei Hauptkomponenten: Action, Domain und Responder. Jede dieser Komponenten hat eine spezifische Rolle, und zusammen helfen sie dabei, eine klare Trennung von Bedenken (Separation of Concerns, SoC) und eine bessere Wartbarkeit des Codes zu gewährleisten.

Action des Action–Domain–Responder Pattern

Die Action-Komponente ist der Einstiegspunkt für eine Benutzeranfrage. Sie empfängt die Anfragen und übersetzt sie in eine Form, die von der Domain-Schicht verarbeitet werden kann. Eine Action ist im Wesentlichen dafür zuständig, die Geschäftslogik auszuführen, indem sie die entsprechenden Domain-Komponenten aufruft.

In C++ könnte eine Action beispielsweise so aussehen:

class Action {
public:
    Response execute(Request& request) {
        // Verarbeitung der Anfrage
        DomainModel model = domainService.getModel(request);
        return responder.respond(model);
    }
};

Die Action nimmt eine Request entgegen, kommuniziert mit der Domain, und ruft einen Responder auf, um die Antwort zu generieren.

Domain des Action–Domain–Responder Pattern

Die Domain-Schicht enthält die Geschäftslogik der Anwendung. Sie ist vollständig unabhängig von der Art und Weise, wie die Benutzeroberfläche oder die Eingabe behandelt wird. Die Domain verarbeitet Daten, führt Berechnungen durch und speichert Informationen in der Datenbank. Sie sollte so weit wie möglich von den Details der Webanwendungsinfrastruktur entkoppelt sein.

Ein Beispiel für eine Domain-Komponente in C++ könnte so aussehen:

class DomainModel {
public:
    std::string name;
    int age;

    DomainModel(std::string n, int a) : name(n), age(a) {}
};

Die Domain ist also für die Speicherung und Verarbeitung von Entitäten wie DomainModel verantwortlich. Sie stellt sicher, dass alle Regeln und Berechnungen korrekt ausgeführt werden.

Responder des Action–Domain–Responder Pattern

Der Responder ist dafür verantwortlich, eine Antwort zu generieren, die an den Benutzer zurückgegeben wird. Während die Action den Antrag verarbeitet und die Domain die Geschäftslogik ausführt, sorgt der Responder dafür, dass das Ergebnis in einem geeigneten Format an den Benutzer übermittelt wird.

Ein Responder könnte so aussehen:

class Responder {
public:
    Response respond(DomainModel& model) {
        // Erzeugt eine Antwort auf die Anfrage
        Response response;
        response.setContent("Name: " + model.name + ", Age: " + std::to_string(model.age));
        return response;
    }
};

Der Responder kümmert sich also um die Formatierung der Antwort und sorgt dafür, dass sie dem richtigen Format entspricht, z. B. als HTML, JSON oder XML.

Wie funktioniert das Action–Domain–Responder Pattern?

Das ADR-Muster trennt klar die Verantwortlichkeiten zwischen den verschiedenen Komponenten. Wenn ein Benutzer eine Anfrage stellt, passiert Folgendes:

  1. Action empfängt die Anfrage und entscheidet, welche Domain-Komponente benötigt wird.
  2. Domain führt die benötigte Geschäftslogik aus und stellt ein Ergebnis bereit.
  3. Responder formatiert das Ergebnis und sendet die Antwort an den Benutzer zurück.

Diese klare Trennung von Aufgaben ermöglicht eine bessere Wartbarkeit und Erweiterbarkeit der Anwendung. Jedes Modul hat nur eine spezifische Aufgabe und kann unabhängig von anderen Modulen entwickelt und getestet werden.

Vorteile des Action–Domain–Responder Pattern

  1. Trennung von Anliegen: Das ADR-Muster trennt klar die Verantwortlichkeiten der verschiedenen Komponenten. Die Action kümmert sich nur um die Anfrage, die Domain nur um die Geschäftslogik und der Responder um die Ausgabe. Diese Trennung erleichtert das Testen und die Wartung.
  2. Erweiterbarkeit: Da die Komponenten entkoppelt sind, können sie problemlos erweitert oder ersetzt werden, ohne dass andere Teile der Anwendung betroffen sind. Zum Beispiel könnte der Responder leicht angepasst werden, um eine andere Art der Antwort zu erzeugen, ohne die Action oder Domain-Schicht zu beeinflussen.
  3. Sauberer Code: Durch die Trennung von Geschäftslogik, Anfragen und Antworten bleibt der Code übersichtlich und leicht verständlich. Dies fördert die Lesbarkeit und Wartbarkeit des Codes.
  4. Flexibilität bei der Antwortgenerierung: Der Responder ermöglicht es, unterschiedliche Antwortformate je nach Bedarf zu erzeugen, ohne dass dies die Geschäftslogik oder die Anfragebearbeitung beeinträchtigt.
  5. Testbarkeit: Durch die Trennung der Verantwortlichkeiten lässt sich jede Komponente unabhängig testen. Die Domain kann z. B. mit Unit-Tests überprüft werden, ohne dass die Action oder der Responder erforderlich sind.

Nachteile des Action–Domain–Responder Pattern

  1. Komplexität bei einfachen Anwendungen: Das ADR-Muster kann für kleinere Anwendungen oder Projekte überdimensioniert erscheinen. In solchen Fällen kann das Hinzufügen der zusätzlichen Schichten unnötig kompliziert sein.
  2. Mehr Code: Durch die Einführung von drei verschiedenen Komponenten können zusätzliche Klassen und Codezeilen erforderlich werden. Dies kann zu einem höheren Wartungsaufwand führen, wenn die Anwendung nur einfache Anforderungen hat.
  3. Potentiell höhere Latenz: Da mehrere Schichten beteiligt sind, könnte es in einigen Fällen zu einer höheren Latenz bei der Bearbeitung einer Anfrage kommen, insbesondere bei komplexeren Logiken und Datenbankabfragen.
  4. Erhöhte Lernkurve: Entwickler, die mit diesem Muster nicht vertraut sind, benötigen möglicherweise Zeit, um das Konzept zu verstehen und richtig anzuwenden. Besonders bei der Trennung von Verantwortlichkeiten kann es anfänglich verwirrend sein.
  5. Mögliche Overhead-Kosten: Durch die separate Handhabung der Anfrage, Geschäftslogik und Antwort kann zusätzlicher Code und Overhead entstehen. Dies kann zu Performance-Einbußen führen, wenn das System nicht richtig optimiert ist.

Fazit

Das Action–Domain–Responder (ADR)-Muster ist eine hervorragende Möglichkeit, Webanwendungen sauber und wartbar zu strukturieren. Es sorgt für eine klare Trennung von Anliegen und erleichtert die Erweiterung der Anwendung. Besonders in größeren, komplexeren Webanwendungen bietet ADR viele Vorteile, da es die Handhabung von Geschäftslogik und Benutzerinteraktionen voneinander trennt. Allerdings kann es für kleinere, einfachere Anwendungen eine zu große Struktur darstellen. In diesen Fällen könnte ein einfacheres Muster wie das Model-View-Controller (MVC)-Pattern ausreichen.

Zurück zur Übersicht: Liste der Design-Pattern

action domain responder Pattern

Gibt es Case Studies oder bekannte Projekte, die ADR im Embedded-Umfeld nutzen?

Es gibt wenige explizite Erwähnungen von ADR im Embedded-Bereich. Dennoch verwenden viele Systeme ähnliche Strukturen – etwa in der Automobilindustrie, bei IoT-Firmware oder in Echtzeitsystemen. Die Architektur vieler AUTOSAR-Komponenten oder RTOS-basierter Anwendungen folgt einem vergleichbaren Prinzip: Ereignis → Verarbeitung → Ausgabe. ADR lässt sich als methodischer Rahmen dafür nutzen.

Gibt es Frameworks oder Tools, die ADR für Embedded C/C++ unterstützen?

Nein, ADR wird derzeit kaum explizit für Embedded C/C++ unterstützt, da es primär aus der Webentwicklung stammt. Die Struktur lässt sich aber leicht manuell nachbilden, insbesondere in C++ mit Klassen oder in C mit Funktionsgruppen und getrennten Modulen. Unit-Test-Frameworks wie GoogleTest, Ceedling oder Catch2 helfen, die einzelnen Komponenten sauber testbar zu halten. Hier ist ein […]

Ist das ADR-Pattern für Embedded-Systeme überhaupt geeignet?

Ja, wenn man es auf abstrakte Rollen überträgt. Statt HTTP-Requests sind es hier z. B. Interrupts, Timer-Events oder Nachrichten. Die Action verarbeitet das Ereignis, die Domain führt die Logik aus, und der Responder erzeugt eine Reaktion (z. B. das Setzen eines Ausgangs oder Senden einer Nachricht). Die Prinzipien bleiben gültig, auch wenn die technische Umgebung ganz anders […]

Was ist der Unterschied zwischen ADR und dem klassischen MVC-Pattern?

ADR ist eine Weiterentwicklung des MVC-Patterns, speziell für Webanwendungen, aber auch für Systeme mit klar getrennten Verantwortlichkeiten. In MVC liegt oft unklar, wo Logik untergebracht wird: Controller, Model oder View. ADR teilt klarer auf: Action empfängt die Anfrage und delegiert. Domain führt die Kernlogik aus. Responder formatiert die Antwort. Im Embedded-Kontext kann ADR eine saubere […]

Welche Vorteile bietet ADR im Vergleich zu Clean Architecture oder Hexagonal Architecture?

ADR ist schlanker und direkter. Es reduziert den Abstraktionsaufwand auf drei zentrale Komponenten, während Clean oder Hexagonal Architecture zusätzliche Layer wie Entities, Use Cases oder Interfaces einführen. Für kleine bis mittelgroße Embedded-Systeme bietet ADR einen guten Kompromiss aus Struktur und Einfachheit, ohne die typischen Überladungen komplexer Architekturen.

Wie lässt sich ADR in ein eventgetriebenes Embedded-System integrieren?

Jedes Event (z. B. von einem Interrupt, Timer, Nachricht oder Sensor) wird einer passenden Action zugewiesen. Die Action delegiert an die Domain, die das Event verarbeitet. Danach übergibt die Action das Ergebnis an den Responder, der eine Aktion ausführt oder einen neuen Zustand erzeugt. So lässt sich auch ein nebenläufiges, eventbasiertes System sauber strukturieren.

Wie lässt sich der Responder-Teil in einem Embedded-System ohne GUI oder HTTP umsetzen?

Der Responder übernimmt die Ausgabe oder Reaktion auf das Ergebnis der Domain. Das kann ein UART- oder CAN-Frame sein, ein GPIO-Pin, ein PWM-Signal oder eine Status-LED. Entscheidend ist, dass der Responder nicht entscheidet, was geschehen soll – sondern nur wie das Ergebnis der Verarbeitung kommuniziert oder umgesetzt wird.

Wie unterstützt ADR die Testbarkeit und Wartbarkeit von Embedded-Software?

Jede Komponente hat eine klar abgegrenzte Aufgabe und kann isoliert getestet werden. Die Domain kann ohne Hardware getestet werden, da sie keine I/O-Funktionalität enthält. Actions können als Reaktion auf simulierte Ereignisse getestet werden. Responder-Tests prüfen nur, ob die richtige Reaktion auf das Domänenergebnis erfolgt. Diese Trennung erleichtert langfristige Wartung erheblich.

com

Newsletter Anmeldung

Bleiben Sie informiert! Wir informieren Sie über alle neuen Beiträge (max. 1 Mail pro Woche – versprochen)