Il problema: catene di chiamate rigide
Quando un utente si registra, il sistema deve: inviare l'email di benvenuto, creare il profilo default, notificare il team di vendita, aggiornare le statistiche, attivare il periodo di prova. Il controller chiama cinque servizi in sequenza. Se aggiungi un sesto step (integrazione CRM), devi modificare il controller. Se il servizio email e lento, rallenta tutto. Se fallisce, blocca i passaggi successivi. Le dipendenze crescono linearmente con le funzionalita.
L'architettura event-driven inverte il flusso: il controller fa una sola cosa — registra l'utente e pubblica un evento UserRegistered. Ogni componente interessato reagisce all'evento indipendentemente. Il controller non sa quanti listener ci sono, ne cosa fanno. I listener non si conoscono tra loro.
Concetti fondamentali
Evento: un fatto accaduto
Un evento e un fatto immutabile che descrive qualcosa che e già successo: OrderPlaced, PaymentReceived, ArticlePublished. Non e una richiesta ("fai qualcosa") ma una notifica ("e successo qualcosa"). Questa distinzione e fondamentale: l'emittente non si aspetta una risposta e non sa chi sta ascoltando.
Producer e Consumer
Il producer emette l'evento. Il consumer (listener/subscriber) reagisce. Un evento può avere zero, uno o molti consumer. Aggiungere un consumer non richiede modifiche al producer. Rimuoverne uno non rompe nulla.
Esempio teorico: ciclo di vita di un ordine
OrderPlaced→SendOrderConfirmationListenerinvia l'email,ReserveInventoryListenerblocca lo stock,NotifyWarehouseListenerprepara la spedizione,UpdateDashboardListeneraggiorna le metriche
PaymentReceived→ConfirmOrderListeneraggiorna lo stato,GenerateInvoiceListenercrea la fattura
OrderShipped→SendShippingNotificationListenernotifica il cliente,StartDeliveryTrackingListenerattiva il tracking
Ogni listener e una classe isolata, testabile, che fa una sola cosa. Aggiungere un'integrazione con un nuovo sistema di analytics? Crei un listener, lo registri sull'evento, e tutto funziona senza toccare il codice esistente.
Sincrono vs Asincrono
Sincrono: i listener vengono eseguiti nella stessa request. Semplice, ma se un listener e lento, rallenta la response. Adatto per operazioni veloci e critiche (validazione, aggiornamento stato).
Asincrono: i listener vengono accodati (Redis, RabbitMQ, database) e eseguiti da worker separati. Non rallenta la response. Adatto per operazioni lente (email, PDF, integrazioni esterne) o non critiche.
In pratica, la maggior parte dei sistemi usa un mix: alcuni listener sincroni per le operazioni critiche, altri asincroni per il resto.
Event-Driven in Soft PHP MVC
Il framework usa eventi tramite l'Observer Pattern nei Model: i lifecycle hooks (beforeSave, afterSave, beforeDelete) sono eventi sincroni che permettono di reagire ai cambiamenti delle entita. Il CacheObserver invalida la cache quando un articolo viene modificato — senza che il Model sappia che la cache esiste.
Quando usare Event-Driven Architecture
Usa eventi quando un'azione ha effetti collaterali che non sono responsabilità del componente che la esegue
Usa eventi quando vuoi che nuove funzionalita possano "agganciarsi" senza modificare il codice esistente
Usa eventi quando il disaccoppiamento tra componenti e una priorità
Non usare eventi per flussi lineari semplici dove una chiamata diretta e più chiara
Non usare eventi se il debugging e già difficile: gli eventi rendono il flusso meno tracciabile
L'architettura event-driven non e un'alternativa a MVC o Hexagonal: e un principio di comunicazione che si applica dentro qualsiasi architettura. Quando i componenti reagiscono a fatti invece di essere chiamati direttamente, il sistema diventa più flessibile, più estensibile e più resiliente.
👉 Leggi l'articolo completo su iadicola.it
SOCIAL SHARE CARD GENERATOR