Evite blocos If /else e torne seu código modular com Strategy Pattern
Este texto é uma tradução livre com alguns outros comentários da postagem original feita pelo Iskander Samatov: https://isamatov.com/avoid-ugly-if-else-blocks-with-strategy/
A sintaxe do ES6 visa tornar nosso código mais conciso e claro. Ele realiza com sucesso esse objetivo: coisas como desestruturação, literais de string, operadores de propagação, etc. são ótimas ferramentas para melhorar a legibilidade do código.
Entretanto, uma parte específica da sintaxe que provavelmente nunca mudará é if /else e troca de instruções. Não sei qual a sua opinião, mas sempre achei que fosse a parte mais feia do meu código. No entanto, é um mal necessário e impossível de evitar.
Nos aplicativos, quase sempre enfrentamos uma situação em que temos que implementar algum tipo de método de roteamento que realize uma variação da ação determinada com base na condição. Esses métodos geralmente acabam tendo longos e feios if /else ou switch statements (opções de pagamento, roteamentos de e-mail, provedores de autenticação, etc).
Neste post, quero compartilhar um padrão que pode ajudá-lo a evitar alguns desses cenários.
Strategy Pattern
O padrão que estou falando é chamado de strategy. Esse padrão foi popularizado pelo GoF
(Gang of Four) e é uma ótima ferramenta para adicionar partes mutáveis e intercambiáveis a certas partes da sua lógica da aplicação.
Então, como isso funciona?
O strategy implementa as partes variáveis da funcionalidade com uma interface acordada para um objeto genérico que chamamos de “Contexto”. O contexto usa diferentes estratégias para executar uma tarefa com base na chamada do cliente.
Pense no conjunto de strategy como uma caixa de ferramentas e no contexto como um artesão. O artesão usa uma ferramenta diferente dependendo do trabalho. Mas, neste caso, todas as ferramentas têm o mesmo tipo de instruções sobre como usá-las.
Aqui está um diagrama que exemplifica essa ideia:
Passport.JS
O Passport.JS é um exemplo perfeito do uso do padrão strategy. O Passpost.JS é uma biblioteca de fácil integração com o sistema de autenticação em seu aplicativo Node.JS. Ele tem várias interfaces diferentes para configurar a autenticação com base no provedor que você deseja usar (Facebook, Google, Twitter, etc ). Tudo o que você precisa fazer é conectar a interface necessária à sua lógica de autenticação. Além disso, todas essas interfaces são intercambiáveis e você pode tranquilamente trocar uma pela outra.
Remetente de recibo
Tenho certeza que agora você tem uma compreensão básica do padrão de Strategy ou, pelo menos, o suficiente da teoria. Vamos tentar criar um sistema simples para entregar recibos aos usuários com base no cliente que eles usaram para fazer o pedido.
Definir strategy
Vamos começar desenvolvendo nossas estratégias. Primeiro vamos definir nossa strategy de email:
Estamos usando o módulo mailgun para enviar os emails. O objeto de strategy possui um método send que aceita receiptHtml e userEmail como parâmetros.
Agora vamos passar para a nossa strategy do Slack:
Estamos usando a biblioteca npm do slack para enviar o recibo por meio do nosso bot slack imaginário. Uma coisa importante a notar aqui:
- A assinatura send do método do strategy é idêntica ao seu equivalente de email.
Gerenciador de recibos
Agora que definimos nossas strategy, vamos definir nossa classe de gerenciador de recebimentos que irá gerar o html para o recebimento e usar nossas strategy para enviar o recebimento para o usuário:
Eu omiti a implementação do método _generateReceiptHtml, pois isso não é relevante para o nosso exemplo. A parte interessante é o método sendReceipt:
- Nós geramos o html para o recebimento usando _generateReceiptHtml
- Enviamos o recibo usando a strategy que nos foi passada como argumento
Uma vez que ambas as nossas strategy tenham a mesma assinatura de método, podemos usá-las de maneira intercambiável.
Agora vamos ver como sendReceipt ficaria se não definíssemos nossas strategy:
Observe como a declaração do switch diminuiu a legibilidade do nosso código. Este método pode não parecer tão ruim agora, mas mais tarde, se decidirmos adicionar mais canais para entregar os recibos, esse método se tornará feio rapidamente.
Client
Agora, para a parte final, vamos ver como é fácil usar nossas strategy junto com nosso gerenciador de recebimentos:
Simples, não é? Tudo o que precisamos fazer é instanciar a strategy apropriada, dependendo do canal que queremos usar, e transmiti-la ao nosso gerente de recebimentos.
E é isso para este post! Pequeno aviso: o padrão de strategy pode não ser aplicável a todos os casos e, às vezes, pode ser um exagero. Porque no final do dia, esse padrão é apenas uma ferramenta e, assim como qualquer ferramenta, você precisa se certificar de que ela se encaixa no seu trabalho.
No entanto, a strategy pode ser uma ótima maneira de impor uma separação de interesses e tornar as partes do seu código muito mais modulares e intercambiáveis.
—
Tem interesse em trabalhar conosco? Nós estamos sempre procurando por pessoas apaixonadas por tecnologia para fazer parte da nossa tripulação! Você pode conferir nossas vagas aqui.
Créditos
- Avoid ugly If/else blocks & make your code modular with Strategy, escrito originalmente por Iskander