Observer: o padrão por trás de todo evento

Observer: o padrão por trás de todo evento

Robson Rabelo - 15 de julho de 2026 - 0 visualizações

De addEventListener ao broker de mensagens: o Observer do zero, a genealogia que organiza a cabeça (RxJS, Signals, filas) e as 3 armadilhas que se repetem em toda escala.

Se você já escreveu addEventListener, .on("data"), subscribe ou publicou um evento numa fila, você já usou o Observer: o padrão GoF mais onipresente do software moderno. A ideia cabe numa frase: quem tem a informação notifica; quem se interessa se inscreve, sem que os dois se conheçam.

O mecanismo, do zero

type Listener<T> = (dado: T) => void;

class Emissor<T> {
  private listeners = new Set<Listener<T>>();

  inscrever(fn: Listener<T>): () => void {
    this.listeners.add(fn);
    return () => this.listeners.delete(fn); // devolve o cancelamento!
  }

  emitir(dado: T) {
    for (const fn of this.listeners) fn(dado);
  }
}

// O domínio emite fatos; não conhece os interessados
class CarrinhoDeCompras {
  readonly aoAdicionar = new Emissor<Item>();

  adicionar(item: Item) {
    this.itens.push(item);
    this.aoAdicionar.emitir(item);
  }
}

// Os interessados se inscrevem, cada um por si
carrinho.aoAdicionar.inscrever((item) => analytics.registrar("add", item));
carrinho.aoAdicionar.inscrever((item) => badge.atualizar());

O ganho estrutural é o mesmo da mensageria em escala, aqui dentro do processo: o carrinho não conhece analytics nem badge; os interessados variam sem tocar em quem emite. Amanhã, o estoque quer reservar ao adicionar? Uma inscrição, zero mudanças no carrinho.

Onde ele vive (a genealogia que organiza a cabeça)

  • DOM e Node: addEventListener e EventEmitter são o padrão, embutidos na plataforma.
  • RxJS: Observer com esteroides: o fluxo de eventos vira valor de primeira classe, com operadores.
  • Signals e reatividade: a inscrição fica automática (ler é inscrever-se), mas o coração é o mesmo: dependentes notificados na mudança.
  • Filas e brokers: o Observer atravessando a rede, com durabilidade e as garantias que processo nenhum dá sozinho.

Entender essa linhagem evita redescobrir os mesmos problemas em cada camada, porque os problemas são os mesmos:

As três armadilhas clássicas (em qualquer escala)

1. O vazamento de inscrição. Quem se inscreve e não cancela vira listener zumbi: callbacks rodando sobre componentes mortos, memória crescendo. Por isso o inscrever do exemplo devolve a função de cancelamento, o mesmo motivo do async pipe e do takeUntilDestroyed. Regra: toda inscrição tem dono e tem fim.

2. O erro que derruba os irmãos. No loop de emitir, o listener 2 lançou exceção: os listeners 3, 4 e 5 nunca rodam? Emissores sérios isolam falhas (try/catch por listener, a DLQ é a versão distribuída disso). Um interessado quebrado não pode censurar os demais.

3. A cascata invisível. Evento que dispara evento que dispara evento: com dezenas de listeners mutando estado, ninguém mais sabe por que algo aconteceu, e a depuração vira espiritismo. Antídotos: eventos como fatos nomeados do domínio ("ItemAdicionado", não "mudouAlgo"), fluxo documentado, e IDs de correlação quando atravessa fronteiras.

Observer: um emissor, muitos interessados

Quando usar (e quando é indireção)

Use quando vários interessados reagem ao mesmo fato, os interessados variam com o tempo, ou você quer desacoplar módulos (o domínio emite; a infraestrutura escuta). Evite quandoum interessado fixo e a sequência importa: uma chamada direta é mais clara, mais rastreável e aparece no stack trace. Evento não é jeito chique de chamar função; é declaração de que você não quer saber quem ouve.

Nos próximos capítulos da série: Adapter (fazer contratos incompatíveis conversarem) e Factory Method (criar sem acoplar). O catálogo aplicado com essa régua é parte da revisão de desenho do nosso serviço de Arquitetura de Software.

Tem uma cascata de eventos que ninguém mais entende? Descreva-a para a IA da Rabelo Digital, aqui no canto da tela, e ela ajuda a redesenhar com fatos nomeados. Sem formulário, sem espera.


Leia também

Compartilhar:

Deixe um Comentário

Categorias

Posts Recentes