Refactorización 2: eliminar while repetitivos

🔁 Refactorización 2: eliminar patrones repetitivos

En esta parte vamos a eliminar estos patrones repetitivos en el código.

Vamos a quitar estos loops while repetidos, moverlos a un método diferente llamado:

leerNumeros(...)

y luego reutilizar ese método 3 veces, cada vez que leemos un valor diferente.

🧩 Patrón repetitivo: copiar una línea completa de while

PRIMERO: copiamos TODO el bloque del while (desde la calculadora original).

while (true){
    System.out.println(prompt);
    value = scanner.nextFloat();
    if (value >= min && value <= max)
        break;
    System.out.println("Ingrese un valor entre " + min + "y" + max);
}

📌 Este patrón aparece una y otra vez: preguntar → leer → validar → error → repetir.

🧱 Crear el método nuevo

Ahora creamos este método:

public static double leerNumeros(String prompt, double min, double max) {

}

Todavía no te preocupes por el contenido, ya lo llenamos con el while.

😵 La parte difícil: en cada while leemos un tipo diferente

Ahora aquí viene la parte difícil:

  • en un loop leemos un float
  • en otro leemos un byte
  • en otro leemos un int

¿Qué hacemos?

❌ Opción mala: hacer 3 métodos:

  • leerByte
  • leerFloat
  • leerInt

Eso termina en 3 métodos casi idénticos… solo cambia una línea, y no es buena refactorización.

✅ Mejor opción: un solo método que devuelva double.

Luego en main hacemos casting al tipo que necesitemos.

🧠 Copiar el while dentro del método

Copiamos el código dentro del método y empezamos a parametrizarlo.

public static double leerNumeros(String prompt, double min, double max) {
    Scanner scanner = new Scanner(System.in);
    double value;

    while (true){
        System.out.println(prompt);
        value = scanner.nextFloat();
        if (value >= min && value <= max)
            break;
        System.out.println("Ingrese un valor entre " + min + "y" + max);
    }

    return value;
}

✅ Parámetro 1: el prompt (texto de entrada)

El primer parámetro que necesitamos es la pregunta, el prompt.

📌 Texto de entrada que el usuario da al sistema: prompt

Entonces en vez de hardcodearlo, lo pasamos como parámetro:

public static double leerNumeros(String prompt, double min, double max) {
    // ...
    while (true){
        System.out.println(prompt);
        // ...
    }
}

✅ Parámetros 2 y 3: min y max

También quitamos números “quemados” como 1, 30, etc.

Los pasamos como parámetros:

  • double min
  • double max

y reemplazamos todo:

if (value >= min && value <= max)
    break;
System.out.println("Ingrese un valor entre " + min + "y" + max);

Ahora el mensaje de error también es genérico.

✅ Retornar el valor leído

Finalmente devolvemos value:

public static double leerNumeros(String prompt, double min, double max) {
    // ...
    return value;
}

Ahora toda la lógica de: leer + validar está en un solo lugar.

♻️ Reutilizar el método 3 veces en main

Ahora podemos borrar los while repetidos y hacer esto:

public static void main(String[] args) {

    int principal = (int) leerNumeros("Principal", 1000, 1_000_000);
    float InteresAnual= (float) leerNumeros("Tasa interés", 1, 30);
    byte anos = (byte) leerNumeros("Años: ", 1, 30); // casting

    double hipo = calcularHipo(principal, InteresAnual, anos);
}

📌 leerNumeros(...) devuelve double, y nosotros hacemos casting al tipo que necesitamos.

🧾 Programa completo (versión 1)

import java.text.NumberFormat;
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {

        int principal = (int) leerNumeros("Principal", 1000, 1_000_000);
        float InteresAnual = (float) leerNumeros("Tasa interés", 1, 30);
        byte anos = (byte) leerNumeros("Años: ", 1, 30); // casting

        double hipo = calcularHipo(principal, InteresAnual, anos);

        String hipotecaFormat = NumberFormat.getCurrencyInstance().format(hipo);
        System.out.println("Hipoteca: " + hipotecaFormat);
    }

    public static double leerNumeros(String prompt, double min, double max) {
        Scanner scanner = new Scanner(System.in);
        double value;

        while (true){
            System.out.println(prompt);
            value = scanner.nextFloat();
            if (value >= min && value <= max)
                break;
            System.out.println("Ingrese un valor entre " + min + "y" + max);
        }

        return value;
    }

    public static double calcularHipo(int principal,
                                      float InteresAnual,
                                      byte anos) {

        final byte meses = 12;
        final byte porcentaje = 100;
        float numeroPagos = anos * meses;
        float mesInteres = InteresAnual / porcentaje / meses;

        double hipo = principal
                *(mesInteres * Math.pow(1 + mesInteres, numeroPagos))
                /(Math.pow(1 + mesInteres, numeroPagos) - 1);

        return hipo;
    }
}

🔧 Pequeño ajuste

PEQUEÑO AJUSTE:

En el método calcularHipo, cambiamos el tipo de numeroPagos a short:

short numeroPagos = (short) (anos * meses);

📌 Ya veremos por qué…

🧾 Programa completo (versión final)

import java.text.NumberFormat;
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        int principal = (int) leerNumeros("Principal", 1000, 1_000_000);
        float InteresAnual = (float) leerNumeros("Tasa interés", 1, 30);
        byte anos = (byte) leerNumeros("Años: ", 1, 30); // casting

        double hipo = calcularHipo(principal, InteresAnual, anos);

        String hipotecaFormat = NumberFormat.getCurrencyInstance().format(hipo);
        System.out.println("Hipoteca: " + hipotecaFormat);
    }

    public static double leerNumeros(String prompt, double min, double max) {
        Scanner scanner = new Scanner(System.in);
        double value;

        while (true){
            System.out.println(prompt);
            value = scanner.nextFloat();
            if (value >= min && value <= max)
                break;
            System.out.println("Ingrese un valor entre " + min + "y" + max);
        }

        return value;
    }

    public static double calcularHipo(int principal,
                                      float InteresAnual,
                                      byte anos) {
        final byte meses = 12;
        final byte porcentaje = 100;
        short numeroPagos = (short) (anos * meses);
        float mesInteres = InteresAnual / porcentaje / meses;

        double hipo = principal
                *(mesInteres * Math.pow(1 + mesInteres, numeroPagos))
                /(Math.pow(1 + mesInteres, numeroPagos) - 1);

        return hipo;
    }
}