Anti-if campaign [resolvido]

depois de um post aqui no fórum, fui dar uma olhada na Anti-If Campaign, que dizem ser uma melhoria de práticas de OOP.
mas ainda tô com muita dúvida em alguns casos, especialmente aqueles que possuem uma entrada desconhecida (um user input) .-.
um exemplo muito simples, uma calculadora, usando a classe Scanner, tendo os métodos somar(int,int), subtrair(int,int) … como faço pra saber qual dos quatro usar a partir de um menu “1. somar\n2. subtrair …” sem utilizar um if? pensei nisso utilizando polimorfismo, enum, mas a ideia de como resolver isso sem if nem switch não me veio a cabeça…

alguém poderia explicar/exemplificar algumas práticas do Anti-If? ty ‘-’

Rapaz, a questão do “ifless” é bem clara neste aspecto. Um if (ou switch) deve ser utilizado quando as situações que ele irá gerenciar são conhecidas.
Uma calculadora básica, por exemplo, sempre irá executar as 4 operações matemáticas. Não há como fugir disso.
O problema do if é quando você coloca o mesmo para gerenciar usuários, por exemplo ou quando deseja comparar algo que não controla, como o tipo de cartão de crédito aceito por uma loja, os percentuais de desconto em venda a vista e coisas do gênero.

Opá da uma olhada em http://www.guj.com.br/articles/137 veja o factory acredito que seja isso que esta buscando.

mas se eu utilizar a Factory, o que vou estar fazendo não é eliminando o if, e sim jogando ele pra outro método ._.

public class CarroFactory { public static Carro getCarro( String tipoCarro ) { if( tipoCarro == null ) return null; else if( tipoCarro.equals("Vectra") ) return new Vectra(); else if( tipoCarro.equals("Omega") ) return new Omega(); else if( tipoCarro.equals("Golf") ) return new Golf(); else if( tipoCarro.equals("Gol") ) return new Gol(); else return null; } }

da pra eliminar o if sim, jogue seus objetos num map e o codigo fica algo parecido como

public static Carro getCarro( String tipoCarro ) { return map.get(tipoCarro); }

isso fica parecendo um abuso de linhas de código, pode até eliminar os “code monster”, mas vai acabar gerando muito código e muitos arquivos a mais .-.
pra uma calculadora básica então, eu teria de ter a interface Operacao, e as classes Soma, Subtracao, Divisao e Multiplicacao, e mapear os objetos dessas classes?
realmente, não tô conseguindo enxergar aonde que estão as boas práticas nisso

whatever floats your boat…

[quote=Mephy]isso fica parecendo um abuso de linhas de código, pode até eliminar os “code monster”, mas vai acabar gerando muito código e muitos arquivos a mais .-.
pra uma calculadora básica então, eu teria de ter a interface Operacao, e as classes Soma, Subtracao, Divisao e Multiplicacao, e mapear os objetos dessas classes?
realmente, não tô conseguindo enxergar aonde que estão as boas práticas nisso[/quote]

Acho que o drsmachado explicou bem o propósito de não usar if e você pegou o espírito da programação. De fato, usar polimorfismo e reflections para implementar uma calculadora simples, que realize as 4 operações básicas é uma aberração, é complicar demais algo que é muito simples (depois ninguém sabe de onde vêm a fama de programador Java ser improdutivo).

Porém, existem casos em que usar if ou switch/case aumento o custo da manutenção de um sistema exponencialmente. Uma situação pela qual passo constantemente é a seguinte, em determinadas rotinas de controle de estoque eu preciso calcular o custo de uma determinada mercadoria. Dependendo da empresa e da situação, o cálculo do custo varia: custo com icms, custo sem icms, custo de reposição, etc. Isso muda métodos de cálculo, campos do banco de dados que tem que ser lidos, etc. Nesse caso, eu coloco em constantes de enumeração o nome da coluna que tem quer ser lido, sobrescreve métodos de cálculo etc., de forma que eu não preciso ficar fazendo if’s ao longo do código. Se eu tiver que testar uma entrada de usuário para determinar qual o tipo do custo, isso é feito uma vez só, ao invés de deixar isso espalhado no sistema.

[quote=Mephy]isso fica parecendo um abuso de linhas de código, pode até eliminar os “code monster”, mas vai acabar gerando muito código e muitos arquivos a mais .-.
pra uma calculadora básica então, eu teria de ter a interface Operacao, e as classes Soma, Subtracao, Divisao e Multiplicacao, e mapear os objetos dessas classes?
realmente, não tô conseguindo enxergar aonde que estão as boas práticas nisso[/quote]

Se o seu código tem que repetir o if/switch em vários lugares para fazer coisas diferentes dependendo da operação, o código fica mais limpo com OOP. pois ao invés de:

switch (op)
{
  case Adicao:
    adiciona();
    break;
  case Subtracao:
    subtrai();
    break;
 /// ... etc..
}

você simplesmente escreveria:

op.executar();

Agora, se o seu código tem esse if em apenas um lugar, não tem muita vantagem pois em OOP você vai precisar de um if/switch ou algo similar para decidir qual classe a ser instanciada.

[quote=balrog]da pra eliminar o if sim, jogue seus objetos num map e o codigo fica algo parecido como

public static Carro getCarro( String tipoCarro ) { return map.get(tipoCarro); }
[/quote]Na minha opinião, um enum é mais indicado que um Map para esse caso.

Mas você pode adotar também reflection e ficar “livre” de amarras (não precisa necessitar abrir uma classe para adicionar outra referência à mesma):
Tutorial Oracle: http://download.oracle.com/javase/tutorial/reflect/index.html
Tutorial GUJ: http://www.guj.com.br/articles/10

[quote=Mephy]isso fica parecendo um abuso de linhas de código, pode até eliminar os “code monster”, mas vai acabar gerando muito código e muitos arquivos a mais .-.
pra uma calculadora básica então, eu teria de ter a interface Operacao, e as classes Soma, Subtracao, Divisao e Multiplicacao, e mapear os objetos dessas classes?
realmente, não tô conseguindo enxergar aonde que estão as boas práticas nisso[/quote]
Orientação a Objetos é assim. Mas se for bem desenhado, o resultado fica melhor que o esperado.
Não é ruim ter mais arquivos e mais código pode significar um código mais limpo e com classes/métodos especializados.