Pular para o conteúdo

apps/service-design/command-pattern

160 · Padrões de Design de Serviço · ≈ 6 min de estudo

Command

Cada operação vira um objeto com execute() e undo(). O objeto carrega tudo que precisa para ser executado, registrado, desfeito ou refeito depois — por quem o emitiu ou por outro processo. Use quando a operação precisa de histórico, reversão em lote ou desfazer depois do fato.

passos
6
arquivos
4
testes
0
tecnologias
5
Infraestrutura realTypeScriptBunElysiaPostgreSQLDocker
Baixar cartão

Cenário

A empresa paga a folha pelo banco: um lote com PIX para cada funcionário e a tarifa. Se um PIX do lote falha por saldo, os já feitos são estornados na ordem inversa. Um comando com valor inválido recusa o lote antes de qualquer execução. O operador pode desfazer o último comando executado, mesmo depois de reiniciar a aplicação.

Planta

Sequência
6/6
alt[um comando falha][todos executados]loop[historico do lote em ordem inversa (LIFO)]loop[cada comando, em ordem]commandCreate de todos (invalido recusa o lote antes de rodar)1BEGIN, execute(), INSERT command_log, COMMIT2BEGIN, undo(), status undone, COMMIT3409 rolled-back, onde falhou4201 completed5undo-last: reconstroi o comando do log e desfaz6API de comandosInvoker (batchExecute)PostgreSQL
6

6 passos — reproduza para seguir o fluxo

Como funciona

6 passos

Requisição como objeto, com desfazer.

Esconde cada passo: lembre antes de tocar para revelar.

Vocabulário compartilhado

  1. 01

    commandCreate monta o comando a partir de um payload (pix-transfer, fee-charge, cashback-credit) e já valida — comando inválido nunca entra em fila

  2. 02

    undo() reverte exatamente o movimento que execute() fez, com os valores capturados na criação; nunca "volta o saldo antigo", o que apagaria o que aconteceu depois

  3. 03

    batchExecute executa cada comando numa transação junto com a linha do histórico em command_log

  4. 04

    Se um comando falha, os executados do lote são desfeitos do último para o primeiro, cada um marcado undone

  5. 05

    undoLast lê o último comando executed do banco, reconstrói o objeto a partir do payload e desfaz — o histórico não depende de memória

  6. 06

    Débito nunca deixa conta negativaO UPDATE ... WHERE balance_cents >= valor falha o comando em vez de furar o saldo

Trade-offs

O que se ganha, o que se paga

4 vantagenscada ganho tem um preço4 custos

Vantagens

  • Desfazer e reverter lote sem código espalhado

  • Histórico persistido e auditável

  • Comando serializável: fila, reprocessamento, desfazer após restart

  • Validação na criação protege o lote inteiro

Custos

  • Uma classe ou caso por operação

  • O undo() precisa ser escrito e testado para cada comando

  • Efeito externo (SMS, webhook) não se desfaz — exige compensação

  • Rollback em lote não é atômico: cada desfazer é uma transação

apps/service-design/command-pattern

4 arquivos

src/

  • command_ledger.tsOs comandos: criação validada, execute() e undo()
  • invoker_command.tsExecução em lote com histórico, rollback LIFO e desfazer o último
  • api_command.tsAPI HTTP: lotes de comandos como dados e undo-last

sql/

  • 01_schema.sqlschemaContas e o histórico de comandos

Executar · com Docker

  1. ./docker.sh up# sobe PostgreSQL
  2. cp .env.example .env# variáveis de ambiente
  3. bun install# dependências
  4. bun run demo# roda o cenário
  5. bun run test# integração contra o serviço real
Requisitos
BunDocker
Sobe junto
PostgreSQL

Por que se relacionam

Teste rápido

Qual destes combina com Command Pattern?

Próximo projeto · Padrões de Design de ServiçoQuery Object
Esc

↑ ↓ navegarEnter abrir191 resultados