Pruebalo en vivo: RealPoll en Azure

Tras mi primer proyecto personal (que con suerte verá la luz en marzo o abril) con Angular.Js, he estado jugando con diferentes tecnologías web haciendo un remake de un proyecto que surgió en un hackatón, presentando Realpoll.

La idea

Profesores y conferenciantes, a menudo, necesitan una manera de interactuar con la audiencia y darles la posibilidad de participar en la charla o en el tema a tratar. Hoy es habitual ver a estudiantes jugando o twitteando desde clase, lo que significa que tienen acceso o bien a una red wifi o bien a banda ancha móvil. La respuesta de algunos centros ha pasado por bloquear este tipo de comunicaciones, pero, y si lo usamos a la inversa?

Esta aplicación web permite a profesores prepararse algunas preguntas de antemano, escoger el número de respuestas, señalar aquellas que sean correctas, y mostrarla en un proyector. Los estudiantes pueden entonces o bien votar usando la url que se muestra, o bien a través de su móvil con el código QR que se genera. Los únicos datos almacenados son las preguntas con sus respectivas respuestas, no los votos, de tal manera que la pregunta se puede reutilizar cuantas veces sea necesario.

La interfaz de votos es muy, muy sencilla, solamente introduce un nombre y haz click en la respuesta escogida, y el resultado se mostará inmediatamente en la página de resultados

Remake de un clásico

RealPoll es, de hecho, un antiguo proyecto desarrollado en un hackathon con las siguientes herramientas:

100% HTML + Javascript

redis para la capa de datos

socket.io para la interacción en tiempo real

express.js para gestionar las rutas y las vistas

google charts para los gráficos de “tarta”

jQuery para manejo de DOM

Heroku como plataforma en la nube

desarrollado con VIM

Para este proyecto, quería mantener la misma idea, pero cambiar completamente las tecnologías empleadas:

50% HTML + Javascript, 50% C#

sql + entity framework para la capa de datos

signalr para la interacción en tiempo real

ASP.net MVC para gestionar las rutas y las vistas

Chart.js para los gráficos de “tarta”

jquery and Angular.js para la gestión de vistas

RazorEngine para generar la vista que se envía por e-mail

Git/github como gestor de código fuente

Windows Azure como plataforma en la nube (conectada a github)

Visual Studio + IE dev tools + Chrome dev tools (+ Safari dev tools en mac)

Sendgrid para el envío de e-mails.

Arquitectura

La parte de servidor es puro ASP.net MVC con los datos almacenados en una tabla de SQL Server y algunos servicios adicionales que me hacen la vida más fácil.

La base de datos, como he mencionado antes, almacena cada pregunta y sus correspondientes respuestas, de tal manera que podamos acceder más adelante a través de una URL. La URL es un hash basado en el identificador de la pregunta, el proceso de votación no se almacena, con lo cual se resetea cada vez que actualizamos la página de resultados. La comunicación entre mdelo y base de datos se realiza a través de Entity framework, rl ORM open-source de Microsoft.

Para poder usar datos sin tener que precocuparme del ORM, he usado técnicas de inyección de dependencias para injectar un conjunto de datos falso. El motor de inyección de dependencias usado ha sido ninject, y aunque he tenido que crear dos clases diferentes para la resolución de dependencias en ASP.net MVC y en SignalR, tenía un punto de entrada único para reemplazar el acceso “falso” usando datos de un origen de datos del ORM. Usando además diferentes opciones de compilación y los ficheros de compilación, he podido hacer diferentes pruebas con exactamente la misma base de código.

Flujo

Nueva pregunta

Al crear una nueva pregunta, se muestra un formulario simple realizado con bootstrap para los componentes de la UI y Angular.js para las actualizaciones cuando el número de respuestas cambia. (una de las cosas que ha quedado pendiente es el tema de la localización, aunque, si hay alguien interesado, acepto pull requests :))

Pregunta creada

Al crear una pregunta, los datos de la misma son actualizados en la base de datos, y vemos una página de confirmación similar a esta:

Para generar la plantilla de e-mail uso RazorParser, una biblioteca disponible vía nuget que genera una vista HTML a partir de un modelo y un fichero. Una vez generado se puede usar como un bloque de texto (string). El envío de e-mail se realiza usando los valores SMTP de sendgrid, usando las funciones estándar de envío de SMTP.

Página de resultados / Dashboard

La página de resultados es una de las más complicadas e interesantes, los gráficos están creados usando chart.js con un wrapper para poder usarlo a través de angular, el código QR está generado usando la api de qrkit y se actualiza en tiempo real usando angular.js y signalr para gestionar la vista.

Cuando el contador llega a 0, la solución correcta se marca en verde, así como los nombres de aquellos que han acertado.

Interfaz móvil

Como bootstrap está preparado para móvil, tuve que hacer solamente algunos cambios para que la interfaz de usuario funcionara correctamente, así como un poco de depuración en el iPhone usando Safari para Mac (cuyas herramientas de desarrollador se han quedado un paso por detrás de las de IE o Chrome). El plugin de “cookie consent” también se adapta, así que sin problemas.

Estadísticas y cookies

Como el objetivo del proyecto era jugar con la tecnología, no he empleado demasiado tiempo con las estadísticas, aunque cada página cuenta con un código de analytics. También, el hecho de estar en la Unión Europea implica cumplir las leyes respecto al control y uso de cookies, con lo cual he usado el plugin [cookie consent] mencionado anteriormente, que muestra al usuario un banner que le permite controlar el tracking que se hace por parte de google analytics.

Código fuente, despliegue y depuración

Para este proyecto he usado git como gestor de código fuente, github como repositorio remoto y el despliegue ha sido en Windows Azure. Al estar basado en git, me permitía poder volver a un despliegue anterior de manera sencilla a la vez que mantengo las opciones de despliegue continuo.

Problemas, curiosidades y “cosas raras”

Hay un bug con angular.js y el “browser link” de visual studio que causa excepciones en el depurador, el equipo de producto de VS es consciente de ello.

Para agregar inyección de dependencias, necesitas definir dos dependency solvers completamente diferentes, ya que heredan de diferentes ensamblados e implementan diferentes interfaces.

completamente diferentes, ya que heredan de diferentes ensamblados e implementan diferentes interfaces. Validar los datos de entrada es más fácil con HTML5, pero Safari (y especialmente Safari para iPhone) no soportan la etiqueta required . Una utilidad interesante para saber qué capacidades tenemos y cuales no es caniuse

. Una utilidad interesante para saber qué capacidades tenemos y cuales no es caniuse Para depurar en Safari para iPhone necesitas Safari en Mac OS X (En windows no funciona :( )

Cuando re-despliegas una solución en azure con la configuración por defecto, todas las excepciones trazadas por elmah se pierden.

He usado algunas transformaciones XML curiosas para manejar cambios locales, remotos y bases de datos falsas, puedes leer más aquí.

Margen para la mejora

Se pueden hacer las cosas mejor, casi siempre, no tengo ni una línea de código de test más allá de mi falsa base de datos, asi que podríamos considerarlo bastante inestable. El objetivo de este mini proyecto era integrar la mayor cantidad de tecnologías posibles para crear una solución lista para desplegar relacionada con datos en tiempo real. Tal vez podría haber agregado algunas pruebas con selenium, y algunos test unitarios tanto para angular como para ASP.net MVC.

Pruébalo

Puedes verlo publicado en Azure o también ver el código publicado en mi repositorio en github y desplegarlo por tí mismo. Necesitaras tus propias APIs y tu propia base de datos para hacer que funcione. Se aprecian comentarios, y si quieres contribuir de vuelta, envía un pull request!