Domain-Driven Design aplicado ao Fluig
Destilação prática de Implementing Domain-Driven Design (Vaughn Vernon) para o Fluig.
O Fluig é uma plataforma de processos — o domínio aqui é literalmente o processo de
negócio do cliente, o que torna DDD mais natural que em qualquer outro lugar: o diagrama
BPM, o formulário e o widget são o modelo, visível para o key-user.
Skill irmã: /fluig:clean-architecture (estrutura de código). No plugin protheus:
/protheus:ddd (mesmos princípios; lá o agregado casa com ExecAuto, aqui com o
documento do processo).
Consulta MCP (antes de modelar)
searchFluigPatterns({ category: "conventions" }) — convenções do plugin de naming/estrutura.
- MCP do PO-UI (
get_component_docs) e do Angular CLI (get_best_practices) na hora de
materializar o modelo em widget — versões nunca fixas, leia o package.json.
- No Fluig Voyager 2.0+, o editor de processos web e os recursos de IA geram diagramas e
formulários — o papel do DDD continua o mesmo: garantir que os nomes e fronteiras
gerados falem a língua do negócio antes de aprovar.
Parte estratégica
1 — Linguagem ubíqua (o BPM é o lugar dela)
No Fluig a linguagem ubíqua tem materialização direta: nome do processo, das atividades,
dos campos do formulário e das colunas do dataset. O key-user lê o diagrama — se a
atividade se chama "Atv_02" ou o campo se chama txt_val1, a linguagem morreu.
- Glossário no brainstorm (termo do cliente → significado → campo/atividade/dataset).
- Atividades nomeadas como o negócio fala: "Liberação de desconto pela supervisão",
não "Aprovação 2".
- Campos de formulário com nome de negócio (
percentualNegociado), datasets idem
(ds_consulta_contratos_vigentes — a convenção ds_[acao]_[entidade] do plugin já
empurra para isso).
- Detalhes e tabela de glossário:
references/estrategico-fluig.md.
2 — Bounded Contexts
Cada processo BPM (com seu formulário, eventos e datasets) é naturalmente um contexto:
"Aprovação de Desconto" ≠ "Admissão de Colaborador" — mesmo que ambos falem de "aprovação".
- 1 processo = 1 modelo. Não reutilize o formulário de um processo em outro "porque é
parecido" — é assim que nasce o form com 40 campos condicionais.
- Widgets são a janela de um contexto: um widget por contexto/finalidade, não um
God-widget com abas para 5 processos.
- Sinal de fronteira violada: evento de workflow com
if sobre "de qual processo veio".
3 — Context Mapping (o Fluig é o integrador-mor)
Quase todo processo Fluig conversa com o ERP — e o Fluig é downstream do Protheus:
o modelo do ERP muda no ritmo da TOTVS, não no seu.
- ACL (Anticorruption Layer): o dataset de integração é a sua ACL natural — ele traduz
o retorno do Protheus (REST/SQL) para as colunas na língua do seu processo. O JSON
do ERP não circula cru pelo formulário/widget.
- Eventos de processo que gravam no ERP: confine a chamada (formato, rota, payload) numa
função de infra — quando o endpoint do Protheus mudar, um lugar muda.
- Padrões completos (conformista, cliente-fornecedor, host aberto):
references/estrategico-fluig.md.
Parte tática (adaptada ao Fluig)
Detalhes e código: references/tatico-fluig.md. O essencial:
| Padrão |
No Fluig |
| Value Object |
Classe/type TS no widget (Cnpj, Dinheiro, Vigencia) com validação na criação; no form, máscara + validação client é UX — a validação de verdade repete no evento server |
| Entidade |
Registro com identidade de negócio (número do contrato) — não o documentid/cardId, que é detalhe da plataforma |
| Agregado |
O documento do processo (formulário pai + tabelas filhas) é o agregado: muda junto, valida junto. A raiz é o formulário; as invariantes são checadas no validateForm (UX) e garantidas nos eventos server (beforeTaskSave/afterStateEntry) |
| Repositório |
Datasets de consulta (ds_*) e serviços de gravação — a plataforma esconde a persistência do card; para dados externos, o dataset-ACL |
| Serviço de domínio |
Função pura de regra compartilhada entre widget (TS) e eventos (JS) — mesma tabela de decisão nos dois lados |
| Evento de domínio |
A movimentação do workflow é o evento ("pedido aprovado" = transição). Consumidores externos: notificação/integração disparada no afterStateEntry da atividade correspondente — nunca espalhada por várias atividades |
Regras de agregado no contexto Fluig:
- 1 processo = 1 agregado principal (o documento). Precisa de dados de outro
agregado (cliente, contrato)? Referencie por código e consulte via dataset — não
copie 20 campos do cliente para dentro do form (cópia desatualiza; consulta não).
- Invariante escrita em uma frase e garantida no servidor — client valida para UX,
evento server é a autoridade.
- Consistência com o ERP é eventual e explícita: o processo grava no Protheus num
ponto definido do fluxo (uma atividade de sistema/evento), com tratamento de falha
visível (pendência/retry), nunca "gravação escondida" em cada passo.
Fluxo de uso
- Brainstorm (
/fluig:brainstorm): glossário + contextos + mapa de integrações
(onde tem ACL?). O diagrama BPM nasce da linguagem ubíqua.
- Modelagem: identifique o agregado (form + filhas), escreva as invariantes,
liste VOs e a tabela de decisão de cada regra. Gabarito:
references/tatico-fluig.md.
- Implementação: estruture com
/fluig:clean-architecture; gere com
/fluig:form, /fluig:workflow, /fluig:dataset, /fluig:widget.
- Teste (
/fluig:test): as invariantes e a tabela de decisão são os specs Jasmine
do domínio; o E2E cobre o caminho feliz do processo.
Regras inegociáveis
- Glossário antes de nomear processo, atividades, campos e datasets.
- Nome técnico da plataforma (
documentid, cardId, WKNumProces) não vaza para
conversa com key-user nem para nome de campo de negócio.
- 1 processo = 1 contexto = 1 modelo; nada de form/dataset "multiuso" entre processos.
- Invariante de agregado garantida em evento server — validação client é só UX.
- Integração com ERP: ACL (dataset/função de infra) única por recurso; falha de
integração é visível no processo, nunca engolida em catch.
- DDD tático onde há regra rica — processo CRUD simples segue os templates padrão do plugin.
1---2name: ddd3description: Aplica Domain-Driven Design (baseado em Implementing DDD, de Vaughn Vernon) ao desenvolvimento Fluig — linguagem ubíqua em processos BPM, formulários e widgets; bounded contexts entre processos; context mapping com ACL nas integrações (Protheus/terceiros); e padrões táticos adaptados (value objects em TypeScript, o documento do processo como agregado, invariantes validadas no servidor, eventos de domínio via movimentação do workflow). Use quando o dev pedir para "modelar o processo", "aplicar DDD", "definir os contextos", "organizar integração com Protheus", "modelar formulário complexo" ou no brainstorm de processos com regra de negócio rica.4---56# Domain-Driven Design aplicado ao Fluig78Destilação prática de *Implementing Domain-Driven Design* (Vaughn Vernon) para o Fluig.9O Fluig é uma **plataforma de processos** — o domínio aqui é literalmente o processo de10negócio do cliente, o que torna DDD mais natural que em qualquer outro lugar: o diagrama11BPM, o formulário e o widget **são** o modelo, visível para o key-user.1213> Skill irmã: `/fluig:clean-architecture` (estrutura de código). No plugin protheus:14> `/protheus:ddd` (mesmos princípios; lá o agregado casa com ExecAuto, aqui com o15> documento do processo).1617## Consulta MCP (antes de modelar)1819- `searchFluigPatterns({ category: "conventions" })` — convenções do plugin de naming/estrutura.20- MCP do PO-UI (`get_component_docs`) e do Angular CLI (`get_best_practices`) na hora de21 materializar o modelo em widget — versões **nunca fixas**, leia o `package.json`.22- No Fluig Voyager 2.0+, o editor de processos web e os recursos de IA geram diagramas e23 formulários — o papel do DDD continua o mesmo: **garantir que os nomes e fronteiras24 gerados falem a língua do negócio** antes de aprovar.2526## Parte estratégica2728### 1 — Linguagem ubíqua (o BPM é o lugar dela)2930No Fluig a linguagem ubíqua tem materialização direta: **nome do processo, das atividades,31dos campos do formulário e das colunas do dataset**. O key-user lê o diagrama — se a32atividade se chama "Atv_02" ou o campo se chama `txt_val1`, a linguagem morreu.3334- Glossário no brainstorm (termo do cliente → significado → campo/atividade/dataset).35- Atividades nomeadas como o negócio fala: "Liberação de desconto pela supervisão",36 não "Aprovação 2".37- Campos de formulário com nome de negócio (`percentualNegociado`), datasets idem38 (`ds_consulta_contratos_vigentes` — a convenção `ds_[acao]_[entidade]` do plugin já39 empurra para isso).40- Detalhes e tabela de glossário: `references/estrategico-fluig.md`.4142### 2 — Bounded Contexts4344Cada **processo BPM** (com seu formulário, eventos e datasets) é naturalmente um contexto:45"Aprovação de Desconto" ≠ "Admissão de Colaborador" — mesmo que ambos falem de "aprovação".4647- 1 processo = 1 modelo. Não reutilize o formulário de um processo em outro "porque é48 parecido" — é assim que nasce o form com 40 campos condicionais.49- Widgets são a **janela** de um contexto: um widget por contexto/finalidade, não um50 God-widget com abas para 5 processos.51- Sinal de fronteira violada: evento de workflow com `if` sobre "de qual processo veio".5253### 3 — Context Mapping (o Fluig é o integrador-mor)5455Quase todo processo Fluig conversa com o ERP — e o Fluig é **downstream** do Protheus:56o modelo do ERP muda no ritmo da TOTVS, não no seu.5758- **ACL (Anticorruption Layer)**: o dataset de integração é a sua ACL natural — ele traduz59 o retorno do Protheus (REST/SQL) para as colunas **na língua do seu processo**. O JSON60 do ERP não circula cru pelo formulário/widget.61- Eventos de processo que gravam no ERP: confine a chamada (formato, rota, payload) numa62 função de infra — quando o endpoint do Protheus mudar, um lugar muda.63- Padrões completos (conformista, cliente-fornecedor, host aberto): `references/estrategico-fluig.md`.6465## Parte tática (adaptada ao Fluig)6667Detalhes e código: `references/tatico-fluig.md`. O essencial:6869| Padrão | No Fluig |70|---|---|71| **Value Object** | Classe/`type` TS no widget (`Cnpj`, `Dinheiro`, `Vigencia`) com validação na criação; no form, máscara + validação client é UX — a validação de verdade repete no evento server |72| **Entidade** | Registro com identidade de negócio (número do contrato) — não o `documentid`/`cardId`, que é detalhe da plataforma |73| **Agregado** | O **documento do processo** (formulário pai + tabelas filhas) é o agregado: muda junto, valida junto. A raiz é o formulário; as invariantes são checadas no `validateForm` (UX) e **garantidas** nos eventos server (`beforeTaskSave`/`afterStateEntry`) |74| **Repositório** | Datasets de consulta (`ds_*`) e serviços de gravação — a plataforma esconde a persistência do card; para dados externos, o dataset-ACL |75| **Serviço de domínio** | Função pura de regra compartilhada entre widget (TS) e eventos (JS) — mesma tabela de decisão nos dois lados |76| **Evento de domínio** | A movimentação do workflow **é** o evento ("pedido aprovado" = transição). Consumidores externos: notificação/integração disparada no `afterStateEntry` da atividade correspondente — nunca espalhada por várias atividades |7778Regras de agregado no contexto Fluig:791. **1 processo = 1 agregado principal** (o documento). Precisa de dados de outro80 agregado (cliente, contrato)? Referencie por **código** e consulte via dataset — não81 copie 20 campos do cliente para dentro do form (cópia desatualiza; consulta não).822. Invariante escrita em uma frase e **garantida no servidor** — client valida para UX,83 evento server é a autoridade.843. Consistência com o ERP é **eventual e explícita**: o processo grava no Protheus num85 ponto definido do fluxo (uma atividade de sistema/evento), com tratamento de falha86 visível (pendência/retry), nunca "gravação escondida" em cada passo.8788## Fluxo de uso89901. **Brainstorm** (`/fluig:brainstorm`): glossário + contextos + mapa de integrações91 (onde tem ACL?). O diagrama BPM nasce da linguagem ubíqua.922. **Modelagem**: identifique o agregado (form + filhas), escreva as invariantes,93 liste VOs e a tabela de decisão de cada regra. Gabarito: `references/tatico-fluig.md`.943. **Implementação**: estruture com `/fluig:clean-architecture`; gere com95 `/fluig:form`, `/fluig:workflow`, `/fluig:dataset`, `/fluig:widget`.964. **Teste** (`/fluig:test`): as invariantes e a tabela de decisão são os specs Jasmine97 do domínio; o E2E cobre o caminho feliz do processo.9899## Regras inegociáveis100101- Glossário antes de nomear processo, atividades, campos e datasets.102- Nome técnico da plataforma (`documentid`, `cardId`, `WKNumProces`) não vaza para103 conversa com key-user nem para nome de campo de negócio.104- 1 processo = 1 contexto = 1 modelo; nada de form/dataset "multiuso" entre processos.105- Invariante de agregado garantida em evento server — validação client é só UX.106- Integração com ERP: ACL (dataset/função de infra) única por recurso; falha de107 integração é visível no processo, nunca engolida em catch.108- DDD tático onde há regra rica — processo CRUD simples segue os templates padrão do plugin.