El gran problema de las Single Page Applications

Buscando la experiencia del usuario la capa de visualización cada vez es más compleja. Se introducen animaciones, efectos, transiciones y otras técnicas para mantener al usuario el máximo tiempo conectado a la aplicación.
El aumento de la complejidad de la visualización y la existencia de diferentes dispositivos en donde mostrar la aplicación, ha provocado que se separe la capa de presentación de la capa de servicio, que ofrecen y gestionan la información, dejando expuesta las operaciones que manejan la información de nuestro aplicativo.

Qué pasó con servidores J2EE

Se habla que, los pesados servidores de aplicaciones J2EE como Jboss (Wildfly), Glassfish o Geronimo están siendo desplazados por entornos más ligeros, sobre todo motivado por la búsqueda del ciclo rápido de prueba. Es decir poder editar, guardar y probar. Saltándose en todo lo posible la fase de despliegue.

A la hora de buscar servidores «ligeros» dos nombres vienen a la cabeza: Jetty y Tomcat. Ambos son contenedores de aplicaciones web, pero con algunas simplificaciones sobre toda la capa de funcionalidades que define J2EE.
De los dos anteriores Apache Tomcat es el de mayor de edad, convirtiéndolo en el contenedor ligero más usado y desplegado. La gente lo conoce bien, y ha evolucionado positivamente a la par que es estándar J2EE, en cuanto al perfil web de todo el compendio.

Hace un par de años, habría apostado que los servidores de aplicaciones completos J2EE habrían dominado el mundo, principalmente por un motivo: la facilidad con la que pueden aislar la capa de negocio y ser compartida entre diferentes aplicaciones mediante el uso de EJBs. Esta simple afirmación tiene toda una letanía de implicaciones como la transaccionalidad, incorporar una capa de modelo de datos independiente, permisos de ejecución, registro de trazas, independencia del sistema de persistencia, serialización, manejo de sesiones, clustering, etc…

Ahora bien, estas funcionalidades incluidas en los servidores empresariales debería haber desplazado a los servidores ligeros fuera del panorama, sin embargo la adopción de arquitecturas con capas de micro servicio ha dado un vuelco a la situación.

Las capas de micro servicio es como volver atrás en el tiempo en un dejavú en el que se sacrifican la mayoría de las funcionalidades que ofrecen los EJBs, nos hace recuperar aquellos apuntes de arquitecturas SOA, llevándonos a la mente términos incómodos como CORBA, SOAP o RMI.

Pero algo bueno tienen que tener para tener un incremento en la adopción y básicamente es que tienen tres puntos fuertes.

Micro-servicios everywhere (en Java)

Comenzar a ejecutar un micro servicio web es tan sencillo como ejecutar un public static void main(String[] args) que abra un socket desde el entorno de programación y así pode darle al play, pause, restart o debug. Esto quedará claro con un ejemplo:

package hello;

import org.springframework.boot.*;import org.springframework.boot.autoconfigure.*;import org.springframework.stereotype.*;import org.springframework.web.bind.annotation.*;

@Controller@EnableAutoConfigurationpublic class SampleController {

	@RequestMapping("/")	@ResponseBody	String home() {		return "Hello World!";	}

	public static void main(String[] args) throws Exception {		SpringApplication.run(SampleController.class, args);	}	}

Este ejemplo está extraído del tutorial de spring-boot. El cual crea un servidor http disponible en el puerto 8080 y que devolverá la cadena de texto «Hello World» a una petición http://localhost:8080/ 

Independizan, no sólo la capa de negocio sin no también las aplicaciones. La mayoría de las arquitecturas de micro servicio exponen la lógica de negocio en algún formato que funcione bien y sin complicaciones sobre las comunicaciones http, y éstas son por excelencia Xml y JSON, donde no importa si un servicio está hecho en Java, .Net o Php.

Y que fácilmente son verificables mediante un simple comando como curl. Basta leer por pantalla la salida del comando y en lenguaje bastante sencillo, comprobar que las fechas tienen un valor correcto, los números tienen los puntos donde toca y las tildes se ven bien.

A mi entender, gran parte de culpa en el auge en la aceptación de micro servicios la tienen los marcos de trabajo spring-boot o dropwizard en conjunción con el gestor de dependencias Maven dentro del mundo de Java.
No han sido los primeros frameworks en incorporar micro servicios, pero sí han calado hondo en el mundo de Java al simplificar lo engorroso que es arrancar un servidor J2EE o un Tomcat con esteroides Axis o CXF. Ambos (en conjunción con los gestores de dependencias) permiten crear servicios web rápidamente en cuestión de minutos con el uso de anotaciones y ofrecen toda una capa de servicios que compensan el abandono de los EJBs como instrumentación, serialización Java a Xml o Json, clustering, cache y otras funciones adicionales.

Lejos quedaron los empaquetado de aplicaciones empresariales EAR, con horas de diversión infinitas escribiendo Xml, ficheros de Ant y Doclets.

Me atrevería a decir que el 80% del éxito de los micro servicios en Java es gracias a Maven. Este gestor de dependencias ha hecho tan sencillo incluir nuevas funcionalidades en un proyecto que tenemos al alcance de un par de clicks más de 800.000 librerías open source accesibles con documentación, fuentes y binarios preparados para ejecutar.

La accesibilidad de tal gran catálogo de componentes implica que una aplicación, rápidamente puede crecer en funcionalidades, pero también en tamaño, número de librerías incluidas y dependencias entre librerías, por lo que es posible que haya que gestionar diferentes versiones de alguna de ellas dentro del mismo contenedor. El cómo mezclar librerías y cómo arrancar y parar contenedores en donde hay más de una aplicación crítica puede volver a más de uno sudoroso por un tiempo, así que la gente tiende a aislar una aplicación por contenedor, favoreciendo aun más la arquitectura de micro servicio.

El auge de los frameworks javascript

Y aun hay otro elemento muy importante que ha catapultado la adopción de micro servicios: angular-js. Los frameworks de programación de aplicaciones web del tipo Single Page Interface – o Single Page Application – en general han promovido el consumo de datos, preferiblemente JSON, directamente del servidor, dejando la lógica de interacción de usuario plenamente en la capa HTML con Javascript. Esto ha producido un combo en la rapidez, tanto en la ejecución de la aplicación puesto que una vez cargado los recursos web sólo se accede al servidor para realizarle peticiones muy concretas y bastante más ligeras que procesar largos ficheros jsp/jspx/html….

Como en la agilidad de programar aplicaciones en las que no es necesario tener que parar y arrancar el servidor si únicamente se han realizado cambios en la capa de presentación. Incluso puede que ni se tenga que tocar el servidor de micro servicios si ya existe con anterioridad y sólo deseamos realizar un nuevo front.

Ahora bien, si el servidor no ofrece la lógica de presentación, ¿quién la hace? Pues no queda otra que introducir un nuevo elemento en medio de la cadena que sirva el contenido «estático» de la aplicación, es decir que ofrezca el HTML, Javascript, CSS e imágenes. Y aquí el ganador sin duda ha sido nodejs. Node es un micro servidor capaz de ejecutar Javascript, lenguaje bastante conocido por los programadores Web y que puede servir dichos ficheros. Aunque realmente se puede llegar a implementar toda la aplicación completa con Node si estás familiarizado con Javascript, pudiendo utilizar frameworks como expressjs o emberjs para realizar los micro servicios que devuelvan contenido en formato JSON, pero no es lo más común.

La capa de servicios es bastante delicada y no suele permitirse que algo no salga bien o no funcione como esperamos. Así que lo más normal es separar la capa de lógica de negocio en micro servicios e implementarlo en un lenguaje bastante maduro con tipado fuerte y compilable como puede ser Java. Y la parte gráfica, más dinámica en el tiempo con prototipos, marcas blancas, o experimentos con otros dispositivos visualizadores como tabletas u cambios de concepto en presentación se realice en HTML dinámico y por lo tanto usemos Node.

El haber introducido Node abre una puerta de posibilidades bastante extensa puesto que se han desarrollado una serie de herramientas sobre esta que simplifican y mejoran el desarrollo de aplicaciones web desde el punto de vista de los elementos con los que tiene que interactuar el navegador web: html, js, css… Estas herramientas van desde unificar varios js en uno, minificar js y css, comprimir imágenes, crear thumbnails, validar ficheros js, utilizar Typescript y un largo sin fin de posibilidades. Recomiendo echar un vistazo frecuente a yeoman.io puesto que es un gran punto de partida al simplificar el comienzo de un proyecto gracias a sus «quick starts» para Node.

Sin entrar en detalle de cómo implementar los micro services que viene siendo de la manera más tradicional (DTO, DAO, Hibernate, …), ya tenemos todo lo necesario para realizar aplicaciones en ciclos rápido de desarrollo en donde podemos tener dos equipos trabajando, uno en la lógica de negocio y otro en la presentación. Y producir así una aplicación web que acepte toneladas de visitas diarias sin requerir armarios de hierro conectados a la red eléctrica produciendo calor.

El gran problema de las Single Page Application

En la sección anterior hemos visto qué elementos utilizar para elaborar rápidamente una aplicación profesional que permita ciclos rápidos de desarrollo, equipos paralelos y minimice la dependencia entre proyectos. Pero todo esta estructura tiene un gran problema. Bueno, esta tiene realmente 2.

Search Engine Optimization

El primero y menos importante es el SEO. Aunque se sabe que el indexador de Google es capaz de ejecutar aplicaciones escritas en los principales frameworks usados como Angularjs (cabe recordar que es un proyecto de Google), mucho del contenido se solicita al servidor mediante alguna acción de la interfaz de usuario como pueda ser seleccionar una categoría, sección o tema, filtrar por fecha. Estas acciones requieren entender conceptualmente los elementos gráficos dispuestos en la pantalla y saber interactuar con ellos para obtener la información deseada. Y aquí es donde entran las dudas de si el indexador de Google es capaz de obtener todo el contenido.

Para garantizar que el indexador encuentre todo el contenido se requiere montar elementos adicionales como el fichero de robots.txt o sitemap.xml en donde aparezcan todas o una gran parte de las urls que contienen el contenido a indexar, ya sean páginas específicas para ello, versiones simplificadas de la aplicación (ambas con un aumento del trabajo a realizar) o si usas un buen framework quizás algunas tareas más sencillas que te simplifique esa tarea.

Exposición de servicios

Pero como he dicho, ese es el problema menor. El gran problema es que en una aplicación de una única página el consumo de los datos se realizará mediante peticiones al servidor en donde los datos viajan claros. Las peticiones se realizan con sencillas llamadas Http como GET http://servidor.dominio.ext/aplicacion/modulo/seccion/id/fecha/… Y la respuestas vienen en un formato fácilmente entendible por Javascript, y también por el Indexador de Google.

Tan clara es la respuesta que se le ofrece, que se le está entregando una información perfectamente estructurada y lista para ser incorporada en los sistemas del indexador, y no sólo los campos que queremos que los usuarios vean en pantalla. Por lo tanto, ¿qué impide que el indexador realice llamadas indiscriminadas al API para exprimir el sistema de información tras la aplicación? Nada.

Una vez que el sistema decodifique las llamadas al API identificando los parámetros y cómo se varían entre llamadas sucesivas, puede sin mucha dificultad extrapolar los valores necesarios para realizar consultas adicionales que pueden ir desde las páginas siguientes, a otras secciones, otros documentos, u otros servicios.

Conclusiones

Hoy en día, el principal activo de las empresas que basan su negocio en Internet es la información. Y proteger el consumo de la información es un derecho y también una obligación si se trata de datos de carácter personal. Por lo tanto debe protegerse bien de accesos no autorizados y el uso de la información en ámbitos no designados para tal fin. Recuerda tener presente varios puntos para proteger la valiosa información:

  • Catalogar bien el API que quedará expuesto públicamente en Internet
  • Revisar periódicamente que la información ofrecida por dichos servicios, tras las modificaciones a lo largo de la vida del proyecto, es necesaria para la capa de presentación y no viola ningún acuerdo legal o marco legislativo.
  • Incorporar controles para evitar el consumo indiscriminado de dichos servicios, como accesos al API con fecha de caducidad y limitadores por número peticiones.
  • Utilizar siempre que sea posible SSL, como norma general. Existe un proyecto a tener en cuenta que pretende generar certificados SSL válidos para los navegadores de forma gratuita con el fin de dotar mayor seguridad a Internet: https://letsencrypt.org/

Aun incorporando esas medidas no se garantiza que el mayor activo de la aplicación tenga un buen destino. Así que es importante decidir si realmente para el objetivo del proyecto es mejor la flexibilidad y agilidad en la elaboración del mismo o mantener el control de la información ofrecida mediante la generación de las páginas HTML de forma más tradicional en donde más fácil establecer límites y controles en consumo de la información.

Autor: Ramón Arnau

Director de Arteco Consulting sl. Ingeniero Informático. Máster en Administración y Dirección de Empresas. Máster en Tecnologías de la Información. Auditor ISO 27001. ITIL.

Un comentario en “El gran problema de las Single Page Applications”

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *