Mejores Prácticas de Desarrollo
Recomendaciones y estándares para el desarrollo backend con AdonisJS 6, Lucid ORM y TypeScript
Introducción
Esta guía establece las mejores prácticas y estándares de código para el desarrollo backend en RedCollege utilizando AdonisJS 6. El objetivo es mantener una base de código coherente, legible y mantenible que todos los desarrolladores puedan entender y modificar con facilidad.
Estructura de Directorios
Mantener una estructura de directorios coherente es crucial para la navegabilidad del proyecto:
Modelos
Principios Generales
- Importaciones: Siempre usar alias
#modelspara importar modelos - Organización: Agrupar por funcionalidad y mantener el mismo esquema en todos los directorios
- Mixins: Utilizar composición para características como SoftDeletes y Auditable
Estructura Recomendada
Recomendaciones Clave
- SoftDeletes: Implementar en todos los modelos para mantener historial
- Auditable: Usar para registrar quién creó/modificó/eliminó registros
- Convenciones de Nombres:
- Modelos: PascalCase singular (ej:
Usuario) - Tablas: snake_case, incluir namespace (ej:
auth.usuarios)
- Modelos: PascalCase singular (ej:
- Tipos: Declarar explícitamente todos los tipos de columnas y relaciones
- Organización: Agrupar campos y relaciones lógicamente
Controladores
Estructura Recomendada
Recomendaciones Clave
- Manejo de Errores:
- Usar bloques try/catch en cada método público
- Devolver respuestas de error específicas y claras
- Autorización:
- Utilizar políticas para centralizar reglas
- Verificar permisos a nivel de establecimiento
- Transacciones:
- Usar en operaciones que modifican múltiples tablas
- Aplicar cuando se manejan relaciones
- Consultas Eficientes:
- Cargar relaciones con
preloadpara evitar problemas N+1 - Aplicar filtros en la base de datos, no en memoria
- Cargar relaciones con
- Respuestas Consistentes:
- Usar métodos helpers:
response.ok(),response.created(), etc. - Estructura de error uniforme:
{ message, error }
- Usar métodos helpers:
Rutas
Estructura Recomendada
Recomendaciones Clave
- Organización:
- Agrupar rutas por dominio funcional
- Usar prefijos para versiones de API (/api/v3/...)
- Estructurar recursos y subrecursos jerárquicamente
- Convenciones RESTful:
- Seguir verbos HTTP estándar (GET, POST, PUT, DELETE)
- Usar sustantivos plurales para recursos (/recursos)
- Middleware:
- Aplicar middleware común a nivel de grupo
- Middleware específico a nivel de ruta cuando sea necesario
- Referencias a Controladores:
- Usar siempre ruta absoluta con # ('#controllers/...')
- Mantener convención controlador.método
Validadores
Estructura Recomendada
Recomendaciones Clave
- Validaciones Específicas:
- Crear esquemas específicos para cada operación (crear/actualizar)
- Definir reglas claras con mensajes de error personalizados
- Tipos:
- Exportar tipos inferidos para usar en controladores
- Usar prefijo 'I' para interfaces derivadas de validadores
- Organización:
- Mantener validadores en misma estructura de directorios que controladores
- Agrupar validadores relacionados en un mismo archivo
- Reglas de Validación:
- Ser específico en tipos y restricciones
- Validar referencias a otros modelos (ids existentes)
- Validar formatos cuando corresponda (regex para emails, fechas, etc.)
Políticas de Autorización
Estructura Recomendada
Recomendaciones Clave
- Métodos Auxiliares:
- Extraer lógica común a métodos reutilizables
- Centralizar verificaciones como acceso a establecimiento
- Granularidad:
- Definir políticas específicas por acción (create, view, update, delete)
- Considerar niveles de permisos (propietario vs administrador)
- Integración con Controladores:
- Usar bouncer en controladores:
await bouncer.with(Policy).authorize('action', resource) - Manejar respuestas de autorización denegada adecuadamente
- Usar bouncer en controladores:
Buenas Prácticas Generales
TypeScript
- Definir Tipos Explícitamente:
- Usar interfaces/types para peticiones y respuestas
- Evitar
any, preferir tipos específicos ounknown
- Imports:
- Usar aliases consistentes:
#models,#controllers,#validators - Agrupar imports por categoría (core, modelos, validators, etc.)
- Usar aliases consistentes:
Base de Datos
- Soft Delete:
- Implementar en todos los modelos que almacenen información valiosa
- Incluir
deletedBypara registrar quién realizó la eliminación - Usar métodos
onlyTrashed()para consultas específicas
- Transacciones:
- Usar
db.transactionpara operaciones que afecten múltiples tablas - Asegurar la integridad de los datos relacionados
- Usar
- Índices y Optimización:
- Crear índices para campos de búsqueda frecuente
- Analizar consultas complejas para optimizar rendimiento
Gestión de Errores
- Estructura de Error:
- Errores Específicos:
- HTTP 400: Validación fallida, datos incorrectos
- HTTP 401: No autenticado
- HTTP 403: No autorizado (autenticado pero sin permisos)
- HTTP 404: Recurso no encontrado
- HTTP 409: Conflicto (ej. duplicación)
- HTTP 500: Error interno del servidor
- Logs:
- Registrar errores críticos con detalles suficientes para diagnóstico
- No incluir información sensible en logs
Seguridad
- Validación:
- Validar TODOS los datos de entrada, sin excepciones
- Usar reglas estrictas y específicas
- Autorización:
- Verificar permisos en cada método de controlador
- Implementar políticas para centralizar lógica de autorización
- Datos Sensibles:
- No devolver datos sensibles en respuestas API
- Usar environment variables para configuraciones sensibles
Ejemplos Prácticos
Modelo Completo
Controlador Eficiente
Rutas Organizadas
Resumen Final
Principios Fundamentales
- Consistencia: Mantener el mismo estilo y estructura en todo el código
- Modularidad: Separar lógica en componentes reutilizables
- Seguridad: Validar datos, verificar permisos, evitar vulnerabilidades
- Mantenibilidad: Escribir código autodocumentado y fácil de entender
- Rendimiento: Optimizar consultas y transacciones de base de datos
Checklist de Calidad
- ¿El código sigue las convenciones de nomenclatura?
- ¿Se implementa soft delete en los modelos relevantes?
- ¿Se usan validadores para todos los datos de entrada?
- ¿Las consultas cargan relaciones eficientemente?
- ¿Se verifica autorización en cada endpoint?
- ¿El manejo de errores es consistente?
- ¿Las transacciones protegen operaciones complejas?
- ¿La estructura de archivos sigue el patrón establecido?
- ¿Los tipos de TypeScript están bien definidos?
- ¿El código es legible y está bien documentado?
Seguir estas prácticas no solo mejorará la calidad del código, sino que facilitará la colaboración entre desarrolladores y el mantenimiento a largo plazo del proyecto RedCollege.