martes, 24 de mayo de 2011

Los aeropuertos los diseñó un informático

Imaginemos un sistema en el que haya que hacer una cola y pasar un control de acceso en cada paso. No hace falta pensar mucho: es un aeropuerto. Cuando una persona quiere hacer un viaje internacional en primer lugar debe dirigirse a las máquinas que le darán su tarjeta de embarque identificándose mediante su pasaporte o DNI. A continuación acude al mostrador de facturación donde se encargarán de recogerle la maleta. Posteriormente franquea el control de acceso de seguridad donde unos vigilantes le someterán a un registro. A continuación, ya en la zona de embarque, pasará el control policial de pasaportes o documentos de identidad, y una vez allí se dirigirá a la puerta de acceso al avión donde le volverán a pedir su tarjeta de embarque y su pasaporte. En total 5 colas, 5 validaciones y 2 documentos identificativos.

A esta organización los informáticos le llaman “delegación de servicios”, e insisten en que es una política eficaz para, por ejemplo, programar aplicaciones web. Lo justifican diciendo que es eficaz que el guardia civil esté especializado en controlar pasaportes y sólo se dedique a inspeccionar la situación legal del viajero. Es eficaz que el que factura maletas sólo haga esa tarea porque tiene las pegatinas preparadas y te imprime eficazmente el nombre de tu aeropuerto de destino. Es eficaz que la persona que te cachea sólo haga eso porque es especialista en encontrar armas en rincones ocultos del cuerpo, y es eficaz que el que se queda con un trozo de tu tarjeta de embarque y te devuelve sólo el pedazo pequeño esté ahí porque él sabe romper tarjetas de embarque como nadie. Bien, pues cualquiera que haya seguido este proceso acaba calculando que incluso en un aeropuerto mediano no colapsado hacen falta unas dos horas para recorrer el camino desde la puerta de entrada de la terminal hasta sentarse en el avión. Y siendo benevolente ignoraré en este artículo que la presunta eficacia de este modelo aeroportuario es cuestionable cuando anualmente se pierden un millón de maletas en el mundo que van a parar lugares equivocados.

El paradigma contrario a este modelo es la “orientación a procesos”. Por ejemplo, un Spa, donde el servicio funciona como en un túnel de lavado: cuando sales de la piscina ya te está esperando el masaje, y cuando terminas ya tienen lista la siguiente ducha. ¿Por qué? porque se orienta hacia el proceso. Estos sistemas es imprescindible que estén bien dimensionados.

Pero en las horas eternas de espera en el aeropuerto todo el mundo se pregunta: ¿por qué no podemos hacer una única cola y cuando nos toque el turno hacemos todos los trámites de golpe? Pues porque esto por fuerza lo diseñó un informático. Y por esta razón los informáticos diseñan sus servidores web igual. Crean un servicio especializado en autentificar al usuario, crean otro de acceso a base de datos y recursos varios, crean un servicio especializado en lógica de negocio, que se puede subdividir en múltiples subservicios, y así hasta la náusea. Y a esto le llaman “arquitectura por capas”.

El modelo en sí mismo no es que sea malo ni bueno, pero es ineficiente en procesos en los que prima la rapidez. Si los recursos hardware fueran ilimitados quizá sí que tendría sentido plantear estas arquitecturas. Con máquinas infinitamente rápidas que manejaran tiempos de respuesta prácticamente nulos no se plantearían problemas. Pero en los aeropuertos, como en nuestros sistemas, se ralentizan los tiempos porque continuamente se están haciendo verificaciones. ¿De qué sirve que te hayan dado una tarjeta de embarque al principio si el encargado del control de acceso ha de volver a examinarla y el de la puerta de embarque la revisará otra vez? ¿De qué sirve enseñar el pasaporte a la máquina de tarjetas de embarque si luego hay que volver a enseñarlo a la guardia civil para pasar el control de acceso y para montar al avión? Es más, ¿y por qué hacen falta dos documentos?

Las arquitecturas por capas emplean mucho tiempo en analizar las peticiones en cada nivel, como una oficina donde hay que explicar la misma historia en cada ventanilla. Aunque el programador intente aliviar la carga de trabajo, al final la programación mediante patrones elegantes de diseño, uso de interfaces abstractos y clases delegadas, en la práctica se validan reiteradamente los parámetros, se acude varias veces al mismo repositorio para identificar los datos del usuario y sesión que ha hecho la solicitud, se vuelven a instanciar objetos de negocio intermedios necesarios, se llama a los mismos servicios, etc. Si los seres humanos fuéramos requests de http sufriríamos la burocracia en nuestras carnes.

Cuando alguien os explique un diagrama de la arquitectura de un sistema y lo que dibuje se parezca a un montón de cajas apiladas, echaos a temblar. Los servidores web corren sobre máquinas físicas y sus recursos son limitados. Y sobrecargar las peticiones a otras máquinas para multiplicar el mismo trabajo contribuye a colapsar el sistema. ¿Sabéis qué pasa si ponéis muchas máquinas? Que el volumen de tráfico entre ellas aumenta de forma mayor que la lineal, oscila entre una dependencia cuadrática y factorial según la topología de máquinas que hayáis elegido. Y por eso es difícil escalar algunos sistemas mal concebidos, porque sólo con añadir unas pocas máquinas se supera el umbral de colapso. ¿Y qué es el umbral de colapso? Es el límite a partir del cual un servidor emplea más tiempo en gestionar comunicaciones con los demás que en realizar su propio trabajo. Cada vez que se hace una petición hay que seguir un protocolo, abrir un socket, establecer comunicación, esperar la respuesta... ¿Sabéis por qué se colapsa un sistema? Porque las máquinas dejan de hacer su trabajo, se dedican a comunicarse entre ellas y sólo esperan que la de al lado les conteste. ¿Y verdad que a nadie se le ha ocurrido poner un límite a las peticiones? Pues es una de las claves esenciales para la estabilidad de un sistema.

Sí que tiene sentido separar los servicios cuando por ejemplo hay un recurso único compartido por muchas máquinas, como típicamente el acceso a base de datos o a ficheros para evitar conflictos de concurrencia. Y aun así si vuestro volumen de peticiones es pequeño programaos vosotros mismos un semáforo. Si sólo queréis hacer operaciones de lectura quitad la capa de acceso de datos y leed directamente porque el sistema operativo ya se encargará de gestionaros el acceso a los ficheros. Más cosas: poned límites al número de peticiones. Los locales públicos inventaron el aforo limitado hace tiempo, y lo podréis ver en cualquier museo en el que el público va entrando a medida que otros salen. Acordaos de vigilar los cuellos de botella: no hagáis como el Zara que sólo tiene una caja y las colas para pagar pueden dar tres vueltas a la tienda. Importantísimo, cachead los datos. Si has emitido una tarjeta de embarque fíate de ella y escribe allí los datos que necesitas, olvídate del DNI y ten a mano un sistema para recuperar a qué usuario corresponde. Y fragmentad vuestras aplicaciones horizontalmente: usad máquinas distintas para resolver peticiones distintas. De igual manera que decidís implementar distintas aplicaciones para ofrecer distintos servicios, separad los casos de uso de vuestra aplicación y repartirlos en máquinas diferentes.

Y cuando programéis, entonces sí, haced las divisiones por capas lógicas en el software. Tiene todo el sentido del mundo que vuestras clases y objetos estén bien estructurados. Sed ordenados, pero no se lo contagiéis al hardware salvo en caso de necesidad. Que corran únicamente los procesos en memoria. Y cuando un analista os lance frases como “aquí vamos a crear una capa intermedia en la que delegaremos algunas validaciones de datos y añadiremos un nivel más bajo en el que delegaremos servicios básicos”, huid. Bueno, programadlos porque os están pagando, pero dejad el código anterior entre comentarios porque lo tendréis que retocar. Y cuando seáis analistas, no planteéis nunca ni una capa más.

No hay comentarios:

Publicar un comentario