Skip to content

Por qué validar y por qué proteger invariantes ​

Índice · Siguiente: entradas y valores

Una aplicación recibe propuestas de cambio. El usuario puede escribir datos incompletos, un cliente de API puede enviar fechas invertidas y una operación puede llegar cuando el estado ya no permite ejecutarla. Validar permite responder qué condición se incumple antes de continuar. La pregunta importante es qué estamos validando: un dato, un estado, una acción o una relación con datos externos.

Un ejemplo que separa las responsabilidades ​

Una reserva tiene fecha de entrada, fecha de salida y un indicador de cierre.

SituaciónProblemaResponsabilidad
La entrada contiene una fecha que no se puede interpretarNo se puede construir el candidatoLectura y conversión de entrada
La salida es anterior a la entradaEl estado contradice el significado de reservaInvariante local
Las fechas son correctas, pero la reserva está cerradaLa acción no está permitidaPolítica de operación
Las fechas son correctas, pero otra reserva ocupa el recursoEl estado externo impide confirmarValidación contextual
Otra operación ocupa el recurso después de consultarLa comprobación previa quedó desactualizadaGarantía transaccional del almacenamiento

Una reserva cerrada no es inválida. Es un estado válido que restringe acciones. Esta diferencia evita introducir la condición !Closed como invariante: hacerlo impediría cerrar cualquier reserva.

Por qué la validación de entrada no basta ​

Validar un formulario ofrece una respuesta temprana y permite mostrar varios errores. Sin embargo, el mismo dominio puede ser utilizado por una importación, un proceso en segundo plano u otra API. Si la relación entre fechas solo vive en la pantalla, otro punto de entrada puede romperla.

La entidad protege el estado con invariantes antes de publicarlo. La validación de entrada y la invariante pueden reutilizar el mismo plan, pero actúan en momentos distintos y devuelven resultados a consumidores distintos.

Por qué un candidato separado ​

Modificar primero la entidad y validar después obliga a restaurar cambios si algo falla. Un candidato inmutable permite comprobar el cambio completo antes de reemplazar el estado actual.

text
Estado actual válido
       ↓ construir candidato
Propuesta de nuevas fechas
       ↓ comprobar invariantes
   ┌── falla ──→ devolver error; conservar estado actual
   └── cumple → publicar candidato como nuevo estado

No necesitas copiar el objeto entero manualmente: un record con componentes inmutables permite construir el candidato con with. Una lista mutable dentro de un record sigue siendo mutable; la garantía requiere que todos los componentes respeten la inmutabilidad.

Por qué reglas, composición y plan ​

Una regla comprueba una condición. La composición indica cómo se relaciona con otras. El plan reúne esa composición y los diagnósticos para repetir la evaluación con candidatos distintos.

Por ejemplo, para comprobar un correo disponible, primero debe aceptarse su contenido y después consultarse el repositorio. Una Sequence expresa esa dependencia. Otros campos independientes pueden seguir acumulando errores.

La plataforma ofrece el motor y el reporte. El dominio adapta los incumplimientos a errores de entidad, modelo o negocio. El usuario de una pantalla puede recibir mensajes por campo; la entidad utiliza los mismos resultados para decidir si publica el estado.

Qué pieza mínima usar ​

Una condición booleana aislada puede resolverse con una regla o un predicado. Usa un plan cuando existan composición, rutas o mensajes. Usa invariantes para proteger estados de entidades. Usa políticas de negocio para autorizar acciones. Usa contexto cuando la respuesta dependa de información externa a ese estado.

No necesitas introducir una entidad para validar un texto, ni una sesión de formulario para procesar una petición única. Las sesiones de plataforma resuelven la coordinación temporal de varias ediciones, no las invariantes del dominio.

Continúa con entradas y objetos de valor para ver cómo una misma política evita que la UI acepte algo que la fábrica rechace.

Uso personal limitado. Uso comercial sujeto a autorización escrita.