Visão geral do fluxo
O fluxo completo de uma operação nos SDKs SUOT pode ser visualizado assim:| Componente | Responsabilidade |
|---|---|
| Command | Declarar a intenção de forma imutável. Não executa nada por si mesmo. |
| Handler | Receber o Command, chamar o serviço externo e devolver um Result. |
| Result | Encapsular o resultado — sucesso ou rejeição — sem efeitos colaterais na leitura. |
A aplicação host é sempre responsável por coordenar as obrigações fiscais e regulatórias. Os SDKs SUOT apenas executam operações individuais — não orquestram fluxos de negócio.
Command
Um Command é um objeto imutável que representa uma intenção, não a execução da operação. Ele carrega todos os dados necessários para que o Handler realize o trabalho, mas não sabe como fazê-lo. Características principais:- Construído com named arguments e Value Objects validados
- Imutável após a construção — nenhuma propriedade pode ser alterada
- Não pode ser executado diretamente — precisa ser passado a um Handler
- Completamente compreensível por IDEs e agentes de IA via PHPDoc e tipos
Handler
O Handler é o executor. Ele recebe um Command, realiza a chamada ao serviço externo (SEFAZ, ANTT etc.) e devolve um Result. O Handler não lança exceções para rejeições esperadas — apenas para falhas de infraestrutura. Regras do Handler:- Recebe exatamente um tipo de Command
- Devolve sempre um Result tipado
- Não lança exceção para respostas de negócio (rejeição, duplicidade, etc.) — isso é representado no Result
- Lança
InfrastructureExceptionapenas para falhas técnicas: timeout, HTTP 5xx, conectividade
Result
O Result encapsula o resultado de uma operação. Ele é imutável — ler suas propriedades não produz efeitos colaterais. O estado de um Result é sempre um de dois:| Estado | Método | Significado |
|---|---|---|
| Sucesso | isSuccess() | A operação foi aceita pelo serviço externo |
| Rejeição | isRejected() | A operação foi recusada por motivo de negócio |
InfrastructureException não é um estado do Result — é uma exceção lançada pelo Handler antes que um Result possa ser criado.
Um Result rejeitado não é um erro — é uma resposta legítima do serviço. A aplicação host deve tratar rejeições como parte do fluxo normal de negócio, não como exceções.
Por que esse padrão?
O fluxo Command → Handler → Result foi escolhido por razões práticas que impactam diretamente a qualidade do software que você escreve: Previsibilidade — toda operação tem a mesma forma. Ao aprender o padrão uma vez, você sabe como interagir com qualquer SDK SUOT. Testabilidade — o Handler pode ser substituído por um mock nos testes unitários. Você testa a lógica da sua aplicação sem precisar chamar SEFAZ ou ANTT. O Result pode ser construído diretamente no teste para simular qualquer cenário. Autocomplete e PHPStan — Commands e Results são classes concretas e totalmente tipadas. Nenhuma array mágica, nenhuma string de chave genérica. O PHPStan ao nível máximo e o servidor de linguagem PHP da sua IDE entendem cada propriedade. IA-readiness — agentes de IA (GitHub Copilot, Cursor, etc.) conseguem sugerir código correto porque os tipos são explícitos e o PHPDoc está em português brasileiro. Separação de responsabilidades — a aplicação host decide quando e por que chamar uma operação; o SDK decide como executá-la. Essa separação mantém a lógica de negócio fora do SDK e o SDK fora da lógica de negócio.Independência dos SDKs
Os SDKs SUOT são independentes entre si. O SDK fiscal não conhece o SDK de transporte e vice-versa. A aplicação host é responsável por coordenar os dois quando uma operação exigir dados de ambos.Próximos passos
Value Objects
Entenda como os campos fiscais são representados com tipagem forte e validação embutida.
Padrão CQRS
Veja como Commands, Queries e Results se encaixam no padrão CQRS dos SDKs SUOT.