Skip to content

ADR-102: Architecture Foundation

Status: Accepted

Contexto

middag-account precisa de uma arquitetura que permita: (1) lógica de domínio testável sem WordPress rodando, (2) injeção de dependências sem chamadas estáticas, (3) camada de abstração que isole o WordPress como detalhe de infraestrutura, (4) auto-discovery de serviços sem registro manual, (5) suporte a PHP 8.4+ com tipagem moderna. O tema legado misturava lógica de negócio com código WordPress, tornando testes unitários lentos e frágeis.

Decisão

Adotar DDD Light com Symfony DI Container 7.4 e uma camada de abstração WordPress de 6 adapters, organizado em camadas com direção de dependência estrita.

DDD Light — Domain Layer Zero-WP

A camada src/Domain/ contém entidades, value objects, repositórios (interfaces), serviços de domínio e enums de status — tudo em PHP puro, zero imports de funções wp_* ou classes WP_*.

Isso permite:

  • Testes unitários rápidos sem bootstrap WordPress (Brain\Monkey para stubs quando necessário)
  • Lógica de negócio reutilizável independente de CMS
  • PHPStan pode enforçar a regra via análise estática

Symfony DI Container 7.4

Container de injeção de dependências com:

  • Injeção de construtor em todas as classes — zero chamadas estáticas
  • Auto-discovery por sufixo: classes terminando em Service, Repository, Controller, Handler, Hooks, Registrar são registradas automaticamente
  • Compilação em produção — container compilado para performance

Camadas e Direção de Dependência

src/
├── Domain/            # Pure PHP — ZERO dependências WordPress
│   ├── {Name}/        # Entidade, RepositoryInterface, Service, Enum
│   └── ...

├── WordPress/         # Camada de abstração CMS (adapters)
│   ├── PostType/      # Registro de CPTs
│   ├── Database/      # Abstração wp_posts/wp_postmeta
│   ├── Hook/          # HookInterface com register()
│   ├── Rest/          # Registro de rotas REST
│   ├── Cron/          # Agendamento WP-Cron
│   ├── Email/         # Templates de email
│   └── Repository/    # Implementações de RepositoryInterface

├── Api/V1/            # REST controllers (middag-account/v1)

├── Integration/       # HubSpot, Stripe, ISSNet, BancoInter, etc.

├── Core/              # Container, Kernel, ServiceProvider, Middleware

└── UI/                # Page controllers Inertia + middleware

Direção: WordPress/ → Domain/ (nunca o inverso). Api/ e Integration/ dependem de Domain/. Core/ bootstrapa tudo.

6 Adapters da WordPress Abstraction Layer

AdapterResponsabilidade
PostTypeRegistro de CPTs middag_{domain}, capabilities
DatabaseAbstração wp_posts + wp_postmeta, toggle CCT
HookHookInterface com register(), prefixo middag/
RestRegistro de rotas REST com permission_callback
CronWP-Cron → thin handler → domain service
EmailTemplates theme-overridable via TemplateRenderer

Repository Pattern

Domain code defines repository interfaces. WordPress adapter layer provides concrete implementations using QueryBuilder and MetaRepository. The DI Container binds interface to implementation. No domain code calls WP_Query, get_post_meta(), or any WordPress function directly.

Detalhes de implementação, CPTs, sub-namespaces e naming conventions em REF-102-01.

PHP 8.4+

  • Enums nativos para status de domínio
  • Match expressions
  • Named arguments
  • Readonly properties
  • Tipagem estrita em todo código

Boot

Plugin inicializa no hook plugins_loaded — nunca imediatamente. O Kernel compila o container DI, registra hooks, carrega serviços descobertos.

Consequências

Positivas:

  • Camada de domínio 100% testável sem WordPress (908 testes, 3722 assertions no tema migrado)
  • Auto-discovery elimina registro manual de serviços — adicionar classe com sufixo correto basta
  • Direção de dependência estrita previne acoplamento acidental ao CMS
  • PHP 8.4+ features melhoram legibilidade e segurança de tipos

Negativas:

  • Curva de aprendizado para devs acostumados com WordPress procedural
  • Overhead do Symfony DI Container (mitigado por compilação em produção)
  • Regra zero-WP no Domain/ requer disciplina — PHPStan deve enforçar continuamente
  • 6 adapters adicionam camada de indireção entre WordPress e lógica de negócio

Referências

  • ADR-101 — Product Vision & Identity
  • ADR-103 — Plugin Ecosystem (§Ecosystem: stack e classificação)
  • REF-102-01 — Persistence & WordPress Adapter Spec
  • REF-102-02 — Plugin Entry Point Spec
  • docs-site/patterns.md — Padrões ativos (14 patterns documentados)