Llevo años manteniendo plataformas para negocios familiares con un stack sin frameworks pesados: Java/JAX-RS + MongoDB en el backend, JavaScript ES6 vainilla + Bootstrap en el frontend. Nada de Spring Boot, nada de React. Y aun así, agregar una entidad nueva al sistema me toma minutos, no horas.
Hace poco alguien me preguntó si el método que uso es "estándar" o si me lo inventé. La respuesta es un poco de ambos, y creo que vale la pena documentarlo porque es más simple de lo que parece.
El problema: CRUD repetido es deuda técnica silenciosa
Cuando un sistema crece, cada entidad nueva (clientes, facturas, comisiones, reservas...) tarda en traer su propio DAO, su propio DTO, su propio formulario, su propia validación, su propia tabla en el frontend. Si copias y pegas el código anterior y ajustas campos, en seis meses tienes seis variantes ligeramente distintas del mismo problema.
La solución: el schema es la fuente de verdad
En vez de escribir cada capa a mano por entidad, defino un schema una sola vez y dejo que todo lo demás se derive de él.
Backend: un DAO genérico
public class GenericsDAO<T> {
// CRUD parametrizado por tipo/colección
// Todas las entidades pasan por aquí salvo lógica muy específica
}
Cada endpoint nuevo en ZephyrResource es, en esencia, una llamada ajustada a este procedimiento general. No reescribo persistencia por entidad; la ajusto.
Frontend: estructura fija, comportamiento derivado del schema
js/
├── main.js # Entry point, event handlers, table rendering
├── api.js # CRUD contra la API
├── config.js # CONFIG global
├── schemas.js # ENTITY_CONFIG: la definición de cada entidad
├── form.js # Genera formularios A PARTIR del schema
├── validator.js # Valida A PARTIR del schema
├── utils.js
├── data.js
└── domElements.js
css/styles.css # Estilos generalizados: mismos botones CRUD para todas las entidades
Cuando necesito una entidad nueva, no escribo un formulario ni un validador desde cero: anexo su definición a ENTITY_CONFIG siguiendo la plantilla, y el resto del sistema (formulario, validación, tabla, exportación CSV) ya sabe cómo tratarla.
¿Me lo inventé? No del todo
Investigando un poco confirmé que esto tiene nombre y antecedentes:
- Generic DAO Pattern: documentado desde hace más de 20 años en Core J2EE Patterns. Un DAO parametrizado por tipo que resuelve la mayoría de los casos CRUD sin duplicar código.
- DTO Pattern: mismo origen, mismo catálogo clásico.
- Metadata-driven / schema-driven architecture: el principio detrás de Django Admin, Rails scaffolding, o herramientas low-code como Retool o Refine.dev. La idea común: la estructura de datos gobierna UI + validación + persistencia, no al revés.
Lo que sí es propio es la combinación exacta para mi stack: DAO genérico en Java + JAX-RS delgado + un motor de schema en JS vainilla que gobierna form/validator/tabla, sin depender de ningún framework externo pesado. No es un framework que bajé de GitHub; es la síntesis de "convention over configuration" resuelta con las herramientas que tenía a mano.
Por qué esto importa si trabajas solo o con presupuesto ajustado
Este enfoque no requiere adoptar un framework nuevo, migrar stack, ni pagar licencias. Si ya tienes:
- Una capa DAO/DTO razonablemente genérica en tu backend
- Un objeto de configuración en el frontend que describa tus entidades (campos, tipos, validaciones)
...ya tienes el 80% del camino. El resto es disciplina: resistir la tentación de escribir un caso especial cuando el schema podría resolverlo.
Conclusión
No hace falta un framework de moda para evitar CRUD repetido. Un DAO genérico bien pensado y un schema que gobierne tu frontend logran lo mismo con mucho menos código y cero dependencias nuevas. Si mantienes sistemas para negocios pequeños con presupuesto ajustado, este patrón te devuelve horas que puedes invertir en lo que sí es específico de cada negocio.
¿Usas algo parecido? Me interesa saber cómo lo resuelven otros que trabajan con stacks "vainilla" sin frameworks pesados.
Top comments (0)