Alejandro González
El síndrome de la complejidad innecesaria
Hay una curiosa manía que se ha vuelto común entre muchos desarrolladores frontend: la de complicar las cosas solo porque se puede. En algún punto del camino, construir interfaces dejó de tratarse de crear experiencias limpias, eficientes y mantenibles… para convertirse en el arte de levantar pequeños sistemas operativos dentro del navegador.
Frameworks como React, Vue o Svelte nacieron con un propósito claro: simplificar el trabajo del desarrollador, no volverlo un infierno de dependencias, contextos y abstracciones redundantes. React, por ejemplo, ofrece una API pensada para el renderizado declarativo y la gestión de estado de forma predecible y minimalista. No necesita convertirse en un ecosistema de capas interminables para cumplir su función.
Es común encontrarse con aberraciones como estas:
/** HADOUKEN: proveedor con 12 capas anidadas (no intentes esto en casa) */
export function HadoukenProviders({ children }: { children: React.ReactNode }) {
const [online, setOnline] = useState(true);
const theme = useMemo(() => ({ primary: "#f43f5e", mode: "dark" as const }), []);
return (
<AppConfigCtx.Provider value={{ appName: "agr.codes" }}>
<ThemeCtx.Provider value={theme}>
<FeatureFlagsCtx.Provider value={{ newNavbar: true, turboMode: false }}>
<ABTestCtx.Provider value={{ bucket: Math.random() > 0.5 ? "A" : "B" }}>
<AnalyticsCtx.Provider value={{ track: (...args:any[]) => console.log("🧪", ...args) }}>
<PermissionsCtx.Provider value={{ role: "insider", canEdit: true }}>
<TenantCtx.Provider value={{ id: "tkt-prod-001", region: "us-east-1" }}>
<LocaleCtx.Provider value={{ lang: "es-MX" }}>
<CurrencyCtx.Provider value={{ code: "MXN", symbol: "___CODE_BLOCK_0___quot; }}>
<DeviceCtx.Provider value={{ isMobile: false }}>
<NetworkCtx.Provider value={{ online, latencyMs: online ? 40 : 9999 }}>
<WizardCtx.Provider value={{ step: 2, total: 5 }}>
{/* Trigger absurdo para demostrar que algo cambia */}
<button
onClick={() => setOnline(o => !o)}
style={{ position: "absolute", right: 16, top: 16 }}
>
Toggle Online
</button>
{children}
</WizardCtx.Provider>
</NetworkCtx.Provider>
</DeviceCtx.Provider>
</CurrencyCtx.Provider>
</LocaleCtx.Provider>
</TenantCtx.Provider>
</PermissionsCtx.Provider>
</AnalyticsCtx.Provider>
</ABTestCtx.Provider>
</FeatureFlagsCtx.Provider>
</ThemeCtx.Provider>
</AppConfigCtx.Provider>
);
}
En algunos proyectos, el código parece más un ritual arcano que una aplicación web. Doce context providers anidados, cada uno conteniendo valores que jamás cambian, envuelven un componente como si cada renderizado fuera un conjuro de energía mística. El desarrollador, orgulloso de su “arquitectura escalable”, no se da cuenta de que acaba de invocar un Hadouken de contextos, donde cada capa agrega complejidad pero no valor. Es el equivalente a abrir doce cajas para encontrar una constante booleana. El resultado: un árbol de React tan denso que ni el reconciler sabe por dónde empezar. Eso no es elegancia ni robustez — es entropía encapsulada en <Provider>
s.
Se suele decir que estos problemas no son culpa del framework, sino del desarrollador. Y es cierto —pero también vale recordar que los frameworks nacieron de los propios desarrolladores. En algún punto, el deseo de optimizar se convirtió en la necesidad de abstraerlo todo, hasta perder de vista la esencia. A veces, entre tanta capa de contexto, build tools y meta-componentes, uno no puede evitar sentir nostalgia por aquella época en la que todo cabía en tres archivos: index.html, styles.css y scripts.js. Eran tiempos más simples… y tal vez, más humanos.