¿Qué es el RPC?

Aunque ciertos conceptos de programación son más viejos que yo, hay ciertas técnicas muy potentes que son desconocidas o ignoradas por mucha (demasiada) gente.

A principios de los 80 (la Wikipedia cita un RFC de 1975 y, cómo no, Xerox) se hizo la formulación obvia que la comunicación entre sistemas se podía modelar como una llana y simple llamada a una función que se ejecuta en otro sistema y nos devuelve el valor.

El mecanismo que se utilice para ello debe ser irrelevante, nosotros sólo queremos ser capaces de escribir:

resultado = suma(a,b)

y que la suma se realice en el sistema remoto. A esto le llamaron llamada de procedimiento remoto o Remote Procedure Call en inglés.

Sun implementó uno de los primeros sistemas de RPC para implementar el sistema de archivos distribuido NFS, y a lo largo del tiempo han ido apareciendo diferentes mecanismos de RPC para diferentes plataformas y necesidades.

Con la popularización de la WWW, el protocolo HTTP y Javascript en los 90, pronto la gente comenzó a implementar comunicaciones entre sistema utilizándolos. Por ejemplo, una web podía exponer algunos de sus contenidos y funcionalidades en HTML para consumo humano, pero también exponerlos para consumo de otros sistemas. Mecanismos simples como poner una URL en la que si hacemos un POST http con unos argumentos, nos devuelve el resultado de una operación en un formato fácilmente parseable.

Pronto, uno de los padres fundadores del HTTP, procesó los principios fundamentales del HTTP y la WWW, en concreto que todo era una cuestión de URLs y acciones como GET/POST/PUT/DELETE que soporta el protocolo HTTP; cada URL representa un recurso y podemos expresar acciones mediante los “verbos” HTTP. A esto le llamó REST y supuso una perspectiva limpia y poderosa de lo que es la WWW.

De allí se pasó a los RESTful Web Services, maneras de exponer servicios en Internet utilizando los principios del REST.

Típicamente, los desarrolladores de servicios web utilizan técnicas similares a las del desarrollo de aplicaciones web para publicar servicios REST, y los desarrolladores de servicio ejecutan las llamadas HTTP correspondientes para utilizarlos. Los formatos se intercambian en cualquier formato de intercambio de datos; desde texto plano, a XML u otros formatos como JSON, YAML o lo que se le ocurra la persona, teniendo que codificarse en origen y decodificarse e interpretarse en destino.

Pero paralelamente, otros desarrolladores recordaron el RPC y desarrollaron sistemas de RPC sobre HTTP. Uno de los primeros fue XMLRPC, que posteriormente evolucionaría hacia el denostado SOAP. Muchas implementaciones de RPC sobre HTTP inicialmente eran malas; en parte por ser nuevas y primitivas, pero principalmente por la interoperabilidad. Mucho RPC anterior era entre sistemas muy homogénenos, con el mismo lenguaje en cliente y en servidor y desarrollados por las mismas personas, pero en el mundo de la WWW, son comunes entornos más heterogéneos, con lo que el RPC es mucho menos sencillo; diferentes modelos de datos y convenciones en cada extremo de la comunicación trae muchas dificultades y muchos RPC primitivos tenían grandes problemas de interoperabilidad.

La visión de la transparencia entre sistemas no se daba. A veces, incluso, utilizando el mismo lenguaje pero diferentes implementaciones del mismo protocolo se tenían muchos problemas.

Queda claro que una idea, por buena que sea, está limitada por sus implementaciones, y el pobre estado de los RPC sobre http ha impulsado muchísimo el uso de REST en vez de RPC. Eso es malo, porque en general REST te da más trabajo que RPC; mientras que en REST uno debe definir el formato de datos de intercambio e implementar la codificación y decodificación de estos, los mecanismos RPC realizan todo el trabajo sucio sin que el programador se tenga que preocupar de nada.

Además, para invocar un servicio REST, simplemente has de usar las librerías de HTTP y de codificación que hayas escogido (parseo de texto plano, XML, JSON, etc.); con un sistema de RPC has de aprender a usar la librería, que si bien te puede ahorrar código, es más complicada conceptualmente.

Esto llevó a que SOAP fuese condenado por gran parte del mercado (la interoperabilidad era siempre problemática, las librerías complejas, etc.) y el REST se popularizase mucho e incluso fuese en la práctica la mejor opción en muchos casos.

Sin embargo, el RPC ha avanzado mucho. Disponemos de librerías decentes de SOAP, XML-RPC y otros protocolos como JSON-RPC para la mayoría de lenguajes, y hoy en día ya no me sorprende consumir un servicio implementado en un lenguaje desde otro sin ningún problema.

Por otra parte, gente como Facebook y Google han inventado protocolos nuevos que son decididamente interoperables y multilenguaje, como Thrift de Facebook (ahora Apache) y los protobuf, que resuelven el RPC de una manera limpia y eficiente.

Con RPC nos podemos ahorrar mucho código repetitivo de comunicación que supone REST, con el consiguiente aumento de productividad.

¿Deja de tener sentido REST y sólo debemos comunicarnos mediante mecanismos RPC, por tanto?

No, desde luego que no. Aún pueden existir problemas de interoperabilidad entre algunas plataformas poco populares, o los mecanismos de RPC puede que no sean buenos. REST es siempre un mínimo común denominador y la verdadera manera de asegurarnos que nuestros servicios pueden ser utilizados universalmente- incluso yo recomendaría que aunque implementemos RPC, ofrezcamos también REST para quien no pueda utilizarlo (recordemos igualmente que puede ser sencillo exponer un mismo servicio tanto con XML-RPC, como con JSON-RPC simultáneamente sin mucho esfuerzo, ampliando horizontes), y REST sigue siendo útil para exploración y “descubribilidad”.

Pero, cuando sea posible y adecuado, ahorrémonos escribir código de más.

Programación declarativa contra funcional

Creo que la gran parte de programadores han dado sus primeros pasos con la programación imperativa tradicional. En esta, se utilizan lenguajes de programación que reflejan más o menos directamente el funcionamiento de los ordenadores típicos; instrucciones ejecutadas secuencialmente con variables que vamos modificando y control de flujo. Por ejemplo, un problema básico de “sumar los números entre n y m” se podría implementar primitivamente de la siguiente manera:

sumar ( valor inferior, valor superior) es
    acumulado = 0
    i = valor inferior
    mientras i <= valor superior
        acumulado = acumulado + i
        i = i + 1
    el resultado es acumulado

Declaramos un acumulador en el que iremos recogiendo el valor intermedio de la suma (esto es, si sumamos los números entre 1 y 10, primero contendrá 1, luego 1+2=3, luego 6, etc.) y realizamos un bucle en el que i va cogiendo los valores entre n y m, ambos inclusive, que vamos sumando en el acumulador.

Lógicamente, la mayoría de los entornos de programación cuentan con funciones estándar y estructuras de control de flujo más elaboradas que nos permiten expresar este algoritmo de una forma más concisa y clara, pero al final son equivalentes a las que usamos en esta implementación u a otras más complicadas.

Aparentemente, el programa no alberga mayor dificultad, especialmente a ojos de un programador medianamente experimentado. Sin embargo, comprender la ejecución del programa pasa por saber visualizar la ejecución del algoritmo; su flujo y su estado. Para un algoritmo de 5 líneas y 2 variables esto no es excesivamente complejo, pero tampoco trivial para quien no esté acostumbrado. Creo que gran parte de la dificultad que encuentran los que aprenden a programar es en esta visualización; antes de inventar uno sus propios algoritmos creo que debe ser capaz de entender uno ya hecho- y para inventar uno posteriormente también necesitará esta habilidad de “visualización”.

Esta primera “valla” con la que uno se topa al aprender a programar es especialmente problemática; no la podemos rodear ni trepar progresivamente, la debemos saltar de golpe y considero que para muchos es una primera valla demasiado fuerte y que, en ocasiones, se rodea inicialmente dañando todo el proceso posterior de aprendizaje.

¿Podemos mejorar esto? Consideremos la siguiente implementación del algoritmo:

sumar ( valor inferior, valor superior):
    el resultado es:
        si valor inferior es igual a valor superior, valor inferior
        si no, valor inferior + sumar (valor inferior + 1, valor superior)

Observemos que aquí no hay estado. Comprender la ejecución de este algoritmo (obviando la implementación de las llamadas a funciones, que si bien es necesaria para comprender cómo el ordenador ejecuta el algoritmo, no es necesaria para comprender cómo funciona) es fácil pensando en una expansión algebraica:

suma de 7 a 23 = 7 + suma de 8 a 23 = 7 + 8 + suma de 9 a 23 = … = 7 + 8 + 9 + … + 22 + suma de 23 a 23 = 7 + 8 + 9 + … + 22 + 23

, con la que estará más familiarizado cualquiera que haya tenido una formación matemática media.

Esta implementación, de una aproximación más funcional/declarativa, a mi entender es más sencilla de comprender y puede permitir al programador novel comenzar a implementar sus primeros algoritmos sin tener que visualizar flujo/estado sino mediante expansiones algebraicas.

Pero la cuestión que se nos plantea en este punto es: ¿ayuda esto a la posterior comprensión de la programación imperativa? Es una pregunta importante, ya que si bien la programación funcional es potente, la programación imperativa es más adecuada para muchos programas que uno tendría que desarrollar (particularmente en un entorno comercial) y modela mucho mejor puntos tan importantes como son la entrada/salida.

Ésta es una cuestión abierta, pero creo que como mínimo, una enseñanza inicial funcional puede ayudar al alumno a elaborar algoritmos medianamente complejos por sí solo y darle una confianza para afrontar el, más complicado a mi entender, mundo imperativo- al menos podrá haber realizado tareas complejas y no sentir la frustración que puede uno sentir al intentar implementar algoritmos iterativos simples y tener muchas dificultades a la hora de visualizar su ejecución.

A meternos con Java

Es deporte olímpico desde hace tiempo meterse con Java. Como plataforma es lenta, insegura e inútil. Como lenguaje, causa daños cerebrales irreparables a los programadores que lo utilizan. Para colmo, ahora ya no es propiedad de Sun (que era bastante molona), sino que ha sido absorbida por la malvada Oracle.

Pues para mi sigue siendo una de las herramientas más útiles que tenemos a nuestra disposición; potente, gratuita y open source.

Comencemos por la última moda. Java es inseguro.

Vaya por delante que servidor navega con todos los plugins desconectados por defecto. Ni Flash, ni Java, ni incluso el lector de PDFs de Chrome cargan si no hago click explícito en ellos. Los navegadores son probablemente el programa de mayor riesgo de seguridad, siendo los banners de publicidad y las webs invadidas los mayores riesgos; innumerables webs sufren ataques que inyectan código malicioso en ellas y los banners de publicidad son una manera relativamente viable de colar código malicioso en webs “de confianza”. Poco software más procesa más datos potencialmente hostiles de Internet.

Todo el código expuesto a Internet ha sufrido vulnerabilidades; los clientes de correo, todos los navegadores y, especialmente, todos los plugins, han sufrido vulnerabilidades graves.

Java no es la excepción, ni mucho menos.

Dos incidentes recientes han sido especialmente notables. En abril, una vulnerabilidad de Java que sólo afectaba a ordenadores con OS X ejecutando la máquina virtual Java distribuida por Apple fue harto comentada al ser uno de los primeros malware afectando en masa a Macs. Gran parte de los medios cargaron contra Oracle por hacer de los ultraseguros Macs un coladero (por ejemplo, tras una rápida búsqueda en Google, podemos leer esto).

En general, estos artículos convenientemente omiten el hecho de que la vulnerabilidad había sido solventada meses antes por Oracle y había distribuido el parche. ¿Por qué no a los Macs? Pues sencillamente porque Oracle y Apple tenían un acuerdo mediante el cual es Apple la responsable de distribuir Java a los Macs (esto probablemente está vinculado a que Apple había escogido Java como una de las plataformas “oficiales” de desarrollo de aplicaciones oficiales para OS X tiempos atrás). Apple por supuesto era consciente de la vulnerabilidad y había escogido no distribuirla.

En mi opinión, es completamente irracional culpar a Oracle/Java de este problema- la culpa reside plenamente en Apple; los agujeros de seguridad son inevitables y lo importante es cómo se gestionan. En este caso, mal gestionado por Apple. Podemos argumentar que Oracle hizo mal en ceder la responsabilidad de seguridad a Apple (porque en efecto, hemos visto que no ha sido buena ídea), pero al menos Oracle a partir de esto ha asumido esta responsabilidad de nuevo.

El segundo incidente que tiene lugar estos días no es así, es una vulnerabilidad de Java. Según se dice, unos investigadores polacos habían alertado a Oracle de ella meses atrás y paralelamente, programadores maliciosos la habrían descubierto también y comenzado a explotar. Si esto es así, podemos cuestionar la diligencia de Oracle en tapar el agujero. Podríamos darles el benefici0 de la duda, pues otros agujeros reportados por el grupo polaco fueron parcheados diligentemente, y uno podría pensar que existe un motivo razonable por el que ese agujero en concreto se haya demorado más- pero creo que no es un argumento sólido. Yo valoro negativamente la actuación de Oracle en este incidente.

Pero en definitiva, dos incidentes de notoriedad; el mayor incompetente en esta fiesta es claramente Apple, seguido de Oracle (a bastante distancia en mi opinión). Creo que es deshonesto intelectualmente machacar a Oracle sin criticar a Apple por encima- y más aún si ignoramos que los agujeros son inevitables, que el histórico del manejo de los agujeros de Java ha sido siempre bastante correcto.

Pero vaya, si sólo hemos de aprender una única cosa de todo esto, es a navegar con los plugins desconectados.

Por otra parte, como siempre que se oye la palabra Java, sale un coro de programadores maltratados alegando que Java les ha jodido la vida. Complejo, pesado, incómodo, etc.

El problema es que para lo que se usa Java, pocas alternativas hay. Sí, para escribir programas pequeños existen bastantes soluciones mejores, como Python o Ruby; Haskell, C++, Matlab, Erlang, R, bash son claramente mejores en otras áreas más específicas.

Pero para escribir aplicaciones “administrativas” grandes, no existe nada mejor. Python y Ruby son dinámicos, lo cual impide de entrada que existan herramientas suficientemente potentes como para poder refactorizar y analizar código con un mínimo de fiabilidad- en un proyecto suficientemente grande esto supone un coste en tiempo suficiente como para compensar cualquier otra ventaja que se pudiera tener. Herramientas como Eclipse son extremadamente valiosas para el desarrollo a gran escala y simplemente no pueden existir tal cual para un lenguaje dinámico (nótese que por ejemplo Google hace análisis sobre lenguajes dinámicos, pero lo hace añadiendo información de tipos al código- con lo cual se gana en herramientas, pero se pierde la supuesta ventaja de los lenguajes dinámicos).

La única alternativa de calado viable es .NET. Sin embargo, es una herramienta con costes que impone unas restricciones bastante duras (e.g. nos obliga a pagar caras licencias en el servidor, lo cuál supone un impedimento importante a los escalados horizontales). Para algunos serán aceptables, para otros lo hace inviable.

Sí, Java como lenguaje sufre muchas carencias; falta de lambdas y una API muy potente pero poco amigable (básicamente, para hacer cosas sencillas, es muy muy fastidioso- y uno quiere hacer cosas sencillas casi siempre); las lambdas suponen un serio inconveniente bastante insalvable (hay cosas que se expresan con mayor concisión y claridad con ellas), pero lo de la API es salvable; uno siempre puede escribir sus fachadas para las APIs complejas y olvidarse del problema (o usar las de otros; Spring en gran parte es eso).

Lo otro es el ecosistema. Sí, existen librerías y frameworks con graves excesos de ingeniería. Sí, Java EE no es la plataforma más sencilla del mundo. Pero eso no es un problema de Java- especialmente porque existen frameworks y librerías bien diseñados y con una complejidad adecuada. Java + Spring MVC no será la plataforma de desarrollo web más sencilla que existe, pero su complejidad está bien alineada con su potencia.

En resumen; sí, Java tiene sus defectos. Pero tiene muchos más “defectos ajenos” que propios. Y es preocupante la cantidad de detractores que no ven la viga en su propio ojo, o que critican con desconocimiento de causa. Yo ciertamente estoy contento de disponer de Java para ciertas tareas, tal como le veo muchos defectos y nunca lo usaría para todo.

¿Cuánto rato se tarda en montar un entorno de desarrollo web Java?

Una de las quejas más comunes sobre desarrollar en Java es lo complejo que resulta montarse el entorno de desarrollo. Ciertamente, la situación hace años era un poco rollo; grandes descargas del JDK perdido entre las tinieblas, Eclipse por piezas difícil de instalar…

¿Cuál es la situación actual? ¿Sigue siendo tan complejo? ¿Los anchos de banda más anchos de hoy en día ayudan?

Para el propósito de este ejercicio, cogeré un Windows sin nada instalado e instalaré todo lo necesario para poder desarrollar un servlet “Hola, Mundo”, con Eclipse (el entorno de desarrollo gráfico gratuito para Java más común).

Los pasos que deberemos realizar son los siguientes

  1. Ir a la página de Oracle, Downloads, Popular Downloads, Java for Developers, JDK, Aceptar la licencia y escoger la versión adecuada (en mi caso Windows x64)… 1 minuto
  2. Descargar los 92mb… 7 minutos
  3. Ejecutar el instalador… 3 minutos (+2 minutos de JavaFX que instala por defecto)
  4. Ir a la página de Eclipse, Download Eclipse, Eclipse IDE for Java EE Developers, escoger la versión adecuada (Windows 64 bits)… 1 minuto
  5. Descargar los 221mb… 16 minutos
  6. Abrir el .zip y extraerlo (en mi caso, a mi carpeta de usuario c:\users\alex, creándose una carpeta dentro c:\users\alex\eclipse)… 4 minutos
  7. Arrancar Eclipse (en mi caso c:\users\alex\eclipse\eclipse.exe),
    escoger la ubicación por defecto del workspace (y marcar que no vuelva a preguntar),
    crear un “dynamic web project”,
    escoger crear un nuevo runtime de Tomcat 7.0 (y darle una ruta, se lo baja y lo instala [unos 8mb]),
    decirle que nos genere un web.xml,
    hacer un click con el botón derecho y sobre la sección de servlets y decirle que nos cree uno, todo por defecto,
    implementar el método doGet haciendo un response.getOutputStream().print(“Hello world”);,
    hacer click derecho en el proyecto,  run as, run on server, hacer que corra en el Tomcat 7 que hemos creado anteriormente,
    editar la URL del navegador que se nos abra para que se corresponda a la ruta donde hemos mapeado el servlet y cargarlo
    … todo unos 7 minutos

En total, unos 40 minutos de los que unos 25 son unos 320mb de descargas. Lógicamente con una conexión más rápida (tengo una de 3 megabits) y sin la virtualización, que obviamente penaliza el rendimiento, podría reducirse un poco.

A destacar que el proceso tradicionalmente más complejo, instalar el Tomcat y configurarlo para que se pueda usar desde el Eclipse, ha sido simplificado por la gente de Eclipse haciendo que instalarlo y autoconfigurarlo directamente al crear un proyecto sea bastante sencillo (el interfaz no es 100% intuitivo y me ha costado un pelín entenderlo, pero bueno).

Por supuesto, este es un proceso mínimo usable; yo preferiría añadirle:

  • Instalación de egit, que sorprendentemente en la versión Java EE de Eclipse no viene cuando otras variantes de Eclipse lo traen por defecto (4 minutos de instalación desde Eclipse Marketplace, incluyendo un reinicio)
  • Instalación de m2eclipse y su plugin para WTP, que nos permite configurar proyectos usando Maven, un sistema bastante estándar de gestión de dependencias (6 minutos de instalación desde Eclipse Marketplace, con otro reinicio)

, y por supuesto, que esto nos instala un sistema de desarrollo “pelado” sin framework, cuando lo recomendable es no desarrollar servlets “a pelo” si no usar algún framework como Spring. Pero esto lo trataremos en otra entrega…

O sea, que podemos montar un entorno de desarrollo, con servidor de aplicaciones y entorno gráfico integrado en menos de una hora. ¿Es mucho, poco? ¿Cuánto se tarda con otras plataformas de desarrollo? ¿Es realmente un factor que eche para atrás de desarrollar con Java? ¿O son otros factores?

Desarrollo web como Dios manda

Con la cantidad de faena a hacer en el mundo del desarrollo web, es natural preguntarse cosas como qué tecnología elegir y por dónde comenzar si uno quiere dedicarse a esto.

No son preguntas triviales- la espectacularidad diversidad de plataformas, filosofías y frameworks intimida y lleva a pensar que no es posible tomar una buena decisión- es impracticable probar todas las alternativas y en las etapas iniciales de aprendizaje es difícil formarse una opinión razonada.

En este post pretendo dar unos apuntes que espero sirvan para colocar a alguien en el buen camino.

Una manera fácil de comenzar es por el lenguaje. Es conveniente que escojamos un lenguaje que cumpla las siguientes características:

  • Popular
  • Con tracción para el desarrollo web
  • De calidad

Comenzando por el principio, un buen punto de partida es mi querido TIOBE. El TIOBE es un ránking de la popularidad de los lenguajes de programación calculado a partir de su presencia en la web. La metodología es inevitablemente discutible, pero el ránking está bastante alineado con mi percepción, así que para mi, es una opción cómoda.

En el top 20 (a junio de 2012) encontramos tan solo 8 lenguajes utilizados comunmente para el desarrollo web: Java, C#, PHP, Python, Perl, Ruby, Javascript y Visual Basic .NET. Fuera del Top 20 encontramos muy poquitas opciones (Haskell, Scala y poco más), así que nos ceñiremos a estos.

Vamos a descartar unos pocos:

  • PHP: pese a ser un lenguaje explícitamente diseñado para el desarrollo web, en mi opinión PHP nunca debe usarse para desarrollar un proyecto desde 0- a no ser que lo que queramos desarrollar sea extremadamente mínimo- ya sea porque se trate de un desarrollo extremadamente pequeño o bien que pretendamos reutilizar completamente un desarrollo existente como WordPress o Magento. Desarrollar grandes bases de código en PHP es un ejercicio frustrante ya que, sencillamente, no está pensado para ello. Sus limitaciones en cuanto a modelo de ejecución, estructura y modularidad son motivo suficiente para descartarlo, pues el resto de lenguajes que consideramos lo superan ampliamente en estos aspectos, ofreciendo PHP muy poco para compensar (su velocidad para proyectos mínimos).Puede sernos útil conocer PHP, pues existe mucho trabajo manteniendo código PHP (sin embargo, no se trata de un trabajo especialmente gratificante) y en algún momento nos puede ser útil. Pero debe ser erradicado lo antes posible.
  • Perl: durante mucho tiempo fue una de las mejores opciones disponibles, en realidad, una de las pocas viables. Una vez más, el resto de lenguajes de la lista le superan en virtudes sin que Perl ofrezca muchas ventajas propias. El mercado de Perl decae lentamente y cada vez se inician menos proyectos que lo utilicen.
  • JavaScript: si bien deberemos conocer JavaScript para desarrollar efectivamente sobre la web, aún no lo considero una opción viable en el lado servidor. Tendremos que aprender JavaScript, pero el grueso del proyecto deberá ser siempre en otro de los lenguajes. Soy anti-aplicaciones web 100% Javascript, creo que su campo de aplicación es extremadamente limitado y presentan desventajas considerables, pero hay quien les encuentra virtudes

C# y Visual Basic .NET son dos opciones que el lector mismo puede escoger descartar o considerar- desarrollar razonablemente en ambos supone unos costes que yo prefiero no asumir (se necesitan licencias de Windows para el desarrollo y despliegue y las versiones gratuitas de Visual Studio tienen bastantes limitaciones)- a parte de que soy un firme creyente en que las herramientas de desarrollo deben ser libres y gratuitas. Si eso no supone un impedimento para el lector, puede aplicar mi opinión sobre Java, ambas plataformas son extremadamente similares; quizás .NET goce de herramientas más sencillas de utilizar inicialmente, el sistema base es más completo que el de Java pero el ecosistema goza de menor vida.

Por tanto, nos quedamos con Java, Python y Ruby. Los dos factores más diferenciales entre los tres para mi son:

  • Pythoncuenta con el framework Django, que a su vez goza del “Admin”. El Admin es un desarrollo genérico que implementa un sistema de gestión de modelos web genérico muy sofisticado, que nos permite definir las entidades con las que trabaja nuestra aplicación (e.g. en una web de contenidos, artículos, categorías, etc.) y obtener prácticamente sin esfuerzo una interfaz de gestión bastante buena que permite a los usuarios gestionar los objetos, añadiendo un sistema de permisos más que aceptable (i.e. podemos decir que los reporteros pueden crear y editar sus artículos y que los administradores pueden crear y gestionar secciones). Dado que en la mayoría de los proyectos se necesita una funcionalidad así y Django nos la proporciona sin dedicarle apenas tiempo (y desarrollar algo de ese calibre es considerablemente costoso), para muchos proyectos Django nos puede ahorrar muchísimo tiempo de desarrollo tedioso, dándonos una gran ventaja.Puede parecer que otras plataformas cuentan con cosas similares (e.g. Roo en Java, el scaffolding de Rails), pero no están a la altura.
  • Javaes el único de los lenguajes que cuenta con tipado estático. El tipado estático (deber declarar explícitamente el tipo de las variables) parece un problema (debemos “perder tiempo” especificando tipos), pero en realidad no lo es (uno ya razona sobre el tipo que debe tener una variable, escribirlo explícitamente no es costoso) y en cambio permite la existencia de herramientas sofisticadas que trabajen sobre el código. En los lenguajes dinámicos, por poner un ejemplo, es extremadamente laborioso localizar dónde se utiliza un determinado trozo de código, algo necesario para tareas como eliminarlo (debemos asegurarnos que no exista otro código que lo utilice y adaptarlo si existe) o modificarlo (debemos asegurarnos que adaptamos el código que lo utilice), tenemos que buscar las referencias por todo el código y esto puede ser extremadamente problemático si la búsqueda no es muy específica (i.e. si tenemos un campo llamado “página” en un objeto concreto, una búsqueda de texto nos reportará usos de “página” en clases no relacionadas, o que contengan “página”), pues podemos tener una cantidad de falsos positivos muy elevada fácilmente.Esto propicia que los cambios en el código sean mucho más trabajo del que debiera. En cambio, en un lenguaje estático es posible implementar búsquedas muy exactas gracias a la presencia de tipos en el código fuente (básicamente, la herramienta puede discernir si la referencia que buscamos es la que encuentra con exactitud). En Java el compilador nos avisará si un cambio/eliminación rompe código, y las herramientas nos pueden localizar exactamente todas las referencias a un trozo de código. Adicionalmente, las herramientas no se quedan aquí, sino que implementan funcionalidades similares mucho más avanzadas y potentes que no pueden ser implementadas efectivamente sobre lenguajes dinámicos.

En mi opinión, ambas herramientas deben estar en el arsenal de un desarrollador web. Python + Django para proyectos sencillos o en los que el Admin de Django suponga una gran ventaja, y Java para proyectos grandes y complejos. Python nos da agilidad y el Admin y Java nos da la potencia para desarrollar sistemas complejos.

Por supuesto, la cosa no se queda aquí. El desarrollo web requiere unos conocimientos de base; más allá de los conocimientos de programación estándar (que obviamente son necesarios), necesitaremos conocer:

  • El protocolo HTTP, el “alma” de las comunicaciones web
  • HTML + CSS, con los que desarrollamos la capa visual de la aplicación
  • JavaScript para las funcionalidades que lo requieran (con jQuery)

Seguramente también necesitaremos un mecanismo de persistencia (donde SQL es la opción más popular, yo recomendaría usar PostgreSQL y evitar el popularísimo MySQL pero infame) y conocimientos básicos de sistemas (deberíamos saber hacer funcionar un servidor web, la base de datos, etc.).

Con todo esto podríamos desarrollar alguna web sencilla con Django, que nos proporciona una plataforma bastante completa y bien documentada con la que podremos implementar bastantes proyectos.

Una vez asentados los fundamentos del desarrollo web, podemos comenzar a investigar Java. Java no es como Django, que incluye prácticamente todo lo necesario en un sencillo paquete y, una vez más nos plantea unos problemas de decisión importantes. Lamentablemente, desconozco una buena referencia completa y vertical de desarrollo Java que ofrezca un stack completo comparable al de Django. Mi recomendación sería partir de Java, añadir Spring (el mecanismo de inyección de dependencias, su librería de JDBC y el motor MVC) y JSP, todo corriendo sobre un contenedor como Jetty o Tomcat (que se integre en nuestro entorno de desarrollo), utilizando Eclipse y Maven para la compilación. Desgraciadamente es una solución más compleja para la parte inicial (y muchas de ellas se deben aprender prácticamente simultáneamente, incrementando la dificultad), pero adoptando todas estas tecnologías tendremos una base similar a la de Django. El camino es mucho más largo, pero nos ofrece una alternativa más apropiada para grandes proyectos.

Lógicamente, esta es una vía “ideal”. Quizás no debe completarse completamente, si no hemos de trabajar en proyectos muy complejos Java es una exageración, o bien la vida nos lleve a sumergirnos en otras tecnologías, pero es un recorrido completo. Si no llegamos a Java (o incluso si llegamos), puede ser conveniente pasar tiempo usando algún microframework que no nos dé un stack completo como el de Django, Django nos lo da casi todo mascado y seguramente hay detalles interesantes de conocer a bajo nivel que nos perdamos. Hacer desarrollo web sin un stack completo ciertamente puede ayudarnos a completar nuestras habilidades. Podemos hacer esto tanto en Python (usando un microframework de los muchos existentes, o incluso desarrollando el nuestro) como en Java (programando directamente servlets en vez de usar el MVC de Spring) o en cualquier otro lenguaje.

nota: más ediciones y sugerencias del de siempre.

What if… PHP y MySQL nunca hubieran existido?

Marvel tenía (o tiene, estoy tremendamente desactualizado) un cómic titulado “What if…?” que trataba de qué pasaría en los universos Marvel si algún acontecimiento clave hubiese seguido otro curso. Así pues, podíamos leer cosas como qué hubiese pasado si Spider-Man hubiese sucumbido al simbionte o Gwen Stacy no hubiera muerto.

Yo, la verdad, prefería “What the…?”, que trataba de situaciones absurdas, pero bueno.

El ejercicio que me propongo hoy es “What if… PHP y MySQL nunca hubieran existido?”

PHP y MySQL fueron en su momento las estrellas del desarrollo web. PHP surgió de un proyecto personal de Rasmus Lerdorf inicialmente publicado en 1995, que según el TIOBE, comenzó a dispararse en popularidad allá por 2002 y gozó de su mejor momento entre 2005 y 2010, donde inició un aparente declive (seguramente por el ascenso de otros lenguajes/frameworks para la web menos demenciales). MySQL empezó como proyecto en 1994 y su primera publicación fue (la Wikipedia no es muy específica en este asunto) entre 1995 y 1998—no encuentro buenas fuentes sobre su ascenso a la fama, pero yo lo situaría aproximadamente por la misma época que el de PHP, y sin que se atisbe una caída en su popularidad (si no contamos su adquisición por parte de Oracle en 2010 y la relativa proliferación de forks).

No es casual, claro, que la web explotara justo en ese momento, entre 1996 y 1998, y que los dos estuvieran en el sitio exacto, en el momento exacto para formar la MP de LAMP. En un momento en el que no había una abundancia de herramientas de desarrollo web decentes (Perl era probablemente la alternativa abierta más popular; los servlets de Java son del 97, pero por ejemplo hasta 1999 no existió Tomcat; ASP de Microsoft data de 1998… no había muchas más cosas y por supuesto, gran parte de lo que hoy está de moda en aquella época ni existía), PHP/MySQL era una tupla muy accesible para desarrollo web —fácil de instalar, fácil de comenzar y fácil de obtener resultados rápidos— y sin mucha competencia que hiciese destacar sus defectos. Esto llevó a que prácticamente todo el segmento “no profesional” y una parte importante del profesional se volcasen en esta plataforma (las “MS Shops”, por supuesto, apostaron por ASP y mucha gran empresa se fue a Java) y posteriormente, como suele suceder, el sector no profesional arrastrase al profesional.

Sin embargo, hoy en día PHP está bastante denostado. Se le sigue reconociendo como vía “rápida y sucia” y goza de una inercia considerable (sobre todo, por la abundancia de mano de obra y código existente a mantener), pero puede decirse que ha pasado de moda y que sus abundantes defectos le están pasando factura; prácticamente podría decirse que Facebook es su único usuario de gran perfil (y con importantes peros). MySQL, en cambio, sigue relativamente saludable, sigue siendo extremadamente popular y, pese a que el sector crítico parece crecer día a día, no parece que vaya a ser eclipsado en breve.

¿Qué hubiera pasado si Rasmus Lerdorf se hubiera avergonzado de su pequeño monstruo y hubiese decidido mantenerlo en el sótano oscuro y lúgubre que nunca debió abandonar? ¿Y si MySQL no hubiese tenido su vertiginosa aceptación, quizás por una mala fama alimentada por alguna deflagración especialmente notable?

Probablemente, el mundo web hubiese sufrido algún retraso. Perl, Java o ASP no eran suficientemente accesibles en ese momento como para tomar el relevo (por diversos motivos: de coste en el caso de ASP, de accesibilidad para Java y Perl). Lo más probable es que Perl hubiese ganado bastante terreno y  hoy en día gozase de más popularidad, incluso entre los imberbes. ¿Se hubiese adelantado algún framework como el popular Ruby on Rails? Yo creo que no; Rails surge ya en 2005 y no creo que se hubiese acelerado mucho su aparición en caso de haber existido un vacío. Simplemente, hubiésemos visto otros frameworks nuevos sobre algún lenguaje existente, o quizás algún framework que el tiempo olvidó habría sido adoptado masivamente. Apostaría por que Python, que explotó en popularidad en 2004, hubiera cubierto el vacío de PHP con algún framework.

¿Consecuencias? Sí, la web retrasada 2-3 años. Probablemente los titubeos propios de PHP se hubiesen trasladado a su sustituto (algún framework sucio y bizantino de Python se habría impuesto), o quizás (Dios no lo quiera) Perl hubiese arrasado y hoy en día estaríamos condenados a prefijar todo con sigilos (pero seguramente con un framework elegante). La versión optimista (para mí) es que la web como plataforma de aplicaciones no hubiese tenido su auge y nos hubiéramos quedado mayormente en la web de contenidos y el modelo de aplicaciones de escritorio… y con toda probabilidad esto habría supuesto un buen bofetón para Linux y en menor medida para Apple (las aplicaciones web son prácticamente automáticamente multiplataforma). ¿Sería esto positivo? Por una parte, uno es de los que suscribe que nunca debimos apostar por la web para aplicaciones (sí, desde luego, para contenidos) y que quizás buen número de informáticos no tendrían que haber lidiado con los problemas de la web para este propósito y destinado su tiempo a cosas más útiles: siendo optimistas, quizá hoy tendríamos aplicaciones de escritorio multiplataforma de despliegue indoloro (e.g. Java y Web Start, pero bien) y todo sería más de color de rosa. El reverso de la moneda sería un monocultivo Microsoft y todos estaríamos desarrollando en Visual Basic (y no, no el .NET), claro está.

A un nivel más elevado y más del mundo real, igual las burbujas web y sociales no hubieran nacido ni estallado nunca. Habría más desarrollo informático empresarial tradicional con el aburrimiento y la solidez consiguientes.

Por otra parte, creo que la historia no habría cambiado sustancialmente sin MySQL. PostgreSQL seguramente ocuparía su lugar, llevándonos a un mundo con más integridad referencial y donde nuestros datos serían un pelín menos volátiles. Defiendo que el movimiento NoSQL hubiera dado un pequeño paso atrás. Sí: con o sin web de aplicaciones y todo eso, Google hubiera existido y hubiese necesitado BigTable/MapReduce (es el contenido lo que es difícil de indexar). Pero parte de la necesidad de NoSQL viene de las deficiencias de MySQL y no del modelo relacional (adicionalmente, este no estaría tan desprestigiado y probablemente serían más de cuatro gatos los que sabrían sacarle partido). Y es que resulta difícil encontrar una implementación peor de SQL que MySQL (si no contamos SQLite, claro, pero ese juega en otra liga).

Cuesta imaginar un efecto real de la no existencia de MySQL: quizás eso quiera decir que pese a que PHP haya caído antes, quizás éste haya sido más instrumental y relevante en el mundo real. MySQL simplemente ofrecía “funciona en Windows y no hay otro popular” (lo de la velocidad son historias); PHP era “tu web, ahora y sin complicaciones”. Uno pensaría también que los deméritos de PHP son menores que los de MySQL: pese a que ambos son sucios y volátiles, opino que PHP es más sucio que volátil, mientras que MySQL es más volátil que sucio… y en informática, lo sucio es doloroso pero inevitable, mientras que lo volátil puede causar daños corporales permanentes.

(correcciones, ediciones y sugerencias del de siempre)

Porqué Django no es La Solución Definitiva

Hace tiempo ya explicaba por aquí las virtudes de Django. En  resumen, se trata de un framework de desarrollo en web Python que implementa un interfaz de administración prácticamente automático a un esquema relacional. Vaya, que defines tus tablas y genera un interfaz dinámico para editar registros que te ahorra una barbaridad de tiempo (como podrá atestiguar cualquiera que haya tenido que hacerse uno).

Tras llevar más tiempo trabajando con Django, sigo convencido que en estos momentos es la mejor solución que existe para desarrollo web basado en CRUD sobre bases de datos; el admin no tiene equivalente alguno que yo conozca, y desarrollarse un sistema similar es extremadamente costoso.

Sin embargo, creo que he aislado unos cuantos defectos clave que hay que tener en cuenta antes de comenzar a usarlo.

1.

Si usamos un esquema donde queramos que la edición de un registro tenga más de un nivel de indirección, el admin no soluciona esto. Pongamos por caso que tenemos una entidad “Empleado” , otra entidad “Proyecto” y una entidad intermedia que nos representa las asignaciones de Empleados a Proyectos (por ejemplo, en esta relación intermedia podríamos querer almacenar el tiempo durante el cual el Empleado está asignado al Proyecto, su porcentaje de dedicación a él, etc.). Podremos añadir un fantástico TabularInline que nos muestre las asignaciones de Empleados dentro de la vista de detalle de Proyecto, pero no hay manera de que se pueda editar el Empleado desde la vista detalle de Proyecto; podremos editar la relación intermedia (primer nivel de indirección), pero la segunda ya no.

Esto nos limita bastante el interfaz sobre esquemas de datos moderadamente complejos que nos podemos encontrar fácilmente en el mundo real; cuando tengamos estos esquemas tendremos que…

  1. Hackear el admin como podamos para que nos permita hacer las ediciones
  2. Buscar a alguien que haya implementado algún plugin que nos añada en esto
  3. Ignorar el admin e implementarlo nosotros mismos
  4. Simplificar nuestro esquema

Ninguna de las tres soluciones es mínimamente satisfactoria

2.

El admin necesita más hipervínculos. En particular, la fantástica funcionalidad de los raw_id_fields, nos permite hacer que los campos clave foránea de nuestras entidades se puedan editar con un popup selector excelente, pero no nos permite saltar a la entidad enlazada. Una de las grandes virtudes de usabilidad de la web son los enlaces, y nos serían extremadamente útiles en más lugares del admin

3.

Django no proporciona suficiente potencia en el SQL subyacente a su ORM. En particular, sería harto conveniente poder disponer de, o bien un inspectdb más potente que nos permita trabajar continuamente con él (añadir campo en nuestra base de datos y que inspectdb añada dinámicamente el campo al modelo), o un mecanismo para poder personalizar automatizadamente el esquema generado; esto principalmente nos debería permitir implementar una “estrategia” de nombrado de tablas y columnas que nos permita, por ejemplo, que los nombres de tablas sean plurales o cambiar el nombre de las claves primarias surrogadas que Django añade automáticamente.

Si no nos gustan los esquemas que genera Django automáticamente (y no deberían gustarnos), las alternativas son o aguantarnos, o especificarle repetidamente los nombres de tablas y columnas que debe usar o hackear Django para que haga lo que queramos. Una vez más, esto no es del todo satisfactorio.

4.

A un nivel más profundo, el código de Django no es muy amigable a la extensión. Es bastante complicado añadir funcionalidad derivando de las clases de Django; el código no siempre es fácil de seguir (ya que usa bastantes metaclases y otras pythonicidades de las que no soy muy fan) ni tiene un diseño orientado a objetos muy elaborado- se echa en falta que ciertas funcionalidades estén, como mínimo, aisladas en un propio método que podamos sobreescribir para cambiarlas (o utilizar el patrón estrategia, idealmente). Siempre nos queda la opción de forkear, pero esto no es muy mantenible, o hacer monkey-patching, lo que tampoco es muy recomendable ni mantenible.

Pese a todos estos puntos, sigo pensando que el admin de Django es realmente algo único que nos puede ahorrar muchísimo trabajo y proporcionar un resultado de gran calidad para muchos, muchísimos proyectos. Pero aún es mejorable- y con unas pocas mejoras localizadas podría mejorar muchísimo.

Mi tema de WordPress

.assistive-text, .screen-reader-text, .menu, #nav-above, #colophon {
 display: none;
}
#page {
 margin-left: auto;
 margin-right: auto;
 max-width: 1000px;
}
#primary {
 max-width: 720px;
 min-width: 320px;
 float: left;
 margin-left: 15px;
 margin-right: 15px;
}
#secondary {
 min-width: 175px;
 width: 240px;
 float: left;
}

Construye tu guía de TV

He publicado en Github tvguide, un miniproyectillo que incluye un scraper de guía televisiva (la de El Mundo) y un mini-interfaz web que muestra los 5 próximos programas de los canales que recibo en mi casa que están recogidos por El Mundo (i.e. falta RAC105 y algunos locales).

El proyecto utiliza Maven y debería ser fácilmente compilable y trabajable desde Eclipse. Para compilarlo antes tendréis que compilar mi librería de utilidades commons.pdp7.

Upserts…

Trabajando en un pequeño experimento, se me ha ocurrido un insert idempotente:

insert into foo (bar) (select ‘bar_value’ as bar where not exists (select 1 from foo where bar = ‘bar_value’));

(la sintaxis es de PostgreSQL, pero supongo que es adaptable a otras bases de datos). Igual intento adaptarlo a hacer upserts.