Queopius

Regolatori di grasso in Laravel

Un controller dovrebbe coordinare l'input HTTP, non concentrare la convalida, le regole aziendali, le query, l'autorizzazione, le trasformazioni, l'invio di e-mail e le decisioni sul flusso completo.

Laravel Controllo dello stato5 minuti
Immagine in primo piano dall'articolo Fat Controllers in Laravel pubblicato in LinkedIn da Queopius
Laravel Controllo dello statoControlloriArchitetturaManutenibilità

Il controller non dovrebbe essere dove vive tutto

In Laravel è molto semplice iniziare a risolvere la logica direttamente all'interno del controller. La richiesta arriva lì, il framework semplifica la convalida, l'interrogazione dei modelli, la restituzione di JSON e l'attivazione dei processi. Per una prima versione, quella velocità può essere utile.

Il problema sorge quando questo modello diventa la norma. Il metodo di archiviazione inizia con la convalida, quindi decide le autorizzazioni, quindi interroga vari modelli, calcola i totali, crea record, invia notifiche e costruisce una risposta manuale. Il controller smette di essere un gateway e diventa il caso d'uso completo.

Un controller sano coordina. Riceve la richiesta, delega la convalida, l'autorizzazione e l'esecuzione e restituisce una risposta. Una volta assorbito tutto il comportamento, l'applicazione può continuare a funzionare, ma ogni endpoint diventa più difficile da leggere, testare e riutilizzare.

Segni di un controller troppo grande

Il segno più evidente è rappresentato dai metodi di archiviazione, aggiornamento o distruzione su più righe. Ma la dimensione non è l’unico indicatore. Vale anche la pena osservare se è presente una convalida manuale all'interno del metodo, query complesse, condizioni aziendali combinate con HTTP, autorizzazioni ripetute o trasformazioni di risposte scritte a mano.

Un altro sintomo comune è trovare l'invio di e-mail, lavori, notifiche o integrazioni eseguite direttamente dal controller. A volte compaiono anche try/catch generici che nascondono errori reali, codice duplicato tra endpoint o risposte incoerenti a seconda di chi ha implementato ciascun metodo.

Se per testare un comportamento aziendale è necessario preparare una richiesta completa, autenticare l'utente, impostare troppe dipendenze ed esaminare tutto HTTP, probabilmente il caso d'uso è troppo legato al controller.

Perché succedono così tante cose?

Il controller è il primo punto visibile quando arriva una richiesta. In un progetto giovane, risolverlo sembra naturale: è a portata di mano, si capisce rapidamente e non richiede la decisione su una struttura. La pressione per fornire funzionalità rafforza tale decisione perché creare un'azione o un servizio sembra un lavoro extra.

Il problema è cumulativo. Un periodo isolato non fa male. Dieci regole distribuite tra più controllori, sì. Quando non esiste un livello applicativo chiaro, ogni endpoint finisce per risolvere la propria versione del processo. Ciò genera duplicazioni, incoerenze e un'architettura che dipende troppo da HTTP.

Laravel non ti obbliga a scrivere controller fat. È semplicemente molto economico iniziare in questo modo. Pertanto, quando l'applicazione è già in grado di sostenere il business, vale la pena verificare se la comodità iniziale ostacola la manutenibilità.

Quali rischi genera?

Un controller di grandi dimensioni rende più difficile la manutenzione degli endpoint. La modifica di una regola può influire sulla convalida, sulla persistenza, sulla risposta, sulle notifiche e sulle autorizzazioni nello stesso metodo. Il costo cognitivo aumenta perché il lettore deve comprendere più livelli contemporaneamente.

Compaiono anche test più fragili. Se il comportamento si trova all'interno del controller, testarlo senza passare attraverso HTTP è complicato. Ciò ti spinge a scrivere test di funzionalità molto ampi per regole che potrebbero essere testate più direttamente se fossero in un'azione o in un servizio.

L'accoppiamento con HTTP rende difficile riutilizzare la logica in comandi, lavori, processi interni o alternative APIs. Un piccolo cambiamento può avere un impatto inaspettato perché la logica non è isolata. Nel medio termine, il refactoring è più spaventoso che continuare ad accumulare codice.

Come perdere peso con un controller

La prima estrazione è solitamente la validazione. Le richieste del modulo ti consentono di rimuovere le regole HTTP dal metodo e lasciare il controller più pulito. L'autorizzazione dovrebbe essere spostata su Politiche o Cancelli quando la decisione viene ripetuta o rappresenta una regola di accesso chiara.

I casi d'uso si adattano bene alle azioni o ai servizi. Il nome e la responsabilità non contano molto: una classe che esprime “crea ordine”, “approva richiesta” o “sincronizza cliente” consente di testare il flusso senza dipendere da HTTP. Le risposte possono essere delegate alle risorse API per evitare trasformazioni manuali sparse.

Processi asincroni, e-mail pesanti o integrazioni dovrebbero andare su Jobs quando ha senso. Eventi e ascoltatori possono aiutare a disaccoppiare gli effetti collaterali, ma non dovrebbero essere usati come nascondiglio per la logica. DTO o oggetti dati possono essere utili se il progetto deve passare i dati tra i livelli in modo più chiaro.

Esempio concettuale

Prima: un metodo di archiviazione convalida i campi, controlla le autorizzazioni, crea più record, calcola gli importi, applica sconti, invia un'e-mail, attiva una notifica, registra l'attività e restituisce una risposta personalizzata. Tutto funziona, ma il controller non coordina più: esegue l'intero caso d'uso.

Dopo: StoreOrderRequest viene convalidato. OrderPolicy autorizza. CreateOrderAction esegue il caso d'uso. OrderResource trasforma l'output. Un lavoro gestisce compiti pesanti. Il controllore si riduce a poche righe che si leggono come una chiara sequenza.

Il vantaggio è pratico. Se la convalida cambia, sai dove toccare. Se il caso d'uso cambia, provalo senza HTTP. Se la risposta cambia, modifichi la risorsa. Se la spedizione cambia, rivedi il lavoro. Ogni pezzo ha meno motivi per cambiare.

Lista di controllo rapida

Un controller merita una revisione se contiene metodi di più di 40 o 50 righe, regole aziendali, convalide ripetute, query complesse, e-mail o notifiche dirette, trasformazioni di risposte manuali o logica duplicata tra endpoint.

La domanda utile non è "posso spostare questo?", ma "sarebbe più chiaro se questa decisione venisse presa al di fuori di HTTP?" Se riesci a testare il caso d'uso senza passare attraverso una richiesta completa, l'applicazione sarà probabilmente più semplice da gestire.

Chiusura

Un controller di grandi dimensioni è solitamente un segnale precoce che l'applicazione sta perdendo la separazione delle responsabilità. Non è sempre urgente, ma è consigliabile rilevarlo prima che ogni endpoint diventi un pezzo fragile.

Se i tuoi controller iniziano ad assomigliare a casi d'uso completi, un audit backend Laravel può aiutarti a rilevare quale logica dovrebbe essere estratta per prima e quali modifiche ridurrebbero maggiormente i rischi.

Il tuo Laravel mostra segnali simili?

Se la tua applicazione funziona, ma ogni modifica inizia a essere più lenta, più fragile o più difficile da spiegare, un audit backend Laravel può aiutarti a risolvere rischi, vantaggi rapidi e priorità tecniche.