Abstract Core
Descrição
O Abstract Core é um módulo separado que contém os conceitos mais fundamentais do modelo, expressos como classes abstratas e interfaces. Ele captura o vocabulário e as interações essenciais entre os subdomínios, sem os detalhes de implementação que variam de um para o outro.
Os módulos especializados dependem do Abstract Core e implementam ou estendem seus tipos, mas não dependem uns dos outros diretamente. Isso permite entender o modelo de alto nível lendo apenas o núcleo abstrato, e reduz o acoplamento entre as partes especializadas.
É um recurso mais forte do que o Highlighted Core, pois muda a estrutura do código, mas pode ser menos invasivo que um Segregated Core quando o core é muito grande para ser movido por inteiro. Só vale a pena quando há muita interação entre módulos e um conjunto de conceitos claramente estável.
Problemas que resolve
- Modelo grande, em que muitos módulos se comunicam entre si e criam uma teia de dependências.
- Dificuldade de entender o todo sem percorrer cada módulo especializado.
- Tipos concretos espalhados, forçando mudanças em cascata quando um módulo evolui.
- Falta de um vocabulário comum que atravesse os subdomínios.
Quando usar
- Quando há muita interação entre módulos e um núcleo conceitual estável pode ser identificado.
- Quando o core é grande demais para ser segregado por inteiro.
- Quando se quer que módulos especializados possam variar sem afetar uns aos outros.
Quando evitar
- Quando o modelo ainda está mudando rapidamente e não há conceitos estáveis o suficiente para abstrair.
- Quando poucos módulos interagem; as abstrações seriam cerimônia sem ganho.
- Quando abstrair esconde regras de negócio importantes ou gera indireção excessiva.
Trade-offs
| Ganho | Custo / Risco |
|---|---|
| Visão de alto nível em um único módulo | Abstrações prematuras podem engessar o modelo |
| Módulos especializados desacoplados entre si | Mais indireção e mais tipos a manter |
| Vocabulário comum entre subdomínios | Exige maturidade para identificar o que é realmente estável |
| Facilita testes com implementações alternativas | Mudanças no núcleo abstrato afetam todos os módulos |
- Estabilidade: o núcleo abstrato muda pouco; modificá-lo tem impacto amplo e exige cuidado.
- Dependências: apontam sempre dos módulos especializados para o núcleo, nunca na outra direção.
- Compromisso: é necessário decidir o que entra no núcleo; muito conteúdo o transforma em uma segunda cópia do modelo.
Diagrama
Policy e Insurable formam o núcleo abstrato; os módulos de seguro de automóvel e de vida o especializam sem se conhecerem.
Exemplo
Uma seguradora oferece seguro de automóvel e de vida, com módulos que evoluem em ritmos diferentes. Ambos precisam participar de campanhas, renovações e relatórios de exposição, o que levou a dependências diretas entre os módulos.
A equipe cria o módulo insurance-core, com apenas Policy, Insurable e Premium, em termos abstratos. Os módulos auto e life o implementam, e renovações e relatórios passam a depender só das abstrações.
// módulo insurance-core
public interface Insurable { Score riskScore(); }
public abstract class Policy {
protected final Insurable subject;
protected Policy(Insurable subject) { this.subject = subject; }
public abstract Money premium();
}
// módulo auto (depende de insurance-core)
public class AutoPolicy extends Policy {
public AutoPolicy(AutoVehicle vehicle) { super(vehicle); }
public Money premium() { return Money.of(100).times(subject.riskScore()); }
}
Padrões relacionados
- Core Domain — o Abstract Core é uma forma de organizar e comunicar o core.
- Highlighted Core — alternativa mais leve, que não altera a estrutura.
- Segregated Core — alternativa que move o core inteiro, em vez de extrair apenas abstrações.
- Module — o núcleo abstrato vive em um módulo próprio.
- Knowledge Level — outra forma de separar conceitos abstratos e regras configuráveis.
- Pluggable Component Framework — usa interfaces abstratas para permitir componentes intercambiáveis.
- Separated Interface — técnica para colocar interface e implementação em pacotes distintos.
- Abstract Factory — comumente usada para criar implementações sem conhecer os tipos concretos.
Referência
- DDD Reference, Eric Evans (2015)
- Domain-Driven Design: Tackling Complexity in the Heart of Software, Eric Evans (Addison-Wesley, 2003)