Charla tecnica · Technitive · Capgemini AD Center
Arquitectura Frontend — Simplificando los mensajes de estado
Charla en Technitive sobre como eliminar el try/catch repetido en cada pantalla llevando los errores y estados al interceptor HTTP.
Charla impartida en Technitive (marzo de 2024) en representacion de Capgemini AD Center, sobre como dejar de repartir try/catch y toasts por todas las pantallas de una aplicacion frontend.
El planteamiento es simple: las reglas de negocio y los fallos HTTP no deberian ser responsabilidad de la pantalla que los origina. La charla recorre una pequeña app Angular de referencia — un dashboard de Formula 1 con pantallas para pilotos, escuderias, circuitos y temporadas — para mostrar como un cambio arquitectonico minimo elimina cientos de lineas de gestion de errores repetida.
El problema
La mayoria de frontends acaban pareciendose: cada metodo valida parametros, llama a un endpoint, comprueba la respuesta, decide que mensaje mostrar y por fin hace el trabajo real. Ese codigo se duplica en cada pantalla, es dificil de mantener consistente, y la logica que deberia vivir en un unico sitio queda dispersa en todos.
- Dificil de mantener — cada pantalla es dueña de su propio UX de error.
- Consume tiempo de desarrollo en boilerplate sin valor de negocio.
- Aumenta innecesariamente el codigo con un try/catch casi identico decenas de veces.
- La logica que deberia estar centralizada queda dividida en N copias independientes.
El problema a escala
Si haces zoom out, el coste se multiplica. Cada feature de la aplicacion — pilotos, escuderias, circuitos, temporadas — posee su propia pantalla, llama a su propio endpoint, gestiona su propio error y monta su propio componente de mensaje. El mismo patron, copia-pegado N veces, con N oportunidades de divergir.
De repente el coste no son tres lineas de try/catch: es una superficie de mantenimiento que crece linealmente con el numero de features y reduce las ganas del equipo de tocar nada.
- N features × el mismo try/catch — y la misma probabilidad de inconsistencia.
- Cada feature posee la maquetacion de su propio UX de error y deriva por su cuenta.
- Añadir un nuevo modo de fallo implica tocar cada feature en lugar de un solo sitio.
El componente MessageBoard
Un componente tipado que vive en la libreria compartida y renderiza cuatro tipos de mensaje: Error, Warning, Success e Info. Cada mensaje lleva un tipo, un cuerpo, una posicion opcional (default o flotante) y un flag opcional de autoClose.
Lo decisivo es donde se monta: en el bootstrap layout de la aplicacion — fuera del router-outlet — junto al header y al footer. Es global y persistente: importa que ruta este activa, la superficie donde aparecen los mensajes siempre esta ahi.
- MessageType: Success | Info | Error | Warn.
- Position: Float | Default — controla si el banner es sticky o inline.
- MessageBase: { type, message, position?, autoClose? } extendido por MessageBoard con un id interno.
- Montado como <header /><message-board /><router-outlet /><footer /> en la raiz de la app.
Estado reactivo con BehaviorSubject
Como el MessageBoard vive en la raiz del arbol, una pantalla profunda no puede comunicarse con el a traves de inputs y outputs. La charla resuelve esto con una pequeña clase de estado reactivo que expone un BehaviorSubject privado y metodos publicos addMessage / removeMessage.
El MessageBoard se suscribe al observable; cualquier servicio, componente o interceptor inyecta ese mismo estado y empuja mensajes a el. Los operadores de RxJS (filter, tap, catchError) hacen la reactividad explicita y facil de extender.
El interceptor HTTP
El interceptor es el cotilla del trafico: inspecciona codigos de estado y cuerpos en cada request y response, y decide que hacer sin que la pantalla que llamo se entere.
Ante un 4xx (error de negocio) o un 5xx (error de servidor) construye un Message a partir del payload del backend, lo empuja al estado y corta el stream — no queda nada que la pantalla tenga que manejar. Ante un 200 con contrato de exito puede tambien disparar un banner verde automatico. Cualquier otro caso se reenvia tal cual al llamante.
- 4xx / 5xx → addMessage(error) y corta el flujo. La pantalla nunca ve el fallo.
- 200 con contrato de exito → addMessage(success) y reenvia el payload.
- 200 normal → reenvia el payload sin tocarlo.
- Resultado: las reglas de negocio se dirigen desde el backend, la pantalla solo posee el happy path.
La arquitectura completa
Juntando todas las piezas, la arquitectura deja de parecer 'una pantalla que pide datos' y empieza a parecer un bucle reactivo cerrado. La pantalla llama a su endpoint, la respuesta atraviesa el interceptor, el interceptor decide si empujar un mensaje al estado compartido, el layout re-renderiza el MessageBoard automaticamente, y la llamada original solo reenvia datos — nunca errores — a la pantalla.
Los pasos numerados del diagrama cuentan la historia entera: 1) la pantalla llama. 2) el endpoint pega al backend. 3) llega la respuesta. 4) el interceptor la inspecciona. 5–6) empuja un mensaje al estado compartido. 7) el layout re-renderiza el MessageBoard automaticamente. 8–9) la llamada solo devuelve datos a la pantalla.
Resultado
En una aplicacion con decenas de pantallas, el patron elimina miles de lineas de gestion de errores duplicada y deja que los componentes se centren en su trabajo real: disparar acciones y renderizar datos. La infraestructura se encarga de que el usuario siempre sepa que esta pasando.