Sugestão para redução de if's?

Opa :smiley:

Existe alguma solução para diminuir o uso de if? Po, eu fiz um método aqui de regra de negócio que é praticamente um if pra cada ‘ponto’ da regra haha

E tudo que vai verificar, sempre vejo um if na frente :oops:

Algum jeito para melhorar isso?

Exemplo de código que eu acho bem sujinho:

	public void carregarArquivoImportado() {
		try
		{
			List registrosArquivo = null;
			if(getTipoArquivo() != null && !getTipoArquivo().equals("")){
				registrosArquivo = getRemarcarPrecoProdutoNaoControladoBO().obterRegistrosArquivo(getArquivoCSV().getInputStream(), getTipoArquivo());
				if(registrosArquivo == null){
					FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "O arquivo enviado está corrompido. Verifique o conteúdo dele.", "O arquivo enviado está corrompido. Verifique o conteúdo dele."));
				}
				dadosTabelaArquivoImportado = new ListDataModel(getRemarcarPrecoProdutoNaoControladoBO().obterRegistrosArquivo(getArquivoCSV().getInputStream(), getTipoArquivo()));
			} else {
				FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Selecionar o Tipo de Arquivo", "Selecionar o Tipo de Arquivo"));
			}
			if(dadosTabelaArquivoImportado.getRowCount() > 0){
				setexibirSubviewArquivo(true);
			} else {
				setexibirSubviewArquivo(false);
			}
			/*if(getRemarcarPrecoProdutoNaoControladoBO().getOfertasDivergencia().size() > 0){
				setDesabilitarBaixarDivergencias(false);
			} else {
				setDesabilitarBaixarDivergencias(true);
			}*/
		} catch (IOException e)
		{
			e.printStackTrace();
		}
	}

[]'s

[quote=padcoe]Opa :smiley:

Existe alguma solução para diminuir o uso de if? Po, eu fiz um método aqui de regra de negócio que é praticamente um if pra cada ‘ponto’ da regra haha

E tudo que vai verificar, sempre vejo um if na frente :oops:

Algum jeito para melhorar isso?

[]'s[/quote]

Tenta usar switch(), acho que o código fica mais limpo.

Quando for if’s simples, para atribuição de valores à variáveis, use o operador ternário ? : que vai dar uma melhorada no visual e na legibilidade do seu código…

Troque códigos assim:

int variavel;
if( condicao1 ) {
   variavel = 1
} else {
   variavel = 2
}

Por códigos assim:

variavel = (condicao1) ? 1 : 2;

[quote]Existe alguma solução para diminuir o uso de if? Po, eu fiz um método aqui de regra de negócio que é praticamente um if pra cada ‘ponto’ da regra haha

E tudo que vai verificar, sempre vejo um if na frente [/quote] Manda o analista conversar com o cliente para diminuir as regras de negócio :smiley:

dependendo da situacao vc pode usar switch case

Troque isso tbm:

if(dadosTabelaArquivoImportado.getRowCount() > 0){  
   setexibirSubviewArquivo(true);  
} else {  
   setexibirSubviewArquivo(false);  
}  
setexibirSubviewArquivo( dadosTabelaArquivoImportado.getRowCount() > 0 );  

Não posso usar operadores ternários…eu pensei nisso!

É muito doido usar muito ifs, fica tudo muito sujo e tem vezes q eu me perco na minha lógica hahaha

E esse aqui:

			while ((linhaLida = bufferedReader.readLine()) != null)
			{
				int count = 0;
				if (numeroLinha == 1)
				{
					for (int i = 0; i < linhaLida.length(); i++)
					{
						if (linhaLida.charAt(i) == ',')
						{
							count++;
						}
					}
					numeroLinha++;
					continue;
				}
				if (count > 3)
				{
					dadosLinha = linhaLida.split(",");
				} else
				{
					dadosLinha = linhaLida.split(";");
				}
				if(tipoArquivo.equalsIgnoreCase("PRODUTOLIBERADO")){
					if (dadosLinha.length < 3)
					{
						return null;
					}
					grm = dadosLinha[0];
					codigoProduto = dadosLinha[1];
					valorCustoRaiaNovo = dadosLinha[2];
				} else if(tipoArquivo.equalsIgnoreCase("PRECOSUGERIDO")){
					if (dadosLinha.length < 5)
					{
						return null;
					}
					grm = dadosLinha[0];
					codigoProduto = dadosLinha[1];
					codigoFaixaPreco = dadosLinha[2];
					descricaoFaixaPreco = dadosLinha[3];
					valorVenda = dadosLinha[4];
				} else if(tipoArquivo.equalsIgnoreCase("ESPECIALMES")){
					if (dadosLinha.length < 6)
					{
						return null;
					}
					grm = dadosLinha[0];
					codigoProduto = dadosLinha[1];
					valorCustoRaiaNovo = dadosLinha[2];
					codigoFaixaPreco = dadosLinha[3];
					descricaoFaixaPreco = dadosLinha[4];
					valorVenda = dadosLinha[5];
				}
				produtoNaoControladoTO = new ProdutoNaoControladoTO();
				if (grm != null && !grm.equals(""))
				{
					produtoNaoControladoTO.setCdGrupoRemarcacao(new Integer(grm));
				}
				if (codigoProduto != null && !codigoProduto.equals(""))
				{
					produtoNaoControladoTO.setCdProduto(new Integer(codigoProduto));
				}
				if (valorCustoRaiaNovo != null && !valorCustoRaiaNovo.equals(""))
				{
					String valorFormatado = valorCustoRaiaNovo.replace(",", ".");
					produtoNaoControladoTO.setVlCustoRaiaNovo(new Double(valorFormatado));
				}

Nao assustem hauehuae

Fazer manunteção nisto deve ser lindo!!! :smiley: rsrsrssr
Meu chefe sempre me fala, que se um metodo tiver mais que 30 linhas estou fazendo mais que uma coisa nele.
Mas sei la! Se a regra de negocio é doida, if no codigo.

sim rsrs

por isso que to querendo saber como melhorar isso rsrs

Tu pode utilizar o Strategy ou o State, com isso pelo menos a manutembilidade melhora.



Abraços.

Aprentemente seus métodos são enormes. Que tal dividir essas regras entre mais métodos. Acredito que com essa prática além de ter um código mais legivel e consistente você com certeza irá encontrar pontos que pode reutilizar, diminuindo desta forma a quantidade de código total. :slight_smile:

Há altas chances de TipoArquivo ter que ser uma classe, e todos aqueles ifs irem embora com polimorfismo.

Dá uma olhada no tópico abaixo e vê se você não passa a ter idéias:
http://www.guj.com.br/posts/list/55885.java

E graças a Deus que não sou eu quem dá manutenção nesse seu sistema. Testar pelo texto de tipoArquivo? Isso me parece extremamente perigoso.

Que a forma de você reduzir essa quantidade de IFs é aplicando Refactoring no seu código eu acho que você mesmo já percebeu …

No seu último exemplo, você poderia ter um objeto para cada tipo de arquivo (Usando polimorfismo, é claro), e esses objetos fariam a regra contida dentro dos IFs.

Da uma lida nisso que vai te ajudar: http://www.refactoring.com/catalog/replaceConditionalWithPolymorphism.html

É importante lembrar que você não vai acabar com todos os Ifs do seu código, mas os desse tipo você consegue.

Se você não entender avisa, pois no momento desse post estou sem tempo pra escrever algo mais elaborado.

[]s

tipoArquivo é um value de um select list de uma jsp, por isso q ta como string…e eu preciso verificar o tipoArquivo pra fazer o if =~~

Esse strategy parece ser bem interessante…vou dar uma lida nele e na sugestao de quebrar o metodo em metodos menores!

Tudo bem, ele vem do jsp. Mas uma hora ou outra, ele deve ser convertido numa classe de negócio.

Provavelmente, sua classe TipoArquivo, ou algum tipo de factory de tipos de arquivo, terão um mapa, que relaciona o String do jsp, com o objeto que representa aquele tipo de arquivo específico.

O fato é que ifs como o que você fez tendem a se multiplicar. O código que controla a lógica do tipo arquivo (como esse) vai ficando espalhado. A criação de um tipo de arquivo novo torna-se um inferno.

O que não acontece quando você concentra tudo em uma única classe, e deixa o if somente na conversão do String para o objeto TipoArquivo da classe certa. :wink:

se eu fizer classe TipoArquivo para cada tipoArquivo, eu vou reduzir o IF, mas isso nao seria uma redundancia de codigo? Pq vai ter o mesmo codigo 3x e com o if, eu teria um a mais…

[quote=ViniGodoy]Tudo bem, ele vem do jsp. Mas uma hora ou outra, ele deve ser convertido numa classe de negócio.

Provavelmente, sua classe TipoArquivo, ou algum tipo de factory de tipos de arquivo, terão um mapa, que relaciona o String do jsp, com o objeto que representa aquele tipo de arquivo específico.

O fato é que ifs como o que você fez tendem a se multiplicar. O código que controla a lógica do tipo arquivo (como esse) vai ficando espalhado. A criação de um tipo de arquivo novo torna-se um inferno.

O que não acontece quando você concentra tudo em uma única classe, e deixa o if somente na conversão do String para o objeto TipoArquivo da classe certa. :wink:[/quote]

Puts, falou tudo sobre a tendência. Não entendi muito bem isso de converter na classe de negócio pq ele funciona assim: tem 3 tipos de arquivos que a pessoa pode fazer upload e eu uso somente 1 TO para todos os tipos ( pq os campos são praticamento iguais e estão na mesma entidade ). E com isso, eu passo o tipo só pro IF saber como ele deve se comportar.

Eu to pensando em fazer o seguinte:

  • criar uma classe de leitura do arquivo para cada tipo de arquivo q eu for ler
  • criar um BO generico que chama essa classe de leitura
  • criar BO especifico que herda o generico

Acho que ai eu já conseguiria reduzir uma boa parte do código, mas eu me sinto muito perdido nisso pq eu acho que escrever praticamente o mesmo código mais de uma vez, ruim…eu devo estar fazendo algo errado hehe :oops:

Fiz aqui o que eu falei e ficou assim:

  • no BOzao, eu criei os atributos que são comuns a todas as classes, getters e settes…isso ta certo ou eu deveria criar cada atributo na sua propria classe?

  • no BOzinho, criei o metodo de leitura de arquivo, separei os métodos e aquela porrada de ifs que tinham na leitura de arquivo sumiram uma boa parte, mas tem uns que ainda ficam ( agora tem 29 linhas o método haha )

  • retirei aquela String pq agora eu só uso a string no controller pra verificar ql classe de negócio chamar :smiley:

Olha como ficou:

	public List obterRegistrosArquivo(
			InputStream arquivoEnviado)
	{
		try
		{
			produtosValidos = new ArrayList();
			produtosDivergencia = new ArrayList();
			String linhaLida;
			String[] dadosLinha = null;
			int numeroLinha = 1;
			ProdutoNaoControladoTO produtoNaoControladoTO;
			InputStreamReader reader = new InputStreamReader(arquivoEnviado);
			BufferedReader bufferedReader = new BufferedReader(reader);
			while ((linhaLida = bufferedReader.readLine()) != null)
			{
				int contadorVirgulas = 0;
				if (numeroLinha == 1)
				{
					for (int i = 0; i < linhaLida.length(); i++)
					{
						if (linhaLida.charAt(i) == ',')
						{
							contadorVirgulas++;
						}
					}
					numeroLinha++;
					continue;
				}
				if (contadorVirgulas > 3)
				{
					dadosLinha = linhaLida.split(",");
				} else
				{
					dadosLinha = linhaLida.split(";");
				}
				if (dadosLinha.length < 3)
				{
					return null;
				}
				produtoNaoControladoTO = this.setarDadosBean(dadosLinha);
				
				if (!this.validarRegistroLinha(produtoNaoControladoTO) && this.validarRegistroProduto(produtoNaoControladoTO))
				{
					getProdutosValidos().add(produtoNaoControladoTO);
				}
			}
		} catch (IOException e)
		{
			e.printStackTrace();
		}
		return getProdutosValidos();
	}

	private ProdutoNaoControladoTO setarDadosBean(String[] valorRegistro){
		ProdutoNaoControladoTO produtoNaoControladoTO = new ProdutoNaoControladoTO();;
		String[] dadosLinha = valorRegistro;
		String grm = dadosLinha[0];
		String codigoProduto = dadosLinha[1];
		String valorCustoRaiaNovo = dadosLinha[2];
		if (grm != null && !grm.equals(""))
		{
			produtoNaoControladoTO.setCdGrupoRemarcacao(new Integer(grm));
		}
		if (codigoProduto != null && !codigoProduto.equals(""))
		{
			produtoNaoControladoTO.setCdProduto(new Integer(codigoProduto));
		}
		if (valorCustoRaiaNovo != null && !valorCustoRaiaNovo.equals(""))
		{
			String valorFormatado = valorCustoRaiaNovo.replace(",", ".");
			produtoNaoControladoTO.setVlCustoRaiaNovo(new Double(valorFormatado));
		}
		return produtoNaoControladoTO;
	}

Esses sao os meus 2 únicos métodos da classe agora e nela só tenho isso…os atributos e os outros métodos ( q são comuns ), estão no BOzao. Melhorou?

[]'s

Vc por um acaso trabalha na Droga Raia?

flws

padcoe parece q melhou sim, mas…acho que poderia “limpar” um pouco mais o método obterRegistrosArquivo:

a) Montar um método especialista em contar virgulas.
b) Talvez se aplicasse o x > y ? n : m no local dos splits fosse resolvido em um única linha.
c) Aliás parece que o item a e b dá para ser resolvido com um método e um if, acho q vale uma tentativa.
d) A parte de baixo onde ocorre a validação também acho que poderia resolver em pequeno método a parte.

A idéi que gostaria de passar é que o método está um pouco embolado dificultando a leitura imediata, talvez um pouco mais de refactoring ajudasse.

Entendi que este método ( obterRegistrosArquivo ) é executado no servidor, vc tem alguma coisa um pouco melhor do que simplesmente o printStackTrace() por ai?

Abraços