Padrões de Projeto em Swift — Strategy
- AI-DLC e pAIr
- Artigo
Iniciando uma série de artigos sobre padrões de projeto (Design Patterns), hoje vamos falar especificamente do padrão Strategy. Além disso, vamos aplicar este padrão na linguagem Swift, que atualmente é utilizada para desenvolvimento iOS, mas que tem projeções futuras de uso como server side. Antes de mais nada, precisamos entender o que é um design pattern e como ele pode ser utilizado.
O QUE É UM PADRÃO DE PROJETO OU DESIGN PATTERN?
Em linhas gerais, design pattern é uma abordagem arquitetural no desenvolvimento de software para que um problema que se repete possa ser resolvido dentro de um determinado padrão, ao invés de simplesmente copiarmos o código e colocá-lo em outro ponto onde este problema ocorre. A vantagem de utilizar design patterns está em ter um código limpo e mais enxuto, portanto menos propenso a produzir bugs. Não significa que eles não existirão, mas serão encontrados mais facilmente quando ocorrerem. Além disso, a tendência à padronização do desenvolvimento torna mais fácil a manutenção do código, seja por desenvolvedores que já estão há mais tempo no projeto, quanto por desenvolvedores recém-chegados.
No livro “Design Patterns: Elements of Reusable Object-Oriented Software”, os autores dividem os Design Patterns em três tipos diferentes: Creational (Criação), Structural (Estrutural) e Behavioural (Comportamental). No decorrer desta série de artigos, vamos passar por todos os padrões de projeto aplicados ao desenvolvimento em Swift. O padrão strategy, assunto deste artigo, é um padrão do grupo Behavioural.
O padrão Strategy tem como meta definir uma família de algoritmos, encapsular cada uma delas e torná-las intercambiáveis. O strategy permite que o algoritmo varie independentemente dos clientes que o utilizam. Esta variação é feita em tempo de execução.
Entendendo o problema
No desenvolvimento mobile, eventualmente nos deparamos com a necessidade de validar o conteúdo de um ou mais campos UITextField (se estão preenchidos ou não ou se possuem um número mínimo de caracteres). Imagine, então, que vamos implementar uma solução para esta validação:
Essa solução certamente funcionará se tivermos apenas estes três tipos de validações possíveis para um campo de texto. Se eventualmente precisarmos adicionar mais um tempo de validação (se o campo tem regra para senha, por exemplo), poderíamos apenas adicionar mais um tipo no enum e adicionar mais uma cláusula no switch. Mas e se nossa gama de validações aumentar, e chegarmos em um ponto em que temos 20, 30 validações diferentes? Temos aqui um cenário em que o padrão strategy se encaixa perfeitamente.
Para explicar como utilizar este padrão, vamos responder a três perguntas e usar o diagrama abaixo, extraído do livro Design Patterns by tutorials:
Who (Quem): um objeto que está em conformidade com a validação que precisamos fazer. Em nosso exemplo, um objeto usando a Strategy para validar o campo.
What (O quê): um protocolo que define a ação que queremos encapsular. No caso, nossa ação será validar determinada regra de um campo.
How (Como): implementações específicas da estratégia. Teremos, então, três estratégias de validação de campos.
Neste mesmo exemplo, nossa implementação ficaria assim:
Por que usar strategy?
Este padrão é um dos mais simples de implementar, talvez um dos mais fáceis, e também segue algumas regras do SOLID, por exemplo.
- Single Responsibility: quando criamos uma estratégia, cada classe fica responsável apenas por um tipo de ação;
- Open/Closed Principle: se usarmos strategy, não precisamos modificar o comportamento do objeto original. Ao invés disso, criamos uma nova estratégia.
Mas quando identificar quando usar este padrão? Existem alguns indícios que podem ajudar nessa decisão:
- Uso de if’s e switches com muitas validações ou possibilidades;
- Ao identificarmos que é possível fazer uma mesma ação de várias formas;
- Se você precisa, com frequência, estender alguma funcionalidade de uma classe para implementar um novo comportamento.


