Sugestao de melhoria do codigo

6 respostas
S

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

6 Respostas

Fefo80

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

staroski

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.

Lucas_Camara

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.

S

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

hugokotsubo

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…

S

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

Criado 13 de novembro de 2021
Ultima resposta 16 de nov. de 2021
Respostas 6
Participantes 5