IF ou SWITCH (RESOLVIDO)

17 respostas
R

Qual dos dois tem mlhor desempenho?
Sabendo que a lógica entrara em uma cadeia de verificações.

17 Respostas

P

Os 2 tem quase o mesmo desempenho, mais evite ao maximo um controle em ifs ou switchs trabalhe mais orientado a objetos.

P

hahaha impossivel.

P

Por que impossível?
Cite um caso que não é possível substituir uma cadeia de ifs ou switchs por um metodo mais elegante?

P

Pedrosa:
Por que impossível?
Cite um caso que não é possível substituir uma cadeia de ifs ou switchs por um metodo mais elegante?

Pedrosa, vc deve ter experiencia sufuciente para saber que condições são inevitais num sistema de verdade. Mas vamos ao exemplo: no meu sistema tem uma regra de negócio que verifica o valor do salario. Se fo abaixo de uma faixa executo um método X, caso contrario o método Y. É isso.

abraços.

P

Um exemplo bem comum:

public class TesteServlet extends HttpServlet {
	protected void service(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {
	String businessLogic = request.getParameter("business");
	ContatoDAO dao;
		try {
			dao = new ContatoDAO();
			if(businessLogic.equals("AdicionaContato")) {
				Contato contato = new Contato();
				contato.setNome(request.getParameter("nome"));
				contato.setEndereco(request.getParameter("endereco"));
				contato.setEmail(request.getParameter("email"));
				dao.adiciona(contato);
			} else if (businessLogic.equals("ListaContato")) {
			} else if (businessLogic.equals("ExcluiContato")) {
			} else if (businessLogic.equals("PesquisaContato")) {	
			
		}
		} catch (SQLException e) {
			throw new ServletException(e);
		}
	}
}

Então é impossível retirar esses IFS porcos daqui?

P

Então é impossível retirar esses IFS porcos daqui?

eu não sei como. Como vc faria?

P

Não sei como esta o código mas tudo é possivel melhorar um pouquinho com uso de reflection, retirando os ifs, leia esse artigo:

http://www.tatanka.com.br/palestras/cj2005-Web+MVC+IoC+Reflection/

P

concordo com vc, tudo é possivel. Ate o Inter é campeão do mundo. rsrs

mas usar reflection é chato e trabalhoso. além disso poucas pessoas dominam e o código fica confuso.

mas se vc prefere… gosto é gosto, já dizia a velhinha que comia ranho. rsrsrsrs

abraços.

V

Uma maneira simples para o caso acima seria criar um map.

Agora, quando cheirar impossível demais, é porque seu código já está mal estruturado em outros lugares. No meu sistema aqui, não temos nenhum switch, nem cadeias de ifs desse tipo.

C

A utilização de estruturas de decisão deve ser moderada, porém também não vejo vantagem em utilizar códigos complexos fazendo uso de Reflection na tentativa de eliminá-las por completo.
Se a estrutura de decisão não fosse importante ela não existiria em TODAS as linguagems de programação. O caso é: “USE COM MODERAÇÃO”.
No exemplo dos vários salários poderíamos por exemplo fazer uso tanto de OO como dos “IFs”. Podería se criar um Factory para resolver o problema, assim teríamos IF ou SWITCH bem localizados nessa classe e estaríamos usando o Polimorfismo através de uma interface comum para deixar o código mais fácil de se reutilizar e até memso extender.

Essa é apenas minha humilde opinião.

P

palmadias:
Então é impossível retirar esses IFS porcos daqui?

eu não sei como. Como vc faria?

Assim:
A interface

public interface BusinessLogic {
    void execute(HttpServletRequest req, HttpServletResponse res) throws Exception;
}

O controlador

public class ControllerServlet extends HttpServlet {
    protected void service (HttpServletRequest request, HttpServletResponse response)  throws ServletException, IOException {
        String business = request.getParameter("business");
        String className = "br.com.xpto.mvc." + business;
         try {
            Class clazz = Class.forName(className);
            BusinessLogic businessLogic = (BusinessLogic) clazz.newInstance();
            businessLogic.execute(request, response);
        } catch (Exception e) {
           throw new ServletException("A lógica de negócios causou uma exceção", e);
       }
    }
}

Exemplo da apostila da Caelum FJ21

P

capalupo:
A utilização de estruturas de decisão deve ser moderada, porém também não vejo vantagem em utilizar códigos complexos fazendo uso de Reflection na tentativa de eliminá-las por completo.
Se a estrutura de decisão não fosse importante ela não existiria em TODAS as linguagems de programação. O caso é: “USE COM MODERAÇÃO”.
No exemplo dos vários salários poderíamos por exemplo fazer uso tanto de OO como dos “IFs”. Podería se criar um Factory para resolver o problema, assim teríamos IF ou SWITCH bem localizados nessa classe e estaríamos usando o Polimorfismo através de uma interface comum para deixar o código mais fácil de se reutilizar e até memso extender.

Essa é apenas minha humilde opinião.

O problema é que as pessoas programam de forma procedural em uma linguagem com recursos de orientação objetos, a gente perde um pouquinho mais de tempo estruturando corretamente e ganha em produtividade e torna o código mais facil de manter.

V

Ninguém falou que estruturas de decisão não são importantes.

O que se falou é que “cadeias de ifs” e “switchs” podem, em todos os casos, serem substituidos por formas mais elegantes e orientadas a objetos, baseadas em polimorfismo. E essas formas, geralmente, tem melhor desempenho também.

E detalhe: não é necessário usar de reflection. Como eu falei, pode-se usar um simples Map ou um enum que, mesmo com o trabalho de cria-los, ainda assim, ficam muito melhores do que os ifs/switchs. E ficam mais flexíveis também.

É lógico que em alguma situações ifs existirão.
Principalmente para testar condições simples.

Já o switch… há tempos que não vejo um e realmente não sinto falta dele.

H

switchs so utilizam um inteiro como argumento.

ifs podem usar outros tipos de objeto como argumento.

quanto ao desempenho creio que seja o mesmo pois ele vai fazendo as verificacoes na ordem que vc coloca assim como o if. Caso o switch nao encontre o valor, ele vai no default. Entao, acredito que o desempenho seja o mesmo.

abraco

C

ViniGodoy wrote:

Ninguém falou que estruturas de decisão não são importantes.

O que se falou é que “cadeias de ifs” e “switchs” podem, em todos os casos, serem substituidos por formas mais elegantes e orientadas a objetos, baseadas em polimorfismo. E essas formas, geralmente, tem melhor desempenho também.

E detalhe: não é necessário usar de reflection. Como eu falei, pode-se usar um simples Map ou um enum que, mesmo com o trabalho de cria-los, ainda assim, ficam muito melhores do que os ifs/switchs. E ficam mais flexíveis também.

É lógico que em alguma situações ifs existirão.
Principalmente para testar condições simples.

Já o switch… há tempos que não vejo um e realmente não sinto falta dele.

Usar Map e Enums nunca substituirá a funcionalidade de estruturas de desvio. Como você faria para executar um determinado bloco de código sem utilizar de Reflection ou de estruturas de decisão apenas com Maps e Enums?

V
capalupo:
Usar Map e Enums nunca substituirá a funcionalidade de estruturas de desvio. Como você faria para executar um determinado bloco de código sem utilizar de Reflection ou de estruturas de decisão apenas com Maps e Enums?

Que mania vcs tem de achar que a existência de uma coisa anula a existência de outra! Ou que por eu falar que reflection não era necessária, eu estaria dizendo que ela era inútil. Eu só estava dizendo que existem maneiras mais simples de se fazer isso, sem o uso da estranha metalinguagem da reflexão.

Bem, é bem simples. Considere uma classe que vai decodificar um protocolo, gerando objetos. E a mensagem virá no protocolo da seguinte forma (muito comum em telecomunicação, por sinal):

4 bytes: tipo da informação
n bytes: payload

Cada tipo de dado exige uma decodificação diferente de payload. Como fazer isso sem ifs e usando maps, sem reflection?

Use o padrão de projetos Strategy para definir a interface e os decodificadores:
public interface Decoder {
   public ProtocolEvent decode(ByteBuffer data);
}

Depois, crie seus decoders e ponha-os num mapa, que relaciona o tipo da informação, com seu decoder específico.

public Map<Integer, Decoder> decoders = new HashMap<Integer, Decoder>();

decoders.put(0x01, new HandShakeDecoder());
decoders.put(0x0F, new WizardSpellDecoder());
decoders.put(0x3F, new SalesDecoder());

Agora, quando uma mensagem chega do protocolo você simplesmente faz:

int messageType = byteBuffer.getInt();
if (!decoders.contains(messageType)) 
    return new UnknownMessage(byteBuffer);
return decoders.get(messageType).decode(byteBuffer);

Viu alguma reflection aí? Note que o mapa usado dessa forma funcionou como uma estrutura de desvio. E no caso de um protocolo com muitas mensagens, ele será consideravelmente mais rápido que um if, já que a performance para achar o decodificador de uma mensagem arbitrária será sempre O(1).

Ok, você também pode ter classes assim associadas a Strings. E usar um arquivo de configuração e os maps para permitir algum grau de flexibilidade ao usuário.

Agora, o que eu não disse é que reflection é inútil. Ela permite flexibilidade e extensibilidade. Essa estratégia não permite isso. Mas é bom lembrar que o reflection tem um custo, que é um aumento significativo da complexidade do código, além da possibilidade de inserir erros que, se não muito bem cobertos por JUnits, só serão pegos em Runtime. A reflection é também mais lenta o que, no caso de uma aplicação de comunicação em tempo real (como a do exemplo acima) pode ser fator decisivo para que não seja utilizada.

O exemplo dos próprios colegas, que fala das regras de negócio, poderia ser feito sem reflection. Cada regra tem um nome, e esse nome está associado a uma classe de regra. Desde que essas classes existam em tempo de compilação (e muitas vezes existem), poderia ser feito através de maps, ao invés de reflection. A desvantagem seria que a adição de novas regras exigiria a recompilação do código. No caso da maior parte dos sistemas comerciais, creio que a flexibilidade pese muito mais do que a performance. Aliás, pesa tão mais que realmente paga até os custos de um código mais complexo.

No final, é seu papel de desenvolvedor analisar qual das relações de vantagens/desvantagens de cada abordagem melhor resolve o seu problema. O que não pode, é achar que existe uma única estratégia, capaz de resolver tudo.

V

Veja o caso do pedrosa:

public class TesteServlet extends HttpServlet { protected void service(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException { String businessLogic = request.getParameter("business"); ContatoDAO dao; try { dao = new ContatoDAO(); BusinessLogic logic = businessLogicMap.get(businessLogic); logic.process(contato, dao); } catch (SQLException e) { throw new ServletException(e); } } }

Em outro momento, claro, você teve que montar um mapa com o nome da businessLogic e sua classe associada.

O uso de reflection aqui, como fez o pedrosa, só se justifica pois viabiliza que essas regras de negócio possam ser obtidas de fora do programa, de maneira dinâmica. É muito comum que sistemas administrativos permitam que os administradores dêem vazão a sua criatividade, e mudem regras o tempo todo. O mercado é dinâmico e exige que a empresa tenha rapidez em mudanças de estratégia.

Agora, não pense que reflection aqui existe só para livrar você do if. Se você está usando única e exclusivamente para isso, você pode estar pagando um custo muito caro de manutenção, complexidade e risco de erros para coisas que poderiam ser resolvidas com maps.

Os protocolos são um ótimo exemplo disso. Suas regras mudam pouco, muitos são até padronizados. Você conhece o que fazer em compile time. Ali, você pode se livrar dessa parafernalha reflexiva toda, e usar um código estático, mas verificável pelo seu compilador.

Criado 13 de março de 2009
Ultima resposta 18 de mar. de 2009
Respostas 17
Participantes 6