Meu codigo tem muito if, meu chefe disse que ta errado, é verdade?

80 respostas
M

é verdade que minha maneira de implementar com 17 ifs em um metodo esta errado?

80 Respostas

Hebert_Coelho

mariazinhahappy:
é verdade que minha maneira de implementar com 17 ifs em um metodo esta errado?
Não é uma boa prática.

O melhor é você definir e repensar seu método.

Esse livro é muito bom para quem precisa desse tipo de coisa: Use a Cabeça - Orientação a Objeto.

charleston10

nao é errado se fosse errado nao existia IF…

mas a alternativa é usar SWITCH…

;]

http://www.tiexpert.net/programacao/java/switch-case-default.php

ViniGodoy

charleston10:
nao é errado se fosse errado nao existia IF…
mas a alternativa é usar SWITCH…

Mais alguém precisa estudar orientação à objetos…
http://c2.com/cgi/wiki?SwitchStatementsSmell

victormagno

Não é EXATAMENTE errado, mas com certeza não é uma boa prática… o código tem que ser auto explicativo, a leitura dele deve ser fluida… como dizem por ai: “Qualquer um faz código que um computador entenda, mas apenas bons profissionais fazem código que pessoas entendem”… ou algo semelhante…

Assiste esse vídeo, é um pequeno resumo do livro Clean Code do Uncle Bob… vai abrir um pouco sua visão sobre isso:

M

entao posso usar o swtich break no lugar dos 17 ifs? é melhor?

romarcio

17 ifs? Você ta testando o que?

Com certeza deve haver uma lógica mais apropriada e simples para seu código.

rogelgarcia

Tá… tá errado.

Posta o código aqui e fale o que ele faz, que a gente pode ajudar melhor.

M

Certamente esse seu codigo precisa de uma refatoração .

Sugiro o livro do Martin Fowler Refatoração

douglas_arantes

Trocar if por swtich não ira resolver o problema.

Realmente códigos com muitos if, não são nem um pouco “elegantes”.
Você deve estudar bem Orientação a Objetos, seja em java, c++, ou qualquer outra linguagem.
Entender o que é acoplamento estático e dinâmico, ou seja saber aproveitar do mecanismo de polimorfismo que linguagens orientadas a objetos
oferecem.

Após estar fluente nos conceitos básicos de OO, ler sobre padrões de projetos, existe muitos livros sobre o assunto, e pode ter certeza
que ira escrever códigos de qualidade.

charleston10

ViniGodoy:
charleston10:
nao é errado se fosse errado nao existia IF…
mas a alternativa é usar SWITCH…

Mais alguém precisa estudar orientação à objetos…
http://c2.com/cgi/wiki?SwitchStatementsSmell

Não comentei que eu iria fazer 17 verificações de condições no Switch apenas comentei que é uma alternativa que
tem outro modo de fazer verificações com estrutura condicional.

Eu não faria isso, de alguma outra forma eu pensaria nem que fosse 3h para tentar minimizar o máximo possível de
código.

Até pq não sei oq ele ta tentando fazer, se é programação estruturada ou orientação a objetos, nao tem como falar
pra usar POO sendo qe nao sei… seria mais facil ele postrar o código…

;]

rafadelnero

Essas perguntas estão meio estranhas, kkkkkk!!!

ViniGodoy

charleston10:

Não comentei que eu iria fazer 17 verificações de condições no Switch apenas comentei que é uma alternativa que
tem outro modo de fazer verificações com estrutura condicional.

Eu não faria isso, de alguma outra forma eu pensaria nem que fosse 3h para tentar minimizar o máximo possível de
código.

Até pq não sei oq ele ta tentando fazer, se é programação estruturada ou orientação a objetos, nao tem como falar
pra usar POO sendo qe nao sei… seria mais facil ele postrar o código…

;]

Mesmo que fosse programação estruturada, ainda cheira mal 17 ifs seguidos. Geralmente você pode resolver melhor usando alguma estrutura associativa, ponteiros, ou outras coisas similares.

nel

ViniGodoy:
charleston10:

Não comentei que eu iria fazer 17 verificações de condições no Switch apenas comentei que é uma alternativa que
tem outro modo de fazer verificações com estrutura condicional.

Eu não faria isso, de alguma outra forma eu pensaria nem que fosse 3h para tentar minimizar o máximo possível de
código.

Até pq não sei oq ele ta tentando fazer, se é programação estruturada ou orientação a objetos, nao tem como falar
pra usar POO sendo qe nao sei… seria mais facil ele postrar o código…

;]

Mesmo que fosse programação estruturada, ainda cheira mal 17 ifs seguidos. Geralmente você pode resolver melhor usando alguma estrutura associativa, ponteiros, ou outras coisas similares.

Ou simplesmente verificar a possibilidade de usar o padrão Strategy. Inclusive, o próprio ViniGodoy apresentou um exemplo de leitura e compreensão simples.
Dá uma olhada: http://www.guj.com.br/java/55885-como-nao-utilizar-if-ou-switch#293436

Uma dica Maria, tente pensar mais orientado a objetos, parece que tudo está muito estruturado na sua cabeça. Analise com calma seu código, pode haver melhores alternativas.

drsmachado

Uma dica é utilizar-se de recursos pré estabelecidos, como um check style.
O PMD é uma ótima ferramenta.
Em geral, as ferramentas de check style conseguem auxiliar em casos como este, com muitas verificações lógicas em um método, excesso de linhas, falta de padronização, falhas ao atender as convenções de nomenclatura e especificações do Java.
Dá trabalho, mas é bem interessante e útil.

Rodrigo_Sasaki

A regra geral que eu uso é tentar manter métodos tão curtos e objetivos quanto possível.

Fazendo isso você percebe que a reusabilidade de código vira algo natural.

Uma função deveria fazer somente uma coisa, se suas funções fazem mais do que isso, pode ser uma boa ideia repensá-las.

Um macete pra conseguir isso é você tentar nomear a função, se for difícil pensar em um nome pra dizer o que ela faz, ela provavelmente está fazendo mais do que uma coisa.

(Todas as dicas que dei aqui eu li no livro Clean Code)

emanuelmm

Pra saber se um código precisa ser refatorado eu olho para o teste unitário. Qt mais complexo o teste, mais o método precisa ser refatorado. =]

victormagno

O nome do livro já diz tudo.

R

se for encadeado, máximo de 2 ou 3 ifs… se nao for encadeado, só pensar em outra maneira de colocar seu código como usando switch, recursividade sei la…

17 ifs ta errado… imagina a manutenção disso depois :stuck_out_tongue:

Hebert_Coelho

emanuelmm:
Pra saber se um código precisa ser refatorado eu olho para o teste unitário. Qt mais complexo o teste, mais o método precisa ser refatorado. =]

Se a pessoa não sabe que 17 ifs é uma péssima prática nem imagino como ficariam os testes… Acho que 35 métodos para cada método testado… -_-’’

charleston10

= ]

emanuelmm

=]
Estou tentando fazer com que ele entenda o problema.

E

a converça ta boa e o codigo ta em falta…

uma vez eu li num forum…

deve ta errado o ingles mas é isso ae…

A

Tb recomendo o livro Clean Code.

Contudo, há situações, em q vão haver vários ifs, e nem por isso significaria má prática.

Hebert_Coelho

andredecotia:
Tb recomendo o livro Clean Code.

Contudo, há situações, em q vão haver vários ifs, e nem por isso significaria má prática.

Sério? Qual?

B

Eu não sou tão xiita quanto ao número de ifs num código, e apesar de 17 ser bem alto, é uma prática bem comum ao validar Forms HTML que vem com muitos dados.

O que recomendo mesmo seria separar esses ifs em vários métodos separados, cada um com sua especialidade. Por exemplo:

// dentro de uma classe de nota fiscal
validaNotaFiscal {
  validaDadosBasicos
  validaRemetente
  validaDestinatario
  validaItensDaNota
  validaTransportadora
  validaInformaçõesComplementares
}

E cada um deles tem mais métodos de validação (CFOP, descontos dos itens), e, claro, os ifs para tratar cada pedacinho.

Outra recomendação é fazer teu código com TinyTypes, e deixar que eles cuidem de suas próprias validações e conversões.

Luiz_Augusto_Prado

Hebert Coelho:
andredecotia:
Tb recomendo o livro Clean Code.

Contudo, há situações, em q vão haver vários ifs, e nem por isso significaria má prática.

Sério? Qual?

O André não tá errado. Nem sempre vc vai poder trabalhar com objetos.

Em todo o caso, sugiro o autor do post procurar um artigo chamado “if bom é if morto” e “Strategy” pra solucionar sua dúvida.

Hebert_Coelho

Luiz Augusto Prado:
Hebert Coelho:
andredecotia:
Tb recomendo o livro Clean Code.

Contudo, há situações, em q vão haver vários ifs, e nem por isso significaria má prática.

Sério? Qual?

O André não tá errado. Nem sempre vc vai poder trabalhar com objetos.

Em todo o caso, sugiro o autor do post procurar um artigo chamado “if bom é if morto” e “Strategy” pra solucionar sua dúvida.

Novamente, sério? Qual?
Qual o motivo se justifica a não usar algum pattern e usar toneladas de ifs independentes de objetos/strings?

Estou perguntando numa boa. Atualmente não imagino.

Luiz_Augusto_Prado

Novamente, sério? Qual?
Qual o motivo se justifica a não usar algum pattern e usar toneladas de ifs independentes de objetos/strings?

Estou perguntando numa boa. Atualmente não imagino.

Em algum momento vc pode ter que classificar em que tipo de objeto se enquadra um dado que acaba de chegar. Nessa hora vc vai precisar usar if. Vc, nem eu podemos imaginar a situação melhor agora porque isso depende da lógica de negócio. Vas vou supor uma bem simples…

o usuário vai se cadastrar em algum lugar e dependendo da idade dele eu vou colocar ele em uma classe diferente:

if( dadosDoUsuario.idade < 18 )
{
 os dados vão para o objeto a
}
else if( dadosDoUsuario.idade >= 18 && dadosDoUsuario.idade<55 )
{
 os dados vão para o objeto b
}
else if( dadosDoUsuario.idade >= 55 && dadosDoUsuario.idade<120 )
{
 os dados vão para o objeto c
}
else
{
 os dados vão pro limbo
}
rogelgarcia

Você sempre terá um algoritmo que evita ninhos de IF.

enum EtapaDaVida {
	JOVEM(18),
	ADULTO(55),
	IDOSO(120);
	
	int idadeMaxima;
	private EtapaDaVida(int idade){
		this.idadeMaxima = idade;
	}
	
}

class User {
	int idade;
}

public class Example {

	public static void main(String[] args) {
		Map<EtapaDaVida, List<User>> grupos = new HashMap<EtapaDaVida, List<User>>();
		for(EtapaDaVida etapa: EtapaDaVida.values()){
			grupos.put(etapa, new ArrayList<User>());
		}
		
		List<User> listaASeparar = ...;

		for (User user : listaASeparar) {
			for(EtapaDaVida etapa: EtapaDaVida.values()){
				if(user.idade < etapa.idadeMaxima){
					grupos.get(etapa).add(user);
					break;
				}
			}
		}
	}
}

Eu também compartilho a opinião que if cheira mal.

Pode reparar, a maioria das gambiarras tem um if no meio… :slight_smile:

E

Você está tentando resolver aquele problema do arquivo-texto com mãe, neta etc. que você tinha mostrado com um monte de ifs?
Parece ser o caso para um algoritmo recursivo.
É que mesmo que você ponha 17 ifs, se você tiver um arquivo com mais de 3 níveis, o seu programa vai acabar quebrando porque não esperava isso.

Problemas que envolvem estruturas de dados em formato de árvore às vezes requerem algoritmos recursivos.

Luiz_Augusto_Prado

rogelgarcia:
Você sempre terá um algoritmo que evita ninhos de IF.

enum EtapaDaVida {
	JOVEM(18),
	ADULTO(55),
	IDOSO(120);
	
	int idadeMaxima;
	private EtapaDaVida(int idade){
		this.idadeMaxima = idade;
	}
	
}

class User {
	int idade;
}

public class Example {

	public static void main(String[] args) {
		Map<EtapaDaVida, List<User>> grupos = new HashMap<EtapaDaVida, List<User>>();
		for(EtapaDaVida etapa: EtapaDaVida.values()){
			grupos.put(etapa, new ArrayList<User>());
		}
		
		List<User> listaASeparar = ...;

		for (User user : listaASeparar) {
			for(EtapaDaVida etapa: EtapaDaVida.values()){
				if(user.idade < etapa.idadeMaxima){
					grupos.get(etapa).add(user);
					break;
				}
			}
		}
	}
}

Eu também compartilho a opinião que if cheira mal.

Pode reparar, a maioria das gambiarras tem um if no meio… :)

Bem legal seu codigo.
Como vc faria se mudasse um pouquinho?

if( dadosDoUsuario.idade < 18 )
{
 os dados vão para o objeto a
}
else if( dadosDoUsuario.idade >= 18 && dadosDoUsuario.idade<55 )
{
 os dados vão para o objeto b
}
else if( dadosDoUsuario.idade >= 55 && dadosDoUsuario.idade<120 || dadosDoUsuario.numeroFilhos>2 )
{
 os dados vão para o objeto c
}
else
{
 os dados vão pro limbo
}

Já eu, não acredito que seja todo o tipo de classificação que possa ser resumida.

rogelgarcia

Após uma refatoração… o novo exemplo (caso alguém queira dar uma analisada) :slight_smile:

Obs: não estou entrando no mérito do que é melhor ou pior… é apenas um exemplo

enum EtapaDaVida {
	
	JOVEM(18),
	ADULTO(55),
	IDOSO(120),
	HIGHLANDER(Integer.MAX_VALUE);
	
	int idadeMaxima;
	private EtapaDaVida(int idade){
		this.idadeMaxima = idade;
	}
	
	public static EtapaDaVida get(int idade){
		for (EtapaDaVida etapa : values()) {
			if(idade <= etapa.idadeMaxima){
				return etapa;
			}
		}
		throw new RuntimeException("resultado inesperado");
	}
	
	public static EtapaDaVida get(Date data){
		return get(Utils.getIdade(data));
	}
}


class Usuario{
	Date nascimento;
}

public class Example {

	public static void main(String[] args) {
		Map<EtapaDaVida, List<Usuario>> grupos = new HashMap<EtapaDaVida, List<Usuario>>();
		for(EtapaDaVida etapa: EtapaDaVida.values()){
			grupos.put(etapa, getListaUsuarios());
		}
		
		//aqui é onde viria o ninho de ifs
		for (Usuariousuario : getListaUsuarios()) {
			EtapaDaVida etapa1 = EtapaDaVida.get(usuario.nascimento);
			grupos.get(etapa1).add(usuario);
		}
	}
	
	public static List<Usuario> getListaUsuarios() {
		return ...;
	}
}


class Utils {

	public static int getIdade(Date data){
		Calendar hoje = Calendar.getInstance();
		Calendar nascimento = Calendar.getInstance();
		nascimento.setTime(data);
		int idade = hoje.get(Calendar.YEAR) - nascimento.get(Calendar.YEAR);
		nascimento.set(Calendar.YEAR, hoje.get(Calendar.YEAR));
		if(nascimento.compareTo(hoje) > 0){
			//nao fez aniversario esse ano
			idade--;
		}
		return idade;
	}
}
rogelgarcia

Edit Coloquei a situação errada .. era para ser OR no lugar do AND.. deixa aqui esse como exemplo de qualquer forma

Condição: dadosDoUsuario.idade >= 55 && dadosDoUsuario.idade<120 && dadosDoUsuario.numeroFilhos>2

public static void main(String[] args) {
		Map<EtapaDaVida, List<Usuario>> grupos = new HashMap<EtapaDaVida, List<Usuario>>();
		for(EtapaDaVida etapa: EtapaDaVida.values()){
			grupos.put(etapa, new ArrayList());
		}
		
		//aqui é onde viria o ninho de ifs
		for (Usuario usuario : getListaUsuarios()) {
			EtapaDaVida etapa1 = EtapaDaVida.get(usuario.nascimento);
			grupos.get(etapa1).add(usuario);
		}
		
		//separar essa condição: dadosDoUsuario.idade >= 55 && dadosDoUsuario.idade<120 && dadosDoUsuario.numeroFilhos>2
		List<Usuario> usuariosAdultosComMaisDeDoisFilhos = new ArrayList<Usuario>();
		usuariosAdultosComMaisDeDoisFilhos.addAll(grupos.get(EtapaDaVida.ADULTO));
		for (Iterator<Usuario> iterator = usuariosAdultosComMaisDeDoisFilhos.iterator(); iterator.hasNext();) {
			Usuario usuario = iterator.next();
			if(usuario.numeroFilhos <= 2){
				iterator.remove();
			}
		}
	}
Luiz_Augusto_Prado
rogelgarcia:
Condição: dadosDoUsuario.idade >= 55 && dadosDoUsuario.idade<120 || dadosDoUsuario.numeroFilhos>2
public static void main(String[] args) {
		Map<EtapaDaVida, List<Usuario>> grupos = new HashMap<EtapaDaVida, List<Usuario>>();
		for(EtapaDaVida etapa: EtapaDaVida.values()){
			grupos.put(etapa, getListaUsuarios());
		}
		
		//aqui é onde viria o ninho de ifs
		for (Usuario usuario : getListaUsuarios()) {
			EtapaDaVida etapa1 = EtapaDaVida.get(usuario.nascimento);
			grupos.get(etapa1).add(usuario);
		}
		
		//separar essa condição: dadosDoUsuario.idade >= 55 && dadosDoUsuario.idade<120 || dadosDoUsuario.numeroFilhos>2
		List<Usuario> usuariosAdultosComMaisDeDoisFilhos = new ArrayList<Usuario>();
		usuariosAdultosComMaisDeDoisFilhos.addAll(grupos.get(EtapaDaVida.ADULTO));
		for (Iterator<Usuario> iterator = usuariosAdultosComMaisDeDoisFilhos.iterator(); iterator.hasNext();) {
			Usuario usuario = iterator.next();
			if(usuario.numeroFilhos <= 2){
				iterator.remove();
			}
		}
	}

Desculpa, mas agora acho que esse remove ai virou gambiarra.
Claro que sempre é bom utilizar as boas técnicas, mas não existe bala de prata.
Dependendo do tempo, do que o cliente pedir e de como a informação vier, não vai ter como escapar.

Hebert_Coelho

Luiz Augusto Prado:
Desculpa, mas agora acho que esse remove ai virou gambiarra.
Claro que sempre é bom utilizar as boas técnicas, mas não existe bala de prata.
Dependendo do tempo, do que o cliente pedir e de como a informação vier, não vai ter como escapar.
na boa? Ainda prefiro assim do que aninhar 300 ifs.

Desculpe, mas ainda assim penso que não existe motivo para 17 ifs seguidos…

rogelgarcia

Nova arquitetura, agora suporta qualquer tipo de condição. As outras estruturas, não coloquei aqui para não ficar lotando…

class Usuario {
	Date nascimento;
	int numeroFilhos;
}

enum Classificacao {
	A(new ClassificadorA()),
	B(new ClassificadorB()),
	C(new ClassificadorC()),
	LIMBO(new ClassificadorLimbo());
	
	Classificador classificador;

	Classificacao(Classificador classificador){
		this.classificador = classificador;
	}

	public static Classificacao get(Usuario usuario) {
		for (Classificacao c : values()) {
			if(c.classificador.isClassificacao(c, usuario)){
				return c;
			}
		}
		throw new RuntimeException("resultado inesperado");
	}
}

interface Classificador {
	public boolean isClassificacao(Classificacao c, Usuario usuario);
}

class ClassificadorA implements Classificador{
	public boolean isClassificacao(Classificacao c, Usuario usuario) {
		return EtapaDaVida.get(usuario.nascimento) == EtapaDaVida.JOVEM;
	}
}
class ClassificadorB implements Classificador{
	public boolean isClassificacao(Classificacao c, Usuario usuario) {
		return EtapaDaVida.get(usuario.nascimento) == EtapaDaVida.ADULTO;
	}
}
class ClassificadorC implements Classificador{
	public boolean isClassificacao(Classificacao c, Usuario usuario) {
		return EtapaDaVida.get(usuario.nascimento) == EtapaDaVida.IDOSO || usuario.numeroFilhos > 2;
	}
}
class ClassificadorLimbo implements Classificador{
	public boolean isClassificacao(Classificacao c, Usuario usuario) {
		return true;
	}
}

public class Example2 {

	public static void main(String[] args) {
		
		Map<Classificacao, List<Usuario>> grupos = new HashMap<Classificacao, List<Usuario>>();
		for(Classificacao etapa: Classificacao.values()){
			grupos.put(etapa, new ArrayList());
		}
		
		//aqui é onde viria o ninho de ifs
		for (Usuario usuario : getListaUsuarios()) {
			Classificacao classificacao = Classificacao.get(usuario);
			grupos.get(classificacao).add(usuario);
		}
		
	}
	
	public static ArrayList<Usuario> getListaUsuarios() {
		return new ArrayList<Usuario>();
	}
}
M
Bruno Laturner:
Eu não sou tão xiita quanto ao número de ifs num código, e apesar de 17 ser bem alto, é uma prática bem comum ao validar Forms HTML que vem com muitos dados. O que recomendo mesmo seria separar esses ifs em vários métodos separados, cada um com sua especialidade. Por exemplo:
// dentro de uma classe de nota fiscal
validaNotaFiscal {
  validaDadosBasicos
  validaRemetente
  validaDestinatario
  validaItensDaNota
  validaTransportadora
  validaInformaçõesComplementares
}
E cada um deles tem mais métodos de validação (CFOP, descontos dos itens), e, claro, os ifs para tratar cada pedacinho.

Outra recomendação é fazer teu código com TinyTypes, e deixar que eles cuidem de suas próprias validações e conversões.

mais se eu usar metodos nao vou ter que por ainda ifs?? ? exemplo

validaNotaFiscal {
  if("mae"){
validaDadosBasicos
  validaRemetente
  }

if ("filha"){
validaDestinatario

}

if("neta"){
  validaItensDaNota
  
}

if("bisneta"){
validaTransportadora
  validaInformaçõesComplementares}
}

acho que isso e uma arvore, me falaram no ultimo post que abri.

rogelgarcia
Luiz Augusto Prado:
rogelgarcia:
Condição: dadosDoUsuario.idade >= 55 && dadosDoUsuario.idade<120 || dadosDoUsuario.numeroFilhos>2
public static void main(String[] args) {
		Map<EtapaDaVida, List<Usuario>> grupos = new HashMap<EtapaDaVida, List<Usuario>>();
		for(EtapaDaVida etapa: EtapaDaVida.values()){
			grupos.put(etapa, getListaUsuarios());
		}
		
		//aqui é onde viria o ninho de ifs
		for (Usuario usuario : getListaUsuarios()) {
			EtapaDaVida etapa1 = EtapaDaVida.get(usuario.nascimento);
			grupos.get(etapa1).add(usuario);
		}
		
		//separar essa condição: dadosDoUsuario.idade >= 55 && dadosDoUsuario.idade<120 || dadosDoUsuario.numeroFilhos>2
		List<Usuario> usuariosAdultosComMaisDeDoisFilhos = new ArrayList<Usuario>();
		usuariosAdultosComMaisDeDoisFilhos.addAll(grupos.get(EtapaDaVida.ADULTO));
		for (Iterator<Usuario> iterator = usuariosAdultosComMaisDeDoisFilhos.iterator(); iterator.hasNext();) {
			Usuario usuario = iterator.next();
			if(usuario.numeroFilhos <= 2){
				iterator.remove();
			}
		}
	}

Desculpa, mas agora acho que esse remove ai virou gambiarra.
Claro que sempre é bom utilizar as boas técnicas, mas não existe bala de prata.
Dependendo do tempo, do que o cliente pedir e de como a informação vier, não vai ter como escapar.

A sintaxe de Java pode ficar um pouco verbosa por falta de recursos da linguagem.. O mais interessante da analise aqui, é a arquitetura resultante e como podemos contornar ifs aninhados..

Veja que se Java possuísse closures, o código podeira ficar assim:

usuariosAdultosComMaisDeDoisFilhos.retain {
   it.numeroFilhos > 2;
}

Acho que o exemplo usando a nova arquitetura (exemplo com Classificadores) é melhor para resolver situações onde a condição pode ser personalizada de qualquer maneira.

Como a condição mudou para 2 variáveis (inicialmente era apenas uma) a solução anterior não era exatamente adequada. E então, esse algoritmo acabou resultando em um aproveitamento da primeira arquitetura, ao invés de uma refatoração.

Apesar de ser um exemplo acadêmico, essa problemática abre questões para várias discussões. :)

M

meu codigo e esse aqui

@Override
	public Object lerArquivoTXTPrepararObjetosParaVirarXML_arvore() {  
		mae_VO mae = new mae_VO();
		filha_VO filha = new filha_VO();
		neta_VO neta = new neta_VO();
		binesta_VO binesta = new binesta_VO();
		
		try {  
			Scanner arquivo = new Scanner(new File("C:\\Projeto Revistas\\catalogacao_2013.log"));  
			while (arquivo.hasNext()) {
				String linha = arquivo.nextLine();
				// coisas que estao no começo
				if (linha.contains("Revifilhaa Mãe") && linha.contains("Início da Execução")) {
					mae.setDataFinal(linha);
					mae.setDataInicial(linha);
					mae.setDescricao(linha);
					mae.setHoraFinal(linha);
					mae.setHoraInicio(linha);
					mae.setId(linha);
					if (linha.contains("erro")) {
						neta.setfilhaatus(Enumfilhaatus.ERRO);
					}	else if (linha.contains("atual"))	{
						neta.setfilhaatus(Enumfilhaatus.ATUAL);
					} else
						neta.setfilhaatus(Enumfilhaatus.U2013);
				}
				
				if (linha.contains("Revifilhaa Filha") && linha.contains("Início da Execução")) {
					filha.setDataFinal(linha);
					filha.setDataInicial(linha);
					filha.setDescricao(linha);
					filha.setHoraFinal(linha);
					filha.setHoraInicio(linha);
					filha.setId(linha);
					if (linha.contains("erro")) {
						neta.setfilhaatus(Enumfilhaatus.ERRO);
					}	else if (linha.contains("atual"))	{
						neta.setfilhaatus(Enumfilhaatus.ATUAL);
					} else
						neta.setfilhaatus(Enumfilhaatus.U2013);
				}
				
				if (linha.contains("Revifilhaa Neta") && linha.contains("Início da Execução")) {
					neta.setDataFinal(linha);
					neta.setDataInicial(linha);
					neta.setDescricao(linha);
					neta.setHoraFinal(linha);
					neta.setHoraInicio(linha);
					neta.setId(linha);
					if (linha.contains("erro")) {
						neta.setfilhaatus(Enumfilhaatus.ERRO);
					}	else if (linha.contains("atual"))	{
						neta.setfilhaatus(Enumfilhaatus.ATUAL);
					} else
						neta.setfilhaatus(Enumfilhaatus.U2013);
				}
				
				if (linha.contains("Revifilhaa Bisneta") && linha.contains("Início da Execução")) {
					binesta.setDataFinal(linha);
					binesta.setDataInicial(linha);
					binesta.setDescricao(linha);
					binesta.setHoraFinal(linha);
					binesta.setHoraInicio(linha);
					binesta.setId(linha);

					if (linha.contains("erro")) {
						neta.setfilhaatus(Enumfilhaatus.ERRO);
					}	else if (linha.contains("atual"))	{
						neta.setfilhaatus(Enumfilhaatus.ATUAL);
					} else
						neta.setfilhaatus(Enumfilhaatus.U2013);
				}
				
				
				// coisas que estao no final
				if (linha.contains("Revista Mãe") && linha.contains("Executado com")) {
					mae.getLifilhaaSuites().add(filha);
					filha = new filha_VO();
				}
				
				if (linha.contains("Revista Filha") && linha.contains("Executado com")
						&& linha.contains("2013")) {
					filha.getLifilhaanetas().add(neta);
					neta = new neta_VO();
				}
				
				if (linha.contains("Revista Bisneta") && linha.contains("Executado com")) {
					neta.getLifilhaabinestas().add(binesta);
					binesta = new binesta_VO();
				}
				
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		 return mae;
	}
rogelgarcia

É… o problema não é só os 17 ifs…

R

É melhor trancar esse tópico,pelo que eu to vendo vai gerar flames comparados aos de Java versus PHP.

Luiz_Augusto_Prado
rogelgarcia:
Nova arquitetura, agora suporta qualquer tipo de condição. As outras estruturas, não coloquei aqui para não ficar lotando..
class Usuario {
	Date nascimento;
	int numeroFilhos;
}

enum Classificacao {
	A(new ClassificadorA()),
	B(new ClassificadorB()),
	C(new ClassificadorC()),
	LIMBO(new ClassificadorLimbo());
	
	Classificador classificador;

	Classificacao(Classificador classificador){
		this.classificador = classificador;
	}

	public static Classificacao get(Usuario usuario) {
		for (Classificacao c : values()) {
			if(c.classificador.isClassificacao(c, usuario)){
				return c;
			}
		}
		throw new RuntimeException("resultado inesperado");
	}
}

interface Classificador {
	public boolean isClassificacao(Classificacao c, Usuario usuario);
}

class ClassificadorA implements Classificador{
	public boolean isClassificacao(Classificacao c, Usuario usuario) {
		return EtapaDaVida.get(usuario.nascimento) == EtapaDaVida.JOVEM;
	}
}
class ClassificadorB implements Classificador{
	public boolean isClassificacao(Classificacao c, Usuario usuario) {
		return EtapaDaVida.get(usuario.nascimento) == EtapaDaVida.ADULTO;
	}
}
class ClassificadorC implements Classificador{
	public boolean isClassificacao(Classificacao c, Usuario usuario) {
		return EtapaDaVida.get(usuario.nascimento) == EtapaDaVida.IDOSO || usuario.numeroFilhos > 2;
	}
}
class ClassificadorLimbo implements Classificador{
	public boolean isClassificacao(Classificacao c, Usuario usuario) {
		return true;
	}
}

public class Example2 {

	public static void main(String[] args) {
		
		Map<Classificacao, List<Usuario>> grupos = new HashMap<Classificacao, List<Usuario>>();
		for(Classificacao etapa: Classificacao.values()){
			grupos.put(etapa, new ArrayList());
		}
		
		//aqui é onde viria o ninho de ifs
		for (Usuario usuario : getListaUsuarios()) {
			Classificacao classificacao = Classificacao.get(usuario);
			grupos.get(classificacao).add(usuario);
		}
		
	}
	
	public static ArrayList<Usuario> getListaUsuarios() {
		return new ArrayList<Usuario>();
	}
}

Esse aqui ficou muito bom!

rogelgarcia:
A sintaxe de Java pode ficar um pouco verbosa por falta de recursos da linguagem.. O mais interessante da analise aqui, é a arquitetura resultante e como podemos contornar ifs aninhados.

Se ficar verboso de mais, a chance da gambiarra ocorrer aumenta.

na boa? Ainda prefiro assim do que aninhar 300 ifs.

Desculpe, mas ainda assim penso que não existe motivo para 17 ifs seguidos...

Isso depende. Eu não vi o fonte do autor do post. Se o patrão dele disse que é possivel melhorar, eu acredito. Provavelmente as condicionais que ele está usando são simples.

Quanto o problema dos IFs serem SEMPRE retirados não concordo pelos motivos que eu já citei.

rogelgarcia

Pessoal só tá expressando idéias e opiniões… É normal pessoas diferentes terem opiniões diferentes… :wink: Ninguém aqui está brigando…

Temos que aprender a conversar e respeitar as opiniões (como está ocorrendo aqui) ao invés de ficar trancando tópicos por medo de gerar flames…

Acho ainda que a discussão aqui, gera um resultado saudável… até para quem está lendo o fórum… Iniciantes por exemplo, podem ver exemplos de casos onde existem ifs, outros casos onde foi montada uma arquitetura, e até uma refatoração… É extremamente difícil achar exemplos assim na internet…

Por falar nisso… nem sei o motivo de trancarem tópicos só porque está “flamando”… Povo quer discutir… deixa discutir… heheheh

PS: Java é melhor que PHP. kkkk

R

Pessoal só tá expressando idéias e opiniões… É normal pessoas diferentes terem opiniões diferentes… :wink: Ninguém aqui está brigando…

Temos que aprender a conversar e respeitar as opiniões (como está ocorrendo aqui) ao invés de ficar trancando tópicos por medo de gerar flames…

Por falar nisso… nem sei o motivo de trancarem tópicos só porque está “flamando”… Povo quer discutir… deixa discutir… heheheh

PS: Java é melhor que PHP. kkkk


Também acho o java melhor,mas é melhor falar baixo pros fanboy não se sentirem ofendidos.

A

Pessoal só tá expressando idéias e opiniões… É normal pessoas diferentes terem opiniões diferentes… :wink: Ninguém aqui está brigando…

Temos que aprender a conversar e respeitar as opiniões (como está ocorrendo aqui) ao invés de ficar trancando tópicos por medo de gerar flames…

Acho ainda que a discussão aqui, gera um resultado saudável… até para quem está lendo o fórum… Iniciantes por exemplo, podem ver exemplos de casos onde existem ifs, outros casos onde foi montada uma arquitetura, e até uma refatoração… É extremamente difícil achar exemplos assim na internet…

Por falar nisso… nem sei o motivo de trancarem tópicos só porque está “flamando”… Povo quer discutir… deixa discutir… heheheh

PS: Java é melhor que PHP. kkkk


1+

Luiz_Augusto_Prado

Pessoal só tá expressando idéias e opiniões… É normal pessoas diferentes terem opiniões diferentes… :wink: Ninguém aqui está brigando…

Temos que aprender a conversar e respeitar as opiniões (como está ocorrendo aqui) ao invés de ficar trancando tópicos por medo de gerar flames…

Acho ainda que a discussão aqui, gera um resultado saudável… até para quem está lendo o fórum… Iniciantes por exemplo, podem ver exemplos de casos onde existem ifs, outros casos onde foi montada uma arquitetura, e até uma refatoração… É extremamente difícil achar exemplos assim na internet…

Por falar nisso… nem sei o motivo de trancarem tópicos só porque está “flamando”… Povo quer discutir… deixa discutir… heheheh

PS: Java é melhor que PHP. kkkk

o GUJ tá ficando ruim pelo exagero.
Já ví moderador aqui falar de coisas totalmente fora da TI e trancar tópicos só por desviar um pouco do assunto.

PS: Não… PHP é bem mais legal! Huahuahuahua
Gostei das suas idéias. As vezes agente acaba usando IFs porque não consegue visualizar forma melhor.

M

voce faria diferente como ??? ?

Hebert_Coelho

Luiz Augusto Prado:
Quanto o problema dos IFs serem SEMPRE retirados não concordo pelos motivos que eu já citei.
Uma coisa é ter ifs, outra coisa é ter 17…

Hebert_Coelho

voce faria diferente como ??? ?Ele já fez…

R

Luiz Augusto Prado:
Novamente, sério? Qual?
Qual o motivo se justifica a não usar algum pattern e usar toneladas de ifs independentes de objetos/strings?

Estou perguntando numa boa. Atualmente não imagino.

Em algum momento vc pode ter que classificar em que tipo de objeto se enquadra um dado que acaba de chegar. Nessa hora vc vai precisar usar if. Vc, nem eu podemos imaginar a situação melhor agora porque isso depende da lógica de negócio. Vas vou supor uma bem simples…

o usuário vai se cadastrar em algum lugar e dependendo da idade dele eu vou colocar ele em uma classe diferente:

if( dadosDoUsuario.idade < 18 )
{
 os dados vão para o objeto a
}
else if( dadosDoUsuario.idade >= 18 && dadosDoUsuario.idade<55 )
{
 os dados vão para o objeto b
}
else if( dadosDoUsuario.idade >= 55 && dadosDoUsuario.idade<120 )
{
 os dados vão para o objeto c
}
else
{
 os dados vão pro limbo
}

esse caso seu da pra usar um switch bem bonitão…

pode até ser que exista situações que exigem várias verificações que não podem ser colocadas num switch mas nesse caso, a boa prática recomenda MUDAR o jeito que está fazendo

Imagina dar manutenção num código com 17 ifs? vc vai procurar 1 por 1 toda vez q for mudar algo? e se tiver que tirar algo? ou colocar algo q depende de uma condição que está ali? ia encadear dentro dos IFs? se envolver threads então…

Algumas vezes deve-se repensar na estratégia sim e evitar isso… fazer como o Bruno Laturner falou por exemplo de colocar as verificações em métodos… desse modo, seria mais facil uma manutenção no código depois… ou pode-se usar recursividade, switch, bibliotecas de auxilio, sei la…

R

Cara se tem uma coisa que eu realmente to esperando no Java 8,é o suporte a lambda expressions, que com certeza vai retirar bastante ifs dos códigos.

R
mariazinhahappy:
meu codigo e esse aqui
@Override
	public Object lerArquivoTXTPrepararObjetosParaVirarXML_arvore() {  
		mae_VO mae = new mae_VO();
		filha_VO filha = new filha_VO();
		neta_VO neta = new neta_VO();
		binesta_VO binesta = new binesta_VO();
		
		try {  
			Scanner arquivo = new Scanner(new File("C:\\Projeto Revistas\\catalogacao_2013.log"));  
			while (arquivo.hasNext()) {
				String linha = arquivo.nextLine();
				// coisas que estao no começo
				if (linha.contains("Revifilhaa Mãe") && linha.contains("Início da Execução")) {
					mae.setDataFinal(linha);
					mae.setDataInicial(linha);
					mae.setDescricao(linha);
					mae.setHoraFinal(linha);
					mae.setHoraInicio(linha);
					mae.setId(linha);
					if (linha.contains("erro")) {
						neta.setfilhaatus(Enumfilhaatus.ERRO);
					}	else if (linha.contains("atual"))	{
						neta.setfilhaatus(Enumfilhaatus.ATUAL);
					} else
						neta.setfilhaatus(Enumfilhaatus.U2013);
				}
				
				if (linha.contains("Revifilhaa Filha") && linha.contains("Início da Execução")) {
					filha.setDataFinal(linha);
					filha.setDataInicial(linha);
					filha.setDescricao(linha);
					filha.setHoraFinal(linha);
					filha.setHoraInicio(linha);
					filha.setId(linha);
					if (linha.contains("erro")) {
						neta.setfilhaatus(Enumfilhaatus.ERRO);
					}	else if (linha.contains("atual"))	{
						neta.setfilhaatus(Enumfilhaatus.ATUAL);
					} else
						neta.setfilhaatus(Enumfilhaatus.U2013);
				}
				
				if (linha.contains("Revifilhaa Neta") && linha.contains("Início da Execução")) {
					neta.setDataFinal(linha);
					neta.setDataInicial(linha);
					neta.setDescricao(linha);
					neta.setHoraFinal(linha);
					neta.setHoraInicio(linha);
					neta.setId(linha);
					if (linha.contains("erro")) {
						neta.setfilhaatus(Enumfilhaatus.ERRO);
					}	else if (linha.contains("atual"))	{
						neta.setfilhaatus(Enumfilhaatus.ATUAL);
					} else
						neta.setfilhaatus(Enumfilhaatus.U2013);
				}
				
				if (linha.contains("Revifilhaa Bisneta") && linha.contains("Início da Execução")) {
					binesta.setDataFinal(linha);
					binesta.setDataInicial(linha);
					binesta.setDescricao(linha);
					binesta.setHoraFinal(linha);
					binesta.setHoraInicio(linha);
					binesta.setId(linha);

					if (linha.contains("erro")) {
						neta.setfilhaatus(Enumfilhaatus.ERRO);
					}	else if (linha.contains("atual"))	{
						neta.setfilhaatus(Enumfilhaatus.ATUAL);
					} else
						neta.setfilhaatus(Enumfilhaatus.U2013);
				}
				
				
				// coisas que estao no final
				if (linha.contains("Revista Mãe") && linha.contains("Executado com")) {
					mae.getLifilhaaSuites().add(filha);
					filha = new filha_VO();
				}
				
				if (linha.contains("Revista Filha") && linha.contains("Executado com")
						&& linha.contains("2013")) {
					filha.getLifilhaanetas().add(neta);
					neta = new neta_VO();
				}
				
				if (linha.contains("Revista Bisneta") && linha.contains("Executado com")) {
					neta.getLifilhaabinestas().add(binesta);
					binesta = new binesta_VO();
				}
				
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		 return mae;
	}

o certo seria retrabalhar como voce está desenvolvendo...

pensando aqui, poderia fazer da seguinte maneira:
criar uma interface FAMILIA com os métodos que as classes possuem em comum... depois ficaria bem mais facil trabalhar fazendo algo como:

Familia mae;
Familia filha;
// etc

// while...
if ( !linha.contains("Início da Execução") ) {
// faz as coisas como "Executado com"... 
continue;
}

// chegou aqui, sabe que a linha tem "Início da Execução"
checkMae(linha);
checkFilha(linha); 
// etc




// dentro desses métodos, voce faz algo como:
public void checkMae(linha) {

   if ( !linha.contains("Mãe")  ) {
      return;
   }

   mae  = new mae_VO( linha ); // aqui dentro voce cria todos os SET
   checkStatus( linha, mae ); // aqui voce checa se tem erros e usa um método do objeto passado por parametro no SET
}

NÂO É A MELHOR MANEIRA. Pensei rapidamente nisso aqui agora... Mas fica bem mais tranquilo o código e essas ideias podem abrir a sua cabeça ou do pessoal ;)

Luiz_Augusto_Prado

EU tenho que viajar hoje, mas ainda gostaria de deixar essa questão aberta.

Sim, entendo tudo o que dizem a respeito da facilidade da manutenção.
Mas mesmo retirando o excesso de IFs, os erros podem até se tornar mais fáceis de ocorrerem.
Eu vou mostrar isso no próximo post e gostaria de discutir isso com o pessoal aqui.
Quero saber como vcs evitam os tipos de erros e gambiarras que eu vou mostrar.
Exemplo do que ocorreu em um momento com o rogelgarcia :

if(usuario.numeroFilhos <= 2)
        {  
            iterator.remove();  
        }

Ontem fui dormir remoendo o código do rogelgarcia , que achei muito legal (abre a cabeça), e tive um insight.
Uma regra geral para a retirada de excessos de IFs. É um problema “matemático”.
Assim que voltar dou o retorno aqui.

Hebert_Coelho

Luiz Augusto Prado:
Quero saber como vcs evitam os tipos de erros e gambiarras que eu vou mostrar.
Exemplo do que ocorreu em um momento com o rogelgarcia :

if(usuario.numeroFilhos <= 2) { iterator.remove(); }

TDD
[=

A
mariazinhahappy:
meu codigo e esse aqui
@Override
	public Object lerArquivoTXTPrepararObjetosParaVirarXML_arvore() {  
		mae_VO mae = new mae_VO();
		filha_VO filha = new filha_VO();
		neta_VO neta = new neta_VO();
		binesta_VO binesta = new binesta_VO();
		
		try {  
			Scanner arquivo = new Scanner(new File("C:\\Projeto Revistas\\catalogacao_2013.log"));  
			while (arquivo.hasNext()) {
				String linha = arquivo.nextLine();
				// coisas que estao no começo
				if (linha.contains("Revifilhaa Mãe") && linha.contains("Início da Execução")) {
					mae.setDataFinal(linha);
					mae.setDataInicial(linha);
					mae.setDescricao(linha);
					mae.setHoraFinal(linha);
					mae.setHoraInicio(linha);
					mae.setId(linha);
					if (linha.contains("erro")) {
						neta.setfilhaatus(Enumfilhaatus.ERRO);
					}	else if (linha.contains("atual"))	{
						neta.setfilhaatus(Enumfilhaatus.ATUAL);
					} else
						neta.setfilhaatus(Enumfilhaatus.U2013);
				}
				
				if (linha.contains("Revifilhaa Filha") && linha.contains("Início da Execução")) {
					filha.setDataFinal(linha);
					filha.setDataInicial(linha);
					filha.setDescricao(linha);
					filha.setHoraFinal(linha);
					filha.setHoraInicio(linha);
					filha.setId(linha);
					if (linha.contains("erro")) {
						neta.setfilhaatus(Enumfilhaatus.ERRO);
					}	else if (linha.contains("atual"))	{
						neta.setfilhaatus(Enumfilhaatus.ATUAL);
					} else
						neta.setfilhaatus(Enumfilhaatus.U2013);
				}
				
				if (linha.contains("Revifilhaa Neta") && linha.contains("Início da Execução")) {
					neta.setDataFinal(linha);
					neta.setDataInicial(linha);
					neta.setDescricao(linha);
					neta.setHoraFinal(linha);
					neta.setHoraInicio(linha);
					neta.setId(linha);
					if (linha.contains("erro")) {
						neta.setfilhaatus(Enumfilhaatus.ERRO);
					}	else if (linha.contains("atual"))	{
						neta.setfilhaatus(Enumfilhaatus.ATUAL);
					} else
						neta.setfilhaatus(Enumfilhaatus.U2013);
				}
				
				if (linha.contains("Revifilhaa Bisneta") && linha.contains("Início da Execução")) {
					binesta.setDataFinal(linha);
					binesta.setDataInicial(linha);
					binesta.setDescricao(linha);
					binesta.setHoraFinal(linha);
					binesta.setHoraInicio(linha);
					binesta.setId(linha);

					if (linha.contains("erro")) {
						neta.setfilhaatus(Enumfilhaatus.ERRO);
					}	else if (linha.contains("atual"))	{
						neta.setfilhaatus(Enumfilhaatus.ATUAL);
					} else
						neta.setfilhaatus(Enumfilhaatus.U2013);
				}
				
				
				// coisas que estao no final
				if (linha.contains("Revista Mãe") && linha.contains("Executado com")) {
					mae.getLifilhaaSuites().add(filha);
					filha = new filha_VO();
				}
				
				if (linha.contains("Revista Filha") && linha.contains("Executado com")
						&& linha.contains("2013")) {
					filha.getLifilhaanetas().add(neta);
					neta = new neta_VO();
				}
				
				if (linha.contains("Revista Bisneta") && linha.contains("Executado com")) {
					neta.getLifilhaabinestas().add(binesta);
					binesta = new binesta_VO();
				}
				
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		 return mae;
	}

Olha... Pelo q sakei d seu código, pra melhorar a legibilidade tb, ao invés de só ifs, vc poderia usar com certeza "if e else if".

Hebert_Coelho
andredecotia:
mariazinhahappy:
meu codigo e esse aqui
@Override
	public Object lerArquivoTXTPrepararObjetosParaVirarXML_arvore() {  
		mae_VO mae = new mae_VO();
		filha_VO filha = new filha_VO();
		neta_VO neta = new neta_VO();
		binesta_VO binesta = new binesta_VO();
		
		try {  
			Scanner arquivo = new Scanner(new File("C:\\Projeto Revistas\\catalogacao_2013.log"));  
			while (arquivo.hasNext()) {
				String linha = arquivo.nextLine();
				// coisas que estao no começo
				if (linha.contains("Revifilhaa Mãe") && linha.contains("Início da Execução")) {
					mae.setDataFinal(linha);
					mae.setDataInicial(linha);
					mae.setDescricao(linha);
					mae.setHoraFinal(linha);
					mae.setHoraInicio(linha);
					mae.setId(linha);
					if (linha.contains("erro")) {
						neta.setfilhaatus(Enumfilhaatus.ERRO);
					}	else if (linha.contains("atual"))	{
						neta.setfilhaatus(Enumfilhaatus.ATUAL);
					} else
						neta.setfilhaatus(Enumfilhaatus.U2013);
				}
				
				if (linha.contains("Revifilhaa Filha") && linha.contains("Início da Execução")) {
					filha.setDataFinal(linha);
					filha.setDataInicial(linha);
					filha.setDescricao(linha);
					filha.setHoraFinal(linha);
					filha.setHoraInicio(linha);
					filha.setId(linha);
					if (linha.contains("erro")) {
						neta.setfilhaatus(Enumfilhaatus.ERRO);
					}	else if (linha.contains("atual"))	{
						neta.setfilhaatus(Enumfilhaatus.ATUAL);
					} else
						neta.setfilhaatus(Enumfilhaatus.U2013);
				}
				
				if (linha.contains("Revifilhaa Neta") && linha.contains("Início da Execução")) {
					neta.setDataFinal(linha);
					neta.setDataInicial(linha);
					neta.setDescricao(linha);
					neta.setHoraFinal(linha);
					neta.setHoraInicio(linha);
					neta.setId(linha);
					if (linha.contains("erro")) {
						neta.setfilhaatus(Enumfilhaatus.ERRO);
					}	else if (linha.contains("atual"))	{
						neta.setfilhaatus(Enumfilhaatus.ATUAL);
					} else
						neta.setfilhaatus(Enumfilhaatus.U2013);
				}
				
				if (linha.contains("Revifilhaa Bisneta") && linha.contains("Início da Execução")) {
					binesta.setDataFinal(linha);
					binesta.setDataInicial(linha);
					binesta.setDescricao(linha);
					binesta.setHoraFinal(linha);
					binesta.setHoraInicio(linha);
					binesta.setId(linha);

					if (linha.contains("erro")) {
						neta.setfilhaatus(Enumfilhaatus.ERRO);
					}	else if (linha.contains("atual"))	{
						neta.setfilhaatus(Enumfilhaatus.ATUAL);
					} else
						neta.setfilhaatus(Enumfilhaatus.U2013);
				}
				
				
				// coisas que estao no final
				if (linha.contains("Revista Mãe") && linha.contains("Executado com")) {
					mae.getLifilhaaSuites().add(filha);
					filha = new filha_VO();
				}
				
				if (linha.contains("Revista Filha") && linha.contains("Executado com")
						&& linha.contains("2013")) {
					filha.getLifilhaanetas().add(neta);
					neta = new neta_VO();
				}
				
				if (linha.contains("Revista Bisneta") && linha.contains("Executado com")) {
					neta.getLifilhaabinestas().add(binesta);
					binesta = new binesta_VO();
				}
				
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		 return mae;
	}

Olha... Pelo q sakei d seu código, pra melhor a legibilidade tb, ao invés de só ifs, vc poderia usar com certeza "if e else if".

Novamente te pergunto, vale a pena ter esse monte de if?

A
Hebert Coelho:
andredecotia:
mariazinhahappy:
meu codigo e esse aqui
@Override
	public Object lerArquivoTXTPrepararObjetosParaVirarXML_arvore() {  
		mae_VO mae = new mae_VO();
		filha_VO filha = new filha_VO();
		neta_VO neta = new neta_VO();
		binesta_VO binesta = new binesta_VO();
		
		try {  
			Scanner arquivo = new Scanner(new File("C:\\Projeto Revistas\\catalogacao_2013.log"));  
			while (arquivo.hasNext()) {
				String linha = arquivo.nextLine();
				// coisas que estao no começo
				if (linha.contains("Revifilhaa Mãe") && linha.contains("Início da Execução")) {
					mae.setDataFinal(linha);
					mae.setDataInicial(linha);
					mae.setDescricao(linha);
					mae.setHoraFinal(linha);
					mae.setHoraInicio(linha);
					mae.setId(linha);
					if (linha.contains("erro")) {
						neta.setfilhaatus(Enumfilhaatus.ERRO);
					}	else if (linha.contains("atual"))	{
						neta.setfilhaatus(Enumfilhaatus.ATUAL);
					} else
						neta.setfilhaatus(Enumfilhaatus.U2013);
				}
				
				if (linha.contains("Revifilhaa Filha") && linha.contains("Início da Execução")) {
					filha.setDataFinal(linha);
					filha.setDataInicial(linha);
					filha.setDescricao(linha);
					filha.setHoraFinal(linha);
					filha.setHoraInicio(linha);
					filha.setId(linha);
					if (linha.contains("erro")) {
						neta.setfilhaatus(Enumfilhaatus.ERRO);
					}	else if (linha.contains("atual"))	{
						neta.setfilhaatus(Enumfilhaatus.ATUAL);
					} else
						neta.setfilhaatus(Enumfilhaatus.U2013);
				}
				
				if (linha.contains("Revifilhaa Neta") && linha.contains("Início da Execução")) {
					neta.setDataFinal(linha);
					neta.setDataInicial(linha);
					neta.setDescricao(linha);
					neta.setHoraFinal(linha);
					neta.setHoraInicio(linha);
					neta.setId(linha);
					if (linha.contains("erro")) {
						neta.setfilhaatus(Enumfilhaatus.ERRO);
					}	else if (linha.contains("atual"))	{
						neta.setfilhaatus(Enumfilhaatus.ATUAL);
					} else
						neta.setfilhaatus(Enumfilhaatus.U2013);
				}
				
				if (linha.contains("Revifilhaa Bisneta") && linha.contains("Início da Execução")) {
					binesta.setDataFinal(linha);
					binesta.setDataInicial(linha);
					binesta.setDescricao(linha);
					binesta.setHoraFinal(linha);
					binesta.setHoraInicio(linha);
					binesta.setId(linha);

					if (linha.contains("erro")) {
						neta.setfilhaatus(Enumfilhaatus.ERRO);
					}	else if (linha.contains("atual"))	{
						neta.setfilhaatus(Enumfilhaatus.ATUAL);
					} else
						neta.setfilhaatus(Enumfilhaatus.U2013);
				}
				
				
				// coisas que estao no final
				if (linha.contains("Revista Mãe") && linha.contains("Executado com")) {
					mae.getLifilhaaSuites().add(filha);
					filha = new filha_VO();
				}
				
				if (linha.contains("Revista Filha") && linha.contains("Executado com")
						&& linha.contains("2013")) {
					filha.getLifilhaanetas().add(neta);
					neta = new neta_VO();
				}
				
				if (linha.contains("Revista Bisneta") && linha.contains("Executado com")) {
					neta.getLifilhaabinestas().add(binesta);
					binesta = new binesta_VO();
				}
				
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		 return mae;
	}

Olha... Pelo q sakei d seu código, pra melhor a legibilidade tb, ao invés de só ifs, vc poderia usar com certeza "if e else if".

Novamente te pergunto, vale a pena ter esse monte de if?

:D
Hum...

Faça a leitura do código dela, e com base "nele" diga-nos como vc o implementaria... Na teoria todos sabemos o q um monte de ifs pode significar, na prática, temos o código acima para com base nele opinar.

Abraços,
André AS.

Hebert_Coelho

:smiley:
Hum…

Faça a leitura do código dela, e com base “nele” diga-nos como vc o implementaria… Na teoria todos sabemos o q um monte de ifs pode significar, na prática, temos o código acima para com base nele opinar.

Abraços,
André AS.
Ei, você quem disse lá tras que monte de if pode não ser má prática. Por isso te refiz a pergunta:

Hebert Coelho:
andredecotia:
Tb recomendo o livro Clean Code.

Contudo, há situações, em q vão haver vários ifs, e nem por isso significaria má prática.

Sério? Qual?
Pode ser que o modo como você trate seus ifs melhore, mas eu ainda não consigo pensar em um.

A

:smiley:
Hum…

Faça a leitura do código dela, e com base “nele” diga-nos como vc o implementaria… Na teoria todos sabemos o q um monte de ifs pode significar, na prática, temos o código acima para com base nele opinar.

Abraços,
André AS.
Ei, você quem disse lá tras que monte de if pode não ser má prática. Por isso te refiz a pergunta:

Hebert Coelho:
andredecotia:
Tb recomendo o livro Clean Code.

Contudo, há situações, em q vão haver vários ifs, e nem por isso significaria má prática.

Sério? Qual?
Pode ser que o modo como você trate seus ifs melhore, mas eu ainda não consigo pensar em um.

Talvez eu não tenha sido claro, vou recolocar de outra forma: Vc poderia com base no q ela nos enviou, analisar, pensar e então, enviar uma opinião factível, visto q ela é estagiária, qlq. coisa muito abstrata é possível q não assimile…

Opinei sendo objetivo com base no q ela enviou. Se ficasse falando de TDD, livros Refactoring, apenas, acho q não ajudaria ela, tanto q, ela enviou o código pra esta finalidade, avaliarmos e com base nele podermos ser mais diretos. Desculpe, mas não foi o seu caso. :wink:

Rodrigo_Sasaki

andredecotia:

Talvez eu não tenha sido claro, vou recolocar de outra forma: Vc poderia com base no q ela nos enviou, analisar, pensar e então, enviar uma opinião factível, visto q ela é estagiária, qlq. coisa muito abstrata é possível q não assimile…

Opinei sendo objetivo com base no q ela enviou. Se ficasse falando de TDD, livros Refactoring, apenas, acho q não ajudaria ela, tanto q, ela enviou o código pra esta finalidade, avaliarmos e com base nele podermos ser mais diretos. Desculpe, mas não foi o seu caso. :wink:


Desculpa, André. Realmente não estou querendo ser chato, mas você deu sua opinião.

Você mesmo disse que uma quantidade grande de ifs pode não ser má prática, porém não disse e não exemplificou nada que justificasse sua resposta. Outros responderam com ideias e exemplos de código tornando essa discussão bastante saudável, mas eu também fiquei curioso quanto ao seu ponto de vista.

Você realmente consegue exemplificar uma situação onde a melhor solução é um encadeamento enorme de ifs?

M

Não alimente spammers

rafadelnero

Só pode ser brincadeira:

if (linha.contains("Revifilhaa Mãe") && linha.contains("Início da Execução")) { mae.setDataFinal(linha); mae.setDataInicial(linha); mae.setDescricao(linha); mae.setHoraFinal(linha); mae.setHoraInicio(linha); mae.setId(linha); if (linha.contains("erro")) { neta.setfilhaatus(Enumfilhaatus.ERRO); } else if (linha.contains("atual")) { neta.setfilhaatus(Enumfilhaatus.ATUAL); } else neta.setfilhaatus(Enumfilhaatus.U2013); }

Mas reutilize essa lógica com um método com passagem de parâmetros, os ifs tem códigos repetidos, isso é extremamente ruim pensando de forma orientada a objetos…

lina

Oi,

Falar que algo é errado por utilizar 17 IFs é muita ignorância. O máximo é dizer que o código não está bom e que pode ser melhorado. O errado é algo que não funciona, ou algo que não condiz com o especificado.

É obvio e muito claro que um código de 17 IFs pode ser melhorado. Nenhum código é perfeito. A ideia já foi feita, agora basta melhorar a lógica.

Acho que o pessoal exagerou na codificação. E acho que muitos usuários responderam coisas absurdas para uma simples pergunta.

Quer ajuda? Pergunte. Nota-se que você é esforçado(a).

Tchauzin!

rogelgarcia

17 ifs está errado!

Assim como: get_nome() também está errado.

Pra mim, não é só código que retorna o esperado que está certo. Se retorna o resultado, mas fazendo gambiarra, pra mim está errado.
E tenho certeza que isso é errado para outros programadores experientes também.

Você liga um arame na sua fiação elétrica e a luz funciona. Tá certo? Não!

ul1sses

rogelgarcia:
17 ifs está errado!

Assim como: get_nome() também está errado.

Pra mim, não é só código que retorna o esperado que está certo. Se retorna o resultado, mas fazendo gambiarra, pra mim está errado.
E tenho certeza que isso é errado para outros programadores experientes também.

Você liga um arame na sua fiação elétrica e a luz funciona. Tá certo? Não!

“Quem” diz o que está errado ou não é o compilador.
O máximo que você pode dizer é sobre o nível de abstração OO, uso de padrões e convenções.

Porém, é obvio que o código dela pode e deve ser melhorado.

RiQuInHo_

uol poxa vida hein ♫♫

17 ifs,pode ser varias condições, se eu faço assim ta errado hahaha (logico que não!).Posso ter ate 30 ifs.

if(this.nomeSegurado == null) {
			msg.append("<br>- Nome não preenchido");
			atributos.add("nomeSegurado");
			invalido = true;
		}

		if(this.dataNascimento == null) {
			msg.append("<br>- Data de nascimento não preenchida");
			atributos.add("dataNascimento");
			invalido = true;
		}

		if(this.sexo == null) {
				msg.append("<br>- Sexo não selecionado");
				atributos.add("sexo");
				invalido = true;
			} ........
rmendes08

Sinceramente, eu acho que o pessoal tá muito preocupado no sintoma do que no problema em si. Na minha opinião, trocar 17 IF’s por 17 classes ou 17 métodos só quebraria a coesão do método e tornaria a leitura do código muito mais sofrida. Na prática, somente serviria para mudar a duplicação de lugar.

ViniGodoy

É impressão minha ou estão discutindo a definição de erro?

Essa definição varia de acordo com o que você queira definir. A ISO, por exemplo, chamaria uma falha de padrão de “não conformidade”.
Agora, não se enganem, não conformidades podem ser tão ou mais problemáticas do que o erro em si. Não é porque você deixou de chamar de erro, que o problema ficou menos problemático.

rmendes08
public Object lerArquivoTXTPrepararObjetosParaVirarXML_arvore() {  
	mae_VO mae = new mae_VO();
	filha_VO filha = new filha_VO();
	neta_VO neta = new neta_VO();
	binesta_VO binesta = new binesta_VO();

	try {  
		Scanner arquivo = new Scanner(new File("C:\\Projeto Revistas\\catalogacao_2013.log")); 

		while (arquivo.hasNext()) {
			String linha = arquivo.nextLine();

			if(linha.contains("Início da Execução")){ // coisas que estao no começo
				if (linha.contains("Revifilhaa Mãe")) {
					mae.setDataFinal(linha);
					mae.setDataInicial(linha);
					mae.setDescricao(linha);
					mae.setHoraFinal(linha);
					mae.setHoraInicio(linha);
					mae.setId(linha);	
				}else if (linha.contains("Revifilhaa Filha")) {
					filha.setDataFinal(linha);
					filha.setDataInicial(linha);
					filha.setDescricao(linha);
					filha.setHoraFinal(linha);
					filha.setHoraInicio(linha);
					filha.setId(linha);
				}else if (linha.contains("Revifilhaa Neta")) {
					neta.setDataFinal(linha);
					neta.setDataInicial(linha);
					neta.setDescricao(linha);
					neta.setHoraFinal(linha);
					neta.setHoraInicio(linha);
					neta.setId(linha);
				}else if (linha.contains("Revifilhaa Bisneta")) {
					binesta.setDataFinal(linha);
					binesta.setDataInicial(linha);
					binesta.setDescricao(linha);
					binesta.setHoraFinal(linha);
					binesta.setHoraInicio(linha);
					binesta.setId(linha);
				}

				if (linha.contains("erro")) {
					neta.setfilhaatus(Enumfilhaatus.ERRO);
				}	else if (linha.contains("atual"))	{
					neta.setfilhaatus(Enumfilhaatus.ATUAL);
				} else{
					neta.setfilhaatus(Enumfilhaatus.U2013);
				}
			}

			if(linha.contains("Executado com")){// coisas que estao no final
				if (linha.contains("Revista Mãe")) { 
					mae.getLifilhaaSuites().add(filha);
					filha = new filha_VO();
				}else if (linha.contains("Revista Filha") && linha.contains("2013")) {
					filha.getLifilhaanetas().add(neta);
					neta = new neta_VO();
				}else if (linha.contains("Revista Bisneta")) {
					neta.getLifilhaabinestas().add(binesta);
					binesta = new binesta_VO();
				}
			}				
		}
	} catch (Exception e) {
		e.printStackTrace();
	}
	
	return mae;
}

Bom, eu tentei remover as duplicações do código … ao invés de trocar o if por classes ou métodos eu procurei remover somente os trechos duplicados. O que eu percebi é que duplicação está nas classes VO. Reparem que elas possuem exatamente a mesma interface, caberia ai declarar uma interface comum a todas ou ainda, criar uma classe só com um campo de tipo.

rogelgarcia

Pessoal me pediu que colocasse o código comentado sobre a resolução para evitar IFS.

Abaixo do código colocarei uma explicação:

/*
 * Esse sistema tem dois conceitos. 
 * Etapa da vida, associado a idade da pessoa.
 * Classificacoes, associadas a qualquer informação da pessoa.
 * 
 * A idéia é resolver essa problemática sugerida pelo colega Luiz Augusto Prado sem o uso de IFS:

 if( dadosDoUsuario.idade < 18 )  
{  
os dados vão para o objeto a  
}  
else if( dadosDoUsuario.idade >= 18 && dadosDoUsuario.idade<55 )  
{  
os dados vão para o objeto b  
}  
else if( dadosDoUsuario.idade >= 55 && dadosDoUsuario.idade<120 || dadosDoUsuario.numeroFilhos>2 )  
{  
os dados vão para o objeto c  
}  
else  
{  
os dados vão pro limbo  
}  

 * 
 * 
 */

/**
 * Esse enum representa as 4 etapas possíveis da vida para esse sistema.
 */
enum EtapaDaVida {
	
	JOVEM(18),
	ADULTO(55),
	IDOSO(120),
	HIGHLANDER(Integer.MAX_VALUE);
	
	//um ENUM pode ter atributos
	int idadeMaxima;
	
	//que sao atribuidos através do construtor
	//após atribuido, o valor é imutável (lembre-se ENUMs são imutáveis)
	private EtapaDaVida(int idade){
		this.idadeMaxima = idade;
	}
	
	/**
	 * Método que retorna a Etapa da vida para determinada idade
	 */
	public static EtapaDaVida get(int idade){
		for (EtapaDaVida etapa : values()) { //values() = [JOVEM, ADULTO, IDOSO, HIGHLANDER]
			if(idade <= etapa.idadeMaxima){ 
				// se a idade for menor que a idade máxima da etapa significa que 
				// é essa a etapa relacionada a idade
				return etapa;
			}
		}
		//se não encontrar etapa relacionada com a idade retorna um erro
		throw new RuntimeException("resultado inesperado");
	}
	
	/**
	 * Método que retorna a Etapa da vida para determinada data.
	 * Irá calcular quantos anos a pessoa tem através de Utils.getIdade
	 * @param data
	 * @return
	 */
	public static EtapaDaVida get(Date data){
		return get(Utils.getIdade(data));
	}
}

class Usuario {
	Date nascimento;
	int numeroFilhos;
}

/**
 * Esse enum representa as 4 classificações do sistema.
 */
enum Classificacao {
	
	//cada enum será construido com um classificador
	A(new ClassificadorA()),
	B(new ClassificadorB()),
	C(new ClassificadorC()),
	LIMBO(new ClassificadorLimbo());
	
	Classificador classificador;

	Classificacao(Classificador classificador){
		this.classificador = classificador;
	}
	
	public boolean isClassificacao(Usuario u){
		//a classificacao utiliza o classificador para determinar se o usuario faz parte dela
		return classificador.isClassificacao(u); //o classificador é uma das classes implementadas abaixo
	}

	public static Classificacao get(Usuario usuario) {
		for (Classificacao c : values()) {//values() = [A, B, C, LIMBO]
			//para cada Classificacao (enum), verificamos se o usuario faz parte dela
			if(c.isClassificacao(usuario)){
				return c; //retorna a classificacao do usuario
			}
		}
		throw new RuntimeException("resultado inesperado");
	}
}

/**
 * Interface que representa um classificador 
 */
interface Classificador {
	/*
	 * Retorna true se esse classificador considera que o usuário faz parte dele
	 */
	public boolean isClassificacao(Usuario usuario);
}

class ClassificadorA implements Classificador{
	public boolean isClassificacao(Usuario usuario) {
		return EtapaDaVida.get(usuario.nascimento) == EtapaDaVida.JOVEM;
	}
}
class ClassificadorB implements Classificador{
	public boolean isClassificacao(Usuario usuario) {
		return EtapaDaVida.get(usuario.nascimento) == EtapaDaVida.ADULTO;
	}
}
class ClassificadorC implements Classificador{
	public boolean isClassificacao(Usuario usuario) {
		return EtapaDaVida.get(usuario.nascimento) == EtapaDaVida.IDOSO || usuario.numeroFilhos > 2;
	}
}
class ClassificadorLimbo implements Classificador{
	public boolean isClassificacao(Usuario usuario) {
		return true;
	}
}

public class Example2 {

	public static void main(String[] args) {
		//monta a estrutura de dados que vai receber a distribuicao
		Map<Classificacao, List<Usuario>> grupos = new HashMap<Classificacao, List<Usuario>>();
		for(Classificacao etapa: Classificacao.values()){
			//para cada chave (Classificacao), criamos uma nova lista
			grupos.put(etapa, new ArrayList<Usuario>());
		}
		
		//aqui é onde viria o ninho de ifs
		for (Usuario usuario : getListaUsuarios()) {
			//retornamos a classificacao do usuario
			Classificacao classificacao = Classificacao.get(usuario);
			//adicionamos o ususario a classificacao correta
			grupos.get(classificacao).add(usuario);
		}
		
	}
	
	public static ArrayList<Usuario> getListaUsuarios() {
		return new ArrayList<Usuario>(); //aqui seria criada a lista de usuarios a serem organizados
	}
}


class Utils {

	//método utilitário para retornar a idade de uma data
	public static int getIdade(Date data){
		Calendar hoje = Calendar.getInstance();
		Calendar nascimento = Calendar.getInstance();
		nascimento.setTime(data);
		int idade = hoje.get(Calendar.YEAR) - nascimento.get(Calendar.YEAR);
		nascimento.set(Calendar.YEAR, hoje.get(Calendar.YEAR));
		if(nascimento.compareTo(hoje) > 0){
			//nao fez aniversario esse ano
			idade--;
		}
		return idade;
	}
}

Não se atente ao número de linhas do código. O importante aqui é a análise da arquitetura criada. Qual a diferença entre esse código e um conjunto de ifs do ponto de vista de organização do sistema e não de esforço para criar tal solução.

Esse sistema possui dois conceitos: Etapa da vida e Classificação.
Os objetos do tipo Usuario, serão organizados em uma lista de acordo com sua classificação. Essa classificação envolve a descoberta da etapa da vida de um usuário.

Etapa da Vida

Para descobrir a etapa da vida, podemos fazer o seguinte:

EtapaDaVida ev = EtapaDaVida.get(usuario.nascimento);

A primeira questão a se notar nesse código é que existe uma estrutura que representa a etapa. É bastante diferente, de termos uma String ou int para identificar essa etapa. Veja que se não tivessemos essa estrutura, é com tipos básicos que teriamos que representar essa informação no sistema. Porém, uma String não define bem o que está sendo representado. Uma String pode conter qualquer coisa, um EtapaDaVida só pode conter etapas de vida.

Nessa solução, pegamos um conceito presente no sistema e criamos uma entidade para representar esse conceito.

Veja que se quiséssemos separar os usuários por etapa de vida, e não tivéssemos essa estrutura. Teriamos um código semelhante a esse:
List<Usuario> listaJovens = new ArrayList<Usuario>();
List<Usuario> listaAdultos = new ArrayList<Usuario>();
List<Usuario> listaIdosos = new ArrayList<Usuario>();
List<Usuario> limbo = new ArrayList<Usuario>();
for (Usuario usuario : getListaUsuarios()) {
	if (Utils.getIdade(usuario.nascimento) < 18) {
		listaJovens.add(usuario);
	} else if (Utils.getIdade(usuario.nascimento) < 55) {
		listaAdultos.add(usuario);
	} else if (Utils.getIdade(usuario.nascimento) < 120) {
		listaIdosos.add(usuario);
	} else {
		limbo.add(usuario);
	} 
}
A estrutura que temos aqui são quatro listas de usuários. Com o Enum:
Map<EtapaDaVida, List<Usuario>> map = new HashMap<EtapaDaVida, List<Usuario>>();
for (Usuario usuario : getListaUsuarios()) {
	EtapaDaVida etapa = EtapaDaVida.get(usuario.nascimento);
	List<Usuario> list = map.get(etapa);
	if(list == null){
		map.put(etapa, list = new ArrayList<Usuario>());
	}
	list.add(usuario);
}
A estrutura que temos aqui é um mapa cuja chave representa um conceito no sistema.

Podemos ainda dizer, que o segundo algoritmo nunca precisará ser modificado caso novas classificações de idade sejam adicionadas ao sistema. Basta adicionar uma nova entrada ao Enum. Diferente do primeiro caso onde o algoritmo de organização será alterado.

O Enum também facilita encontrar referencias no sistema que utilizam esse conceito.

O segundo algoritmo não possui uma sequencia de IFs para testar diversas condições. Ele possui um algoritmo que recebe uma entrada, e processa. Sem variações.

Sabe aquele erro que só acontece em determinadas condições no sistema? Então, geralmente essas condições são uma sequencia de IFs onde um caso não foi previsto. Na arquitetura proposta, não existem casos não previstos.

Classificacao

A solução dada à Classificação, é semelhante a solução da EtapaDeVida. Porém, a classificação pode conter qualquer condição. Por isso, foi criada uma interface Classificador. Cada enum Classificacao, possui um objeto dessa interface. Esse objeto, especifico do enum é capaz de dizer se determinado dado é da Classificacao ou não. No final das contas, pode-se utilizar o enum para dizer se o dado faz parte da classificacao. Por trás dos panos ele usa o classificador.

As vantagens apresentadas na EtapaDeVida também acontecem nessa situação. E ainda, se determinada condição de uma classificação mudar, é necessário mudar apenas um único ponto no sistema. Um ponto muito bem definido.

----------------------------------------------
Pegando o gancho do colega Luiz Augusto Prado, um algoritmo deve ser uma fórmula matemática. Deve-se dar um input, que retorna um output, sem determinadas condições. É como uma máquina, que devido as suas engrenagens sempre funciona, não importando a situação. Imagine a marcha de um carro, não existem ifs perguntando a posicao da alavanca para mudar a engrenagem da marcha. A alavanca está relacionada ao cambio e a modificacao da posição implica a mudança da engrenagem (sem ifs).

Com construções avançadas, onde existe uma engrenagem no seu sistema, é possível ter muito mais segurança, e afirmar com mais precisão que um sistema é robusto. Não tem ifs.. pode bater com pau que ele vai funcionar.

No dia a dia do desenvolvimento vão existir situações onde outros fatores vão importar no resultado da sua programação, principalmente o tempo. É perfeitamente normal que faça alguma solução que não seja ideal. Mas é importante saber, quando uma arquitetura pode ou precisa ser melhorada e fazer isso. Caso contrário, quando o sistema tiver já com seus anos de desenvolvimento, a zona vai ser tão grande que a manutenção fica impraticável (quem aqui conhece um sistemas desse?? rsrsrs)
----------------------------------------------

Não necessariamente a solução dos 17 ifs é a utilização de uma interface Classificação. É necessário analisar os requisitos e pensar em uma solução que seja adequada e tenha bom custo x beneficio.

A
rogelgarcia:
Pessoal me pediu que colocasse o código comentado sobre a resolução para evitar IFS.

Abaixo do código colocarei uma explicação:

/*
 * Esse sistema tem dois conceitos. 
 * Etapa da vida, associado a idade da pessoa.
 * Classificacoes, associadas a qualquer informação da pessoa.
 * 
 * A idéia é resolver essa problemática sugerida pelo colega Luiz Augusto Prado sem o uso de IFS:

 if( dadosDoUsuario.idade < 18 )  
{  
os dados vão para o objeto a  
}  
else if( dadosDoUsuario.idade >= 18 && dadosDoUsuario.idade<55 )  
{  
os dados vão para o objeto b  
}  
else if( dadosDoUsuario.idade >= 55 && dadosDoUsuario.idade<120 || dadosDoUsuario.numeroFilhos>2 )  
{  
os dados vão para o objeto c  
}  
else  
{  
os dados vão pro limbo  
}  

 * 
 * 
 */

/**
 * Esse enum representa as 4 etapas possíveis da vida para esse sistema.
 */
enum EtapaDaVida {
	
	JOVEM(18),
	ADULTO(55),
	IDOSO(120),
	HIGHLANDER(Integer.MAX_VALUE);
	
	//um ENUM pode ter atributos
	int idadeMaxima;
	
	//que sao atribuidos através do construtor
	//após atribuido, o valor é imutável (lembre-se ENUMs são imutáveis)
	private EtapaDaVida(int idade){
		this.idadeMaxima = idade;
	}
	
	/**
	 * Método que retorna a Etapa da vida para determinada idade
	 */
	public static EtapaDaVida get(int idade){
		for (EtapaDaVida etapa : values()) { //values() = [JOVEM, ADULTO, IDOSO, HIGHLANDER]
			if(idade <= etapa.idadeMaxima){ 
				// se a idade for menor que a idade máxima da etapa significa que 
				// é essa a etapa relacionada a idade
				return etapa;
			}
		}
		//se não encontrar etapa relacionada com a idade retorna um erro
		throw new RuntimeException("resultado inesperado");
	}
	
	/**
	 * Método que retorna a Etapa da vida para determinada data.
	 * Irá calcular quantos anos a pessoa tem através de Utils.getIdade
	 * @param data
	 * @return
	 */
	public static EtapaDaVida get(Date data){
		return get(Utils.getIdade(data));
	}
}

class Usuario {
	Date nascimento;
	int numeroFilhos;
}

/**
 * Esse enum representa as 4 classificações do sistema.
 */
enum Classificacao {
	
	//cada enum será construido com um classificador
	A(new ClassificadorA()),
	B(new ClassificadorB()),
	C(new ClassificadorC()),
	LIMBO(new ClassificadorLimbo());
	
	Classificador classificador;

	Classificacao(Classificador classificador){
		this.classificador = classificador;
	}
	
	public boolean isClassificacao(Usuario u){
		//a classificacao utiliza o classificador para determinar se o usuario faz parte dela
		return classificador.isClassificacao(u); //o classificador é uma das classes implementadas abaixo
	}

	public static Classificacao get(Usuario usuario) {
		for (Classificacao c : values()) {//values() = [A, B, C, LIMBO]
			//para cada Classificacao (enum), verificamos se o usuario faz parte dela
			if(c.isClassificacao(usuario)){
				return c; //retorna a classificacao do usuario
			}
		}
		throw new RuntimeException("resultado inesperado");
	}
}

/**
 * Interface que representa um classificador 
 */
interface Classificador {
	/*
	 * Retorna true se esse classificador considera que o usuário faz parte dele
	 */
	public boolean isClassificacao(Usuario usuario);
}

class ClassificadorA implements Classificador{
	public boolean isClassificacao(Usuario usuario) {
		return EtapaDaVida.get(usuario.nascimento) == EtapaDaVida.JOVEM;
	}
}
class ClassificadorB implements Classificador{
	public boolean isClassificacao(Usuario usuario) {
		return EtapaDaVida.get(usuario.nascimento) == EtapaDaVida.ADULTO;
	}
}
class ClassificadorC implements Classificador{
	public boolean isClassificacao(Usuario usuario) {
		return EtapaDaVida.get(usuario.nascimento) == EtapaDaVida.IDOSO || usuario.numeroFilhos > 2;
	}
}
class ClassificadorLimbo implements Classificador{
	public boolean isClassificacao(Usuario usuario) {
		return true;
	}
}

public class Example2 {

	public static void main(String[] args) {
		//monta a estrutura de dados que vai receber a distribuicao
		Map<Classificacao, List<Usuario>> grupos = new HashMap<Classificacao, List<Usuario>>();
		for(Classificacao etapa: Classificacao.values()){
			//para cada chave (Classificacao), criamos uma nova lista
			grupos.put(etapa, new ArrayList<Usuario>());
		}
		
		//aqui é onde viria o ninho de ifs
		for (Usuario usuario : getListaUsuarios()) {
			//retornamos a classificacao do usuario
			Classificacao classificacao = Classificacao.get(usuario);
			//adicionamos o ususario a classificacao correta
			grupos.get(classificacao).add(usuario);
		}
		
	}
	
	public static ArrayList<Usuario> getListaUsuarios() {
		return new ArrayList<Usuario>(); //aqui seria criada a lista de usuarios a serem organizados
	}
}


class Utils {

	//método utilitário para retornar a idade de uma data
	public static int getIdade(Date data){
		Calendar hoje = Calendar.getInstance();
		Calendar nascimento = Calendar.getInstance();
		nascimento.setTime(data);
		int idade = hoje.get(Calendar.YEAR) - nascimento.get(Calendar.YEAR);
		nascimento.set(Calendar.YEAR, hoje.get(Calendar.YEAR));
		if(nascimento.compareTo(hoje) > 0){
			//nao fez aniversario esse ano
			idade--;
		}
		return idade;
	}
}

Não se atente ao número de linhas do código. O importante aqui é a análise da arquitetura criada. Qual a diferença entre esse código e um conjunto de ifs do ponto de vista de organização do sistema e não de esforço para criar tal solução.

Esse sistema possui dois conceitos: Etapa da vida e Classificação.
Os objetos do tipo Usuario, serão organizados em uma lista de acordo com sua classificação. Essa classificação envolve a descoberta da etapa da vida de um usuário.

Etapa da Vida

Para descobrir a etapa da vida, podemos fazer o seguinte:

EtapaDaVida ev = EtapaDaVida.get(usuario.nascimento);

A primeira questão a se notar nesse código é que existe uma estrutura que representa a etapa. É bastante diferente, de termos uma String ou int para identificar essa etapa. Veja que se não tivessemos essa estrutura, é com tipos básicos que teriamos que representar essa informação no sistema. Porém, uma String não define bem o que está sendo representado. Uma String pode conter qualquer coisa, um EtapaDaVida só pode conter etapas de vida.

Nessa solução, pegamos um conceito presente no sistema e criamos uma entidade para representar esse conceito.

Veja que se quiséssemos separar os usuários por etapa de vida, e não tivéssemos essa estrutura. Teriamos um código semelhante a esse:
List<Usuario> listaJovens = new ArrayList<Usuario>();
List<Usuario> listaAdultos = new ArrayList<Usuario>();
List<Usuario> listaIdosos = new ArrayList<Usuario>();
List<Usuario> limbo = new ArrayList<Usuario>();
for (Usuario usuario : getListaUsuarios()) {
	if (Utils.getIdade(usuario.nascimento) < 18) {
		listaJovens.add(usuario);
	} else if (Utils.getIdade(usuario.nascimento) < 55) {
		listaAdultos.add(usuario);
	} else if (Utils.getIdade(usuario.nascimento) < 120) {
		listaIdosos.add(usuario);
	} else {
		limbo.add(usuario);
	} 
}
A estrutura que temos aqui são quatro listas de usuários. Com o Enum:
Map<EtapaDaVida, List<Usuario>> map = new HashMap<EtapaDaVida, List<Usuario>>();
for (Usuario usuario : getListaUsuarios()) {
	EtapaDaVida etapa = EtapaDaVida.get(usuario.nascimento);
	List<Usuario> list = map.get(etapa);
	if(list == null){
		map.put(etapa, list = new ArrayList<Usuario>());
	}
	list.add(usuario);
}
A estrutura que temos aqui é um mapa cuja chave representa um conceito no sistema.

Podemos ainda dizer, que o segundo algoritmo nunca precisará sem modificado caso novas classificações de idade sejam adicionadas ao sistema. Basta adicionar uma nova entrada ao Enum. Diferente do primeiro caso onde o algoritmo de organização será alterado.

O Enum também facilita encontrar referencias no sistema que utilizam esse conceito.

O segundo algoritmo não possui uma sequencia de IFs para testar diversas condições. Ele possui um algoritmo que recebe uma entrada, e processa. Sem variações.

Sabe aquele erro que só acontece em determinadas condições no sistema? Então, geralmente essas condições são uma sequencia de IFs onde um caso não foi previsto. Na arquitetura proposta, não existem casos não previstos.

Classificacao

A solução dada a classificação é semelhante a solução da EtapaDeVida. Porém, a classificação pode conter qualquer condição. Por isso, foi criada uma interface Classificador. Cada enum Classificacao, possui um objeto dessa interface. Esse objeto, especifico do enum é capaz de dizer se determinado dado é da Classificacao ou não. No final das contas, pode-se utilizar o enum para dizer se o dado faz parte da classificacao. Por trás dos panos ele usa o classificador.

As vantagens apresentadas na EtapaDeVida também acontecem nessa situação. E ainda, se determinada condição de uma classificação mudar, é necessário mudar apenas um único ponto no sistema. Um ponto muito bem definido.

----------------------------------------------
Pegando o gancho do colega Luiz Augusto Prado, um algoritmo deve ser uma fórmula matemática. Deve-se dar um input, que retorna um output, sem determinadas condições. É como uma máquina, que devido as suas engrenagens sempre funciona, não importando a situação. Imagine a marcha de um carro, não existem ifs perguntando a posicao da alavanca para mudar a engrenagem da marcha. A alavanca está relacionada ao cambio e a modificacao da posição implica a mudança da engrenagem (sem ifs).

Com construções avançadas, onde existe uma engrenagem no seu sistema, é possível ter muito mais segurança, e afirmar com mais precisão que um sistema é robusto. Não tem ifs.. pode bater com pau que ele vai funcionar.

No dia a dia do desenvolvimento vão existir situações onde outros fatores vão importar no resultado da sua programação, principalmente o tempo. É perfeitamente normal que faça alguma solução que não seja ideal. Mas é importante saber, quando uma arquitetura pode ou precisa ser melhorada e fazer isso. Caso contrário, quando o sistema tiver já com seus anos de desenvolvimento, a zona vai ser tão grande que a manutenção fica impraticável (quem aqui conhece um sistemas desse?? rsrsrs)
----------------------------------------------

Não necessariamente a solução dos 17 ifs é a utilização de uma interface Classificação. É necessário analisar os requisitos e pensar em uma solução que seja adequada e tenha bom custo x beneficio.

"Poxa vida ehm uôooou". rs. :D

rogelgarcia

Apenas para completar o tópico.. O resultado do algoritmo que tem que ler o seguinte arquivo:

[18/01/2013 15:26:19] Revista Mãe => Início da Execução
[18/01/2013 15:26:19] 		Revista Filha => Início da Execução
[18/01/2013 15:26:19] 				Revista Neta  => Início da Execução
[18/01/2013 15:26:19] 				Revista   => Executando
[18/01/2013 15:26:19] 				Revista   => Início execução 
[18/01/2013 15:26:19] 				Revista   => Valores 
                      					@.codigo = 4
                      					@.nome = Cupom Brinde
                      					@.tipoDeCupom = Vale 
[18/01/2013 15:26:19] 						Revista Bisneta  => Início da Execução
[18/01/2013 15:26:27] 								SUCESSO 
[18/01/2013 15:26:28] 								SUCESSO 
[18/01/2013 15:26:31] 								SUCESSO 
[18/01/2013 15:26:31] 								SUCESSO 
[18/01/2013 15:26:31] 								SUCESSO 
[18/01/2013 15:26:32] 								SUCESSO 
[18/01/2013 15:26:33] 								SUCESSO 
[18/01/2013 15:26:33] 						Revista Bisneta => Executado com SUCESSO
                      						Duração Total: 13s 948ms
[18/01/2013 15:26:33] 						Revista Bisneta => Início da Execução
[18/01/2013 15:26:33] 								SUCESSO 
[18/01/2013 15:26:33] 								SUCESSO 
[18/01/2013 15:26:36] 								SUCESSO 
[18/01/2013 15:26:37] 								SUCESSO 
[18/01/2013 15:26:38] 								ERRO 
[18/01/2013 15:26:38] 								SUCESSO 
[18/01/2013 15:26:38] 								SUCESSO 
[18/01/2013 15:26:38] 								SUCESSO 
[18/01/2013 15:26:38] 						Revista Bisneta => Executado com INSTABILDADE
                      						Duração Total: 5s 469ms
[18/01/2013 15:27:48] 				Revista Neta => Executado com FALHA 
                      				Duração Total: 1m 28s 954ms
[18/01/2013 15:27:48] 		Revista Filha => Executado com FALHA
                      		Duração Total: 1m 28s 955ms
[18/01/2013 15:27:48] Revista Mãe => Executado com FALHA
                      Duração Total: 1m 28s 963ms
De acordo com o que eu entendi que deve ser feito.. O programa deve extrair informações de execuções de revista. Buscando conjuntos assim:
[18/01/2013 15:26:19] Revista Mãe => Início da Execução
[18/01/2013 15:27:48] Revista Mãe => Executado com FALHA
                      Duração Total: 1m 28s 963ms
[18/01/2013 15:26:19] 						Revista Bisneta  => Início da Execução
[18/01/2013 15:26:33] 						Revista Bisneta => Executado com SUCESSO
                      						Duração Total: 13s 948ms
O que tem que ser extraído é o timestamp de início e fim. O tempo de duração e o status da execução. É necessario criar uma estrutura de árvore e armazenar as filhas dentro da mae. As netas dentro das filhas, etc. As estruturas de dados de Revista e Status são:
enum Status {
	SUCESSO,
	INSTABILDADE,
	FALHA,
	ERRO
}

class Revista {
	String inicio;
	String fim;
	Status status;
	String tipo;
	List<Revista> filhas = new ArrayList<Revista>();
	Revista parent = null;
	String duracao;
	
	@Override
	public String toString() {
		return toString("");
	}

	private String toString(String padding) {
		String value = "";
		if(this.parent == null){
			value = padding + "root\n";
		} else {
			value += String.format("%s + %s %s %s %s %s%n", padding, tipo.toUpperCase(), status, duracao, inicio, fim);
		}
		for (Revista filha : filhas) {
			value += filha.toString(padding+"   ");
		}
		return value;
	}
}
O main é bem pequeno:
public static void main(String[] args) throws IOException {
	Reader log = new FileReader("revista.txt");
	List<String> lines = readLines(log);
	Revista root = new Revista();
	readLevel(root, lines);
	System.out.println(root);
}

O que ele faz é..
1. Cria um reader para o arquivo
2. readLines: Lê as linhas do arquivo e salva em uma lista
3. Cria uma revista para ser o root (é uma revista que ficará no topo, para ser o node principal da árvore)
4. readLevel: Método recursivo que dada uma lista de linhas e uma revista. Le o conteúdo e preeche os dados (método principal do algoritmo)
5. Imprime o resultado

Método: readLevel (contém a lógica principal para resolver o problema)
private static void readLevel(Revista parent, List<String> lines) {
	if(lines.size() == 0){//acabou o arquivo
		return;
	}
	String firstLine = lines.get(0); //[18/01/2013 15:26:19] (...) => Início da Execução
	int level = getLevel(firstLine);//level basicamente é a identação da linha
	int lastLineIndex = getCloseNode(lines, level);//[18/01/2013 15:27:48] (...) => Executado com FALHA
	String lastLine = lines.get(lastLineIndex); 
	Status status = getStatus(lastLine); // FALHA, SUCESSO, etc
	String duracao = lines.get(lastLineIndex+1).substring(level); //Duração Total: 1m 28s 963ms
	String tipo = getTipo(firstLine); // Mãe, Filha, Neta Bisneta
	
	Revista revista = new Revista(); //configura a revista com os dados extraidos
	revista.parent = parent;
	revista.status = status;
	revista.duracao = duracao;
	revista.tipo = tipo;
	revista.inicio = firstLine.substring(0, 21);//[18/01/2013 15:27:48]
	revista.fim = lastLine.substring(0, 21);//[18/01/2013 15:27:48]
	
	parent.filhas.add(revista); //adiciona essa revista na revista parent
	
	readLevel(revista, lines.subList(1, lastLineIndex)); //le o interno dessa revista
	
	readLevel(parent, lines.subList(lastLineIndex+2, lines.size())); //le as revistas subsequentes (irmãs da variavel revista)
}
Outros métodos auxiliares que extraem as informações:
private static String getTipo(String line) {
	//[18/01/2013 15:26:19] Revista Mãe => Início da Execução
	//                              ^^^
	int close = line.indexOf(" =>");
	line = line.substring(0, close).trim();
	int begin = line.lastIndexOf(" ");
	return line.substring(begin);
}

private static Status getStatus(String statusLine) {
	//[18/01/2013 15:27:48] 		Revista Filha => Executado com FALHA
	return Status.valueOf(statusLine.substring(statusLine.trim().lastIndexOf(' ') + 1).trim());
}

/**
 * Retorna a próxima linha que fecha com o nível
 * Ex.:
 * [18/01/2013 15:26:19] Revista Mãe => Início da Execução
 * Para esse nível       ^
 * Retorna essa linha
 * [18/01/2013 15:27:48] Revista Mãe => Executado com FALHA
 *                       ^
 */
private static int getCloseNode(List<String> lines, int level) {
	for (int i = 1; i < lines.size(); i++) {
		if(getLevel(lines.get(i)) == level){
			return i;
		}
	}
	throw new RuntimeException("file inconsistent");
}

private static int getLevel(String line) {
	//[18/01/2013 15:26:19] 		Revista Filha => Início da Execução
	//retorna a posição do caracter 'R'
	int lineStart = line.indexOf(']') + 2;
	while(line.charAt(lineStart) == '\t'){
		lineStart++;
	}
	return lineStart;
}

static String[] ignore = {
	"(.*?)Revista   =>(.*?)", //[18/01/2013 15:26:19] 				Revista   => Início execução 
	"(.*?)@\\.(.*?)", //    @.codigo = 4
	"\\[(.*?)\\]\\s+[A-Z]+\\s?", //[18/01/2013 15:26:36] SUCESSO 
};

/**
 * Lê as linhas do arquivo ignorando as não desejadas
 */
public static List<String> readLines(Reader log) throws IOException {
	List<String> lines = new ArrayList<String>();
	//TODO CLOSE
	BufferedReader in = new BufferedReader(log);
	String linha = null;
	OUTER:
	while((linha = in.readLine()) != null){
		for (String pattern : ignore) {//ignora as linhas não desejadas
			if(linha.matches(pattern)){
				continue OUTER;
			}
		}
		lines.add(linha);
	}
	return lines;
}

O código é recursivo e genérico. Suporta quantos níveis forem de filhos e não importa o nome da Revista.

Saída do programa (no meu arquivo coloquei duas maes para testar melhor o algoritmo)
root
    +  MÃE FALHA Duração Total: 1m 28s 963ms [18/01/2013 15:26:19] [18/01/2013 15:27:48]
       +  FILHA FALHA Duração Total: 1m 28s 955ms [18/01/2013 15:26:19] [18/01/2013 15:27:48]
          +  NETA FALHA Duração Total: 1m 28s 954ms [18/01/2013 15:26:19] [18/01/2013 15:27:48]
             +  BISNETA SUCESSO Duração Total: 13s 948ms [18/01/2013 15:26:19] [18/01/2013 15:26:33]
             +  BISNETA INSTABILDADE Duração Total: 5s 469ms [18/01/2013 15:26:33] [18/01/2013 15:26:38]
    +  MÃE SUCESSO Duração Total: 1m 28s 963ms                       [19/01/2013 15:26:19] [19/01/2013 15:27:48]
       +  FILHA FALHA Duração Total: 1m 28s 955ms [19/01/2013 15:26:19] [19/01/2013 15:27:48]
          +  NETA FALHA Duração Total: 1m 28s 954ms [19/01/2013 15:26:19] [19/01/2013 15:27:48]
             +  BISNETA SUCESSO Duração Total: 13s 948ms [19/01/2013 15:26:19] [19/01/2013 15:26:33]
             +  BISNETA INSTABILDADE Duração Total: 5s 469ms [19/01/2013 15:26:33] [19/01/2013 15:26:38]
rogelgarcia

Última situação… agora que o cérebro está fervendo com tantas informações… um exemplo mais simples:

Como calcular a idade de uma data (quantos anos se passaram)

Para resolver essa questão propus o seguinte método (atualizado)

public static int getIdade(Date data){
		//burocracia
		Calendar hoje = Calendar.getInstance();
		Calendar nascimento = Calendar.getInstance();
		nascimento.setTime(data);

		//diferenca de anos
		int idade = hoje.get(Calendar.YEAR) - nascimento.get(Calendar.YEAR);
		//verificar aniversario
		nascimento.set(Calendar.YEAR, hoje.get(Calendar.YEAR));
		if(nascimento.get(Calendar.DAY_OF_YEAR) > hoje.get(Calendar.DAY_OF_YEAR)){
			//nao fez aniversario esse ano
			idade--;
		}
		return idade;
	}

Basicamente, o que esse algoritmo faz é verificar a diferença em anos de hoje até a data passada como parametro.
Depois ele pega a data passada como parametro, e passa para o ano atual. Teremos duas datas no mesmo ano.
Se não tiver passado o aniversário, temos que remover 1 da idade.
Matemática pura.

Agora, veja essa outra solução de outro site:

Calendar dob = Calendar.getInstance(); dob.setTime(dateOfBirth); Calendar today = Calendar.getInstance(); int age = today.get(Calendar.YEAR) - dob.get(Calendar.YEAR); if (today.get(Calendar.MONTH) < dob.get(Calendar.MONTH)) { age--; } else if (today.get(Calendar.MONTH) == dob.get(Calendar.MONTH) && today.get(Calendar.DAY_OF_MONTH) < dob.get(Calendar.DAY_OF_MONTH)) { age--; }
Fonte: http://stackoverflow.com/questions/1116123/how-do-i-calculate-someones-age-in-java

É desnecessário fazer tantos testes sendo que a matemática resolve…

A

EDITED.

A
rogelgarcia:
Apenas para completar o tópico.. O resultado do algoritmo que tem que ler o seguinte arquivo: ...
[18/01/2013 15:26:19] Revista Mãe => Início da Execução
[18/01/2013 15:26:19] 		Revista Filha => Início da Execução
[18/01/2013 15:26:19] 				Revista Neta  => Início da Execução
[18/01/2013 15:26:19] 				Revista   => Executando
[18/01/2013 15:26:19] 				Revista   => Início execução ...

Liked.

Luiz_Augusto_Prado

Olá pessoa! Desculpem-me pela demora.

Vou tentar mostar alguns erros que já passei aqui, mas antes vou postar um código:

Classe ICondicao:

package testeiforstrategy;


interface ICondicao<T>
{
    public boolean execute(T p); 
} 


class Parametros
{  
	String nome;
	int idade;
	int QtFilhos;
}  


class CondicaoA implements ICondicao<Parametros>
{  
    public boolean execute(Parametros p) 
	{
		if(p.idade<18)
		{
			System.out.println("O usuário \""+ p.nome +"\" é JOVEM");
			return true;
		}
        return false;
    }
}

class CondicaoB implements ICondicao<Parametros>
{  
    public boolean execute(Parametros p) 
	{  
		if(p.idade<55)
		{
			System.out.println("O usuário \""+ p.nome +"\" é ADULTO");
			return true;
		}
        return false;
    }  
}  

class CondicaoC implements ICondicao<Parametros>
{  
    public boolean execute(Parametros p) 
	{  
		if( p.idade<120 || p.QtFilhos>0)
		{
			System.out.println("O usuário \""+ p.nome +"\" é IDOSO ou já possui Filhos");
			return true;
		}
        return false;
    }  
}  

class CondicaoD implements ICondicao<Parametros>
{  
    public boolean execute(Parametros p) 
	{  
		System.out.println("O usuário \""+ p.nome +"\" é Muito Idoso ou já possui Filhos");
		return true; 
    }  
}

As classes TesteIfOrStrategy1 e TesteIfOrStrategy2 são a mesma coisa, mas

Classe de teste TesteIfOrStrategy1 aproxima-se mais do feito pelo rogelgarcia

package testeiforstrategy;

enum EnumCondicoes 
{
    A(new CondicaoA()), 
	B(new CondicaoB()), 
	C(new CondicaoC()), 
	D(new CondicaoD());
    ICondicao condicao;  
    EnumCondicoes(ICondicao condicao)
	{  
        this.condicao = condicao;  
    }
    public static <T> boolean isCondicao(T p) 
	{  
        for (EnumCondicoes c : values()) 
		{  
            if(c.condicao.execute(p))
			{  
                return true;  
            }  
        }   
		throw new RuntimeException("resultado inesperado");
    }  
}  

/**
 * @author Luiz A. Prado
 * sobre assunto discutino no link:
 * http://www.guj.com.br/java/291925-meu-codigo-tem-muito-if-meu-chefe-disse-que-ta-errado-e-verdade
 * 
 */
public class TesteIfOrStrategy1
{	
	/**
	 * @param args the command line arguments
	 */
	public static void main(String[] args)
	{
		Parametros p = new Parametros();
		p.nome = "Luiz";
		p.idade = 66;
		p.QtFilhos = 3;
		
		EnumCondicoes.isCondicao(p); 
	}
}

classe de teste TesteIfOrStrategy2 é o que prefiro utilizar

package testeiforstrategy;

import java.util.ArrayList;
import java.util.List;

class Seletor
{
	List condicoes; 	
	Seletor()
	{
		condicoes = new ArrayList<ICondicao>(); 
	}
	public void add(ICondicao c)
	{
		condicoes.add(c);
	}
    public <T> boolean isCondicao(T p) 
	{  
        for (Object c : condicoes) 
		{  
            if(((ICondicao)c).execute(p))
			{  
                return true;  
            }  
        }   
		throw new RuntimeException("resultado inesperado");
    } 
}  

/**
 * @author Luiz A. Prado
 * sobre assunto discutino no link:
 * http://www.guj.com.br/java/291925-meu-codigo-tem-muito-if-meu-chefe-disse-que-ta-errado-e-verdade
 * 
 */
public class TesteIfOrStrategy2
{
	/**
	 * @param args the command line arguments
	 */
	public static void main(String[] args)
	{
		Parametros p = new Parametros();
		p.nome = "Luiz";
		p.idade = 66;
		p.QtFilhos = 3;
		
		Seletor s = new Seletor();
		s.add(new CondicaoA());
		s.add(new CondicaoB());
		s.add(new CondicaoC());
		s.add(new CondicaoD());
		s.isCondicao(p); 
	}
}

Eu acredito que o uso de IFs ou Strategy não estão errados. É mais uma questão de gosto.
Mas se for para falar de erros, vou mostrar 2 exemplos que costumam me dar trabalho no Strategy:

  1. ORDEM: No arquivo TesteIfOrStrategy1 entre as linhas 4 e 9 e na TesteIfOrStrategy2 entre as linhas 47 e 53 são inseridos as condicionais. Se vc errar esta ordem ou esquecer de inserir uma das condições, o programa roda, mas com o funcionamento incorreto. E neste caso seria melhor que o programa parasse de funcionar quando dessemos pauladas.

  2. FRAGMENTACAO DA LOGICA: No arquivo ICondição eu reuní todas as classes (metodos) das condicionais, para facilitar a comparação das condicionais. Em uma empresa onde trabalhei isso não acontecia. Cada classe ficava em um arquivo separado. Isso não tem como acontecer quando utilizamos IFs seguidos. A análise era muito chata porque a condicional de uma dependia da outra. Olhe o codigo exemplo abaixo para entender o que quero dizer.
    Isso é só um exemplo. O mesmo problema poderia ocorrer com outros tipos de objetos ou combinando operadores:

if(i<10)
{
...
}
else if(i=10)
{
...
}
else if(i<10)
{
...
}

Se quisermos mudar de 10 para 20, teremos que ficar atentos em 3 condicionais. Quando as condicionais estão espalhadas em vários arquivos, estes erros ficam chatos de se controlar. Nesse ultimo caso, eu acharia mais fácil de analisar as condicionais em uma sequencia de ifs.

Hebert Coelho:
Luiz Augusto Prado:
Quero saber como vcs evitam os tipos de erros e gambiarras que eu vou mostrar.
Exemplo do que ocorreu em um momento com o rogelgarcia :

if(usuario.numeroFilhos <= 2) { iterator.remove(); }

TDD
[=

Se eu escrevesse um codigo de 300 ifs seguidos sem erros, o TDD acusaria a má esconha do pattern?

Hebert_Coelho

Luiz Augusto Prado:
Hebert Coelho:
Luiz Augusto Prado:
Quero saber como vcs evitam os tipos de erros e gambiarras que eu vou mostrar.
Exemplo do que ocorreu em um momento com o rogelgarcia :

if(usuario.numeroFilhos <= 2) { iterator.remove(); }

TDD
[=

Se eu escrevesse um codigo de 300 ifs seguidos sem erros, o TDD acusaria a má esconha do pattern?

Erro o JUnit apontaria, má pratica existem plugins para isso.

Luiz_Augusto_Prado

Quais os plugins que vc usa para evitar as más práticas?

Hebert_Coelho

Luiz Augusto Prado:
Hebert Coelho:

Erro o JUnit apontaria, má pratica existem plugins para isso.

Quais os plugins que vc usa para evitar as más práticas?

Atualmente uso o Intellij e ele faz essa análise.
Com o eclipse utilizava o findbug e o pmd.

wbdsjunior

Hebert Coelho:
Luiz Augusto Prado:
Hebert Coelho:

Erro o JUnit apontaria, má pratica existem plugins para isso.

Quais os plugins que vc usa para evitar as más práticas?

Atualmente uso o Intellij e ele faz essa análise.
Com o eclipse utilizava o findbug e o pmd.

Ainda para o Eclipse você tem o Checkstyle, o JDepend e o Metrics.

Criado 22 de janeiro de 2013
Ultima resposta 19 de fev. de 2013
Respostas 80
Participantes 27