Clean Code: Domain Driven com Tabelas de Decisão e Tuple Patterns
- Marcos Jonatan Suriani
- 22 de out. de 2020
- 3 min de leitura
Atualizado: 23 de out. de 2020

Há anos venho me deparando com situações em que a regra do domínio (vulgo regra de negócio) quando escrita em linguagem natural, seja para critérios de aceite ou documentação, tende a ser de leitura complexa. Há casos que esta escrita natural até possui um padrão de escrita - como Given-When-Then, contudo o problema persiste!
Quando regras de negócio possuem tomadas de decisão e são convertidas em código-fonte, condicionais e desvios de fluxo tendem a ser implementados, o que tende tornar o código mais difícil de ler e manter, principalmente por características inerentes à complexidade ciclomática.
Para exemplificar, considere a seguinte regra de negócio fictícia escrita no padrão Given-When-Then:
Feature: Desconto em inscrição em um plano na plataforma
Cenário: Residência em País Bonificado
Dado que usuário reside em país com benefício
Quando se inscrever em qualquer plano e utilizar Pagamento anual ou mensal
Então aplicar 50% de desconto
Cenário: Plano Padawan com Pagamento Mensal
Dado que usuário não reside em país com benefício
Quando se inscrever no Plano Padawan e utilizar Pagamento Mensal
Então aplicar 10% de desconto
Cenário: Plano Padawan com Pagamento Anual
Dado que usuário não reside em país com benefício
Quando se inscrever no Plano Padawan e utilizar Pagamento Anual
Então aplicar 15% de desconto
Cenário: Plano Mestre Jedi com Pagamento Mensal
Dado que usuário não reside em país com benefício
Quando se inscrever no Plano Mestre Jedi e utilizar Pagamento Mensal
Então aplicar 20% de desconto
Cenário: Plano Mestre Jedi com Pagamento Anual
Dado que usuário não reside em país com benefício
Quando se inscrever no Plano Mestre Jedi e utilizar Pagamento Anual
Então aplicar 25% de desconto
Notou como fica extenso, de difícil leitura, e procurar a regra correta demanda que muito texto seja lido?
Será que parte da problemática se deve à conversão de uma regra escrita em linguagem natural para uma linguagem de programação, contendo seus paradigmas, semânticas e sintaxe?
Como podemos pelo menos tentar reduzir esta distância?
Tabelas de Decisão
A Tabela de decisão é uma maneira de expressar, em forma de tabela, qual o conjunto de condições que é necessário ocorrer para que um determinado conjunto de ações deva ser executado. O ponto principal de uma tabela de decisão é a regra de decisão, que define o conjunto de ações a ser tomado, a partir de um conjunto de condições. [wikipedia]
A vantagem do uso de tabelas de decisão se dá pelo fato de ser muito focada em palavras-chave e ubíquas relacionadas ao negócio - orientada a domínio, se assim podemos dizer :)
Em outras palavras, podemos considerar que é uma forma tabular de tomada de decisão.
A mesma regra escrita em linguagem natural acima foi convertida para uma tabela de decisão, conforme segue:
Feature: Desconto em inscrição em um plano na plataforma

Convertemos cerca de 24 linhas de texto em uma tabela 6x8, contando com cabeçalho e rodapé. O que achou?
Show me the Code!

Seguindo o exemplo citado acima, há uma abordagem clássica para codificar estas estruturas de controle de fluxo e tomadas de decisão.
decimal PercentualDesconto(Plano plano, Usuario usuario, Pagamento pagamento)
{
if (PaisComBeneficio(usuario.PaisResidencia))
return 50;
if (plano == Plano.Padawan && pagamento == Pagamento.Mensal)
return 10;
if (plano == Plano.Padawan && pagamento == Pagamento.Anual)
return 15;
if (plano == Plano.MestreJedi && pagamento == Pagamento.Mensal)
return 20;
if (plano == Plano.MestreJedi && pagamento == Pagamento.Anual)
return 25;
return 0;
}
Utilizando o Tuple Patterns do C# 8 podemos reduzir drasticamente a complexidade e evitar controles de fluxo com if/then/else.
decimal PercentualDesconto(Plano plano, Usuario usuario, Pagamento pagamento) =>
(plano, pagamento, PaisComBeneficio(usuario.PaisResidencia)) switch
{
(_, _, true) => 50,
(Plano.Padawan, Pagamento.Mensal, _) => 10,
(Plano.Padawan, Pagamento.Anual, _) => 15,
(Plano.MestreJedi, Pagamento.Mensal, _) => 20,
(Plano.MestreJedi, Pagamento.Anual, _) => 25,
(_, _, _) => 0
}
Em termos de atributos qualitativos, o que achou do readability?
O quão distante ficamos do formato tabular para tomada de decisão?
Esta é apenas mais uma abordagem em meio a inúmeras possibilidades! Se tiver uma diferente ou sugestão de melhorias, deixe seu comentário. Vamos adorar conhecer!
Comments