Como nao aprender orientacao a objetos: o excesso de ifsAglomerados de ifs aparecem com frequencia, e chegam ate a ter um aspecto engracado. Em alguns casos poder dar a impressao de que estamos usando orientacao a objetos, ja que cada clausula costuma envolver a invocacao de um metodo, dependendo do tipo do objeto. Infelizmente, essa sensacao e falsa, e chegou ate a gerar o conhecido movimento anti if campaign na internet.O exemplo a seguir mostra uma sequencia de ifs que indicam condicoes distintas de execucao:public double calculaBonus(Funcionario f) { if (f.getCargo().equals("gerente")) { return f.getVendasDoMes() * 0.05 + getSalario() * 0.1; } else if (f.getCargo().equals("diretor")) { return f.getVendasDoMes() * 0.05 + getSalario() * 0.2 + (Today.isDecember() ? getSalario() : 0); } else { return f.getVendasDoMes() * 0.01; }}Esse tipo de condicional pode ser retrabalhado em objetos (ou funcoes dependendo da linguagem) que definam o comportamento a ser executado em cada caso. Heranca e poliformismo podem (e na maioriam dos casos, devem) ser usados de maneira controlada para alterar um comportamento:class Funcionario { // outros atributos e metodos aqui public double getBonus() { return vendasDoMes * 0.01; }}class Gerente extends Funcionario { // outros atributos e metodos aqui public double getBonus() { return vendasDoMes * 0.05 + getSalario() * 0.1; }}Nesse caso, os responsaveis pelo comportamento sao encontrados de acordo com uma condicao: o tipo que o objeto representa, sendo que cada subtipo pode redefinir o comportamento do metodo. Nao havera necessidade de ifs, ja que essa descoberta de qual metodo executar e feita pela maquina virtual: funcionario.getBonus().Esses ifs nao costumam aparecer sozinhos. Assim como o comportamentodo bonus, surgem em breve outros comportamentos com os mesmos ifs em outras partes do sistema:public double liberaVerba(Funcionario f, Produto produto) { if (f.getCargo().equals("gerente")) { return produto.getValor() < 5000 || produto.getTipo().equals(Tipo.URGENTE); } else if (f.getCargo().equals("diretor")) { return produto.getValor() < 10000; } else { return produto.getValor() < 1000 ||produto.getTipo().equals(Tipo.USO_DIARIO); }}Esse tipo de codigo fica entao muito instavel: uma mudanca decomportamento deve ser alterada em diversos lugares distintos e, piorainda, e muito facil esquecer um deles ao criar um novo comportamento:alguns dos pontos de multiplos ifs sao esquecidos. Ao escrever o mesmo codigo pela segunda vez, seguimos a pratica sugerida no Pragmatic Programmers, de nao nos repetir (DRY).Mas o uso da heranca e delicado, e o desenvolvedor deve estar ciente de que ela pode trazer um acoplamento indesejado e suas alternativas. O uso de interfaces se encaixaria aqui com perfeicao.Outros tipos de condicoes podem determinar qual acao deve ser tomada, como por exemplo o valor de um parametro, resultando em uma abordagem que utiliza um mapa. Note como, nesse caso, novamente, nenhum switch ou sequencias de ifs precisam ser feitos: ifs sao substituidos por polimorfismo:private Map<String, Aplicador> taxas = new HashMap<String, Aplicador>();public void processa(String taxa, double juros) { impostosRecolhidos += taxas.get(taxa).aplicaComJuros(juros);}De todas as variacoes, a solucao do registro (em geral um Map) e a chave e a abordagem mais simples e capaz de separar responsabilidades distintas. Uma outra variacao, que remove a necessidade de registrar os itens no mapa, mas abusa de reflection, muitos casos desnecessariamente, e a seguinte:interface AplicadorDeTaxa