El Usuario Inesperado
Hasta ahora, hemos asumido que el usuario siempre interactuará con nuestra aplicación de la manera correcta. Pero en el mundo real, los usuarios cometen errores: dejan campos vacíos, ingresan texto donde se esperan números, o seleccionan combinaciones de filtros que no devuelven ningún dato. Una aplicación profesional no debe "romperse" en estos casos.
Un error críptico en rojo es una de las peores experiencias de usuario. Nuestro objetivo MLOps es crear productos de datos confiables y robustos. Esto implica anticipar posibles fallos y, en lugar de mostrar un error, guiar al usuario con un mensaje claro y útil. Aquí es donde entra en juego la validación de entradas.
SIN Validación
La app se rompe y muestra un error técnico incomprensible.
CON Validación
La app muestra un mensaje útil que guía al usuario.
La Herramienta: validate() y need()
                Shiny nos proporciona una forma elegante de manejar estas situaciones con la función validate() en combinación con need(). Funcionan de la siguiente manera:
validate(need(condición, "mensaje"))
                        Este es el patrón que usarás dentro de cualquier función render... (como renderPlot, renderText, etc.).
- need(condición, "mensaje"): Esta función comprueba una- condición. Si la condición es- FALSE(es decir, algo está mal), detiene la ejecución y devuelve el- "mensaje". Si la condición es- TRUE, no hace nada y el código continúa.
- validate(...): Es el contenedor. Si- need()devuelve un mensaje de error,- validate()se encarga de mostrarlo en el lugar del output de una forma elegante y amigable, en lugar de romper la aplicación.
Puedes encadenar múltiples `need()` dentro de un `validate()` para comprobar varias condiciones a la vez.
Guía Práctica: Blindando Nuestro Simulador
Vamos a aplicar estas técnicas para hacer que nuestro simulador de puntajes sea a prueba de errores del usuario.
Paso 1: Identificar los Puntos de Falla
En nuestro simulador, el usuario podría:
- Dejar un campo vacío (lo que R interpreta como NA).
- Ingresar un valor que no es un número (ej. "abc").
- Ingresar un número fuera del rango válido (ej. -10 o 150).
Cualquiera de estos casos haría que la función predict() falle. Nuestro objetivo es atraparlos antes.
Paso 2: Implementar la Validación en el Server
La validación debe ocurrir justo antes de que se intente hacer el cálculo principal. Por lo tanto, el lugar perfecto es dentro de nuestro eventReactive que calcula la predicción.
Acción: Modifica el conductor reactivo `puntaje_predicho` en tu archivo `server.R`.
# En server.R
puntaje_predicho <- eventReactive(input$run_prediction, {
    
    # --- INICIO DE LA VALIDACIÓN ---
    validate(
      # Condición 1: Asegurarse de que el input de lectura no esté vacío y sea un número
      need(input$sim_lectura, "Por favor, ingrese un valor para Lectura Crítica."),
      need(is.numeric(input$sim_lectura), "El valor de Lectura Crítica debe ser un número."),
      
      # Condición 2: Asegurarse de que el input de sociales no esté vacío y sea un número
      need(input$sim_sociales, "Por favor, ingrese un valor para Sociales."),
      need(is.numeric(input$sim_sociales), "El valor de Sociales debe ser un número."),
      # Condición 3: Asegurarse de que el input de ciencias no esté vacío y sea un número
      need(input$sim_ciencias, "Por favor, ingrese un valor para Ciencias Naturales."),
      need(is.numeric(input$sim_ciencias), "El valor de Ciencias Naturales debe ser un número.")
    )
    # Condición 4: Validar que los números estén en el rango correcto (0-100)
    validate(
      need(input$sim_lectura >= 0 && input$sim_lectura <= 100, "El puntaje de Lectura debe estar entre 0 y 100."),
      need(input$sim_sociales >= 0 && input$sim_sociales <= 100, "El puntaje de Sociales debe estar entre 0 y 100."),
      need(input$sim_ciencias >= 0 && input$sim_ciencias <= 100, "El puntaje de Ciencias debe estar entre 0 y 100.")
    )
    # --- FIN DE LA VALIDACIÓN ---
    # El código de predicción solo se ejecutará si todas las validaciones pasan
    nuevos_datos <- data.frame(
        punt_lectura_critica = input$sim_lectura,
        punt_sociales_ciudadanas = input$sim_sociales,
        punt_ciencias_naturales = input$sim_ciencias
    )
    
    prediccion <- predict(modelo_matematicas, newdata = nuevos_datos)
    
    return(round(prediccion))
})
¡Y eso es todo! Vuelve a ejecutar tu aplicación e intenta ingresar valores incorrectos. Verás cómo ahora, en lugar de un error, aparecen mensajes amigables que guían al usuario.
Paso 3: Versionar la Mejora de Robustez
Hacer una aplicación más robusta es una mejora funcional muy importante. Es un cambio que añade valor directo al producto de datos y debe ser registrado como tal.
# Solo hemos modificado el server.R
git add server.R
# Un commit que describe la mejora en la experiencia de usuario
git commit -m "feat(simulator): Añade validación de entradas para una experiencia de usuario robusta"
git push