|
| 1 | +--- |
| 2 | +id: ADR-011 |
| 3 | +titulo: Frontend como Modular Monolith (no Microfrontends) |
| 4 | +fecha: 2025-11-06 |
| 5 | +estado: Aceptado |
| 6 | +decision_makers: |
| 7 | + - Tech Lead Frontend |
| 8 | + - Arquitecto de Software |
| 9 | +contexto: Sistema IACT Frontend |
| 10 | +tags: [frontend, arquitectura, react] |
| 11 | +--- |
| 12 | + |
| 13 | +# ADR-011: Frontend como Modular Monolith (no Microfrontends) |
| 14 | + |
| 15 | +## Estado |
| 16 | + |
| 17 | +**Aceptado** - 2025-11-06 |
| 18 | + |
| 19 | +## Contexto |
| 20 | + |
| 21 | +El frontend de IACT (IVR Analytics & Customer Tracking) necesita una arquitectura escalable que permita: |
| 22 | + |
| 23 | +1. Desarrollo independiente de módulos (Dashboard, Reportes, Alertas, Admin) |
| 24 | +2. Build y deploy simplificado |
| 25 | +3. Performance optimo (dashboard debe cargar en <3 segundos) |
| 26 | +4. Mantenibilidad a largo plazo con equipo pequeño (2-3 desarrolladores) |
| 27 | + |
| 28 | +### Opciones Evaluadas |
| 29 | + |
| 30 | +#### Opción 1: Microfrontends (Module Federation) |
| 31 | + |
| 32 | +**Pros**: |
| 33 | +- Despliegue independiente de módulos |
| 34 | +- Tecnologías diferentes por módulo (React, Vue, etc) |
| 35 | +- Equipos completamente autónomos |
| 36 | +- Escalabilidad organizacional |
| 37 | + |
| 38 | +**Contras**: |
| 39 | +- Complejidad significativa (orquestación, comunicación inter-apps) |
| 40 | +- Overhead de performance (múltiples bundles, inicializaciones) |
| 41 | +- Duplicación de dependencias (React cargado múltiples veces) |
| 42 | +- Testing end-to-end complejo |
| 43 | +- Requiere shared state complejo (eventos custom, storage) |
| 44 | +- Overhead de CI/CD (múltiples pipelines) |
| 45 | + |
| 46 | +#### Opción 2: Monolito Tradicional |
| 47 | + |
| 48 | +**Pros**: |
| 49 | +- Simplicidad máxima |
| 50 | +- Build único y rápido |
| 51 | +- Testing integrado natural |
| 52 | + |
| 53 | +**Contras**: |
| 54 | +- Acoplamiento alto |
| 55 | +- Escalabilidad limitada (todo en un directorio) |
| 56 | +- Refactorings globales riesgosos |
| 57 | + |
| 58 | +#### Opción 3: Modular Monolith (SELECCIONADA) |
| 59 | + |
| 60 | +**Pros**: |
| 61 | +- Balance entre autonomía y simplicidad |
| 62 | +- Build único y deploy único (simple CI/CD) |
| 63 | +- Performance óptimo (sin overhead microfrontends) |
| 64 | +- Code splitting por módulo (lazy loading) |
| 65 | +- State management unificado (Redux global) |
| 66 | +- Testing integrado natural |
| 67 | +- Refactorings globales posibles |
| 68 | +- Migración futura a microfrontends si necesario |
| 69 | + |
| 70 | +**Contras**: |
| 71 | +- Requiere disciplina de equipo (no acoplar módulos) |
| 72 | +- Una tecnología para todos (React) |
| 73 | +- Deploy atómico (no por módulo) |
| 74 | + |
| 75 | +## Decisión |
| 76 | + |
| 77 | +Implementar el frontend como **Modular Monolith**: |
| 78 | + |
| 79 | +### Estructura de Módulos |
| 80 | + |
| 81 | +``` |
| 82 | +src/ |
| 83 | +├── app/ Aplicación raíz |
| 84 | +├── components/ Componentes compartidos |
| 85 | +├── hooks/ Hooks compartidos |
| 86 | +├── modules/ Módulos de negocio (AUTÓNOMOS) |
| 87 | +│ ├── dashboard/ |
| 88 | +│ │ ├── hooks/ |
| 89 | +│ │ ├── state/ Redux slice local |
| 90 | +│ │ ├── DashboardModule.jsx |
| 91 | +│ │ └── index.js |
| 92 | +│ ├── reports/ |
| 93 | +│ ├── alerts/ |
| 94 | +│ └── admin/ |
| 95 | +├── pages/ Páginas (componen módulos) |
| 96 | +├── state/ Redux store global |
| 97 | +└── styles/ Estilos globales |
| 98 | +``` |
| 99 | + |
| 100 | +### Reglas de Módulos |
| 101 | + |
| 102 | +1. **Encapsulación**: Módulos exportan solo su componente principal (index.js) |
| 103 | +2. **Estado local**: Cada módulo tiene su propio slice de Redux |
| 104 | +3. **Sin dependencias entre módulos**: Módulos NO importan otros módulos |
| 105 | +4. **Comunicación vía Redux**: Si necesitan compartir datos, usar Redux store |
| 106 | +5. **Lazy loading**: Módulos grandes con React.lazy() para code splitting |
| 107 | + |
| 108 | +### Ejemplo: Módulo Dashboard |
| 109 | + |
| 110 | +```javascript |
| 111 | +// src/modules/dashboard/index.js |
| 112 | +export { default } from './DashboardModule'; |
| 113 | + |
| 114 | +// src/modules/dashboard/DashboardModule.jsx |
| 115 | +import { useDashboardData } from './hooks/useDashboardData'; |
| 116 | + |
| 117 | +function DashboardModule() { |
| 118 | + const { widgets } = useDashboardData(); |
| 119 | + return <div>{/* render widgets */}</div>; |
| 120 | +} |
| 121 | + |
| 122 | +export default DashboardModule; |
| 123 | + |
| 124 | +// src/modules/dashboard/state/dashboardSlice.js |
| 125 | +import { createSlice } from '@reduxjs/toolkit'; |
| 126 | + |
| 127 | +const dashboardSlice = createSlice({ |
| 128 | + name: 'dashboard', |
| 129 | + initialState: { widgets: [] }, |
| 130 | + reducers: { /* ... */ }, |
| 131 | +}); |
| 132 | + |
| 133 | +// src/pages/DashboardPage.jsx |
| 134 | +import DashboardModule from '@modules/dashboard'; |
| 135 | + |
| 136 | +function DashboardPage() { |
| 137 | + return <DashboardModule />; |
| 138 | +} |
| 139 | +``` |
| 140 | + |
| 141 | +### Beneficios Específicos para IACT |
| 142 | + |
| 143 | +1. **Performance**: |
| 144 | + - Bundle único optimizado con code splitting |
| 145 | + - Objetivo: Dashboard <3s (fácil de medir y optimizar) |
| 146 | + - No overhead de comunicación entre microfrontends |
| 147 | + |
| 148 | +2. **Desarrollo**: |
| 149 | + - Equipo pequeño (2-3 devs) puede trabajar eficientemente |
| 150 | + - Refactorings globales son viables (ej: cambiar librería UI) |
| 151 | + - Debugging simple (un solo contexto) |
| 152 | + |
| 153 | +3. **Deploy**: |
| 154 | + - CI/CD simple: un build, un deploy |
| 155 | + - Rollback completo (no inconsistencias entre versiones de módulos) |
| 156 | + - Un solo ambiente (no orquestación) |
| 157 | + |
| 158 | +4. **Mantenimiento**: |
| 159 | + - Dependencias centralizadas (un package.json) |
| 160 | + - Actualizaciones globales (ej: React 18 → 19) |
| 161 | + - Testing E2E natural (todo en un contexto) |
| 162 | + |
| 163 | +## Consecuencias |
| 164 | + |
| 165 | +### Positivas |
| 166 | + |
| 167 | +1. Simplicidad operacional (un repo, un build, un deploy) |
| 168 | +2. Performance óptimo para dashboard IACT (<3s objetivo alcanzable) |
| 169 | +3. Testing integrado natural |
| 170 | +4. Curva de aprendizaje baja para nuevos desarrolladores |
| 171 | +5. Herramientas estándar de React (no Module Federation) |
| 172 | + |
| 173 | +### Negativas |
| 174 | + |
| 175 | +1. Requiere disciplina de equipo para mantener módulos desacoplados |
| 176 | +2. Deploy atómico (un cambio en módulo X requiere redeploy completo) |
| 177 | +3. Una sola tecnología (React) para todo |
| 178 | +4. Escalabilidad organizacional limitada (equipos autónomos totalmente) |
| 179 | + |
| 180 | +### Mitigaciones |
| 181 | + |
| 182 | +1. **Disciplina**: Code reviews estrictos, linting de imports entre módulos |
| 183 | +2. **Deploy atómico**: Aceptable dado el tamaño del sistema y equipo |
| 184 | +3. **Tecnología única**: React es suficiente para todos los módulos IACT |
| 185 | +4. **Escalabilidad**: Si el equipo crece >10 devs, reevaluar (ADR futuro) |
| 186 | + |
| 187 | +### Plan de Migración (Si necesario en futuro) |
| 188 | + |
| 189 | +Si el sistema crece significativamente, la estructura modular facilita migración a microfrontends: |
| 190 | + |
| 191 | +``` |
| 192 | +Paso 1: Módulos ya están encapsulados |
| 193 | +Paso 2: Separar cada módulo a su propio repo |
| 194 | +Paso 3: Implementar Module Federation |
| 195 | +Paso 4: Migrar módulo por módulo (gradual) |
| 196 | +``` |
| 197 | + |
| 198 | +## Alternativas Rechazadas |
| 199 | + |
| 200 | +### Microfrontends (Module Federation) |
| 201 | + |
| 202 | +Rechazado por: |
| 203 | +- Complejidad innecesaria para equipo pequeño |
| 204 | +- Overhead de performance (dashboard <3s crítico) |
| 205 | +- Sistema IACT no requiere despliegue independiente por módulo |
| 206 | + |
| 207 | +### Monolito Tradicional (sin estructura modular) |
| 208 | + |
| 209 | +Rechazado por: |
| 210 | +- Falta de escalabilidad (todo mezclado en un directorio) |
| 211 | +- Acoplamiento alto (difícil mantener) |
| 212 | + |
| 213 | +## Referencias |
| 214 | + |
| 215 | +- **Modular Monolith**: https://www.kamilgrzybek.com/blog/posts/modular-monolith-primer |
| 216 | +- **React Code Splitting**: https://reactjs.org/docs/code-splitting.html |
| 217 | +- **Redux Toolkit**: https://redux-toolkit.js.org/ |
| 218 | +- **Requisito RF-012**: Dashboard con 10 widgets (carga <3s) |
| 219 | + |
| 220 | +## Decisión Relacionadas |
| 221 | + |
| 222 | +- **ADR-012**: Redux Toolkit para state management |
| 223 | +- **ADR-013**: Webpack para bundling (code splitting) |
| 224 | + |
| 225 | +## Notas |
| 226 | + |
| 227 | +Esta decisión es reversible si: |
| 228 | +- Equipo crece >10 desarrolladores frontend |
| 229 | +- Se requiere despliegue independiente por módulo |
| 230 | +- Performance no se puede lograr (<3s) |
| 231 | + |
| 232 | +Revisar esta decisión en: **Q2 2026** (6 meses después de lanzamiento v1.0) |
| 233 | + |
| 234 | +--- |
| 235 | + |
| 236 | +**Decidido por**: Tech Lead Frontend, Arquitecto de Software |
| 237 | +**Fecha**: 2025-11-06 |
| 238 | +**Estado**: Aceptado |
0 commit comments