DEV Community

Cover image for Service Layer: dove vive la logica che non appartiene al controller
Dev-Iadicola
Dev-Iadicola

Posted on • Originally published at iadicola.it

Service Layer: dove vive la logica che non appartiene al controller

Il problema: controller che fanno troppo

Un OrderController ha un metodo store() che: valida l'input, verifica la disponibilita dei prodotti, calcola il totale con sconti, crea l'ordine nel database, scala l'inventario, invia l'email di conferma, notifica il magazzino, aggiorna le statistiche. Sono 80 righe di codice procedurale in un metodo del controller. Funziona, ma non e riutilizzabile: se devi creare ordini da un'API, da un import CSV, o da un job schedulato, devi duplicare la logica.

Il Service Layer e lo strato architetturale che contiene la logica di business dell'applicazione. Ogni operazione significativa — creare un ordine, processare un pagamento, generare un report — ha un Service dedicato che incapsula la logica, indipendente dal meccanismo di input (HTTP, CLI, queue).

Struttura del Service Layer

Un Service Layer tipico si posiziona tra i controller e il layer di persistenza:

  • Controller → riceve la request, valida l'input, chiama il Service
  • Service → contiene la logica di business, coordina le operazioni, chiama Repository/Model
  • Repository/Model → accede ai dati, persiste le modifiche

Il Service non sa nulla di HTTP: non riceve Request, non restituisce Response. Riceve dati primitivi o DTO e restituisce risultati o lancia eccezioni. Questo lo rende invocabile da qualsiasi contesto.

Esempio pratico: ArticleService in Soft PHP MVC

Nel framework, l'ArticleService centralizza la logica degli articoli:

  • getPublished(int $page, int $perPage): PaginatedResult — articoli pubblicati con paginazione
  • getBySlug(string $slug): ?Article — singolo articolo per slug
  • getByTag(string $tag): array — articoli filtrati per tag
  • getRelated(Article $article, int $limit): array — articoli correlati

Il BlogController chiama $this->articleService->getPublished($page, 12) e passa il risultato alla View. L'ApiController chiama lo stesso metodo e restituisce JSON. Il comando CLI sitemap:generate chiama lo stesso metodo per generare la sitemap. Una logica, tre contesti diversi.

Service vs Helper vs Utility

  • Service: contiene logica di business del dominio. Spesso stateful (tiene dipendenze iniettate). OrderService, PaymentService.
  • Helper: funzioni di utilita generiche senza stato. Str::slug(), Path::resolve(). Non contengono logica di business.
  • Utility: simile a Helper ma più specifico. Spesso classi statiche con un singolo scopo. ImageResizer, CsvParser.

La differenza chiave: un Service conosce il dominio. Sa cosa significa "creare un ordine" con tutte le regole che comporta. Un Helper non sa nulla del dominio — manipola stringhe, file, date.

Quando introdurre un Service

Non ogni applicazione ha bisogno di un Service Layer. Ecco le regole pratiche:

  • Serve un Service quando la stessa logica viene usata da più controller o da contesti diversi (web, CLI, API)
  • Serve un Service quando il metodo del controller supera le 20 righe di logica di business
  • Serve un Service quando la logica deve essere testata unitariamente senza HTTP
  • Non serve un Service per CRUD banali dove il controller fa solo Model::find($id) e passa alla view
  • Non serve un Service se la logica e specifica di un solo controller e non verra mai riutilizzata

Pattern di naming e organizzazione

I Service seguono convenzioni chiare:

  • Nome: {Dominio}ServiceArticleService, OrderService, UserService
  • Metodi: verbi che descrivono azioni di business — createOrder(), cancelSubscription(), non handle() o process()
  • Directory: app/Services/ — separati da Controller, Model e Helper
  • Dipendenze: iniettate nel costruttore — Repository, Mailer, EventDispatcher

Il Service Layer non e un pattern complesso: e buon senso architetturale. Separare "cosa entra e cosa esce" (controller) da "cosa succede nel mezzo" (service) e il refactoring più utile che puoi fare in un'applicazione PHP che sta crescendo.


👉 Leggi l'articolo completo su iadicola.it

Top comments (0)