= ]
=]
Estou tentando fazer com que ele entenda o problema.
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…
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.
[quote=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.[/quote]Sério? Qual?
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.
[quote=Hebert Coelho][quote=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.[/quote]Sério? Qual?[/quote]
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.
[quote=Luiz Augusto Prado][quote=Hebert Coelho][quote=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.[/quote]Sério? Qual?[/quote]
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.[/quote]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.
[quote]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. [/quote]
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
}
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…
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.
[quote=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… :)[/quote]
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.
Após uma refatoração… o novo exemplo (caso alguém queira dar uma analisada)
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;
}
}
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
[code] public static void main(String[] args) {
Map<EtapaDaVida, List> grupos = new HashMap<EtapaDaVida, List>();
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();
}
}
}[/code]
[quote=rogelgarcia]Condição: dadosDoUsuario.idade >= 55 && dadosDoUsuario.idade<120 || dadosDoUsuario.numeroFilhos>2
[code] public static void main(String[] args) {
Map<EtapaDaVida, List> grupos = new HashMap<EtapaDaVida, List>();
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();
}
}
}[/code][/quote]
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.
[quote=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. [/quote]na boa? Ainda prefiro assim do que aninhar 300 ifs.
Desculpe, mas ainda assim penso que não existe motivo para 17 ifs seguidos…
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>();
}
}
[quote=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.[/quote]
mais se eu usar metodos nao vou ter que por ainda ifs?? ? exemplo
[code]validaNotaFiscal {
if(“mae”){
validaDadosBasicos
validaRemetente
}
if (“filha”){
validaDestinatario
}
if(“neta”){
validaItensDaNota
}
if(“bisneta”){
validaTransportadora
validaInformaçõesComplementares}
}[/code]
acho que isso e uma arvore, me falaram no ultimo post que abri.
[quote=Luiz Augusto Prado][quote=rogelgarcia]Condição: dadosDoUsuario.idade >= 55 && dadosDoUsuario.idade<120 || dadosDoUsuario.numeroFilhos>2
[code] public static void main(String[] args) {
Map<EtapaDaVida, List> grupos = new HashMap<EtapaDaVida, List>();
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();
}
}
}[/code][/quote]
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.
[/quote]
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.
meu codigo e esse aqui
[code]@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;
} [/code]