Event Bus e padrão Observer em Rust: implementação de arquitetura orientada a eventos

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Event Bus e padrão Observer em Rust: construindo uma arquitetura flexível orientada a eventos



No desenvolvimento moderno de software, surge frequentemente a necessidade de baixo acoplamento entre componentes. O padrão Observer e sua implementação prática — Event Bus (barramento de eventos) — permitem organizar uma interação eficiente entre módulos sem dependências diretas. Rust, com seu sistema de tipos rigoroso e foco em segurança, oferece excelentes oportunidades para implementar esse padrão. Neste artigo, vamos explorar como construir seu próprio Event Bus em Rust, utilizando os recursos nativos da linguagem e crates populares.



O que é Event Bus e o padrão Observer?



Padrão Observer define uma relação "um para muitos" entre objetos: quando um objeto (publicador) muda seu estado, todos os objetos dependentes (assinantes) são notificados automaticamente. Event Bus é um barramento centralizado que gerencia inscrições e distribuição de eventos, permitindo que qualquer componente publique eventos e se inscreva neles.



Principais vantagens:

  • Baixo acoplamento: publicadores e assinantes não se conhecem diretamente
  • Escalabilidade: fácil adicionar novos assinantes sem alterar o código existente
  • Testabilidade: é possível testar componentes isoladamente, simulando eventos
  • Assincronicidade: eventos podem ser processados em segundo plano


Implementação básica do Event Bus em Rust



Vamos começar com uma implementação síncrona simples, usando recursos padrão do Rust. A base será um HashMap, onde a chave é o tipo do evento e o valor é uma lista de manipuladores.



use std::collections::HashMap;use std::any::{Any, TypeId};use std::marker::PhantomData;

// Tipo de evento com identificador únicopub trait Event: Any + Clone + Send + 'static { fn event_type(&self) -> TypeId { TypeId::of::<Self>() }}

// Manipulador de eventopub trait EventHandler<E: Event>: Send + 'static { fn handle(&self, event: &E);}

// O barramento de eventospub struct EventBus { handlers: HashMap<TypeId, Vec<Box<dyn Any>>>,}

impl EventBus { pub fn new() -> Self { EventBus { handlers: HashMap::new(), } }

pub fn subscribe<E: Event, H: EventHandler<E>>(&mut self, handler: H) { let type_id = TypeId::of::<E>(); let boxed_handler = Box::new(handler) as Box<dyn Any>; self.handlers.entry(type_id).or_insert(Vec::new()).push(boxed_handler); }

pub fn publish<E: Event>(&self, event: &E) { let type_id = event.event_type(); if let Some(handlers) = self.handlers.get(&type_id) { for handler in handlers { if let Some(typed_handler) = handler.downcast_ref::<Box<dyn EventHandler<E>>>() { typed_handler.handle(event); } } } }}


Exemplo de uso



// Definindo eventos#[derive(Clone)]struct UserLoggedIn {    user_id: u32,    username: String,}

impl Event for UserLoggedIn {}

#[derive(Clone)]struct DataUpdated { table: String, record_id: u64,}

impl Event for DataUpdated {}

// Definindo manipuladoresstruct Logger;impl EventHandler<UserLoggedIn> for Logger { fn handle(&self, event: &UserLoggedIn) { println!("[LOG] User {} (ID: {}) logged in", event.username, event.user_id); }}

struct EmailNotifier;impl EventHandler<UserLoggedIn> for EmailNotifier { fn handle(&self, event: &UserLoggedIn) { println!("[EMAIL] Sending welcome email to {}", event.username); }}

fn main() { le

Recommendations