Sugestao de melhoria do codigo

Ola pessoal tudo bem? Sei que voces tem o tempo curto, mas gostaria de pedir, se possivel que me apontem uma forma de melhorar esse codigo… estou bem no comeco entao =]

Enunciado:

Faça um programa que leia e valide as seguintes informações:

  • Nome: maior que 3 caracteres;
  • Idade: entre 0 e 150;
  • Salário: maior que zero;
  • Sexo: ‘f’ ou ‘m’;
  • Estado Civil: ‘s’, ‘c’, ‘v’, ‘d’;
public static void main(String[] args) {
  String nome;
  int idade;
  double salario;
  String sexo;
  String estadoCivil;
  
  Scanner scan = new Scanner(System.in);
  
  while (true) {
    System.out.println("Entre com seu nome ");
    nome = scan.next();
    
    if (nome.length() < 3) {
      System.out.println("Entre com minimo de 3 caracteres: ");
    } else {
      break;
    }
  }
  
  while (true) {
    System.out.println("Entre com sua idade ");
    idade = scan.nextInt();
    
    if (idade >= 0 && idade <= 150) {
      break;
    } else {
      System.out.println("Entre com valores entre 0 e 150: ");
    }
  }

  while (true) {
    System.out.println("Entre com seu salario ");
    salario = scan.nextDouble();

    if (salario > 0) {
      break;
    } else {
      System.out.println("Entre com valores acima de 0: ");
    }
  }

  while (true) {
    System.out.println("Entre com seu genero/sexo ");
    sexo = scan.next();
    sexo.toLowerCase();

    if (sexo.equals("f") || sexo.equals("m")) {
      break;
    } else {
      System.out.println("Entre com valores validos como f ou m: ");
    }
  }

  while (true) {
    System.out.println("Entre com seu Estado Civil ");
    estadoCivil = scan.next();
    estadoCivil.toLowerCase();

    if (estadoCivil.equals("s") || estadoCivil.equals("c") || estadoCivil.equals("v") || estadoCivil.equals("d")) {
      break;
    } else {
      System.out.println("Entre com valores validos como s, c, v, d: ");
    }
  }
}

Muito Obrigado

O código não está ruim. Como você pensou que ele poderia ser “melhorado”?

1 curtida

Eu não implementaria tudo dentro do método main.
Aqueles while eu colocaria dentro de um método para fazer a leitura de alguma coisa.

1 curtida

Poderia ser algo assim (resolvi postar apenas para apresentar outra forma de fazer):

public static void main(String[] args) {
  try (Scanner scanner = new Scanner(System.in)) {
    String nome = lerNome(scanner);
  }
}

public static String lerNome(Scanner scanner) {
  System.out.println("Entre com seu nome: ");
  String nome = scanner.next();
  
  if (nome.length() < 3) {
    System.out.println("Entre com minimo de 3 caracteres!");
    return lerNome(scanner);
  }
  
  return nome;
}

Obs.: Só talvez não seja uma boa usar recursão para ler o dado caso um valor inválido seja informado, mas como o programa é pequeno não acho que seja um grande problema assim.

1 curtida

Fefo80 - Eu achei que tem muitos whiles… claro, que como pedira enunciado acabei fazendo assim… Ainda estou no comeca do aprendizado… Derrepente criaria alguma classe para validar e nao ficar tudo dentro de um lugar só como foi sugerido. Vamos seguindo no aprendizado que a lista de exercicios ainda é grande ahahha.

@staroski Verdade… .tudo dentro do main nao ficaria legal… nao me atentei a isso… obrigado =]

@Lucas_Camara Muito obrigado pela sugestao… vou estudar a respeito

Para ler entradas do teclado, ainda mais nos casos em que você mistura leitura de números e strings, é melhor usar nextLine.

Por exemplo, se começarmos digitando o nome “Fulano de Tal”, next() só irá ler “Fulano”, e ao chamar nextInt() depois, ele irá ler “de” e tentar converter para número, e dará erro. Enfim, tem várias outras situações que podem dar problema, prefira usar somente nextLine e depois converter a linha para o tipo que precisa (inteiro, double, etc).

Tem também isso:

sexo.toLowerCase();

Em Java strings são imutáveis, então métodos como toLowerCase() não modificam a string. Na verdade eles retornam outra string, então a linha acima só chama o método, mas o retorno é perdido. O certo seria jogar em uma variável (podendo ser inclusive a mesma):

sexo = sexo.toLowerCase();

Ou ainda:

sexo = scan.nextLine().toLowerCase();

E também dá pra remover algumas repetições criando métodos, como por exemplo:

public static String lerString(Scanner scan, String prompt, List<String> valoresValidos) {
    while (true) {
        System.out.println(prompt);
        String valor = scan.nextLine().toLowerCase();
        if (valoresValidos.contains(valor)) {
            return valor;
        } else {
            System.out.println("Valores válidos: " + String.join(", ", valoresValidos));
        }
    }
}

Aí no main bastaria fazer:

String sexo = lerString(scan, "Entre com seu genero/sexo ", Arrays.asList("m", "f"));
String estadoCivil = lerString(scan, "Entre com seu Estado Civil", Arrays.asList("s", "c", "v", "d"));

Para os demais, não sei se compensa fazer algo mais complicado e generalizado. Talvez seja exagero para um exercício, mas enfim, daria para ter algo assim (obs: o código abaixo usa recursos que só funcionam a partir do Java 8):

// imports
import java.util.Arrays;
import java.util.List;
import java.util.Scanner;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;

//-----------------------------------------------------
// versão que recebe um validador
public static <T> T lerDados(Scanner scan, String prompt, Function<String, T> conversor, Predicate<T> validador, String mensagemErro) {
    // passa o validador, e a lista de valores válidos é nula
    return lerDados(scan, prompt, conversor, validador, null, mensagemErro);
}

// versão que recebe a lista de valores válidos
public static <T> T lerDados(Scanner scan, String prompt, Function<String, T> conversor, List<T> valoresValidos) {
    // não tem validador, então usa a lista de valores válidos (e a mensagem de erro será construída a partir dos valores válidos)
    return lerDados(scan, prompt, conversor, null, valoresValidos, "");
}

private static <T> T lerDados(Scanner scan, String prompt, Function<String, T> conversor, Predicate<T> validador,
        List<T> valoresValidos, String mensagemErro) {
    while (true) {
        // mostra a mensagem
        System.out.println(prompt);
        // lê os dados
        String line = scan.nextLine().toLowerCase();
        try {
            // converte para o tipo desejado
            T valor = conversor.apply(line);
            // verifica se é válido
            if (validador != null) { // se tem validador, usa
                if (validador.test(valor)) {
                    return valor; // válido, retorna
                } else {
                    System.out.println(mensagemErro);
                }
            } else if (valoresValidos != null && valoresValidos.size() > 0) {
                // se tem valores válidos, verifica se é um deles
                if (valoresValidos.contains(valor)) {
                    return valor;
                } else {
                    System.out.println("Valores válidos: " + String.join(", ", valoresValidos.stream().map(v -> v.toString()).collect(Collectors.toList())));
                }
            } else {
                // se não tem validador e nem lista de valores válidos, não tem o que validar
                // então assume-se que o valor é válido
                return valor;
            }
        } catch (Exception e) {
            System.out.println(mensagemErro);
        }
    }
}

E no main ficaria:

Scanner scan = new Scanner(System.in);

String nome = lerDados(scan, "Entre com seu nome", Function.identity(), s -> s.length() >= 3, "Entre com mínimo de 3 caracteres");
int idade = lerDados(scan, "Entre com sua idade", Integer::parseInt, n -> n >= 0 && n <= 150, "Entre com valores entre 0 e 150");
double salario = lerDados(scan, "Entre com seu salario ", Double::parseDouble, n -> n > 0, "Entre com valores acima de 0: ");

String sexo = lerDados(scan, "Entre com seu genero/sexo ", Function.identity(), Arrays.asList("m", "f"));
String estadoCivil = lerDados(scan, "Entre com seu Estado Civil", Function.identity(), Arrays.asList("s", "c", "v", "d"));

Mas novamente: pra um exercício simples, provavelmente é exagero…


Outro detalhe é que não precisa fechar o System.in. Pra programas simples assim não faz diferença, mas enfim…

1 curtida

Muito obrigado pelas dicas… vou estudar e refatorar o codigo aqui… valeu