Patrón Result, Manejo de Opcionales y Null Object
Tony Hoare, el creador de la referencia null en 1965, la denominó públicamente como su "error del billón de dólares" debido a la incontable cantidad de fallos, vulnerabilidades y horas de depuración que el temido NullPointerException (o undefined is not a function) ha causado en la industria.
En el diseño de software moderno, el código limpio trata la ausencia de valores y los errores de negocio de forma explícita y tipada.
1. El Patrón Null Object (Objeto Nulo) #
En lugar de devolver null cuando no se encuentra una entidad y obligar a todos los llamadores a realizar comprobaciones if (usuario != null), se devuelve una instancia especial que implementa la misma interfaz con un comportamiento neutro o inocuo.
1interface Logger { 2 log(mensaje: string): void; 3} 4 5class ConsoleLogger implements Logger { 6 log(mensaje: string): void { 7 console.log(`[LOG]: ${mensaje}`); 8 } 9} 10 11// ✅ Null Object: no hace nada, pero evita evaluar if (logger !== null) 12class NullLogger implements Logger { 13 log(mensaje: string): void { 14 // Intencionalmente vacío 15 } 16} 17 18class ServicioPago { 19 constructor(private logger: Logger = new NullLogger()) {} 20 21 procesar() { 22 this.logger.log("Procesando pago..."); // Seguro, nunca lanzará TypeError 23 } 24}
2. El Tipo Optional<T> #
Hacer que una función devuelva Optional<Usuario> en lugar de Usuario comunica explícitamente en el contrato de la firma que el valor puede no existir, obligando al compilador a verificar su presencia.
1// ❌ MAL: Puede devolver null y causar sorpresas en producción 2public Usuario buscarPorEmail(String email) { ... } 3 4// ✅ BIEN: La firma avisa explícitamente de la opcionalidad 5public Optional<Usuario> buscarPorEmail(String email) { 6 if (existeEnBD(email)) { 7 return Optional.of(obtenerDeBD(email)); 8 } 9 return Optional.empty(); 10} 11 12// Uso funcional fluido: 13buscarPorEmail("admin@empresa.com") 14 .map(Usuario::getNombre) 15 .ifPresent(System.out::println);
3. El Patrón Result / Either: Errores de Negocio vs Excepciones #
Lanzar excepciones (throw new Exception(...)) para controlar flujos habituales de negocio (como "usuario ya registrado" o "saldo insuficiente") es costoso en rendimiento (captura de stack trace) y rompe la predictibilidad del código.
El Patrón Result encapsula el resultado en un tipo contenedor con dos posibles estados: Ok(valor) o Err(fallo).
Resumen del tema
Conceptos clave #
- Null Object Pattern: sustituye
nullpor una clase polimórfica que ofrece un comportamiento por defecto seguro. Optional<T>: hace que la ausencia de datos sea parte del sistema de tipos estático, evitando comprobaciones manuales redundantes.- Result / Either: maneja errores de validación y negocio esperados sin lanzar excepciones, reservando los bloques
throwpara errores irrecuperables del sistema (pérdida de red, base de datos caída).
Qué debes recordar #
No devuelvas null en tus métodos ni aceptes null como argumento si puedes evitarlo. Usa tipos Optional o el patrón Result para que tus contratos sean transparentes y seguros.