CQRS e Event Sourcing em Kotlin: arquitetura para código impecável

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

Por que CQRS e Event Sourcing não são apenas palavras da moda

\n\n

Imagine que seu código é um enorme museu. Normalmente, armazenamos apenas a versão mais recente do artefato: "é assim que o pedido se parece agora". Mas e se quisermos saber como o pedido chegou a esse estado? Quem apertou o botão "Enviar"? Quando o status mudou? É aqui que entram em cena CQRS (Command Query Responsibility Segregation) e Event Sourcing em Kotlin.

\n\n

Neste guia, não vamos apenas copiar a teoria da Wikipedia. Vamos analisar exemplos reais, escrever código e entender como esses padrões transformam o caos das operações CRUD em uma arquitetura enxuta. Se você está cansado do "código espaguete" e quer construir sistemas fáceis de escalar e depurar — está no lugar certo.

\n\n

O que é CQRS em palavras simples

\n\n

Na arquitetura padrão, usamos os mesmos modelos para ler e escrever dados. É como se você estivesse comendo sopa e ao mesmo tempo mexendo com a mesma colher. O CQRS propõe separar as responsabilidades:

\n\n
    \n
  • Command (Comando) — altera o estado. Requisições de escrita (Create, Update, Delete).
  • \n
  • Query (Consulta) — lê o estado. Apenas operações SELECT.
  • \n
\n\n

Por que isso é necessário? Imagine uma loja online. Quando um usuário finaliza um pedido, precisamos verificar o estoque, dar baixa no produto, criar um registro no banco de dados, enviar um e-mail. Isso é um comando complexo. E quando o cliente apenas visualiza a lista de seus pedidos — isso é uma consulta simples. Misturá-los em um único método é o caminho certo para os bugs.

\n\n

Vantagens do CQRS em Kotlin

\n
    \n
  • Desempenho: é possível otimizar leitura e escrita de formas diferentes (bancos de dados diferentes, caches, índices).
  • \n
  • Segurança: separação de direitos de acesso (admin escreve, usuário lê).
  • \n
  • Escalabilidade: comandos e consultas podem ser distribuídos em servidores diferentes.
  • \n
\n\n

Event Sourcing: preservando a história, não os fatos

\n\n

Se o CQRS separa as operações, o Event Sourcing muda a forma de armazenar dados. Em vez de armazenar o estado atual (por exemplo, "saldo: 1000 reais"), armazenamos uma sequência de eventos: "Depósito de 500", "Compra de 200", "Dedução de taxa de 50".

\n\n

O estado atual é simplesmente o resultado da aplicação de todos os eventos em ordem. Isso dá um superpoder: podemos "rebobinar" o tempo, restaurar o estado em qualquer data ou analisar o comportamento dos usuários.

\n\n

Exemplo da vida real: conta bancária

\n
// Evento\ndata class MoneyDeposited(val amount: BigDecimal, val timestamp: Instant)\ndata class MoneyWithdrawn(val amount: BigDecimal, val timestamp: Instant)\n\n// Agregado (entidade)\nclass BankAccount {\n    private var balance: BigDecimal = BigDecimal.ZERO\n    private val events = mutableListOf<Any>()\n\n    fun deposit(amount: BigDecimal) {\n        if (amount <= BigDecimal.ZERO) throw IllegalArgumentException("O valor deve ser positivo")\n        val event = MoneyDeposited(amount, Instant.now())\n        apply(event)\n        events.add(event)\n    }\n\n    fun withdraw(amount: BigDecimal) {\n        if (amount > balance) throw IllegalStateException("Saldo insuficiente")\n        val event = MoneyWithdrawn(amount, Instant.now())\n        apply(event)\n        events.add(event)\n    }\n\n    private fun apply(event: Any) {\n        when (event) {\n            is MoneyDeposited -> balance += event.amount\n            is MoneyWithdrawn -> balance -= event.amount\n        }\n    }\n\n    fun getBalance(): BigDecimal = balance\n    fun getUncommittedEvents(): List<Any> = events.toList()\n}
\n\n

Como CQRS e Event Sourcing trabalham juntos

\n\n

Esta é a dupla clássica. O CQRS é responsável por separar os canais, e o Event Sourcing é responsável pelo armazenamento

Blogs

Book Recommendations