Hace poco tiempo, en CourseIt sacamos una nueva sección llamada desafíos la cual se basa en una serie de pruebas principalmente algorítmicas que los usuarios pueden resolver para mejorar su nivel en el uso de Javascript.

Hoy queremos contarles sobre la linea de pensamiento que tuvimos a la hora de desarrollarlo y la arquitectura final a la que llegamos luego de una gran cantidad de iteraciones.

Antes de empezar a hablar estrictamente de los desafíos, veamos como está planteado CourseIt a gran escala.

Nuestra arquitectura esta basada en microservicios. Los usuarios consumen un Frontend hecho en React que busca la información en un servidor creado en Node que a su vez se nutre de diversos microservicios para poder brindar la información necesaria.

Teniendo esto en cuenta, para nosotros los desafíos son simplemente un microservicio más, con una estructura similar a la siguiente:

Una de las grandes ventajas de trabajar con este esquema es la capacidad de elegir la tecnología y librerías más adecuadas para cada microservicio, pero antes de poder tomar esa decisión hay que entender bien que problema se está queriendo resolver y cuál es la solución que vamos a dar a dicho problema.

Conceptualmente, un desafío es un pseudo editor de texto embebido en la web que ante una acción impulsada por el usuario corre una batería de tests unitarios indicando si el problema fue resulto correctamente.  Para representarlo visualmente creamos la siguiente interface gráfica:

Con esta solución planteada, avanzamos a pensar qué tecnologías y librerías íbamos a utilizar para llevarla a la realidad.

Desde el punto de vista del Frontend, el mayor desafío técnico fue decidir si crear un pseudo editor de texto desde cero o buscar alguna solución open source para satisfacer nuestras necesidades.

Como nota personal, admito que en el momento cero me vi tentado a crear este componente por mi cuenta. Pero en pos de ser más rápidos a nivel producto y que nuestras necesidades en esta instancia eran bastante básicas, terminamos utilizando una librería llamada CodeMirror.

Las cosas se pusieron verdaderamente interesantes al momento de codear el Backend. Para los tests unitarios decidimos utilizar mocha por dos motivos: el primero fue que es una librería con una dificultad de aprendizaje muy baja lo cual nos sirve para escalar esta funcionalidad y sumar muchos desafíos en poco tiempo.

El segundo fue que es altamente flexible a la hora de reportar resultados de los tests (Mocha reporters) lo cual para nosotros era algo muy importante ya que una de nuestras necesidades era poder mostrar el resultado en una UI, no sólo en la terminal.

Una vez solucionado el problema de que librerías utilizar - tanto en el Frontend como en el Backend - invertimos mucho tiempo en pensar la mejor forma de que nuestro microservicio sea escalable y resiliente a personas malintencionadas. Luego de mucho brainstorming y pruebas terminamos con un esquema en donde los tests no corren al mismo nivel que vive el microservicio sino que tienen un mayor grado de abstracción. De este modo, en caso de haber alguna falla el servicio no se ve afectado en su totalidad, solo el contenedor donde corre ese test especifico.

Para hacer esto utilizamos Docker y visualmente quedo algo así:

En la  imagen de arriba tenemos cuatro usuarios ejecutando la acción de probar código en el mismo segundo. Esto dispara que nuestro microservicio cree de forma dinámica cuatro contenedores (uno para cada usuario) en los cuales se va a ejecutar la batería de tests correspondiente en base al código que entrega cada uno. Luego de hacerlo, el reporter de Mocha devuelve la información a nuestro Frontend para que este le de a cada usuario el feedback correspondiente. Los contenedores que antes se crearon dinamicamente, ahora se destruyen para no ocupar espacio innecesario.

El resultado final de este proyecto es el siguiente:

Sobre mi

¡Hola! Mi nombre es Juani Gallo y soy uno de los fundadores de CourseIt. Si te quedaste con alguna duda sobre el post o hay algo que quieras hablar conmigo, no dudes en mandarme un mensaje privado a mi Twitter https://twitter.com/_JuanGallo que con gusto voy a tratar de ayudarte!