DDD do jeito certo

Usando “Specification Pattern” para respeitar o “Open/Closed Principle”

Como implementar regras de negócio que podem mudar com o passar do tempo sem violar o “Open/Closed Principle” do SOLID? Afinal, a violação desse princípio deixaria os códigos difíceis de manter além de implicar na escritas de testes que “quebrariam” pelos motivos errados.

Na programação orientada a objeto, o princípio do aberto/fechado estabelece que “entidades de software (classes, módulos, funções, etc.) devem ser abertas para extensão, mas fechadas para modificação“; isto é, a entidade pode permitir que o seu comportamento seja estendido sem modificar seu código-fonte. (Wikipedia)

Há anos, temos visto sempre os mesmos exemplos, triviais, porém distantes do “mundo real”, onde a solução para o desafio imposto pelo princípio implica em suportar alguma variação de polimorfismo.

public abstract class Employee
{
  // ...
  public abstract bool IsElegibleForRetirement();
  // ..
}

O problema destas abordagens é que elas ignoram cenários onde comportamentos expressos por mais de um elemento do contrato (mais de um método) variam independentemente. Além disso, soluções baseadas em herança geram evidente custo de acoplamento.

Uma solução, mais elegante em nossa opinião, possível em diversos cenários, é recorrer a adoção do Specification pattern.

Specification Pattern é um padrão de design de software, onde regras de negócio podem ser recombinadas através de lógica booleana. (Wikipedia em tradução livre)

public class RetirementLaw_287_2016 : IRetirementSpecification
{
  public bool IsSatisfiedBy(Employee e) { /* .. */ }
} 

A “beleza” dessa abordagem é que ela se encaixa perfeitamente para, por exemplo, implementar suporte a leis e regulações (como no caso da lei de aposentadoria, indicado no exemplo). Assim, sempre que uma nova regulação entra em vigor, podemos criar uma nova versão da especificação. Outro ponto forte dessa ideia é a facilidade de tornar o código compreensível pelo especialista do domínio.

O que acha?

Em Resumo
  • O problema

    Com frequência, precisamos suportar regras de negócio que mudam ao longo do tempo (muitas vezes por imposição legal). Em casos de desenvolvimento ingênuo, ocorrem violações do "Open/Closed Principle", ou ainda, aumento do índice de acoplamento.
  • O Insight

    No lugar de polimorfismo simples, podemos adotar o padrão Specification. Nesse caso, a lógica que "muda" com o tempo fica isolada e adequadamente identificada.
  • Os benefícios

    O código resultante é mais fácil de manter e de entender, sobretudo pelos especialistas de domínio. Além disso, o código também fica mais fácil de testar.

Mais posts da série DDD do jeito certo

1 comentário
  1. Jeferson Viana Perito

    Já usei esse padrão alinhado com builder pattern para construir objetos de domínio, “forçando” a passar pelas especificações e manter todo objeto na memória válido perante regras de negócio.

Deixe uma resposta

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *