Type something to search...
Estándar de Codificación y Gestión de Errores en Arquitecturas de Microservicios

Estándar de Codificación y Gestión de Errores en Arquitecturas de Microservicios

En el ecosistema de aplicaciones web modernas, la arquitectura de microservicios distribuidos se ha consolidado como un paradigma dominante. Su flexibilidad, escalabilidad y resiliencia son innegables. Sin embargo, esta distribución introduce una complejidad significativa en la gestión de estados y, especialmente, en el manejo de errores. Cuando una operación involucra a múltiples servicios, identificar la causa raíz de un fallo puede convertirse en una tarea titánica, afectando la experiencia del usuario, los tiempos de resolución y la mantenibilidad del sistema.

Este documento establece un estándar completo y directamente aplicable para la codificación, documentación y gestión de errores visibles al usuario final. El objetivo es crear un marco de trabajo robusto que, aunque inicialmente se implementará en un entorno de backend con Java (Spring Boot) y frontend con Angular, ha sido diseñado con un enfoque agnóstico al lenguaje para garantizar su longevidad y adaptabilidad a futuras tecnologías.

Adoptar este estándar permitirá no solo presentar mensajes de error claros y útiles al usuario, sino también establecer una base documental sólida que facilite la observabilidad, la trazabilidad y la colaboración entre equipos de desarrollo, QA y soporte técnico.


El Estándar Detallado

1. Filosofía y Principios Fundamentales

Antes de detallar la implementación, es crucial entender los principios que guían este estándar:

  • El Error como Ciudadano de Primera Clase: Los errores no son un caso excepcional, sino una parte inherente del flujo de una aplicación. Deben ser diseñados, documentados y probados con el mismo rigor que las funcionalidades exitosas.
  • Claridad para el Usuario, Detalle para el Desarrollador: La información presentada al usuario final debe ser concisa, clara, traducible y orientada a la acción. Por el contrario, la información registrada para los equipos técnicos debe ser rica en detalles para permitir un diagnóstico rápido y preciso.
  • Seguridad por Opacidad: Los códigos y mensajes de error públicos nunca deben revelar detalles de la infraestructura interna, nombres de clases, trazas de pila (stack traces) o cualquier información que pueda ser explotada por un actor malicioso.
  • Trazabilidad Extrema: Cada error debe ser unívocamente identificable y correlacionable a través de los distintos servicios y sistemas de observabilidad (logs, métricas, trazas distribuidas).

2. Formato del Código de Error

Todo error visible al usuario final o que cruce los límites de un microservicio deberá ser identificado por un código único y opaco. Este código actúa como una clave inmutable que desacopla el error en sí de su representación (el mensaje).

La estructura propuesta es: MSS-ECNNN[-EXTCODE]

  • MSS (MicroService Short-identifier): Identificador numérico único de 3 dígitos asignado a cada microservicio. Esta asignación debe ser gestionada en un registro centralizado para evitar colisiones.

    • Ejemplo: 101 para “Servicio de Autenticación”, 205 para “Servicio de Pedidos”.
  • EC (Error Category): Código alfabético de 2 letras que clasifica la naturaleza del error. Esto permite un filtrado y análisis rápido. (Ver sección 3 para el catálogo de categorías).

    • Ejemplo: IV para “Validación de Entrada”, BR para “Regla de Negocio”.
  • NNN (Numeric Sequence): Secuencia numérica de 3 dígitos, única dentro del microservicio para esa categoría. Se recomienda iniciar en 001 y aumentar de forma secuencial.

    • Ejemplo: 001, 002, 047.
  • [EXTCODE] (External Code - Opcional): Componente opcional para encapsular errores originados en servicios de terceros. Proporciona una correlación directa sin exponer el formato original del tercero.

    • Formato: EXT_<ID_SERVICIO>_<CODIGO_ERROR_ORIGINAL>
    • ID_SERVICIO: Un identificador corto y predefinido para el servicio externo (ej. STRIPE, SENDGRID, AWS_S3).
    • CODIGO_ERROR_ORIGINAL: El código de error devuelto por el servicio externo, sanitizado para ser compatible con la URL (ej. reemplazando espacios o caracteres especiales por _).
    • Ejemplo: 205-DP003-EXT_STRIPE_card_declined

Ejemplo completo: 205-BR001 representa el primer error de “Regla de Negocio” definido en el microservicio “Pedidos” (ID 205).

3. Clasificación de Errores Comunes

La estandarización de categorías (EC) es fundamental para la observabilidad y la generación de métricas. El catálogo inicial es el siguiente:

CódigoCategoríaDescripción
IVInput ValidationErrores relacionados con la validación de datos de entrada (formato, rango, campos obligatorios). Suelen ser errores del tipo 400 Bad Request.
AUAuthentication & AuthorizationFallos de autenticación (token inválido, credenciales incorrectas) o autorización (sin permisos para la acción). Errores 401 Unauthorized o 403 Forbidden.
BRBusiness RuleViolación de una regla de negocio específica. La solicitud es sintácticamente correcta pero semánticamente inválida en el contexto actual (ej. stock insuficiente). Suele ser un 409 Conflict o 422 Unprocessable Entity.
DPDependency FailureUn servicio externo del que depende el microservicio no está disponible o ha devuelto un error (otra API interna, base de datos, sistema de colas). Errores del tipo 502 Bad Gateway o 503 Service Unavailable.
SYSystem ErrorErrores inesperados o no controlados en el servidor (excepciones RuntimeException, NullPointerException, etc.). Siempre deben ser investigados. Corresponden a un 500 Internal Server Error.
NTNetwork & TimeoutErrores de comunicación, ya sea porque una dependencia no respondió a tiempo o por problemas en la red. Corresponde a un 504 Gateway Timeout.
CFConfiguration ErrorEl servicio no puede iniciarse o funcionar correctamente debido a una configuración faltante o incorrecta (variables de entorno, secretos, etc.).
NFNot FoundEl recurso solicitado no existe. Corresponde a un 440 Not Found.

4. Catálogo Inicial de Códigos de Error

A continuación, se presenta un catálogo de ejemplo con 10 códigos para dos microservicios hipotéticos: Gestión de Usuarios (ID: 101) y Procesamiento de Pedidos (ID: 205).

CódigoMensaje usuarioDescripción técnicaSeveridadEstadoAcción esperadaServicio externo (si aplica)
101-IV001El correo electrónico proporcionado no tiene un formato válido. Por favor, revísalo.El campo email en el DTO de registro de usuario no supera la validación de la expresión regular ^(.+)@(.+)$.BajaActivoUsuario: Corregir el formato del email. Frontend: Realizar validación en cliente para prevenir el error.N/A
101-AU001Tu sesión ha expirado. Por favor, inicia sesión de nuevo.El JWT recibido en la cabecera Authorization ha caducado. La fecha de expiración (exp) es anterior a la fecha actual.MediaActivoSistema: Redirigir al usuario a la página de login. Usuario: Volver a introducir sus credenciales.N/A
101-AU002No tienes permisos para realizar esta acción. Contacta al administrador si crees que es un error.El usuario autenticado, extraído del token, no posee el rol requerido (ROLE_ADMIN) para acceder al endpoint.MediaActivoFrontend: Ocultar o deshabilitar la opción que provoca el error. Soporte: Verificar los roles del usuario si este levanta un ticket.N/A
101-BR001El correo electrónico ya está registrado en nuestra plataforma. Intenta iniciar sesión.Se intentó crear un usuario con un email que ya existe en la tabla users de la base de datos (violación de UNIQUE constraint).BajaActivoUsuario: Usar la opción “recuperar contraseña” o iniciar sesión. Frontend: Ofrecer un enlace directo a la página de login.N/A
205-IV001El identificador del producto no es válido. Debe ser un número positivo.El productId recibido en la línea de un pedido es nulo, cero o negativo. La validación @Positive falló en el DTO.BajaActivoUsuario: Informar del error. Es un caso raro que indica un bug en el frontend. Desarrollo: Investigar cómo se pudo enviar un ID inválido desde el cliente.N/A
205-BR001No hay suficiente stock para el producto ‘Nombre del Producto’. Solo quedan X unidades.La cantidad solicitada de un producto es mayor que el stock disponible registrado en la base de datos para ese productId.MediaActivoUsuario: Reducir la cantidad del producto o eliminarlo del carrito. Sistema: El mensaje debe incluir el stock actual para ser útil.N/A
205-BR002No se pueden añadir productos de diferentes vendedores en un mismo pedido.La lógica de negocio impide mezclar productos de sellerId distintos en una sola transacción para simplificar la logística.MediaActivoUsuario: Finalizar la compra actual y crear un nuevo pedido para los otros productos. Frontend: Mostrar una advertencia al intentar añadir un producto incompatible.N/A
205-DP001El servicio de inventario no está respondiendo. Por favor, inténtalo de nuevo en unos minutos.La llamada HTTP al microservicio de Inventario (ID 310) para verificar el stock ha resultado en un timeout o error 5xx.AltaActivoSistema: Implementar un reintento con exponential backoff. Si persiste, activar un circuit breaker. Soporte: Revisar el estado del servicio de Inventario.N/A
205-DP002Tu pago no pudo ser procesado por el proveedor. Razón: Fondos insuficientes.La pasarela de pagos (Stripe) devolvió un error 402 Request Failed con el código card_declined y el motivo insufficient_funds.MediaActivoUsuario: Intentar con otro método de pago o verificar los fondos de su tarjeta. Sistema: No reintentar automáticamente. Invalidar el pedido.EXT_STRIPE_insufficient_funds
205-SY001Ha ocurrido un error inesperado al procesar tu pedido. Nuestro equipo ya ha sido notificado.Se ha capturado una NullPointerException no esperada en la clase OrderProcessingService al calcular los impuestos. Se ha creado una alerta en Sentry/Datadog.AltaActivoSistema: Registrar el trace_id y toda la información de la petición. Desarrollo: Priorizar la corrección de este bug. Usuario: Reintentar más tarde o contactar a soporte con el trace_id si se le muestra.N/A

5. Documentación y Centralización

La documentación es lo que transforma este estándar de una idea a una herramienta útil.

  • Estructura de Archivos: Cada microservicio debe incluir en su repositorio un archivo docs/errors/errors.md. Este archivo contendrá la tabla completa de errores que el servicio puede generar.
  • Control de Versiones: El archivo errors.md debe ser versionado junto con el código fuente del microservicio. Cualquier adición o modificación de un código de error debe formar parte de un Pull Request, permitiendo su revisión.
  • Formato de Documentación: Se utilizará la tabla Markdown definida en la sección anterior. Este formato es fácil de leer para humanos y de parsear por máquinas.

Ejemplo de microservice-orders/docs/errors/errors.md:

Catálogo de Errores - Servicio de Pedidos

  • Nombre Lógico: Servicio de Procesamiento de Pedidos
  • ID del Microservicio: 205
CódigoMensaje usuarioDescripción técnicaSeveridadEstadoAcción esperadaServicio externo (si aplica)
205-IV001El identificador del producto no es válido. Debe ser un número positivo.El productId recibido en la línea de un pedido es nulo, cero o negativo. La validación @Positive falló en el DTO.BajaActivoUsuario: Informar del error. Desarrollo: Investigar cómo se pudo enviar un ID inválido.N/A

6. Recomendaciones para Centralización y Escalabilidad

Para que el estándar sea efectivo en una organización grande, se recomienda:

  • Repositorio Central de Errores: Un pipeline de CI/CD debería agregar los archivos errors.md de todos los microservicios tras cada release exitosa en un repositorio central o una página de Confluence/Wiki. Esto crea un único punto de verdad para que los equipos de QA, Soporte y Frontend puedan consultar cualquier código de error sin necesidad de acceder a los repositorios individuales.
  • Automatización y Linters: El pipeline de CI/CD debe incluir pasos para:
    • Validar la Unicidad: Asegurar que no existan códigos MSS-ECNNN duplicados dentro del mismo microservicio.
    • Validar el Formato: Comprobar que todos los nuevos códigos sigan la estructura definida.
    • Detectar Nuevos Servicios Externos: Lanzar una advertencia si se añade un EXTCODE con un <ID_SERVICIO> no registrado previamente, para asegurar que se documente centralmente.
  • Generación de Artefactos: Se pueden crear scripts que lean estos archivos .md para generar automáticamente artefactos útiles, como:
    • Enums de TypeScript para el frontend, permitiendo un manejo de errores tipado (case ErrorCodes.USER_EMAIL_EXISTS:).
    • Clases de constantes en Java para el backend.
    • Plantillas para sistemas de tickets (Jira, Zendesk).

Conclusión

Este estándar de codificación y gestión de errores proporciona un marco de trabajo unificado y resiliente, diseñado para escalar con la complejidad de una arquitectura de microservicios. Al tratar los errores como un componente central del diseño de software, logramos múltiples beneficios:

  1. Mejora la Experiencia del Usuario (UX): Los mensajes son claros, consistentes y orientados a la acción.
  2. Agiliza la Resolución de Incidencias: Los códigos únicos y la documentación detallada permiten a los equipos de soporte y desarrollo identificar y solucionar problemas rápidamente.
  3. Potencia la Observabilidad: La estructura de códigos y categorías facilita la creación de dashboards, alertas y métricas significativas sobre la salud del sistema.
  4. Aumenta la Seguridad: La opacidad de los códigos previene la fuga de información sensible de la infraestructura.

Futuras Líneas de Aplicación:

  • Integración con Plataformas de Observabilidad: Enriquecer automáticamente las trazas distribuidas (ej. en Jaeger o Datadog) con la “Descripción Técnica” del error a partir de su código.
  • Desarrollo de un “Servicio de Errores”: Una pequeña API central que, dado un código de error, devuelva su documentación completa, incluyendo el mensaje de usuario localizado en diferentes idiomas.
  • Generación de SDKs de Cliente: Automatizar la creación de librerías para diferentes lenguajes (JS/TS, Python, Go) que encapsulen la lógica de manejo de estos códigos de error estandarizados.

La adopción disciplinada de este estándar no es una carga adicional, sino una inversión estratégica en la calidad, mantenibilidad y escalabilidad a largo plazo de la plataforma.

Related Posts

Convención de Nombres en Clases Java: Mejora de Legibilidad y Mantenibilidad

Convención de Nombres en Clases Java: Mejora de Legibilidad y Mantenibilidad

En proyectos de gran escala, identificar rápidamente el tipo de una clase facilita la comprensión del código, la colaboración y la depuración. Sin un esquema de nombres estandarizado, es común que los

Leer más
Estructuración de Carpetas en Proyectos de Software

Estructuración de Carpetas en Proyectos de Software

En proyectos de software de gran escala, la falta de una estructura de carpetas bien definida puede generar desorden, dificultando la mantenibilidad, escalabilidad y comprensión del código. Muchas vec

Leer más
Desarrollo de Software Implementando Gitflow

Desarrollo de Software Implementando Gitflow

Introducción El desarrollo de software requiere metodologías y flujos de trabajo que permitan un control eficiente del código fuente. Uno de los enfoques más utilizados para la gestión de versiones

Leer más
Implementando Trunk Based Development con Ramas de Vida Corta en Tu Equipo: Una Guía Completa

Implementando Trunk Based Development con Ramas de Vida Corta en Tu Equipo: Una Guía Completa

En el ámbito del desarrollo de software, la elección de una estrategia de versionamiento eficiente y estable es fundamental para el éxito de un equipo. El Trunk Based Development (TBD) tradicional, do

Leer más
Arquitectura DDD y Hexagonal: Construyendo Software para el Futuro

Arquitectura DDD y Hexagonal: Construyendo Software para el Futuro

En el dinámico mundo del desarrollo de software, la complejidad es el enemigo silencioso. Las aplicaciones crecen, los requisitos cambian y, sin una guía clara, el código puede convertirse rápidamente

Leer más
Manejando el Caos: Una Guía Definitiva sobre Excepciones de Dominio 🎯

Manejando el Caos: Una Guía Definitiva sobre Excepciones de Dominio 🎯

En el desarrollo de software moderno, escribir código que funciona perfectamente en escenarios ideales es solo el primer paso. La verdadera fortaleza de un sistema se manifiesta cuando debe enfrentar

Leer más
El Arte de Conectar: Forjando un DataSource Dinámico en Spring Boot

El Arte de Conectar: Forjando un DataSource Dinámico en Spring Boot

En el vertiginoso universo del desarrollo de software, donde la seguridad es un pilar innegociable y la agilidad es la moneda de cambio, nos enfrentamos a desafíos que van más allá de la simple lógica

Leer más