Recebi um desafio na faculdade, de escrever uma estrutura de tomada de decisão, aquela famosa "coisa bizarra" chamada Switch.
Imagine o seguinte, nós temos 4 regiões, sendo elas: Sul, Norte, Leste e Oeste. E para cada valor setado, desejo retornar uma região diferente, por exemplo:
Região | Valor |
Sul | 2 |
Norte | 3 |
Leste | 5 |
Oeste | 7 |
Com essa tabela ficou mais claro, se eu passar como parâmetro o valor 2, quero receber a região Sul. Bom, escrevendo o teste, poderemos refatorar depois, certo?
Crie um projeto no Eclipse/Visual Studio, e dê o nome de SubstituindoSwitch, feito isso, crie um source folder de test e crie um pequeno teste de unidade, em seu interior:
public class SustituindoSwitchTest {
@Test
public void DeveBuscarRegiaoSul() {
Assert.assertEquals("Sul", new SubstituindoSwitch().buscaRegiao(2));
}
@Test
public void DeveBuscarRegiaoNorte() {
Assert.assertEquals("Norte", new SubstituindoSwitch().buscaRegiao(3));
}
@Test
public void DeveBuscarRegiaoLeste() {
Assert.assertEquals("Leste", new SubstituindoSwitch().buscaRegiao(5));
}
@Test
public void DeveBuscarRegiaoOeste() {
Assert.assertEquals("Oeste", new SubstituindoSwitch().buscaRegiao(7));
}
}
Agora vamos resolver da forma mais simples. E o Switch cai como uma luva certo? Olha ele aí:
public class SubstituindoSwitch {
public String buscaRegiao(int valor) {
switch (valor) {
case 2:
return "Sul";
case 3:
return "Norte";
case 5:
return "Leste";
case 7:
return "Oeste";
default:
return "Região não encontrada.";
}
}
}
Bom, resolvemos o problema certo? Sim! Mas se temos toda aquela história de orientação a objetos e polimorfismo, por que usamos essa estrutura forrada de responsabilidades e totalmente procedural?
Podemos começar a pensar apenas em dividir as responsabilidades, ali no switch ficou claro que nossa classe SubstituindoSwitch tem uma grande responsabilidade de avaliar e claro devolver o retorno esperado e isso não é nada vantajoso. Vamos tentar encontrar semelhanças na responsabilidade. Para todas as situações um determinado valor é avaliado e caso seja ele o correto, recebemos uma String. E aí identificamos uma responsabilidade, vamos construir uma interface para esses responsabilidade:
public interface Regiao {
public boolean avalia(int valor);
public String procedencia();
}
Pronto, já definimos a responsabilidade, agora precisamos delegar os respectivos comportamentos, sabemos que o quando o valor for 7, desejamos receber a string Oeste, ok?
public class Oeste implements Regiao {
@Override
public boolean avalia(int valor) {
return valor == 7;
}
@Override
public String procedencia() {
return "Oeste";
}
}
E podemos fazer isso para todas as outras três regiões esperadas(Sul, Norte e Leste), cada uma dessas regiões com a mesma responsabilidade mas diferentes comportamentos. Certo? Implemente as outras classes para podermos dar continuidade. Caso a preguiça domine, vá até meu Github.
Agora voltaremos a nossa classe SubstituindoSwitch, e faremos algumas pequenas modificações, a primeira de todas é apagar o devorador de responsabilidades switch:
public class SubstituindoSwitch {
private List<Regiao> regioes;
public SubstituindoSwitch() {
regioes = new ArrayList<>();
regioes.add(new Sul());
regioes.add(new Norte());
regioes.add(new Leste());
regioes.add(new Oeste());
}
public String buscaRegiao(int valor) {
for (Regiao regiao : regioes) {
if (regiao.avalia(valor))
return regiao.procedencia();
}
return "Região não encontrada.";
}
}
Vou tentar ao máximo deixar claro o que está acontecendo no código acima, a primeira coisa que fizemos foi definir uma lista de regiões, ou seja, uma lista que armazenará todas as opções de regiões possíveis. Nosso método buscaRegiao continuou recebendo o parâmetro valor, mas ele não mais detém a responsabilidade de conter os valores das regiões, ele apenas delega a responsabilidade de acordo com uma avaliação também executada por cada responsável pelo valor, poxa, perdi até o fôlego. Detalhando:
if (regiao.avalia(valor))
return regiao.procedencia();
Esse
if
passa o valor para a região, a região detém o comportamento esperado e ela retorna o resultado desejado. Bom, só rodar os testes, e se maravilhar com o resultado. Bom, o próximo desafio é substituir o if
, aí já envolve um pouco mais de estudo. :PQualquer dúvida, comente abaixo ou email-me: abner.terribili@lambda3.com.br.
Se surgir dúvidas, tem o exemplo lá no meu Github:
Para os Java: https://github.com/aterribili/SubstituindoSwitch
Para os C#: https://github.com/aterribili/SubstituindoSwitch-CSharp
Abraços!
Nenhum comentário:
Postar um comentário