nexus-core-v3 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +134 -0
- package/agents/README.md +133 -0
- package/agents/_protocol.md +107 -0
- package/agents/analyst.md +138 -0
- package/agents/architect.md +146 -0
- package/agents/data-engineer.md +170 -0
- package/agents/dev.md +134 -0
- package/agents/devops.md +141 -0
- package/agents/nexus-master.md +147 -0
- package/agents/pm.md +133 -0
- package/agents/po.md +138 -0
- package/agents/qa.md +192 -0
- package/agents/sm.md +122 -0
- package/agents/squad-creator.md +121 -0
- package/agents/ux-design-expert.md +165 -0
- package/artifact-manifest.json +903 -0
- package/bin/nexus.mjs +37 -0
- package/checklists/README.md +49 -0
- package/checklists/architect-checklist.md +47 -0
- package/checklists/change-checklist.md +61 -0
- package/checklists/db-predeploy-checklist.md +57 -0
- package/checklists/design-quality-checklist.md +57 -0
- package/checklists/discovery-checklist.md +36 -0
- package/checklists/foundation-checklist.md +39 -0
- package/checklists/launch-checklist.md +39 -0
- package/checklists/pm-checklist.md +48 -0
- package/checklists/po-master-checklist.md +64 -0
- package/checklists/reality-check-checklist.md +49 -0
- package/checklists/story-dod-checklist.md +52 -0
- package/checklists/story-draft-checklist.md +36 -0
- package/dist/bin/dashboard.html +279 -0
- package/dist/bin/nexus.mjs +20008 -0
- package/dist/constitution.yaml +76 -0
- package/knowledge/README.md +57 -0
- package/knowledge/architecture/architectural-styles-map.md +182 -0
- package/knowledge/architecture/design-patterns-gof.md +192 -0
- package/knowledge/architecture/distributed-patterns-cheatsheet.md +201 -0
- package/knowledge/architecture/saas-subscription-blueprint.md +355 -0
- package/knowledge/architecture/system-design-tradeoffs.md +231 -0
- package/knowledge/architecture/t3-fullstack-typesafe-stack.md +273 -0
- package/knowledge/copy/landing-copy-that-converts.md +168 -0
- package/knowledge/data/postgres-indexing-and-tuning.md +263 -0
- package/knowledge/data/schema-modeling-decisions.md +273 -0
- package/knowledge/data/supabase-rls-patterns.md +316 -0
- package/knowledge/data/zero-downtime-migrations.md +308 -0
- package/knowledge/devops/cicd-pipeline-best-practices.md +318 -0
- package/knowledge/devops/production-dockerfile.md +283 -0
- package/knowledge/devops/twelve-factor-app.md +398 -0
- package/knowledge/engineering/clean-code-principles.md +429 -0
- package/knowledge/engineering/effective-code-review.md +204 -0
- package/knowledge/engineering/testing-strategy-beyond-unit.md +307 -0
- package/knowledge/governance/risk-matrix.md +56 -0
- package/knowledge/integration/mcp-server-selection-matrix.md +235 -0
- package/knowledge/marketing/copy-que-converte.md +43 -0
- package/knowledge/marketing/funil-e-jornada.md +36 -0
- package/knowledge/negocios/proposta-vencedora.md +38 -0
- package/knowledge/negocios/roi-e-unit-economics.md +46 -0
- package/knowledge/pipeline/1-descobrir.md +26 -0
- package/knowledge/pipeline/2-estrategizar.md +26 -0
- package/knowledge/pipeline/3-estruturar.md +27 -0
- package/knowledge/pipeline/4-construir.md +27 -0
- package/knowledge/pipeline/5-endurecer.md +28 -0
- package/knowledge/pipeline/6-lancar.md +27 -0
- package/knowledge/pipeline/7-operar.md +27 -0
- package/knowledge/security/lgpd-conformidade-basica.md +35 -0
- package/knowledge/security/owasp-secure-coding-gates.md +220 -0
- package/knowledge/security/owasp-top10-threat-assessment.md +287 -0
- package/knowledge/security/threat-modeling-stride.md +34 -0
- package/knowledge/web-craft/a11y-audit-checklist.md +251 -0
- package/knowledge/web-craft/accessible-component-patterns.md +383 -0
- package/knowledge/web-craft/anti-ai-look.md +114 -0
- package/knowledge/web-craft/design-system-from-code.md +195 -0
- package/knowledge/web-craft/intrinsic-css-layout.md +420 -0
- package/knowledge/web-craft/style-cloning.md +185 -0
- package/knowledge/web-craft/visual-polish-review.md +183 -0
- package/package.json +55 -0
- package/runbooks/campanha-de-conteudo.md +36 -0
- package/runbooks/feature-em-projeto-existente.md +37 -0
- package/runbooks/mvp-startup.md +38 -0
- package/runbooks/resposta-a-incidente.md +37 -0
- package/squads/exemplo-conteudo/agents/editor-chefe.md +48 -0
- package/squads/exemplo-conteudo/agents/pesquisador.md +44 -0
- package/squads/exemplo-conteudo/agents/redator.md +45 -0
- package/squads/exemplo-conteudo/knowledge/estilo-editorial.md +21 -0
- package/squads/exemplo-conteudo/squad.yaml +19 -0
- package/squads/exemplo-conteudo/tasks/pesquisar-fontes.md +26 -0
- package/squads/exemplo-conteudo/tasks/planejar-pauta.md +27 -0
- package/squads/exemplo-conteudo/tasks/redigir-artigo.md +26 -0
- package/squads/exemplo-conteudo/tasks/revisar-artigo.md +27 -0
- package/squads/marketing/agents/analista.md +56 -0
- package/squads/marketing/agents/chefe-marketing.md +65 -0
- package/squads/marketing/agents/conteudo.md +55 -0
- package/squads/marketing/agents/copy.md +55 -0
- package/squads/marketing/agents/growth.md +56 -0
- package/squads/marketing/agents/social.md +55 -0
- package/squads/marketing/squad.yaml +17 -0
- package/squads/marketing/tasks/aprovar-campanha.md +43 -0
- package/squads/negocios/agents/chefe-negocios.md +65 -0
- package/squads/negocios/agents/financas-roi.md +55 -0
- package/squads/negocios/agents/suporte.md +55 -0
- package/squads/negocios/agents/vendas-proposta.md +56 -0
- package/squads/negocios/squad.yaml +17 -0
- package/squads/negocios/tasks/aprovar-proposta.md +40 -0
- package/squads/security/agents/appsec-reviewer.md +59 -0
- package/squads/security/agents/chefe-seguranca.md +65 -0
- package/squads/security/agents/compliance-auditor.md +60 -0
- package/squads/security/agents/threat-modeler.md +60 -0
- package/squads/security/squad.yaml +20 -0
- package/squads/security/tasks/aprovar-gate-seguranca.md +42 -0
- package/squads/security/tasks/emitir-parecer-conformidade.md +42 -0
- package/tasks/README.md +72 -0
- package/tasks/accessibility-wcag-checklist.md +69 -0
- package/tasks/advanced-elicitation.md +42 -0
- package/tasks/analyze-performance.md +54 -0
- package/tasks/analyze-project-structure.md +59 -0
- package/tasks/apply-qa-fixes.md +57 -0
- package/tasks/architect-analyze-impact.md +62 -0
- package/tasks/archive-squad.md +52 -0
- package/tasks/audit-codebase.md +53 -0
- package/tasks/build-component.md +61 -0
- package/tasks/calculate-roi.md +63 -0
- package/tasks/ci-cd-configuration.md +51 -0
- package/tasks/collect-visual-evidence.md +62 -0
- package/tasks/compose-molecule.md +57 -0
- package/tasks/consolidate-patterns.md +54 -0
- package/tasks/create-brownfield-prd.md +54 -0
- package/tasks/create-competitor-analysis.md +42 -0
- package/tasks/create-deep-research-prompt.md +62 -0
- package/tasks/create-doc.md +62 -0
- package/tasks/create-epic.md +49 -0
- package/tasks/create-front-end-spec.md +56 -0
- package/tasks/create-migration-plan.md +57 -0
- package/tasks/create-next-story.md +66 -0
- package/tasks/create-prd.md +53 -0
- package/tasks/create-project-brief.md +47 -0
- package/tasks/create-rls-policies.md +59 -0
- package/tasks/create-schema.md +57 -0
- package/tasks/create-service.md +55 -0
- package/tasks/create-squad.md +100 -0
- package/tasks/create-suite.md +62 -0
- package/tasks/db-apply-migration.md +56 -0
- package/tasks/db-domain-modeling.md +57 -0
- package/tasks/db-dry-run.md +50 -0
- package/tasks/db-env-check.md +57 -0
- package/tasks/db-load-csv.md +54 -0
- package/tasks/db-policy-apply.md +58 -0
- package/tasks/db-rollback.md +51 -0
- package/tasks/db-run-sql.md +61 -0
- package/tasks/db-seed.md +52 -0
- package/tasks/db-smoke-test.md +51 -0
- package/tasks/db-snapshot.md +48 -0
- package/tasks/db-verify-order.md +49 -0
- package/tasks/deliberate.md +46 -0
- package/tasks/design-indexes.md +59 -0
- package/tasks/dev-develop-story.md +61 -0
- package/tasks/document-project.md +59 -0
- package/tasks/execute-checklist.md +57 -0
- package/tasks/execute-epic-plan.md +52 -0
- package/tasks/execute-subtask.md +51 -0
- package/tasks/extend-pattern.md +63 -0
- package/tasks/extend-squad.md +60 -0
- package/tasks/extract-patterns.md +64 -0
- package/tasks/extract-tokens.md +59 -0
- package/tasks/facilitate-brainstorming-session.md +42 -0
- package/tasks/generate-ai-frontend-prompt.md +57 -0
- package/tasks/generate-documentation.md +60 -0
- package/tasks/generate-migration-strategy.md +57 -0
- package/tasks/generate-shock-report.md +56 -0
- package/tasks/mcp-management.md +66 -0
- package/tasks/orchestrate.md +50 -0
- package/tasks/perform-market-research.md +42 -0
- package/tasks/plan-create-context.md +57 -0
- package/tasks/plan-create-implementation.md +58 -0
- package/tasks/po-close-story.md +60 -0
- package/tasks/po-manage-story-backlog.md +59 -0
- package/tasks/po-pull-story.md +60 -0
- package/tasks/po-sync-story.md +59 -0
- package/tasks/pr-automation.md +50 -0
- package/tasks/pre-push-quality-gate.md +54 -0
- package/tasks/push.md +53 -0
- package/tasks/qa-browser-console-check.md +52 -0
- package/tasks/qa-create-fix-request.md +58 -0
- package/tasks/qa-evidence-requirements.md +55 -0
- package/tasks/qa-false-positive-detection.md +55 -0
- package/tasks/qa-fix-issues.md +55 -0
- package/tasks/qa-gate.md +53 -0
- package/tasks/qa-migration-validation.md +58 -0
- package/tasks/qa-nfr-assess.md +45 -0
- package/tasks/qa-review-story.md +56 -0
- package/tasks/qa-risk-profile.md +45 -0
- package/tasks/qa-security-checklist.md +64 -0
- package/tasks/qa-test-design.md +47 -0
- package/tasks/qa-trace-requirements.md +48 -0
- package/tasks/release-management.md +53 -0
- package/tasks/repository-cleanup.md +61 -0
- package/tasks/route.md +44 -0
- package/tasks/run-tests.md +50 -0
- package/tasks/security-audit.md +54 -0
- package/tasks/setup-database.md +60 -0
- package/tasks/setup-design-system.md +60 -0
- package/tasks/shard-doc.md +60 -0
- package/tasks/spec-assess-complexity.md +55 -0
- package/tasks/spec-critique.md +64 -0
- package/tasks/spec-gather-requirements.md +48 -0
- package/tasks/spec-research-dependencies.md +42 -0
- package/tasks/spec-write-spec.md +50 -0
- package/tasks/test-as-user.md +52 -0
- package/tasks/ux-create-wireframe.md +54 -0
- package/tasks/ux-user-research.md +55 -0
- package/tasks/validate-next-story.md +61 -0
- package/tasks/validate-squad.md +55 -0
- package/tasks/verify-subtask.md +52 -0
- package/tasks/version-management.md +45 -0
- package/templates/README.md +47 -0
- package/templates/architecture-tmpl.md +115 -0
- package/templates/competitor-analysis-tmpl.md +87 -0
- package/templates/epic-tmpl.md +83 -0
- package/templates/front-end-spec-tmpl.md +110 -0
- package/templates/market-research-tmpl.md +98 -0
- package/templates/migration-plan-tmpl.md +92 -0
- package/templates/prd-tmpl.md +95 -0
- package/templates/project-brief-tmpl.md +100 -0
- package/templates/qa-verdict-tmpl.md +73 -0
- package/templates/rls-policies-tmpl.md +93 -0
- package/templates/schema-design-tmpl.md +107 -0
- package/templates/spec-tmpl.md +88 -0
- package/templates/squad/agent-dna-tmpl.md +72 -0
- package/templates/squad/chief-dna-tmpl.md +98 -0
- package/templates/squad/squad-task-tmpl.md +50 -0
- package/templates/squad/squad-yaml-tmpl.md +47 -0
- package/templates/story-tmpl.md +63 -0
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# Constitution do Nexus Core v3 — FONTE ÚNICA (INV-6).
|
|
2
|
+
# ConstitutionProjector deriva daqui: markdown (docs), gates.json (enforcement) e l0Domain (SYNAPSE L0).
|
|
3
|
+
# NÃO editar a projeção materializada; editar apenas este arquivo.
|
|
4
|
+
version: 3.0.0
|
|
5
|
+
|
|
6
|
+
articles:
|
|
7
|
+
- id: "I"
|
|
8
|
+
title: CLI First
|
|
9
|
+
severity: NON-NEGOTIABLE
|
|
10
|
+
body: >
|
|
11
|
+
Toda inteligência, execução e automação vive no CLI. Observabilidade é secundária;
|
|
12
|
+
UI é terciária. Nenhuma capacidade essencial pode existir apenas na UI.
|
|
13
|
+
- id: "II"
|
|
14
|
+
title: Agent Authority
|
|
15
|
+
severity: NON-NEGOTIABLE
|
|
16
|
+
body: >
|
|
17
|
+
Operações exclusivas pertencem a um único agente dono. Outros agentes são bloqueados
|
|
18
|
+
(fail-closed). Delegação é o padrão para trabalho especializado.
|
|
19
|
+
- id: "III"
|
|
20
|
+
title: Story-Driven Development
|
|
21
|
+
severity: MUST
|
|
22
|
+
body: >
|
|
23
|
+
Todo desenvolvimento parte de uma story com critérios de aceite. Progresso é rastreável
|
|
24
|
+
por ID; nada é entregue sem rastreabilidade.
|
|
25
|
+
- id: "IV"
|
|
26
|
+
title: No Invention
|
|
27
|
+
severity: MUST
|
|
28
|
+
body: >
|
|
29
|
+
Cada afirmação de spec/feature rastreia a um requisito, restrição ou achado de pesquisa.
|
|
30
|
+
Nenhuma feature inventada. Declarado = real, verificável em CI.
|
|
31
|
+
- id: "V"
|
|
32
|
+
title: Quality First
|
|
33
|
+
severity: MUST
|
|
34
|
+
body: >
|
|
35
|
+
Typecheck, lint e testes passam antes de qualquer entrega. Cobertura com ratchet.
|
|
36
|
+
Degradação graciosa nunca esconde código morto.
|
|
37
|
+
- id: "VI"
|
|
38
|
+
title: Absolute Imports
|
|
39
|
+
severity: SHOULD
|
|
40
|
+
body: >
|
|
41
|
+
Preferir imports por pacote (@nexus/*) a caminhos relativos profundos, mantendo o grafo
|
|
42
|
+
de dependências explícito e acíclico.
|
|
43
|
+
- id: "VII"
|
|
44
|
+
title: Squad Charter
|
|
45
|
+
severity: NON-NEGOTIABLE
|
|
46
|
+
body: >
|
|
47
|
+
Squads herdam a constituição INTEGRAL. Operações exclusivas do core (git_push, pr_create,
|
|
48
|
+
pr_merge, mcp_manage → devops) JAMAIS são sobrescritas ou duplicadas por squad. Autoridades
|
|
49
|
+
de squad são ADITIVAS e namespaced 'squad.{id}.{operation}'; conflito com operação exclusiva
|
|
50
|
+
bloqueia a composição do gate (fail-closed) — o gate permanece único.
|
|
51
|
+
|
|
52
|
+
authorities:
|
|
53
|
+
- operation: git_push
|
|
54
|
+
owner: devops
|
|
55
|
+
exclusive: true
|
|
56
|
+
matchPatterns:
|
|
57
|
+
- tool: Bash
|
|
58
|
+
subcommand: git push
|
|
59
|
+
- operation: pr_create
|
|
60
|
+
owner: devops
|
|
61
|
+
exclusive: true
|
|
62
|
+
matchPatterns:
|
|
63
|
+
- tool: Bash
|
|
64
|
+
subcommand: gh pr create
|
|
65
|
+
- operation: pr_merge
|
|
66
|
+
owner: devops
|
|
67
|
+
exclusive: true
|
|
68
|
+
matchPatterns:
|
|
69
|
+
- tool: Bash
|
|
70
|
+
subcommand: gh pr merge
|
|
71
|
+
- operation: mcp_manage
|
|
72
|
+
owner: devops
|
|
73
|
+
exclusive: true
|
|
74
|
+
matchPatterns:
|
|
75
|
+
- tool: Bash
|
|
76
|
+
subcommand: claude mcp
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# NEXUS Knowledge — os skills dos agentes
|
|
2
|
+
|
|
3
|
+
Esta é a 5ª camada de conteúdo. Se o DNA é *quem* o agente é e a task é *o que ele faz*, o **knowledge
|
|
4
|
+
pack** é o **craft diferenciado** — o conhecimento que faz o agente produzir trabalho que se destaca,
|
|
5
|
+
não trabalho genérico. É a forma estruturada e versionada de "dar habilidade pro agente".
|
|
6
|
+
|
|
7
|
+
> No design antigo isso se fazia jogando repositórios soltos no contexto. Aqui é **curado**: cada pack
|
|
8
|
+
> é conhecimento focado, específico e reutilizável — não um dump de arquivos.
|
|
9
|
+
|
|
10
|
+
## Formato canônico
|
|
11
|
+
|
|
12
|
+
```markdown
|
|
13
|
+
---
|
|
14
|
+
id: anti-ai-look
|
|
15
|
+
domain: web-craft # web-craft | copy | ...
|
|
16
|
+
agents: [ux-design-expert] # quem puxa este pack
|
|
17
|
+
when: "quando desenhar/implementar uma página que precisa parecer bespoke"
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
# {título}
|
|
21
|
+
|
|
22
|
+
## O problema / o tell ← o que torna o trabalho medíocre (concreto, nomeado)
|
|
23
|
+
## Os princípios do craft ← como o expert faz diferente (específico, com exemplos)
|
|
24
|
+
## Checklist ← auto-verificação objetiva ("isto parece de IA?")
|
|
25
|
+
## Antes → depois ← exemplos concretos do ruim vs do bom
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Regra de qualidade (o que separa skill de listicle)
|
|
29
|
+
|
|
30
|
+
- **Específico, nunca genérico.** "Use boa tipografia" é lixo. "Pareie uma display face de caráter com
|
|
31
|
+
uma workhorse de texto numa escala modular (~1.25); não use Inter em tudo" é craft. Se um modelo
|
|
32
|
+
capaz já faria sem ser instruído, a linha não é skill — é ruído.
|
|
33
|
+
- **Nomeia os tells.** Um bom pack lista os sinais concretos do trabalho ruim (ex.: gradiente
|
|
34
|
+
índigo→violeta, grid de 3 cards com emoji) para o agente reconhecer e fugir.
|
|
35
|
+
- **Tem exemplo.** Antes (o tell) → depois (o craft). Concreto vence abstrato.
|
|
36
|
+
|
|
37
|
+
## Como o agente consome
|
|
38
|
+
|
|
39
|
+
- **Modo interativo:** o agente carrega o pack sob demanda quando faz aquela classe de trabalho (igual
|
|
40
|
+
o DNA referencia em `knowledge:`).
|
|
41
|
+
- **Modo motor (`nexus run`):** o pack é injetado no prompt do agente spawnado pela camada
|
|
42
|
+
`@nexus/synapse` (recall por palavra-chave do domínio).
|
|
43
|
+
|
|
44
|
+
## Ética (importante — isto vai pra produção)
|
|
45
|
+
|
|
46
|
+
Skills de "clonar estilo" ensinam a **técnica** (extrair a linguagem de design: cor, tipo, espaço,
|
|
47
|
+
motion) — nunca copiar assets/conteúdo de terceiros. Linguagem de design é craft; pirataria de
|
|
48
|
+
asset é problema de IP. Os packs reforçam essa linha.
|
|
49
|
+
|
|
50
|
+
## Packs
|
|
51
|
+
|
|
52
|
+
| Pack | Domínio | O que dá ao agente |
|
|
53
|
+
|---|---|---|
|
|
54
|
+
| `web-craft/anti-ai-look` | web-craft | páginas bespoke que não parecem de IA |
|
|
55
|
+
| `web-craft/style-cloning` | web-craft | extrair e reaplicar a linguagem de design de uma referência |
|
|
56
|
+
| `web-craft/design-system-from-code` | web-craft | consolidar um design system a partir de um codebase |
|
|
57
|
+
| `copy/landing-copy-that-converts` | copy | copy de landing com voz e gatilhos reais, não texto genérico |
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: architectural-styles-map
|
|
3
|
+
domain: architecture
|
|
4
|
+
agents: [architect]
|
|
5
|
+
when: "ao decidir a forma estrutural de um projeto (camadas, fronteiras, organização)"
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Mapa de estilos arquiteturais — escolher a forma estrutural sem cargo-cult
|
|
9
|
+
|
|
10
|
+
## O problema
|
|
11
|
+
|
|
12
|
+
A decisão de forma estrutural quase nunca é tomada por critério — é tomada por hábito ("foi o que usei no
|
|
13
|
+
último projeto"), por moda ("todo mundo faz Clean + CQRS + Event Sourcing") ou por medo ("melhor sobrar
|
|
14
|
+
camada do que faltar"). O resultado tem cara reconhecível e é o equivalente arquitetural do "look de IA":
|
|
15
|
+
|
|
16
|
+
1. **Clean/Onion/Hexagonal aplicado a um CRUD de 4 tabelas** — 5 projetos na solution, mappers de DTO para
|
|
17
|
+
entidade para DTO, e a "regra de dependência" defendida com unhas e dentes num sistema que nunca terá
|
|
18
|
+
uma segunda implementação de repositório.
|
|
19
|
+
2. **CQRS com bancos de leitura e escrita separados** num domínio onde leitura e escrita têm o mesmo
|
|
20
|
+
modelo e a mesma carga. A própria fonte tem um artigo chamado *"CQRS is not a general purpose style of
|
|
21
|
+
architecture"* exatamente por causa disso.
|
|
22
|
+
3. **Event Sourcing "porque dá auditoria"** num sistema que só precisava de uma coluna `updated_at` e uma
|
|
23
|
+
tabela de log. Append-only log, versionamento de evento, projeções e *eventual consistency* — três
|
|
24
|
+
problemas novos para resolver um que não existia.
|
|
25
|
+
4. **Layered/N-tier chamado de "arquitetura"** quando na verdade é uma `Controller → Service → Repository`
|
|
26
|
+
anêmica: a camada de domínio não tem comportamento, só getters/setters (o *anemic domain model*, listado
|
|
27
|
+
como anti-padrão na própria fonte).
|
|
28
|
+
5. **Bounded contexts demais** — cada agregado virou um "microsserviço" antes de existir uma única regra de
|
|
29
|
+
negócio estável. Fronteira de contexto sem *context mapping*, então tudo acopla via banco compartilhado.
|
|
30
|
+
6. **Zero documentação de decisão** — ninguém sabe *por que* o sistema é Hexagonal e não Layered. Sem ADR,
|
|
31
|
+
a decisão não tem rastro; seis meses depois alguém "simplifica" e quebra a fronteira de propósito.
|
|
32
|
+
|
|
33
|
+
A regra-mãe: **estilo arquitetural é resposta a uma força concreta (taxa de mudança, número de
|
|
34
|
+
integrações, criticidade, assimetria leitura/escrita), não um default.** Se você não consegue nomear a
|
|
35
|
+
força que justifica a camada, a camada é custo sem retorno. Estrutura existe para *isolar o que muda por
|
|
36
|
+
razões diferentes* — não para parecer sofisticada.
|
|
37
|
+
|
|
38
|
+
> Fonte de referência (curadoria real): `mehdihadeli/awesome-software-architecture`
|
|
39
|
+
> (`awesome-architecture.com`) — seções *Architectural Styles* (Clean, Hexagonal, Onion, Layered, Vertical
|
|
40
|
+
> Slice, Modular Monolith), *Domain Driven Design* (strategic/tactical), *CQRS*, *Event Sourcing*,
|
|
41
|
+
> *Architecture Documentation* (C4, ADR, arc42).
|
|
42
|
+
|
|
43
|
+
## Os princípios / o conhecimento
|
|
44
|
+
|
|
45
|
+
### 1. A família "regra de dependência" — Clean, Hexagonal, Onion são a MESMA ideia com nomes diferentes
|
|
46
|
+
|
|
47
|
+
Os três compartilham um único princípio: **dependências apontam para dentro, em direção ao domínio; o
|
|
48
|
+
domínio não conhece infraestrutura.** Isso é a aplicação do *Dependency Inversion Principle* (listado em
|
|
49
|
+
*architectural-design-principles* na fonte) na escala de toda a aplicação. A diferença entre eles é
|
|
50
|
+
*vocabulário e ênfase*, não mecânica.
|
|
51
|
+
|
|
52
|
+
| Estilo | Autor / origem | A regra de dependência (exata) | Vocabulário próprio | Ênfase distintiva |
|
|
53
|
+
|---|---|---|---|---|
|
|
54
|
+
| **Layered / N-tier** | Clássico (Fowler, PoEAA) | Cada camada depende **da de baixo** (UI → App → Domínio → Dados). Dependência desce. | Presentation, Business, Data Access | Simplicidade; mas o domínio acaba dependendo do banco |
|
|
55
|
+
| **Hexagonal (Ports & Adapters)** | Alistair Cockburn (2005) | O núcleo define **ports** (interfaces); **adapters** externos dependem do núcleo, nunca o contrário. Simétrico: driving (entrada) e driven (saída). | Port, Adapter, driving/driven side | Testabilidade: troca-se qualquer adapter (DB, UI, fila) sem tocar no núcleo |
|
|
56
|
+
| **Onion** | Jeffrey Palermo (2008) | Camadas **concêntricas**; dependência aponta para o centro. Centro = Domain Model; fora = Infra/UI. | Domain Model → Domain Services → App Services → Infra | Domínio no centro absoluto; infraestrutura é a casca mais externa |
|
|
57
|
+
| **Clean** | Robert C. Martin / "Uncle Bob" (2012) | **The Dependency Rule:** "source code dependencies can only point inwards". Entities → Use Cases → Interface Adapters → Frameworks & Drivers. | Entities, Use Cases, Interface Adapters, Frameworks | Síntese de Onion + Hexagonal + DDD; nomeia explicitamente *Use Cases* como anel próprio |
|
|
58
|
+
|
|
59
|
+
**Como decidir entre eles** (não confunda "diferente" com "melhor"):
|
|
60
|
+
|
|
61
|
+
| Sua situação | Estilo indicado | Por quê |
|
|
62
|
+
|---|---|---|
|
|
63
|
+
| CRUD simples, pouca regra, time pequeno | **Layered** (ou Vertical Slice) | A inversão completa é custo sem retorno; descer a dependência é honesto e barato |
|
|
64
|
+
| Muitos pontos de I/O (DB + filas + APIs externas + UI) que mudam independentemente | **Hexagonal** | Ports/adapters isolam cada integração; cada uma vira um adapter trocável |
|
|
65
|
+
| Domínio rico, regras no centro, quero proteger o modelo de qualquer tecnologia | **Onion** ou **Clean** | Domínio no centro, infra na casca; *persistence ignorance* garantida |
|
|
66
|
+
| Quero um nome de camada explícito para "o que o sistema faz" (orquestração de caso de uso) | **Clean** | É o único que dá ao anel de *Use Cases* status de primeira classe |
|
|
67
|
+
| Feature-oriented, quero minimizar acoplamento horizontal entre camadas | **Vertical Slice** | Corta por funcionalidade, não por camada técnica; cada slice é coeso ponta a ponta |
|
|
68
|
+
|
|
69
|
+
> Pragmatismo: para a maioria dos sistemas de negócio, **Hexagonal e Clean convergem na prática**. Escolha
|
|
70
|
+
> um vocabulário e seja consistente. O erro caro não é escolher "errado" entre eles — é aplicar qualquer
|
|
71
|
+
> um dos três a um problema que era Layered.
|
|
72
|
+
|
|
73
|
+
### 2. DDD não é um estilo de camada — é tático **e** estratégico, e você quase sempre quer o estratégico primeiro
|
|
74
|
+
|
|
75
|
+
A fonte separa DDD em dois blocos, e essa separação é a decisão mais subestimada:
|
|
76
|
+
|
|
77
|
+
| | DDD **Tático** | DDD **Estratégico** |
|
|
78
|
+
|---|---|---|
|
|
79
|
+
| Pergunta que responde | "Como modelo *dentro* de uma fronteira?" | "*Onde* ficam as fronteiras?" |
|
|
80
|
+
| Artefatos (da fonte) | Entities, **Value Objects**, **Aggregates** (aggregation), Domain Services, Application Services, Domain Events, Repositories, Rich Domain Model | **Bounded Contexts**, **Context Mapping**, Ubiquitous Language, Core/Supporting/Generic **Subdomains**, Strategic Design Patterns |
|
|
81
|
+
| Quando aplicar | Quando o domínio tem invariantes e comportamento (não é CRUD) | Quando o sistema cobre múltiplas áreas de negócio que evoluem em ritmos diferentes |
|
|
82
|
+
| Erro comum | *Anemic Domain Model* — entidade sem comportamento, só getters/setters (anti-padrão na fonte) | Fatiar em microsserviços por agregado, sem *context mapping*, criando acoplamento por banco compartilhado |
|
|
83
|
+
|
|
84
|
+
**Sequência correta:** estratégico **antes** de tático. Primeiro descubra os *bounded contexts* (onde a
|
|
85
|
+
linguagem ubíqua muda de significado é onde a fronteira está), depois aplique o modelo tático *dentro* de
|
|
86
|
+
cada contexto. Decidir Aggregates antes de saber o Core Domain é otimizar a parte errada.
|
|
87
|
+
|
|
88
|
+
**Quando NÃO fazer DDD tático:** se o domínio é genérico (autenticação, notificação, billing de
|
|
89
|
+
prateleira) ou é CRUD puro, o modelo rico é over-engineering. Use *Transaction Script* (também listado na
|
|
90
|
+
fonte como design pattern) — é honesto para lógica procedural simples.
|
|
91
|
+
|
|
92
|
+
Mapeamento de aggregate ↔ estilo: o **Aggregate** é a fronteira de consistência *transacional*; o
|
|
93
|
+
**Bounded Context** é a fronteira de *modelo/linguagem* (e candidato a fronteira de deploy/serviço). Não
|
|
94
|
+
confunda os dois — um contexto contém vários agregados.
|
|
95
|
+
|
|
96
|
+
### 3. CQRS e Event Sourcing — dois eixos independentes, ambos com alto custo de entrada
|
|
97
|
+
|
|
98
|
+
O erro número um é tratá-los como pacote ("Clean + CQRS + ES"). São **decisões ortogonais**: dá para ter
|
|
99
|
+
CQRS sem Event Sourcing, Event Sourcing sem CQRS separado, e a maioria dos sistemas não quer nenhum dos
|
|
100
|
+
dois.
|
|
101
|
+
|
|
102
|
+
**CQRS** = separar o modelo de *escrita* (commands) do modelo de *leitura* (queries). É a aplicação do
|
|
103
|
+
princípio **CQS** (Command Query Separation, listado na fonte) na escala de arquitetura. Pode ser leve (dois
|
|
104
|
+
modelos, um banco) ou pesado (dois bancos, sincronizados por eventos).
|
|
105
|
+
|
|
106
|
+
| Use CQRS quando… | NÃO use CQRS quando… |
|
|
107
|
+
|---|---|
|
|
108
|
+
| Leitura e escrita têm **modelos genuinamente diferentes** (escrita normalizada, leitura em projeções desnormalizadas) | Leitura e escrita compartilham o mesmo modelo — separar é duplicação pura |
|
|
109
|
+
| Assimetria de carga forte (ex.: 100x mais leitura que escrita) que justifica escalar os lados separadamente | Carga simétrica e modesta — um modelo único escala bem |
|
|
110
|
+
| Domínio complexo onde a lógica de escrita se beneficia de não carregar concern de leitura | CRUD; a própria fonte: *"CQRS is not a general purpose style of architecture"* |
|
|
111
|
+
| Já existe Event Sourcing (projeções de leitura caem naturalmente) | Time pequeno sem experiência — *eventual consistency* entre os lados é armadilha sutil |
|
|
112
|
+
|
|
113
|
+
**Event Sourcing** = persistir o estado como uma **sequência imutável de eventos** (append-only log), não
|
|
114
|
+
como snapshot do estado atual. Reconstrói qualquer estado passado por replay.
|
|
115
|
+
|
|
116
|
+
| Use Event Sourcing quando… | NÃO use Event Sourcing quando… |
|
|
117
|
+
|---|---|
|
|
118
|
+
| **Auditoria/compliance** exige histórico completo e imutável de cada mudança | Um `updated_at` + tabela de log resolve a auditoria que você realmente precisa |
|
|
119
|
+
| Você precisa de **queries temporais** (estado em qualquer ponto no tempo) | Você só precisa do estado atual e consistência imediata |
|
|
120
|
+
| Domínio rico onde o *evento* é a verdade do negócio (financeiro, logística, jogos) | CRUD simples — ES introduz versionamento de evento, projeções e *eventual consistency* sem retorno |
|
|
121
|
+
| Forense/debug: replay do log reproduz o caminho até o bug | Time sem maturidade para lidar com migração de schema de eventos antigos |
|
|
122
|
+
|
|
123
|
+
**Sinal de over-engineering (qualquer um destes = pare):** o domínio é CRUD; não há requisito de auditoria
|
|
124
|
+
temporal nem de histórico; a leitura e a escrita têm o mesmo modelo; o time nunca operou *eventual
|
|
125
|
+
consistency* em produção. Nesses casos, Layered + um modelo de domínio honesto entrega mais valor com
|
|
126
|
+
ordens de magnitude menos risco.
|
|
127
|
+
|
|
128
|
+
### 4. Documentar a decisão — C4 (a forma) + ADR (o porquê)
|
|
129
|
+
|
|
130
|
+
Estrutura sem documentação de decisão apodrece: a próxima pessoa não sabe *por que* a fronteira existe e a
|
|
131
|
+
quebra "simplificando". A fonte (*Architecture Documentation*) aponta o par canônico:
|
|
132
|
+
|
|
133
|
+
| Ferramenta | O que captura | Granularidade | Quando produzir |
|
|
134
|
+
|---|---|---|---|
|
|
135
|
+
| **C4 Model** (Simon Brown) | A **forma** do sistema em 4 níveis: **Context** (sistema + atores) → **Container** (apps/serviços/bancos) → **Component** (dentro de um container) → **Code** (raro, gerado) | Do macro ao micro; pare no nível que agrega valor (geralmente Context + Container) | No design inicial e quando a topologia muda |
|
|
136
|
+
| **ADR** (Architecture Decision Record, Michael Nygard) | O **porquê** de cada decisão: contexto, decisão, alternativas, consequências. "A LOG that answers WHY" | Uma decisão por arquivo, numerado, imutável (decisões revogadas viram "superseded") | Toda decisão estrutural com trade-off (escolha de estilo, fronteira, CQRS sim/não) |
|
|
137
|
+
| **arc42** | Template guarda-chuva de documentação (a fonte: *"the template for software architecture documentation"*) | Documento vivo do sistema | Quando se quer um doc de arquitetura completo e padronizado |
|
|
138
|
+
|
|
139
|
+
Regra prática: **C4 mostra o que você construiu; ADR explica por que não construiu de outro jeito.** Os dois
|
|
140
|
+
juntos. Diagrama sem ADR vira desenho bonito sem rastro de decisão; ADR sem C4 vira prosa sem mapa.
|
|
141
|
+
Mantenha ambos versionados junto do código (*Architecture as Code*, citado na fonte).
|
|
142
|
+
|
|
143
|
+
## Checklist — "esta forma estrutural é justificada ou é cargo-cult?"
|
|
144
|
+
|
|
145
|
+
Antes de fechar a decisão de estilo, responda. Qualquer "sim" da coluna errada é um tell a corrigir:
|
|
146
|
+
|
|
147
|
+
- [ ] Consigo **nomear a força concreta** (taxa de mudança, número de integrações, criticidade, assimetria
|
|
148
|
+
leitura/escrita) que justifica cada camada/fronteira que estou adicionando?
|
|
149
|
+
- [ ] Estou aplicando Clean/Onion/Hexagonal a um **CRUD simples**? (Se sim → Layered ou Vertical Slice.)
|
|
150
|
+
- [ ] Defini os **bounded contexts** (estratégico) **antes** de detalhar Aggregates/Value Objects (tático)?
|
|
151
|
+
- [ ] Meu modelo de domínio tem **comportamento**, ou é anêmico (só getters/setters)?
|
|
152
|
+
- [ ] Estou adotando **CQRS** sem que leitura e escrita tenham modelos genuinamente diferentes ou
|
|
153
|
+
assimetria de carga real?
|
|
154
|
+
- [ ] Estou adotando **Event Sourcing** sem requisito real de auditoria temporal / histórico imutável?
|
|
155
|
+
- [ ] O time **já operou** *eventual consistency* em produção, se estou indo para CQRS pesado ou ES?
|
|
156
|
+
- [ ] Cada agregado virou microsserviço **antes** de ter *context mapping* definido? (Se sim → recue.)
|
|
157
|
+
- [ ] Existe um **ADR** registrando *por que* este estilo e não os alternativos?
|
|
158
|
+
- [ ] Existe um **C4** (ao menos Context + Container) mostrando a forma para quem chega depois?
|
|
159
|
+
- [ ] Se eu remover esta camada/separação, **algo concreto quebra** — ou só fica "menos sofisticado"?
|
|
160
|
+
|
|
161
|
+
## Tabela de decisão — "use o estilo X quando o sistema tem a característica Y"
|
|
162
|
+
|
|
163
|
+
| Característica do sistema (Y) | Estilo / decisão (X) | Evite |
|
|
164
|
+
|---|---|---|
|
|
165
|
+
| CRUD, poucas regras, time pequeno, baixa criticidade | **Layered / N-tier** ou **Vertical Slice** | Clean/Onion/Hexagonal, CQRS, ES |
|
|
166
|
+
| Feature-oriented, quer coesão ponta a ponta por funcionalidade | **Vertical Slice Architecture** | Camadas horizontais espessas |
|
|
167
|
+
| Muitos I/O independentes (DB + filas + APIs + UI) que trocam separadamente | **Hexagonal (Ports & Adapters)** | Layered (acopla domínio ao DB) |
|
|
168
|
+
| Domínio rico, modelo precisa ser protegido de qualquer tecnologia | **Onion** ou **Clean** | Anemic domain model |
|
|
169
|
+
| Preciso de status explícito para "casos de uso" / orquestração | **Clean Architecture** | — |
|
|
170
|
+
| Sistema cobre várias áreas de negócio em ritmos diferentes | **DDD estratégico**: bounded contexts + context mapping | Microsserviço por agregado sem mapping |
|
|
171
|
+
| Dentro de uma fronteira com invariantes e comportamento | **DDD tático**: Aggregates, Value Objects, Domain Events, Repositories | Transaction script com regra espalhada |
|
|
172
|
+
| Lógica procedural simples, domínio genérico (auth, notificação) | **Transaction Script** | DDD tático completo |
|
|
173
|
+
| Leitura e escrita com modelos diferentes OU assimetria de carga forte | **CQRS** (leve: 1 banco; pesado: 2 bancos só se a escala exigir) | CQRS em CRUD simétrico |
|
|
174
|
+
| Auditoria/compliance com histórico imutável + queries temporais | **Event Sourcing** (+ projeções; geralmente com CQRS) | ES "pela auditoria" quando log+timestamp basta |
|
|
175
|
+
| Só precisa do estado atual, consistência imediata | **Snapshot/estado** (persistência tradicional) | Event Sourcing |
|
|
176
|
+
| Múltiplos contextos mas ainda sem regra estável / time pequeno | **Modular Monolith** (módulos com fronteira interna) | Microsserviços prematuros |
|
|
177
|
+
| Qualquer decisão estrutural com trade-off | **Registrar um ADR** + diagrama **C4** (Context + Container) | Decisão sem rastro |
|
|
178
|
+
|
|
179
|
+
> Princípio de fechamento: **comece no estilo mais simples que respeita as forças do sistema e evolua sob
|
|
180
|
+
> pressão real.** É barato promover Layered → Hexagonal quando as integrações crescerem; é caro desmontar
|
|
181
|
+
> Event Sourcing aplicado cedo demais. A sofisticação correta é a que você consegue justificar num ADR — o
|
|
182
|
+
> resto é o "look de IA" da arquitetura.
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: design-patterns-gof
|
|
3
|
+
domain: architecture
|
|
4
|
+
agents: [architect]
|
|
5
|
+
when: "ao reconhecer um problema recorrente de design e escolher (ou descartar) um padrão"
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Design Patterns (GoF) — índice sintoma → padrão → trade-off
|
|
9
|
+
|
|
10
|
+
23 soluções nomeadas para problemas recorrentes de design OO, catalogadas pelo Gang of Four (1994)
|
|
11
|
+
e mantidas com critérios atuais em [refactoring.guru](https://refactoring.guru/design-patterns).
|
|
12
|
+
Este pack é o **índice de decisão**: para cada padrão, o problema que resolve, o code smell que
|
|
13
|
+
sinaliza que ele cabe, um exemplo minimal em TypeScript, e — o que mais importa — **quando NÃO usar**,
|
|
14
|
+
porque um padrão aplicado fora de hora é a forma mais cara de over-engineering.
|
|
15
|
+
|
|
16
|
+
## O problema
|
|
17
|
+
|
|
18
|
+
Reconhecer um padrão é fácil; saber se ele **cabe** é o craft. Dois erros simétricos:
|
|
19
|
+
|
|
20
|
+
1. **Reinventar.** Resolver na unha um problema que já tem solução nomeada, testada e comunicável —
|
|
21
|
+
e errar nos casos de borda que o padrão já cobre.
|
|
22
|
+
2. **Cargo-culting.** Aplicar o padrão porque você sabe o nome, não porque o problema pediu. Uma
|
|
23
|
+
`AbstractFactoryBuilderStrategy` para instanciar uma struct de config. Isto é o tell de IA da
|
|
24
|
+
arquitetura: estrutura sem justificativa. A régua do pack-âncora vale aqui — **uma decisão de
|
|
25
|
+
design só existe se você consegue justificar por que ela é assim e não o default.**
|
|
26
|
+
|
|
27
|
+
A fonte é explícita sobre o custo: quase todo padrão lista, nas próprias contras, *"o código fica
|
|
28
|
+
mais complicado"* / *"novas interfaces e classes são introduzidas"*. Padrão é dívida de indireção
|
|
29
|
+
paga adiantada na esperança de flexibilidade futura. Só vale se a flexibilidade **vier**.
|
|
30
|
+
|
|
31
|
+
> Os padrões variam em escala: **idiomas** são o nível mais baixo (presos a uma linguagem);
|
|
32
|
+
> **padrões arquiteturais** são o mais alto (desenham a aplicação inteira). Os 23 GoF ficam no meio —
|
|
33
|
+
> design de classes e objetos, não arquitetura de sistema. Não confunda escolher um GoF com decidir
|
|
34
|
+
> arquitetura.
|
|
35
|
+
|
|
36
|
+
## Os princípios / o conhecimento
|
|
37
|
+
|
|
38
|
+
### As 3 categorias (intenção — definição da fonte)
|
|
39
|
+
|
|
40
|
+
| Categoria | O que resolve (definição refactoring.guru) | Eixo |
|
|
41
|
+
|---|---|---|
|
|
42
|
+
| **Creational** (5) | "mecanismos de criação de objetos que aumentam flexibilidade e reuso do código existente" | *como nascem* os objetos |
|
|
43
|
+
| **Structural** (7) | "como montar objetos e classes em estruturas maiores, mantendo-as flexíveis e eficientes" | *como se compõem* |
|
|
44
|
+
| **Behavioral** (11) | "comunicação efetiva e atribuição de responsabilidades entre objetos" | *como conversam* |
|
|
45
|
+
|
|
46
|
+
### Creational — sintoma → padrão → quando NÃO
|
|
47
|
+
|
|
48
|
+
| Padrão | Code smell que sinaliza | Resolve | NÃO use quando |
|
|
49
|
+
|---|---|---|---|
|
|
50
|
+
| **Factory Method** | `new ConcreteX()` espalhado; `switch(type)` para instanciar | criar objetos cujo tipo exato você não sabe de antemão; deixar o framework ser estendido por subclasse | só há 1 tipo concreto e não há hierarquia de criadores — vira subclasse à toa |
|
|
51
|
+
| **Abstract Factory** | criar **famílias** de objetos que precisam ser compatíveis entre si (botão+checkbox do mesmo tema) | produzir famílias relacionadas sem amarrar a classes concretas | os produtos não formam família / não precisam casar — interfaces demais sem ganho |
|
|
52
|
+
| **Builder** | **construtor telescópico**: `new X(a,b,c,d,null,null,true)` | construir objeto complexo passo a passo; mesmas etapas, representações diferentes | objeto simples com poucos campos — o builder é mais código que o construtor |
|
|
53
|
+
| **Prototype** | subclasses que só diferem em **como inicializam**; código de init repetido | clonar objetos sem depender da classe concreta | objetos com referências circulares (a própria fonte avisa: clonar fica "muito complicado") |
|
|
54
|
+
| **Singleton** | querer "uma instância só" e ponto de acesso global | garantir instância única + acesso global | **quase sempre.** Viola SRP, mascara acoplamento, complica teste (construtor privado, sem mock por herança), exige cuidado com threads. Prefira injeção de dependência |
|
|
55
|
+
|
|
56
|
+
```ts
|
|
57
|
+
// Factory Method — esconde o `new` concreto atrás de uma escolha
|
|
58
|
+
interface Transport { deliver(): string; }
|
|
59
|
+
class Truck implements Transport { deliver() { return "via estrada"; } }
|
|
60
|
+
class Ship implements Transport { deliver() { return "via mar"; } }
|
|
61
|
+
|
|
62
|
+
abstract class Logistics {
|
|
63
|
+
abstract createTransport(): Transport; // o "factory method"
|
|
64
|
+
planDelivery() { return this.createTransport().deliver(); }
|
|
65
|
+
}
|
|
66
|
+
class RoadLogistics extends Logistics { createTransport() { return new Truck(); } }
|
|
67
|
+
class SeaLogistics extends Logistics { createTransport() { return new Ship(); } }
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### Structural — sintoma → padrão → quando NÃO
|
|
71
|
+
|
|
72
|
+
| Padrão | Code smell que sinaliza | Resolve | NÃO use quando |
|
|
73
|
+
|---|---|---|---|
|
|
74
|
+
| **Adapter** | interface incompatível: classe legada/3rd-party não encaixa no seu código | fazer interfaces incompatíveis colaborarem (tradutor) | você pode simplesmente alterar a classe de serviço — a fonte diz: às vezes editar direto é mais simples |
|
|
75
|
+
| **Bridge** | explosão combinatória de subclasses em 2 eixos (Forma × Cor) | separar abstração de implementação em hierarquias independentes; trocar impl em runtime | a classe é altamente coesa — a fonte avisa que aplicar aqui só complica |
|
|
76
|
+
| **Composite** | `if (isLeaf) … else (itera filhos) …`; tratar nó e folha diferente | árvore de objetos tratada uniformemente via interface comum (polimorfismo + recursão) | as classes diferem demais para uma interface comum — você supergeneraliza |
|
|
77
|
+
| **Decorator** | subclasses combinatórias para empilhar comportamentos (`BufferedEncryptedStream`) | adicionar comportamento em runtime empilhando wrappers | comportamento depende da **ordem** do empilhamento, ou você precisa remover um wrapper específico (a fonte cita ambos como difíceis) |
|
|
78
|
+
| **Facade** | cliente precisa orquestrar 10 classes do subsistema na ordem certa | uma interface simples para um subsistema complexo | a facade vira **god object** acoplado a tudo — sinal de que virou problema, não solução |
|
|
79
|
+
| **Flyweight** | **milhões** de objetos similares estourando a RAM, com estado duplicável | compartilhar estado intrínseco entre muitos objetos para caber na RAM | NÃO há problema real de RAM. A fonte é taxativa: *"use only when"* há explosão de objetos drenando memória. Caso contrário troca RAM por CPU e ofusca o código |
|
|
80
|
+
| **Proxy** | precisa de lazy-init / controle de acesso / cache / log **transparente** ao redor de um objeto | substituto que controla acesso (virtual, protection, remote, logging, caching, smart-ref) | uma chamada direta resolve — proxy adiciona classe e latência sem motivo |
|
|
81
|
+
|
|
82
|
+
```ts
|
|
83
|
+
// Decorator — empilha comportamento sem subclasse combinatória
|
|
84
|
+
interface DataSource { write(s: string): string; }
|
|
85
|
+
class FileSource implements DataSource { write(s: string) { return s; } }
|
|
86
|
+
|
|
87
|
+
abstract class Decorator implements DataSource {
|
|
88
|
+
constructor(protected wrappee: DataSource) {}
|
|
89
|
+
write(s: string) { return this.wrappee.write(s); }
|
|
90
|
+
}
|
|
91
|
+
class Encrypt extends Decorator { write(s: string) { return super.write(`enc(${s})`); } }
|
|
92
|
+
class Compress extends Decorator { write(s: string) { return super.write(`zip(${s})`); } }
|
|
93
|
+
|
|
94
|
+
new Encrypt(new Compress(new FileSource())).write("dado"); // enc(zip(dado)) — ordem importa!
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### Behavioral — sintoma → padrão → quando NÃO
|
|
98
|
+
|
|
99
|
+
| Padrão | Code smell que sinaliza | Resolve | NÃO use quando |
|
|
100
|
+
|---|---|---|---|
|
|
101
|
+
| **Chain of Responsibility** | série de `if/else` decidindo quem trata o request, em ordem | passar request por cadeia de handlers; cada um trata ou repassa | a fonte avisa: um request pode **acabar sem tratamento** — ruim se todo request precisa de resposta |
|
|
102
|
+
| **Command** | querer enfileirar / agendar / desfazer / logar operações | encapsular request como objeto (undo/redo, fila, log, remoto) | a operação é direta e nunca precisa ser adiada/revertida — só adiciona camada sender↔receiver |
|
|
103
|
+
| **Iterator** | código de travessia duplicado; expor estrutura interna da coleção | percorrer coleção sem expor sua representação | coleção simples (array) — a fonte diz: overhead desnecessário e menos eficiente que acesso direto |
|
|
104
|
+
| **Mediator** | teia de dependências diretas N×N entre componentes (UI clássico) | centralizar a comunicação em um mediador | poucos componentes pouco acoplados — o mediador vira **god object** com o tempo |
|
|
105
|
+
| **Memento** | precisar de snapshot/restore sem violar encapsulamento (undo) | salvar/restaurar estado sem expor campos internos | snapshots frequentes (estoura RAM) ou linguagem dinâmica que não garante imutabilidade do memento (JS/TS incluídos — a fonte cita) |
|
|
106
|
+
| **Observer** | objetos que precisam reagir a mudanças de outro, lista dinâmica | pub/sub: notificar muitos assinantes sobre eventos | ordem de notificação importa — a fonte avisa que assinantes são notificados em ordem imprevisível |
|
|
107
|
+
| **State** | conditionals gigantes sobre `this.status` espalhados pela classe | objeto muda comportamento conforme estado interno (máquina de estados) | poucos estados que raramente mudam — a fonte diz que é exagero |
|
|
108
|
+
| **Strategy** | `switch` entre variantes do **mesmo** algoritmo; classes que só diferem num comportamento | família de algoritmos intercambiáveis em runtime | só há 1-2 algoritmos estáveis; ou a linguagem tem funções de 1ª classe — a fonte sugere passar uma função/lambda em vez de criar classes |
|
|
109
|
+
| **Template Method** | classes com algoritmos quase idênticos, diferindo em poucos passos | esqueleto do algoritmo na superclasse, passos sobrescritos por subclasse | cliente fica preso ao esqueleto; cresce em passos → difícil manter; risco de violar LSP ao suprimir passo |
|
|
110
|
+
| **Visitor** | adicionar operações a uma hierarquia estável sem tocar nas classes | separar algoritmo dos objetos sobre os quais opera (acumula info na travessia) | a hierarquia de elementos muda muito — a fonte avisa: cada novo elemento força atualizar **todos** os visitors |
|
|
111
|
+
| **Interpreter** *(GoF clássico, fora do catálogo refactoring.guru)** | gramática simples e recorrente a avaliar (filtros, expressões) | representar uma gramática como classes e interpretá-la | gramática não-trivial → use parser/AST de verdade. Raro o suficiente para a fonte nem catalogar |
|
|
112
|
+
|
|
113
|
+
```ts
|
|
114
|
+
// Strategy — algoritmos intercambiáveis. Em TS, muitas vezes uma função basta:
|
|
115
|
+
type PricingStrategy = (base: number) => number;
|
|
116
|
+
const retail: PricingStrategy = b => b;
|
|
117
|
+
const black: PricingStrategy = b => b * 0.7;
|
|
118
|
+
|
|
119
|
+
class Cart {
|
|
120
|
+
constructor(private price: PricingStrategy) {} // injete a estratégia
|
|
121
|
+
total(base: number) { return this.price(base); }
|
|
122
|
+
}
|
|
123
|
+
new Cart(black).total(100); // 70 — sem classes Strategy/ConcreteStrategy: a fonte aceita
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### Pares que se confundem (escolha por intenção, não por estrutura)
|
|
127
|
+
|
|
128
|
+
| Você quer… | Use | NÃO confunda com |
|
|
129
|
+
|---|---|---|
|
|
130
|
+
| compatibilizar interface existente | **Adapter** | Facade (simplifica subsistema inteiro, não 1 classe) |
|
|
131
|
+
| adicionar responsabilidade transparente | **Decorator** | Proxy (controla acesso, mesma interface mas outro intento) / Adapter (muda interface) |
|
|
132
|
+
| trocar algoritmo de fora | **Strategy** | State (muda sozinho conforme estado interno; estados se conhecem) |
|
|
133
|
+
| esconder criação por subclasse | **Factory Method** | Abstract Factory (famílias) / Builder (passo a passo) |
|
|
134
|
+
| eixos independentes que variam | **Bridge** | Strategy (Bridge é decisão estrutural maior; Strategy é tática) |
|
|
135
|
+
|
|
136
|
+
### Padrões e refactoring — a relação
|
|
137
|
+
|
|
138
|
+
A fonte (refactoring.guru) trata os dois como complementares: **refactoring** é *"o processo
|
|
139
|
+
sistemático de melhorar código sem criar funcionalidade nova"*, e **code smells** são *"indicadores
|
|
140
|
+
de problemas… fáceis de notar, mas podem ser sintoma de um problema mais profundo."* O fluxo natural:
|
|
141
|
+
|
|
142
|
+
```
|
|
143
|
+
code smell → refactoring → (às vezes) design pattern como destino do refactoring
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
Os smells **são** os gatilhos da coluna "sintoma" das tabelas acima — `switch(type)` pede Strategy/
|
|
147
|
+
State/Factory; construtor telescópico pede Builder; conditionals sobre status pedem State. O padrão
|
|
148
|
+
é o **alvo** de um refactoring guiado por smell — não um ponto de partida. Comece pelo smell, não
|
|
149
|
+
pelo padrão. Se não há smell, não há padrão a aplicar.
|
|
150
|
+
|
|
151
|
+
## Checklist — antes de introduzir um padrão
|
|
152
|
+
|
|
153
|
+
Qualquer "não" é um sinal de over-engineering — pare:
|
|
154
|
+
|
|
155
|
+
- [ ] Existe um **code smell concreto e nomeável** hoje (não "pode ser que no futuro")?
|
|
156
|
+
- [ ] Consigo justificar por que a indireção extra **se paga** com flexibilidade que vou usar?
|
|
157
|
+
- [ ] Escolhi pela **intenção** do padrão, não pela estrutura parecida (Strategy vs State, Adapter vs Facade)?
|
|
158
|
+
- [ ] Considerei a alternativa mais simples da própria fonte (função/lambda em vez de Strategy; editar a classe em vez de Adapter; DI em vez de Singleton)?
|
|
159
|
+
- [ ] Li a seção **"NÃO use quando"** deste padrão e nenhum item bate no meu caso?
|
|
160
|
+
- [ ] Se é Singleton/Facade/Mediator: tenho como evitar o god-object / o acoplamento global?
|
|
161
|
+
- [ ] Estou no nível certo (design de classe), e não confundindo isto com decisão **arquitetural**?
|
|
162
|
+
|
|
163
|
+
## Tabela de decisão "use X quando Y"
|
|
164
|
+
|
|
165
|
+
| Quando Y (o sintoma)… | Use X | Categoria |
|
|
166
|
+
|---|---|---|
|
|
167
|
+
| não sei o tipo concreto a instanciar | Factory Method | Creational |
|
|
168
|
+
| preciso de famílias de objetos compatíveis | Abstract Factory | Creational |
|
|
169
|
+
| construtor com muitos parâmetros opcionais | Builder | Creational |
|
|
170
|
+
| subclasses só diferem na inicialização | Prototype | Creational |
|
|
171
|
+
| (raramente) instância única global controlada | Singleton — prefira DI | Creational |
|
|
172
|
+
| interface incompatível com a minha | Adapter | Structural |
|
|
173
|
+
| explosão de subclasses em 2+ eixos | Bridge | Structural |
|
|
174
|
+
| estrutura em árvore tratada uniformemente | Composite | Structural |
|
|
175
|
+
| empilhar comportamentos em runtime | Decorator | Structural |
|
|
176
|
+
| esconder a complexidade de um subsistema | Facade | Structural |
|
|
177
|
+
| milhões de objetos similares estourando RAM | Flyweight | Structural |
|
|
178
|
+
| controlar acesso (lazy/cache/log/remoto) transparente | Proxy | Structural |
|
|
179
|
+
| múltiplos handlers possíveis, em ordem | Chain of Responsibility | Behavioral |
|
|
180
|
+
| enfileirar / agendar / desfazer operações | Command | Behavioral |
|
|
181
|
+
| percorrer coleção sem expor a estrutura | Iterator | Behavioral |
|
|
182
|
+
| teia N×N de dependências entre componentes | Mediator | Behavioral |
|
|
183
|
+
| snapshot/restore sem violar encapsulamento | Memento | Behavioral |
|
|
184
|
+
| muitos objetos reagindo a um evento | Observer | Behavioral |
|
|
185
|
+
| comportamento muda conforme estado interno | State | Behavioral |
|
|
186
|
+
| trocar variante de algoritmo em runtime | Strategy | Behavioral |
|
|
187
|
+
| algoritmos quase iguais com poucos passos variáveis | Template Method | Behavioral |
|
|
188
|
+
| operações novas sobre hierarquia estável | Visitor | Behavioral |
|
|
189
|
+
| avaliar uma gramática simples recorrente | Interpreter | Behavioral |
|
|
190
|
+
|
|
191
|
+
> Fonte dos critérios, intents e prós/contras: [refactoring.guru/design-patterns](https://refactoring.guru/design-patterns).
|
|
192
|
+
> O catálogo da fonte cobre 22 padrões; o GoF clássico inclui **Interpreter** (23º), aqui mantido por completude.
|