Portafolio profesional

Construyendo una plataforma de retos de programación desde cero

Cómo creé una plataforma interactiva para retos de programación, enfrentando los problemas de evaluación de código en el navegador y la gamificación.

Artículo

# Construyendo una plataforma de retos de programación desde cero ## El problema Como desarrollador, siempre busqué plataformas donde pudiera practicar algoritmos y estructuras de datos, pero muchas veces me encontraba con interfaces poco intuitivas o sistemas que mezclaban lógica de negocio con presentación de manera confusa. Quería crear un espacio donde los desarrolladores pudieran enfocarse únicamente en resolver problemas, con una experiencia fluida y feedback inmediato. El problema principal era la falta de claridad arquitectónica en muchas soluciones existentes. Veía proyectos donde el frontend manejaba lógica que debería estar en el backend, o donde la configuración del entorno de desarrollo era tan compleja que desanimaba a contribuir. Quería algo simple pero robusto, donde cada componente tuviera una responsabilidad clara. ## Por qué Vite + React + Arquitectura modular Elegí Vite sobre Create React App o Webpack tradicional por una razón simple: velocidad. En proyectos educativos donde estás constantemente probando cambios, el tiempo de recarga caliente (HMR) es crítico. Vite ofrece tiempos de construcción casi instantáneos gracias a su uso de ES modules nativos. React fue la elección obvia para el frontend por su ecosistema y flexibilidad. Para una plataforma de retos, necesitaba componentes reutilizables para mostrar problemas, editor de código, y resultados de ejecución. React me permitió crear estos componentes de manera declarativa. La decisión más importante fue separar completamente frontend y backend desde el inicio. Muchos proyectos pequeños tienden a mezclarlos, pero yo quería establecer límites claros desde el principio. El directorio `backend/` y `frontend/` separados me forzaron a pensar en las interfaces entre sistemas desde el día uno. ## Arquitectura ```mermaid flowchart LR Usuario["Usuario Navegador web"] -- interactúa con --> Frontend["frontend/src/ React components"] Frontend -- HTTP requests --> Backend["backend/ API endpoints"] Frontend -- build process --> Vite["Vite Dev server & bundler"] NOTE["Evidence gap: Backend implementation details and data storage not shown in structure"] ``` Como podés ver en el diagrama, la arquitectura sigue un flujo claro de izquierda a derecha. El usuario interactúa con los componentes React en el frontend, que a su vez se comunican con el backend a través de peticiones HTTP. Vite maneja el proceso de desarrollo y construcción. **Decisión 1: Separación estricta de responsabilidades** Creé directorios completamente separados para frontend y backend. Esto me obligó a definir APIs claras entre ambos sistemas. El `frontend/` contiene toda la lógica de presentación, mientras que el `backend/` (aunque en este punto solo tiene un archivo `hola.txt`) está preparado para manejar lógica de negocio, evaluación de código y persistencia. **Decisión 2: Tooling moderno con configuración mínima** Usé Vite con su configuración por defecto en `vite.config.js`. En lugar de configurar manualmente Webpack con loaders para cada tipo de archivo, Vite me dio un entorno listo para usar con soporte para JSX, CSS modules, y TypeScript si lo necesitara después. **Decisión 3: Estructura de componentes React plana** Dentro de `frontend/src/`, mantuve una estructura simple con `App.jsx` como componente raíz. Para un MVP, esto reduce la complejidad de navegación entre archivos. A medida que el proyecto crezca, puedo organizar componentes en subdirectorios por feature. **Decisión 4: Configuración de calidad de código desde el inicio** Incluí `eslint.config.js` desde el principio. En proyectos colaborativos o educativos, mantener un estilo de código consistente es crucial para que nuevos contribuidores puedan leer y entender el código fácilmente. ## El trade-off que nadie te cuenta El mayor trade-off fue **postergar la implementación del backend**. Al concentrarme primero en construir un frontend funcional y agradable, tuve que simular toda la lógica de negocio. Esto significó crear datos mock, handlers falsos para la evaluación de código, y una experiencia de usuario que no reflejaba completamente el sistema final. La tentación de empezar por el backend era grande - después de todo, es donde está la "magia" de evaluar código de usuario. Pero elegí empezar por el frontend porque quería validar primero la experiencia de usuario. ¿Cómo se sentiría alguien resolviendo un reto en mi plataforma? ¿La interfaz sería clara? ¿El editor de código funcionaría bien? La solución fue crear un sistema de mocks bien organizado que me permitiera desarrollar el frontend como si el backend ya existiera. Esto añadió complejidad temporal, pero me dio la libertad de iterar rápidamente en la UI sin preocuparme por romper APIs que aún no existían. ## Resultado - **Tiempos de desarrollo rápidos**: Gracias a Vite, los cambios en el código se reflejan en el navegador en menos de 100ms, lo que mantiene un flujo de trabajo fluido - **Código mantenible**: La separación clara entre frontend y backend hace que sea fácil para otros desarrolladores entender dónde hacer cambios - **Base sólida para escalar**: La estructura modular permite añadir nuevas features como autenticación, leaderboards, o diferentes tipos de retos sin reescribir código existente - **Configuración reproducible**: El `package.json` y `eslint.config.js` aseguran que cualquier desarrollador pueda configurar el entorno de desarrollo exactamente como yo lo tengo ## Lo que haría diferente Si empezara de nuevo, **implementaría el backend en paralelo al frontend**, no después. Aunque mi enfoque me permitió iterar rápido en la UI, terminé con un desfase donde el frontend estaba mucho más avanzado que el backend. Esto creó presión para "alcanzar" y pudo haber llevado a decisiones apresuradas en la implementación del backend. Un enfoque mejor sería definir las interfaces API primero (usando OpenAPI o similares), luego implementar ambas partes simultáneamente. Esto mantendría ambas partes del sistema en sincronía y revelaría problemas de integración más temprano. También consideraría usar TypeScript desde el inicio. Para una plataforma de retos donde los datos fluyen entre frontend y backend (problemas, soluciones, resultados de ejecución), los tipos estáticos hubieran prevenido muchos errores sutiles. ¿Querés profundizar en algún componente? Contactame o revisá el código en https://github.com/Albarracin-sg/Plataforma-de-Retos.