In questo post analizziamo in profondità il concetto di evento e di messaggio nelle architetture software moderne.Il fraintendimento tra eventi e messaggi è molto diffuso, e porta a frasi come “Useremo eventi con RabbitMQ per tutto!” — ma questa affermazione denota una visione errata che genera codice difficile da mantenere e scalare. In questo articolo ci concentriamo proprio su questi concetti e su come separarli correttamente.
Una distinzione fondamentale
Quando progetti sistemi software, soprattutto sistemi distribuiti o basati su microservizi, spesso utilizziamo eventi e messaggi. Sebbene questi termini possano sembrare intercambiabili, in realtà rappresentano concetti differenti:
- Evento: una notifica interna che qualcosa è accaduto.
- Messaggio: un’unità di comunicazione che viene inviata da un componente a uno o più destinatari, potendo contenerne uno o più eventi al suo interno.
Confondere questi concetti può portare a errori di architettura, uso improprio di strumenti come code o bus di messaggi, e difficoltà nella manutenzione del codice. Iniziamo definendo cosa si intende per “evento” nel contesto dello sviluppo di software.
Cos’è un evento
Un evento è una particolare struttura dati che rappresenta il fatto che qualcosa è accaduto. In un linguaggio orientato agli oggetti, l’evento è tipicamente un oggetto che incapsula l’informazione relativa al fatto stesso.
Per esempio, in PHP un evento che segnala la creazione di un utente può essere descritto così:
class UtenteCreatoEvento
{
public function __construct(
public string $idUtente
) {}
}
In questo esempio la semplice istanza di UtenteCreatoEvento indica che un nuovo utente è stato creato. L’oggetto non ha bisogno di contenere molti campi — in alcuni casi potrebbe non avere affatto proprietà — perché il fatto che l’evento sia stato generato è già di per sé informativo.
L’evento non contiene necessariamente informazioni sul trasporto o su cosa deve accadere dopo: è semplicemente un modo di rappresentare internamente ad un sistema che un evento di dominio si è verificato. Questo concetto è collegato al pattern architetturale Observer, dove il codice che genera l’evento può notificare varie parti del sistema senza conoscerle direttamente.
Se ogni parte del codice reagisse direttamente agli eventi scrivendo tutta la logica nello stesso punto, il codice diventerebbe fortemente accoppiato, difficile da leggere e impossibile da mantenere. Immagina questo codice:
Dispatcher di eventi in Symfony e dominio
In sistemi come Symfony esiste un componente chiamato EventDispatcher che consente di pubblicare eventi e registrare i relativi gestori. Tuttavia, è importante capire che questo componente è uno strumento di infrastruttura, non di dominio. Un esempio di evento definito in Symfony potrebbe essere:
use Symfony\Contracts\EventDispatcher\Event;
class ArticoloPubblicatoEvento extends Event
{
public function __construct(public string $titolo) {}
}
Questo evento può essere usato per notificare a più listener che un articolo è stato pubblicato, ad esempio per inviare notifiche, aggiornare indici di ricerca o registrare statistiche, ma rimane un concetto interno all’applicazione.
Per gestire eventi di dominio in modo separato dall’infrastruttura, molti progetti implementano un proprio “publisher” interno, come nel seguente esempio in PHP:
class EditoreEventiDominio
{
private array $iscritti = [];
public function iscrivi(DominioEventSubscriberInterface $sub)
{
$this->iscritti[] = $sub;
}
public function pubblica(DominioEvento $evento): void
{
foreach ($this->iscritti as $listener) {
if ($listener->gestisce($evento)) {
$listener->gestisci($evento);
}
}
}
}
Questo semplice sistema segue il pattern Observer: mantiene una lista di subscription interne che vengono chiamate quando l’evento viene pubblicato.
Cos’è un messaggio
A differenza dell’evento, un messaggio è l’unità di comunicazione inviata tra componenti o servizi, e spesso utilizza un mezzo di trasporto specifico (code, bus, HTTP, ecc.). Un messaggio può contenere al suo interno uno o più eventi o altre informazioni utili allo scopo del destinatario.
Un esempio di messaggio JSON che trasporta informazioni su un evento potrebbe essere il seguente:
{
"evento": {
"tipo": "utente.creato",
"timestamp": 1700000000,
"dati": {
"idUtente": "1234",
"nome": "Mario Rossi"
}
}
}
Questo oggetto JSON è un messaggio vero e proprio: contiene un evento (utente.creato) ma è pensato per essere inviato tramite un meccanismo di trasporto verso altri sistemi o servizi.
Differenza pratica tra evento e messaggio
La differenza chiave è che l’evento rappresenta un fatto accaduto all’interno dell’applicazione, mentre il messaggio è un mezzo di comunicazione che può trasportare quell’evento (o più eventi), con tutte le specifiche necessarie affinché un altro sistema o componente possa elaborarlo.
| Concetto | Scopo | Uso tipico |
|---|---|---|
| Evento | Notificare che qualcosa è accaduto | Trigger interni, logica di dominio |
| Messaggio | Comunicare informazioni tra componenti o servizi | Trasporto tramite code, API, bus di messaggi |
Un evento non è pensato per il trasporto tra sistemi: è un concetto di dominio o di infrastruttura interna. Un messaggio, invece, è progettato per viaggiare tramite un canale di comunicazione e può contenere informazioni su eventi o comandi.
Esempio pratico con Symfony Messenger
In Symfony, quando vogliamo inviare qualcosa verso un altro processo o servizio, usiamo il componente Messenger. Questo gestisce la serializzazione, l’invio attraverso un trasporto (per esempio RabbitMQ) e la ricezione da parte di un consumer. Un esempio di invio messaggio potrebbe essere:
use Symfony\Component\Messenger\MessageBusInterface;
class InviaNotifica
{
public function __construct(private MessageBusInterface $bus) {}
public function esegui(string $idUtente)
{
$messaggio = new NotificaUtenteMessage($idUtente);
$this->bus->dispatch($messaggio);
}
}
Qui NotificaUtenteMessage è un messaggio che sarà inviato al trasporto configurato. Il componente Messenger si occupa della consegna vera e propria. {index=10}
Conclusione
In sintesi, eventi e messaggi sono concetti correlati ma distinti. Gli eventi rappresentano fatti avvenuti, mentre i messaggi sono unità di comunicazione che possono trasportare eventi e altre informazioni tra componenti o servizi. Capire questa differenza è fondamentale per progettare sistemi scalabili e manutenibili.
Separando correttamente il dominio dagli strumenti di trasporto e scegliendo l’approccio giusto in base alle necessità (sincrono vs asincrono, uno-a-uno vs uno-a-molti), potrai evitare errori di progettazione comuni e ottenere architetture più robuste.



