Pular para o conteúdo principal

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​

GanhoCusto / Risco
Visão de alto nível em um único móduloAbstrações prematuras podem engessar o modelo
Módulos especializados desacoplados entre siMais indireção e mais tipos a manter
Vocabulário comum entre subdomíniosExige maturidade para identificar o que é realmente estável
Facilita testes com implementações alternativasMudanç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​