Resumen

Proteger los datos que entran a tu sistema es una de las decisiones más importantes en programación orientada a objetos. Cuando las propiedades de una clase aceptan cualquier valor sin restricción, los bugs aparecen en los lugares menos esperados. Aquí se explica cómo aplicar guard clauses, el principio fail fast y el patrón Factory para blindar la clase Producto en C#.

¿Por qué las propiedades públicas sin validación son un riesgo?

Cuando las variables de una clase son completamente públicas, cualquier parte del código puede asignarles valores absurdos: un precio negativo, una cantidad de texto donde se espera un número o un nombre vacío. El resultado es un sistema frágil que se rompe en tiempo de ejecución.

La solución consiste en tres cambios principales [0:42]:

  • Convertir los campos a privados.
  • Agregar setters con guard clauses para precio y cantidad.
  • Eliminar código que no se utiliza, como la propiedad descripcion y el override de ToString.

Eliminar código innecesario forma parte de lo que se conoce como refactorización: mejorar la estructura del código sin cambiar su comportamiento observable. Si una propiedad no se usa, quitarla reduce ruido y facilita el mantenimiento.

¿Qué es un guard clause y cómo implementa fail fast?

Un guard clause es una validación que se coloca al inicio de un método o setter [1:12]. Su propósito es rechazar datos inválidos de inmediato, antes de que el resto de la lógica se ejecute. Si la condición no se cumple, se lanza una excepción y el flujo se detiene.

Esto responde al principio fail fast (falla temprano, falla claro): los datos inválidos jamás deben penetrar en el sistema. Cuando otros métodos consumen precio, pueden confiar en que siempre contiene un valor válido.

¿Cuál es la diferencia entre validar antes y validar después?

Consideremos un método ProcesarPago [1:30]. Si primero ejecutas cien líneas de lógica de negocio y luego validas, habrás desperdiciado procesamiento ante un dato erróneo. En cambio, si colocas el guard clause al inicio, el método se detiene antes de hacer cualquier trabajo innecesario.

La estrategia correcta es rechazar datos inválidos inmediatamente. Aceptarlos y validar después genera bugs difíciles de rastrear; no validar nada es todavía peor.

¿Cómo se aplican los guard clauses en la clase Producto?

La implementación convierte los campos en privados usando el prefijo de guion bajo (_nombre, _precio, _cantidad) [2:35]. Cada propiedad expone un get que retorna el campo privado y un set que ejecuta la validación antes de asignar el valor:

  • _nombre se inicializa con un valor vacío para evitar errores de nulo.
  • _precio valida que el valor sea positivo.
  • _cantidad valida que sea un entero coherente.

Si algún valor no cumple la condición, el setter lanza una excepción y la asignación nunca ocurre.

¿Qué es el patrón Factory y por qué centralizar la creación de objetos?

El patrón Factory agrupa en un solo lugar la lógica de construcción, validación y generación de identificadores [3:10]. En este caso se crea la clase ProductFactory dentro de la carpeta SRC/Factories.

ProductFactory es una clase estática: no se puede instanciar. Contiene una variable estática nextId inicializada en uno que genera IDs secuenciales automáticamente.

Su método principal es Crear, que recibe nombre, precio, cantidad y una categoría (con valor por defecto Otros) [3:40]. Internamente aplica guard clauses para cada parámetro y retorna una nueva instancia de Producto con el ID incrementado.

También existe CrearConStock, otro método estático que valida adicionalmente que la cantidad sea mayor a cero antes de delegar en Crear [4:15]. Esto muestra cómo se pueden componer métodos Factory para cubrir distintos escenarios de negocio.

El orden correcto dentro de un guard clause es [4:35]:

  • Validar la condición.
  • Lanzar la excepción si falla.
  • Asignar el valor si pasa.

Este flujo garantiza que solo datos correctos lleguen al objeto. Aplicar guard clauses junto con campos privados, setters protegidos y el patrón Factory convierte una clase vulnerable en una estructura robusta y predecible. ¿Qué otras validaciones agregarías a tu clase Producto?