[Resolvido] Tratando excesso de ifs

2 respostas
Frantic_Avenger

Olá a todos

Estava lendo no blog da Caelum sobre Como não aprender orientação a objetos: o excesso de ifs porém não entendi muito bem, no exemplo descrito na página:
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; 
	}
}

/*<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>*/

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; 
	}
}
Apesar de ler:
Não haverá necessidade de ifs, já que essa descoberta de qual método executar é feita pela máquina virtual: funcionario.getBonus()
Não consegui entender, alguém poderia me explicar? Como consigo calcular o bônus de gerente ou de diretor sem fazer nenhum if? Como a classe Map e HashMap poderiam me ajudar (nunca as utilizei)? E como a interface também poderia me ajudar nesse tratamento?

2 Respostas

narciso.benigno

Olá Frantic, como está?

O que acontece é este método que calculaBonus está dentro de uma classe, da classe Funcionário no primeiro caso. Esta implementação assume que ele tem que conhecer todos os tipos de funcionários que existem no sistema, isto é, ele verifica se o cargo do cara. A responsabilidade de conhecer todos os cargos está em um unico lugar isso é muito a cara de procedural, e o motivo principal para switch ser tão ruim! E isso é problematico, por que? Por que quando eu adicionar um cargo novo terei que alterar essa lógica cheia de ifs (o que sinceramente é chato pra burro, e sujeito a erros acima de tudo).

Então ao invéz disso colocamos a lógica de calcular o bonus do gerente dentro da classe Gerente (isto significa que dados está próximo do comportamento), o gerente deve saber qual o seu bonus, por isso fizemos:

class Gerente extends Funcionario {   
    // outros atributos e metodos aqui   

    // REPARE que não preciso do if, por que sei que aqui o cargo é de gerente então simplesmente retorno o bonus de gerente.
    public double getBonus() {     
        return vendasDoMes * 0.05 + getSalario() * 0.1;   
    }  
}

Desta forma evitamos ifs, os ifs em si não são um grandioso problema, o problema é quando usamos eles para capturar vários (mais de um) comportamento diferente, e também usamos um pouco do conceito do SOLID, que diz que os códigos tem que ser estaveis (fechados para mudanças), vamos alterar este comportamento apenas se mudar o cálculo do bonus, e não quando surgir um novo tipo de funcionário. Quando surgir um novo funcionario analista por exemplo, qual será nosso trabalho? colocar mais um if no código? Não! quando colocamos mais um if no código estamos sujeitos a erros, e podemos quebrar todos os outros cálculos de bonus que estavam funcionando, não queremos isso! Ao invéz disso criamos um novo tipo de funcionário que vai ser o Analista:

class Analista extends Funcionario {
    public double getBonus() {
        return this.getSalario() * 0.5;
    }
}

Abraço,

P.S.: Interface já é uma história bem longa, acho que antes de chegar em interface, você deve bater bastante em várias teclas como polimorfismo (por que essa é a maior funcão de interface: polimorfismo), e entender os problemas de herança, para isto tem um outro post da Caelum:

http://blog.caelum.com.br/como-nao-aprender-orientacao-a-objetos-heranca/

Abraço,

Frantic_Avenger

Muito obrigado pela resposta narciso.benigmo, irei continuar meus estudos e tentar amadurer o funcionamento desta implementação, havendo qualquer dúvida posto aqui novamente.

Criado 14 de dezembro de 2011
Ultima resposta 14 de dez. de 2011
Respostas 2
Participantes 2