domingo, 14 de noviembre de 2010

La evolución de las especies abstractas

Dice un principio del mundo de desarrollo del software, medio en serio medio en coña, que cualquier problema (en el ámbito este del desarrollo) se resuelve con otra capa más de abstracción; con otro wrapper sobre la tecnología existente.

La palabra wrapper, en el contexto de la informática, no tiene una fácil traducción. Envoltorio, lo definen en algunos sitios. Pero no es muy preciso. Ciertamente, a veces una tecnología hace como de envoltorio de otra. La envuelve de modo que tú sólo ves la tecnología más exterior. Como si fueran capas de una cebolla. Sólo ves la capa más externa que es con la que interactúas. A mí me gusta llamarlo capas o niveles de abstracción. Porque cada vez que la humanidad desarrolla una de estas capas, se crean nuevos conceptos que son abstractos, para que no tengas que lidiar con la vieja tecnología que, cosas de la evolución, de repente se nos antoja muy complicada. Es cierto que estos conceptos abstractos nuevos nos simplifican la vida, haciéndonosla más fácil, pero ay de ti como quieras bucear hasta los niveles más interiores; ya te puedes armar de paciencia. Se van creando capas sobre capas con el paso de los años, y, sin darnos cuenta, vamos creando un mundo cada vez más complejo, aunque afortunadamente, se supone que la gran mayoría de nosotros sólo lidiamos con la capa más exterior, y por ende, más simple.
Esto es especialmente cierto en el mundo del desarrollo software. Pero como todos sabemos, cada vez más cosas son software, así que esta teoría se aplica a nuestra vida cotidiana cada día más sin casi sin darnos cuenta.

Sin embargo no deja de preocuparme (más bien fascinarme) los sucesivos niveles de abstracción a medida que avanzan los años. Y no soy el único. Tanto es así, que el “teorema” que menciono al principio tiene también un corolario, con el mismo nivel de seriedad, que dice: Todos, menos el problema de exceso de niveles de abstracción.
Como si de una amenaza, casi un profecía, se tratase, este corolario nos advierte ya hoy de lo peligroso de este problema y nos acerca una de las conclusiones de esta mi reflexión: simplificamos a costa de complicar.

En el mundo de la arquitectura software el concepto de complejidad está muy de moda. Todos los más reconocidos gurús nos sugieren evitarla a toda costa. Y eso es precisamente lo que se está haciendo: la mejor manera de simplificar una pieza de software es hacer un wrapper sobre ésta que sea más sencillo de dominar. He aquí el origen del teorema.

No deja de ser paradójico, que esas piezas de software encargadas de abstraer otra pieza de software, para hacernos la vida más sencilla a los informáticos, son auténticas joyas de la programación; un software realmente complejo, tanto que la mayoría de los programadores/analistas/arquitectos sabemos que no estamos a esa altura. Creo que la empresas o fundaciones encargadas de desarrollar estos wrappers son las que aglutinan a la élite de la programación, y es generalmente ahí donde se forjan los gurús que toman las riendas de la comunidad de los desarrollos durante un tiempo; hasta que se desarrolla un nuevo wrapper sobre lo que ellos desarrollaron y entonces quedan eclipsados (que no desprestigiados, ni mucho menos).

Estas capas de abstracción no se desarrollan de un día para otro. Tardan mucho en pensarse, desarrollarse y sobre todo implantarse. Cada pocos años emerge una, aunque no todas llegan a buen puerto. Esta evolución a base de wrappers me recuerda a un árbol grande cortado, en el que se pueden ver los diferentes anillos concéntricos que nos revelan la edad del árbol. Del mismo modo, desde que existe el software, la edad o el nivel de evolución de la humanidad (y seguramente el de otras vidas extraterrestres :-) ) se mide por cuántas capas de abstracción nos encontramos en el día a día. Podríamos compararlo mejor, con las diferentes y sucesivas capas de sustrato que vemos en la pared de una colina que han cortado transversalmente para hacer una carretera. No hace falta ser geólogo para ver que han pasado muchos años por esa colina. Cada capa de la pared es de un color y un grosor que nos da una pista de lo que pasó en la época de esa capa. Y eso mismo sucede con el software, y es especialmente fácil de ver para los que llevamos una pila de años desarrollando software. Para los que no, voy a intentar explicarlo en el resto de este post.
Hace años, tampoco me voy a remontar a más de 30, no es necesario para entender esto de los niveles de abstracción, cuando desarrollabas un software generalmente lo hacías para un microprocesador concreto. Si tu ordenador tenía un procesador Z80, escribías un código muy críptico para dar instrucciones al procesador; es lo que se llama el lenguaje ensamblador. Una parte del microprocesador convierte ese código a 0 y 1 que es lo que al final entienden todos los microprocesadores.
Claro, tu código sólo servía para los ordenadores que tenían ese procesador. O peor aún, a pesar de que algunos ordenadores de aquella época compartían el procesador Z80, lo que programabas para un Amstrad no valía para un ZX Spectrum.
Esto fue así durante mucho tiempo.

Luego llegaron lenguajes de más alto nivel, como el Basic, Pascal o especialmente el C, que fue el que más triunfó. No he usado más documentación que mi propia memoria para escribir esto, así que no me machaquéis por las imprecisiones, especialmente las imprecisiones en el tiempo. El caso es que allá por los años 80 se empezó a popularizarse en todo el mundo el lenguaje C (en España como siempre, íbamos con algunos años de retraso). Y esta fue para mí la primera gran capa de abstracción. Entonces tú escribías el código de un programa sin pensar en que procesador se iba a ejecutar. De eso se encargaba el compilador, que era un programa al que le decías “conviérteme este código en lenguaje ensamblador para el procesador i8086” “o para el m68000”. El compilador fue el artífice de ese nivel de abstracción. No sólo el lenguaje C hacía que te olvidases de en qué procesador se ejecutaría el programa, sino que además simplificó mucho la vida del programador, ya que éste era mucho más fácil de entender, y por tanto de modificar y mejorar.
Y para mí este fue el primer gran paso hacia la carrera, aun hoy vigente, de intentar simplificar la vida al máximo del desarrollador.

El lenguaje C estuvo mucho tiempo entre nosotros. Tanto fue su éxito que aun hoy mucha gente programa en C. O por lo menos en C++, que no es sino otro nivel de abstracción sobre el lenguaje C. Se trata de la programación orientada a objetos. Los objetos, informáticamente hablando, no son más que una abstracción sobre las tradicionales estructuras de datos de otros lenguajes. Tenemos pues una segunda capa de abstracción que empezó a triunfar en España a principios de los 90. Una década más o menos después del asentamiento del lenguaje C.

Pero entonces (poquitos años antes, para ser preciso) empezó el boom (y la guerra) de los sistemas operativos (Windows, OS/2, Unix, Linux, Mac, etc). El sistema operativo es otro nivel más de abstracción, que se coloca entre el desarrollador y el procesador. A pesar del gran avance que supuso el C y el C++, hacer algo tan sencillo como pintar en pantalla una ventana con los botones de cerrar, minimizar y maximizar, podían ser miles de líneas de código en C.
Así que el sistema operativo proporcionaba (y aún hoy día se hace así) al programador una serie de funciones para que no tuviésemos que preocuparnos por las tareas más habituales como gestionar ficheros, ventanas, sonidos, tipos de letra, procesos en paralelo, controlar el ratón, el teclado, la tarjeta gráfica, etc. Fue un gran avance. Lógicamente, ya no bastaba con saber C++, sino que tenías que conocer las miles de funciones que los sistemas operativos nos brindaban. Hacer un programa que abría una ventana, de pedía que eligieses un fichero de tu disco duro y lo imprimiese, se podía hacer con apenas 20 líneas de código. El sistema operativo ya se encargaba de generar las instrucciones concretas para cada procesador. Insisto, fue un gran avance. Hay que decir que, a su vez, el sistema operativo estaba desarrollado en C. Una vez más, como pasó con los compiladores, se utilizó software, el sistema operativo, para facilitar el desarrollo del software. Y una vez más, se simplificó la vida de mucha gente, no sólo de los programadores. Los sistemas operativos de ventanas fueron un gran progreso para la humanidad en general.


¿Dónde estamos? Ah sí, el sistema operativo. Ahora, al usar las librerías propias del sistema operativo, ya no programabas contra un microprocesador, sino contra un sistema operativo. El código en C++ que pudieras escribir para Windows sólo valía para Windows. No funcionaría en Linux ni en Mac. Cierto es que con ciertas variaciones, especialmente en todo lo relativo a la interfaz de usuario, se podría hacer que un software corriese en diferentes sistemas operativos. Por eso había un Photoshop para Windows y otro para el sistema operativo de los Mac, que entonces creo se llamaba Sistema. Pero aun así, creedme, era un esfuerzo titánico migrar una aplicación de un sistema operativo a otro. Lógicamente, el código para pasar una foto de color a blanco y negro es el mismo, independientemente de para qué sistema operativo se desarrolle. Pero la ventana, los botones y en general todo el interfaz del Photoshop se programan muy diferente si lo haces para Windows que si lo haces para Mac. A veces por algo tan absurdo, como el hecho de que el ratón de los Mac sólo tiene un botón y el de los PC tiene dos.

Tener que pensar para qué sistema operativo desarrollar era frustrante para los comodones programadores. Los que programaban aplicaciones como el Word o el Photoshop lo tenían asumido porque el interfaz cambia tanto de un sistema operativo a otro que no había más remedio. Pero para los que por entonces ya programábamos aplicaciones “servidor” que no tienen ni siquiera ventanas, como pueda ser un servidor Web, ¿por qué pensar en el sistema operativo? Alguien muy listo (y con mucho tiempo libre) pensó en lo que será nuestro siguiente nivel de abstracción.

El invento se llamó Java, y la principal innovación, es que existe una especie de microprocesador virtual que sabe interpretar el código Java. Es lo que se llama la máquina virtual Java, o JVM. Esto ya va sonando más ¿eh? Si es que, a medida que nos movemos hacia las capas más externas, más masa crítica de usuarios encontramos, porque más sencilla de entender, y por tanto más desarrolladores encontramos. Poco tiempo antes habían surgido los lenguajes interpretados como el Perl o el PHP, cuya filosofía es similar a Java, pero en general se ejecutan más lentos.
La magia de Java es que existe una máquina virtual para Windows, otra para Mac, otra para Linux, para Solaris, para AIX, etc. Así, yo hago un programa en Java, que dicho sea de paso es más fácil de entender que el C++, y luego lo ejecuta la máquina virtual. Así que me da igual el sistema operativo. La máquina virtual ejecuta el código java, que lo convierte en instrucciones para el sistema operativo, y este lo convierte en instrucciones para el procesador , pasando por el hecho de que el sistema operativo está programado en C. No es que éste convierta el código Java en código C y éste luego se convierte a ensamblador. No, el sistema operativo lo convierte directamente a código ensamblador, pero el sistema operativo existe porque se desarrolla en C. Desarrollar un sistema operativo en lenguaje ensamblador directamente, sería poco menos que imposible. Sería como construir el Golden Gate sólo con martillos y llaves inglesas manuales.
Los lenguajes de programación interpretados como el Perl o el PHP hacen algo muy similar. Hay intérpretes de Perl y PHP para los principales sistemas operativos. Pera la filosofía de Java era más eficiente. Corrían bien entrados los 90 cuando Java empezó a triunfar. Y tanto fue así, que Microsoft empezó a imitarlo años después. Demasiados para mi gusto. Java había calado muy hondo y había cientos de miles sino millones de programadores desarrollando en Java. Microsoft lanzó su .Net para competir con Java, y aunque hay que reconocer que es una pieza de software muy buena, Java le lleva ventaja.

Una vez más, se usa software, esta vez la JVM de java o la CLI de .Net, para crear otra capa de abstracción. Y aquí ya se abre la caja de Pandora y se lía parda :-). Porque cuando empiezas a programar en Java (voy a referirme en los sucesivo a Java, aunque es igualmente aplicable a .Net) empiezas a usar librerías de código fuente que son wrappers sobre otra librerías y estas a su vez lo son de otras y así hasta... qué sé yo... ¿12 niveles? Sólo voy a citar un ejemplo, que aunque rebasa el nivel de complejidad que quería darle a este Post, puede ser ilustrativo:

El otro día estaba trabajando con un framework, Spring Integration, que hacía una consulta a una base de datos y enviaba lo que leía a una máquina remota. Todo esto lo hacía sin apenas programar 10 líneas de java y unas cuantas líneas XML. Esto hace años habrían sido miles de líneas de código. Esto es posible hoy día porque Spring Integration, en sus archivos de configuración XML, usa un wrapper sobre las librerías Spring Framework, que para el caso concreto del acceso a base de datos usa unas librerías llamadas JPA que son un wrapper sobre otras llamas Hibernate, que a su vez son un wrapper sobre JDBC que a su vez es un wrapper para independizarse de la base de datos, que a su vez es un wrapper sobre el SQL, que a su vez es un wrapper para uniformar la manipulación de las tablas de las bases de datos.

Y si la aplicación es web, prepara otras cuantas capas de abstracción en el navegador, desde las librerías más modernas de Javascript como Jquery UI o ExtJS, hasta el motor de renderizado de HTML de los diferentes navegadores...

Ya el C tenía sus propias librerías que eran wrappers de otras librerías, pero nivel de abstracción que ha adquirido el mundo Java/web asusta. No obstante no pretendo centrarme en los wrappers del código fuente, sino en los wrappers de las tecnologías software. Como la siguiente, siguiendo más o menos la línea de tiempo:
Los lenguajes basados en Java como Groovy o Scala. Hace unos años, no contentos con la simplificación que representa Java, alguien decide que se pueden hacer grandes aplicaciones sin tantas líneas de código Java (y mira que ya vienen siendo pocas) y desarrolla Groovy un lenguaje de programación nuevo, que genera, por decirlo de forma sencilla, código Java, para que sea ejecutado por la JVM.


No se vayan todavía, aun hay más. A medida que las aplicaciones de hoy días son más y más monstruosas, la figura de un administrador de sistemas se hace imperativa, porque estas aplicaciones ya no son como antes que las programa un programador y las instala en un PC y listo. No. La aplicación consta de muchos componentes que se instalan por separado generalmente en distintas máquinas, muchas veces totalmente deslocalizadas. Claro, si tu aplicación necesita de, digamos 20 máquinas cada una con su sistema operativo y su configuración propia, gestionar todas esas máquinas, que no fallen nunca, replicarlas para ofrecer alta disponibilidad, actualizarlas, hacer backups de todas ellas, etc. se convierte en un esfuerzo muy grande y muy complicado. ¿Has dicho complicado? No. Pasa. Nada.
Se mete un nuevo nivel de abstracción y asunto zanjado.
Dicho y hecho. Aquí tenemos la virtualización de los sistemas operativos y con ello la tan de moda Nube, que es otra abstracción más.

Pero vamos por partes, que he soltado ahí la palabrota virtualización muy a la ligera. La virtualización lo que permite es ejecutar varios sistemas operativos sobre un mismo ordenador que ejecuta a su vez otro sistema operativo llamada el sistema operativo Host. En este host, que puede ser, digamos un Windows Server, abres en una ventana un Linux, en otra otro Windows y en otra un MacOS. Y estos tres usando los recursos hardware del sistema Host. Lógicamente no funcionan tan rápido como si se ejecutasen directamente sobre el PC. ¿Para qué hacer eso si el hardware está muy barato hoy día? Se preguntan los más novatos. Para simplificar su administración, la administración de la red de equipos en general. Un sistema operativo que se ejecuta virtualizado en una ventana, tiene toda su información en un fichero gigante del sistema host. Esto significa, que si me llevo ese fichero a un disco duro externo acabo de hacer un backup completo, no sólo de los datos como viene siendo habitual, sino del sistema operativo en sí, con toda su configuración. Si el hardware falla, sólo tengo que llevarme ese fichero a otro PC y en 30 segundos tengo todo funcionando como si no hubiese pasado.
Se pueden hacer cosas como tener 10 PC potentes ejecutando 60 máquinas virtuales, es decir, con 10 sistemas operativos Host, tengo 60 sistemas operativos corriendo. Y el programador no sabe si la máquina donde se ejecutará su código es una máquina virtual o no. Seguramente lo sea. Y si alguna de los 10 PCs host falla y se apaga de golpe no pasa nada, porque lo que se estaba ejecutando en ese PC también se estaba ejecutando simultáneamente en otros dos más. Así que el sistema global que gestiona todas las máquinas virtuales y los host, se encarga de que ahora, en lugar de estar funcionando en una máquina virtual sobre el PC A, estás en un clon de esa máquina virtual en el PC B. Y todo esto de forma transparente para el usuario. El administrador de sistemas recibirá una alerta de que se ha muerto el PC A, se reemplaza, y se reintegra en el sistema y empieza a clonar algunas de las máquinas virtuales por si fallase otro PC.

Esta magia, por si no os parece suficientemente sorprendente, creedme, es algo muy complicado y la gente que desarrolla esta tecnología no son precisamente cuatro becarios.

La virtualización tiene otras muchas ventajas, como la eficiencia energética o la asignación dinámica (sin parar la máquina) de recursos como más memoria o más espacio en disco. En general, insisto, es un gran avance.

Y, como ya me he precipitado en avanzar, existe otro nivel más de abstracción que lo que llaman la nube, el cloud computing. Este concepto de la nube es más un cómo y no un qué. Tú haces un programa y lo hospedas en la nube, de, digamos Google, o Amazon. La nube es siempre la nube de alguna empresa. Y esa nube hace referencia a una cantidad ingente de máquinas Host que ejecutan sistemas operativos virtualizados. Lo que acabamos de ver. Sucede que el programador no se preocupa ni siquiera por el sistema operativo virtualizado. Nosotros sólo subimos nuestro programa a la nube (a una de esas máquinas virtualizadas en realidad) con alguna herramienta generalmente integrada en el entorno de desarrollo. Luego ya ellos, los de la nube, tienen todo configurado para que mi programa se replique por multitud de sistemas operativos virtualizados para que siempre esté online. El concepto de la nube también tiene algo de complejidad pero nada que ver con la que entraña la virtualización de sistemas operativos o la que pueda tener la máquina virtual Java o un sencillo compilador de C.

Ahora mismo, a las puertas del 2011, estamos aquí, con la nube hasta en la sopa. Sin embargo, esto no es más que una parada más. Nadie sabe donde acaba esto. ¿Cuánto llegará a complicarse con el fin de simplificarnos la vida?

Imaginad por un instante, que alguien, no voy a decir ya un romano del siglo I AC, basta con decir del siglo XVIII, viaja en el tiempo hasta hoy, y nos ve usando una hoja de cálculo de Google Docs. Y pide: “explícame como funciona esto, hasta el último detalle”. No podría asimilar tanta complejidad de golpe. Imagino que sería algo similar a cuando los griegos clásicos intentaban entender la vida y el universo sin un microscopio ni un telescopio. No estaban preparados para absorber tanta complejidad y de ahí el origen de la mitología. Que digo yo.

A veces me gusta comparar la evolución del software con la evolución de las especies de Darwin. Imagino el álgebra de Bool, el álgebra binaria, el de los 1's y 0's, sería como la primera bacteria unicelular que apareció. Luego fue mutando y desarrollándose, adquiriendo complejidad hasta ser un pez, luego un anfibio, un reptil, un mamífero, un mono y finalmente el hombre (por no enrollarme demasiado). Si el álgebra de Bool es esa primera bacteria, ¿qué es la nube? ¿los primeros reptiles? ¿un dinosaurio? ¿un ave? ¿tal vez esté tan avanzada la cosa que sea el equivalente a un gorila? El caso es que el software, como la vida, ha ido desarrollándose y adquiriendo una complejidad alucinante.
Aunque para ser honesto, me sigue pareciendo mucho más complicada la vida. Creo que el sistema nervioso de cualquier mamífero tiene muchas más capas de abstracción (desde los átomos hasta el cerebro) que lo que llamamos la nube. Pero tiempo al tiempo.

¿Llegará el software a ser tan complicado como un cerebro humano? ¿Cual es el siguiente paso en esta carrera de abstracciones? Yo la siguiente la veo clara. De hecho, ya está prácticamente aquí. Se trata de eliminar el ordenador. El hardware es un atraso :-). Es decir, que sólo tendríamos una pantalla con una tarjeta de red, un teclado y un ratón, y lo que es todo el almacenamiento, procesador, y resto de hardware está en la nube. Yo encenderé mi pantalla y automáticamente recibiré por red el sistema operativo. Para que esto llegue hemos de pensar que la conexión a internet será tan segura como lo es hoy la corriente eléctrica o el agua. En realidad este concepto lleva varios años entre nosotros y no acabo de entender porqué no triunfa más. Se acabarían los problemas con los discos duros que se estropean, tarjetas gráficas que se quedan obsoletas, procesadores que se recalientan porque el ventilador lleno de polvo ha dejado de girar… Podría ser el fin de la piratería también. Al no tener el control absoluto sobre el sistema operativo sólo podrías instalar software legal. Pero tendrías todo el software del mundo y pagarías sólo por su uso. Por ejemplo, pagaría 10 céntimos de euro por cada minuto que utilice el word, o 50 centimos por cada minuto que use el 3D Studio Max (que consume mucha más memoria y procesador). Pagaríamos sólo por el uso. Dedicaré otro post a este asunto de virtualizar nuestro ordenador de sobremesa.

¿Y el siguiente paso? Aquí ya me adentro en terreno pantanoso porque no veo nada suficientemente claro. Supongo (deseo más bien) que se hará un wrapper sobre el interfaz de entrada salida… Tiene que llegar el día en que nos libremos del ratón el teclado y la pantalla. La pantalla quizá se soluciona con un microproyector, o mejor, con unas gafas que simulan una pantalla de 80 pulgadas (que ya existen hoy día aunque con una calidad un poco penosa). O ya puestos a soñar, pongamos otro wrapper más, para que podamos manejar nuestro ordenador virtual con la mente (que también se están haciendo pinitos en este sentido). Creo voy a parar aquí. No os voy a aburrir con mis paranoias de que en realidad no existimos sino que somos software, o que quizá se pueda virtualizar un cerebro y hacer que éste lleve 7 vidas paralelas como si de sistemas operativos virtuales se tratasen... bueno, ya.


Desde que empecé a pensar este post llevo buscando un ejemplo de un wrapper en el mundo ajeno al software, para ilustrar mejor este concepto y se pudiese entender mejor todo esto que cuento. Sin embargo, esta característica del software no se ve mucho en el mundo analógico. Os digo las dos mejores que se me han ocurrido. 
La primera sería un fondo de inversión. Yo puedo contratar un fondo que invierta en biotecnología en Sudamérica. Y si la biotecnología en Sudamérica va a más yo gano dinero. Pero en realidad el fondo está invirtiendo en empresas concretas de biotecnología en diferentes países de Sudamérica. Podría haber invertido yo directamente en esas empresas, pero tendría que averiguar cuales son, estudiarlas un poco… El fondo de inversión es esa capa de abstracción que me simplifica la vida a la hora de invertir.

El otro ejemplo es un termómetro digital. Seguro que a todos nos costó (a mi aun hoy me cuesta) ver la temperatura que marca el termómetro cuanto te lo quitas después de unos minutos. El funcionamiento de un termómetro clásico no puede ser más simple, sin embargo, su lectura es complicada. Así que alguien aprende a digitalizar lo que el mercurio quiere decir, y te lo muestra en una pantalla que dice 37.5C tienes fiebre. Ahora resulta mucho más fácil leer la temperatura, pero mira qué exageradamente complicado es un termómetro digital frente a uno analógico.

En cualquier caso, generalmente el mundo analógico sólo tiene un nivel de abstracción: pasar al mundo digital, y una vez entra en el terreno digital, el terreno del software, es cuando empieza esa escalada de capas y capas de abstracción. 
Lo mismo pasó con la música y el vídeo, que desde que se convirtieron en digital ambas industrias en general han sufrido tal evolución que no han sido capaces de manejarla con elegancia. Y le diría a los señores de la industria del automóvil que se vayan preparando :-).


En fin, todo esto, para darle la razón a Nicholas Negroponte -el profeta más que gurú- en que el futuro es de los bits y no de los átomos.