ADR: Action-Domain-Responder, l'MVC ripensato per il web
Pillar article su Action-Domain-Responder: come l'evoluzione di MVC proposta da Paul M. Jones risolve i problemi dei controller troppo grandi.
3 min di letturaArchitettura
Luigi Iadicola, Programmatore - Napoli
In questo articolo
Il problema dell'MVC nel contesto HTTP
MVC è stato progettato per interfacce desktop con interazione continua. Nel web, il ciclo è diverso: una request arriva, viene elaborata, una response parte. Non c'è interazione continua — è un singolo scambio. Eppure forziamo la logica in Controller con molti metodi (index, show, store, update, destroy) che fanno cose completamente diverse. Un UserController con 7 metodi e 7 responsabilità: non è coeso.
ADR (Action-Domain-Responder), proposto da Paul M. Jones nel 2014, è una reinterpretazione di MVC specifica per il web HTTP. L'idea: ogni endpoint è una singola Action (classe) che chiama il Domain e passa il risultato a un Responder.
I tre componenti
Action
L'Action è una classe con un singolo metodo (__invoke()) che gestisce un singolo endpoint. Non UserController con 7 metodi, ma CreateUserAction, ListUsersAction, DeleteUserAction — ognuna con una sola responsabilità. L'Action estrae i dati dalla request, chiama il Domain, e passa il risultato al Responder.
Domain
Il Domain è identico al Model/Service Layer: contiene la business logic, indipendente da HTTP. Riceve dati primitivi, esegue la logica, restituisce risultati o lancia eccezioni. L'Action non contiene logica di business — delega tutto al Domain.
Responder
Il Responder traduce il risultato del Domain in una HTTP response. Se il Domain restituisce un utente, il Responder decide se renderizzare HTML, JSON, XML, o un redirect. La logica di presentazione — quale status code, quali header, quale formato — è nel Responder, non nell'Action.
ADR vs MVC: confronto diretto
- Controller (MVC): classe con molti metodi.
UserController::store(),UserController::index(). Responsabilità multiple. - Action (ADR): classe con un metodo.
CreateUserAction::__invoke(). Singola responsabilità. - View (MVC): template passivo che riceve dati. Non decide il formato della response.
- Responder (ADR): attivo. Decide status code, header, content-type, e quale template usare in base al risultato.
Esempio pratico in PHP
Un endpoint per creare un utente:
CreateUserAction: estrae name ed email dalla request, chiama$this->domain->createUser($name, $email), passa il risultato a$this->responder->created($user)o$this->responder->validationError($errors).UserDomain: valida i dati, crea l'utente nel database, dispara l'eventoUserCreated. Nessuna dipendenza da HTTP.UserResponder: se il risultato è un utente, restituisce 201 con JSON o redirect. Se sono errori, restituisce 422 con il form e i messaggi.
Vantaggi concreti
- Single Responsibility: ogni Action fa una cosa. Niente controller con 500 righe.
- Testabilità: l'Action è una classe piccola con dipendenze iniettabili. Il test è diretto.
- Content negotiation: il Responder gestisce i formati (HTML, JSON, XML) senza if nel controller.
- Navigabilità: cerchi "crea utente"? Apri
CreateUserAction. Non devi cercare quale metodo di quale controller.
Quando usare ADR
- Usa ADR quando i controller crescono troppo e diventano ingestibili
- Usa ADR per API che devono supportare multipli formati di response
- Usa ADR quando vuoi massima coesione: una classe per endpoint
- Non usare ADR se i controller sono piccoli e gestibili: il overhead di una classe per endpoint non si giustifica
- Non usare ADR se il team è abituato a MVC e il cambio di paradigma creerebbe confusione
ADR non è un sostituto di MVC: è un'evoluzione per il contesto HTTP. Quando i controller crescono e la coesione diminuisce, ADR riporta ordine con una regola semplice: una classe, un endpoint, una responsabilità.
Hai lo stesso problema in azienda?
Raccontami cosa non va e da quando. Guardo la situazione con te prima di proporre qualsiasi intervento.
Ricevi il prossimo articolo
Una mail per ogni articolo nuovo, nient'altro. Ti disiscrivi con un clic dal link in fondo a ogni email.