Documentación continua en la nube

Tenemos Travis para integración continua, Scrutinizer para inspección continua… pero hasta hace unos días no existía un servicio para generar documentación continua de proyectos.

Para mí es un follón generar y subir a la web los phpDocs de mis proyectos de software libre cada vez que hago commit (ya que quiero tenerlos siempre actualizados); y también es un follón administrar y configurar Jenkins u otros servicios de integración continua para que generen los docs con cada build.

Así que he pensado que no sería tan complicado hacer un sistema que genere y aloje los documentos de mis proyectos en GitHub. Y si es útil para mí, también puede serlo para otros.

Dicho y hecho. Aquí lo tienes, tan sencillo como autorizar la aplicación en tu cuenta en GitHub y elegir qué repositorios quieres documentar. Cada vez que hagas push al repositorio, los documentos serán automáticamente generados y podrás verlos en github-phpdoc.israelviana.es/docs/[tu nombre de usuario GitHub]/[nombre del repositorio]:

Github-phpDocs landing page

Github-phpDocs landing repo list

GitHub-phpDoc documentación

Puedes probarlo ya en github-phpdoc.israelviana.es

El servicio es gratuito y open-source; por supuesto, el código está en GitHub y la documentación en la nube ;-)

De momento solo soporta proyectos en PHP alojados en GitHub (repositorios públicos de momento), pero si hay suficiente demanda se puede ampliar a otros lenguajes o alojamientos.

¿Y tú, generas documentación del código de tus proyectos? Si tienes proyectos PHP en GitHub te agradecería que probases el servicio y me dieras todo el feedback posible. ¡Gracias de antemano!

Y por último, una pregunta: ¿Estarías dispuesto a pagar 2€ por documentación privada de repositorios privados?

Tests de integración con Zarangotest

¿Cuántas veces hemos tenido que pelearnos con los ficheros de configuración a la hora de desplegar nuestro proyecto?

Respuesta: un montón. Y la mayoría de ellas, evitables.

La versión de PHP, las extensiones instaladas, los datos de conexión a la base de datos correctos… son algunas de las comprobaciones que debemos hacer cada vez que desplegamos una nueva versión de la aplicación. Y como es de bien nacidos automatizar los tests, algunos lo hacen con PHPUnit, otros de soluciones caseras… y otros usamos Zarangotest.

Zarangotest (cuyo nombre proviene del zarangollo, delicioso plato tradicional murciano) es un sencillísimo framework que podría haber escrito cualquiera, cuyos objetivos son organizar los tests (primordialmente los de integración), proporcionar una serie de tests ya escritos y presentar los resultados en una bonita página HTML.

Captura de un informe de Zarangotest
 ¿Cómo se usa Zarangotest?

Zarangotest, a diferencia de otros frameworks de test, está pensado para usar desde el servidor web, no desde la consola.

  1. Cargas el fichero de zarangotest: require_once ‘zarangotest.php’;
  2. Inicializas tus test según tus necesidades: cargar ficheros de configuración, declarar constantes…
  3. Declaras un array y lo vas rellenando de tests. Cada test es una instancia de la clase Zarangotest, y puedes especificar un título y una categoría (por si quieres agrupar tus tests para organizarlos mejor).
  4. Una vez declarado tu juego de tests, llamas a la función zarangotest($juegoDeTests, “Un título”).
<?php

include 'zarangotest.php';

$juegoDeTests = array();

/** Test Mysqli */
$juegoDeTests[] = new Zarangotest("Extensión mysqli", "Extensiones", function() {
    return function_exists("mysqli_close");
});

zarangotest($juegoDeTests, "MiProyecto");

Como puedes ver, el contenido de los tests consiste en una función anónima que devuelve true o false. Cualquier otro valor devuelto se considerará como un fracaso en la ejecución del test y se mostrará en el informe. Así pues, ejecutamos el script y obtenemos el informe:

Informe de Zarangotest

¿Y los tests pre-fabricados?

Zarangotest no está del todo terminado. Cuando lo esté, los tests prefabricados estáran disponibles como clases separadas. Mientras tanto, puedes utilizar el código de prefabricados.php.

¿Y esto no se puede hacer con PHPUnit?

Sí, se puede. Aunque PHPUnit está pensado para tests unitarios, se puede utilizar para hacer tests de integración e incluso tests funcionales. Pero si no dominas PHPUnit o no quieres/puedes desplegarlo en tus servidores, Zarangotest es una buena alternativa. Además, Zarangotest genera directamente el informe en HTML, algo que no es tan ágil con PHPUnit.

Es todo por el momento. En las próximas semanas iré subiendo actualizaciones, mejoras y más documentación a Zarangotest. Mientras tanto, sería genial que le echaras un vistazo y comentaras tus impresiones aquí :-)

Descargar Zarangotest

Modelos experimentales de persistencia para aplicaciones web (II): Object Freezer-Relational

En el anterior post vimos un invento de Sebastian Bergmann llamado Object Freezer, que consiste en almacenar objetos PHP en CouchDB de forma automática. Es un buen método para no tener que definir esquemas de bases de datos, escribir sentencias SQL, hacer mapeo objeto-relacional… en definitiva, es una solución que nos puede ahorrar un montón de trabajo.

Pero, una vez aceptadas las ventajas de la congelación, quizá sea necesario guardar esos objetos en una base de datos diferente a CouchDB. Por ejemplo, en MySQL. Y de esto trata el presente artículo: de congelar objetos y guardarlos en MySQL.

Un brevísimo repaso a la congelación

Congelar un objeto (“freeze”) es convertirlo en un array manteniendo los objetos hijos y evitando duplicidad de los mismos. La operación inversa, la descongelación (“thaw”), sería recoger ese array y convertirlo de nuevo en el objeto original.

¿Por qué MySQL, si con NoSQL nos ahorramos todo el trabajo?

  1. A veces no es viable o rentable cambiar de servidor de bases de datos, por la inversión económica y de formación que requieren los sistemas tradicionales.
  2. Interoperabilidad: si en el futuro queremos migrar la aplicación, quizá poder manipular la información con SQL facilite la tarea.
  3. Rendimiento: las bases de datos relacionales se basan en algoritmos muy evolucionados y rápidos, y sistemas como MySQL-MyISAM han demostrado un rendimiento muy alto.

Entonces… ¿Se trata de guardar arrays en MySQL?

Exacto. Eso es lo que hace Object Freezer-Relational, una extensión de Object Freezer escrita por un servidor :-)

Lo primero que debemos pensar a la hora de guardar objetos en MySQL es: ¿cuál es el esquema de tablas? Porque si con CouchDB éramos NoSQL y guardábamos la información en arrays JSON, ahora tenemos que ceñirnos al álgebra relacional, las tablas, los índices y las claves primarias.

Así que este es el esquema que podemos usar:

  • Tabla objects
    • id: el ID único del objeto.
    • className: indica la clase de la cual es instancia el objeto almacenado.
    • isDirty y isRoot: dos atributos que utiliza Object Freezer internamente.
  • Tabla properties
    • name: nombre del atributo.
    • value: contiene el valor del atributo o bien un ID si el atributo hace referencia a otro objeto.
    • type: tipo de dato (int, float, string, boolean, array, objeto…).
    • object_id: ID del objeto al que pertenece el atributo. Hace referencia a objects.id.

Llegados a este punto uno podría pensar: “hey, te estás cargando el modelo relacional”. Efectivamente. Si queremos guardar objetos sin definir su esquema de BD, no nos queda más remedio que soluciones experimentales como la que te presento hoy. Sí, es una “des-normalización”, pero gracias a ella te ahorras escribir SQL.

Object Freezer-Relational se encarga de gestionar este esquema. De hecho, no es siquiera necesario crearlo, ya que lo hace automáticamente.

Vale, ya veo que mola. ¿cómo se usa?

Usar Object Freezer-Relational es tan sencillo como usar Object Freezer indicando los datos de acceso a MySQL:

$storage = new Object_Freezer_RelationalStorage(
    new Object_Freezer,
    NULL,
    FALSE,
    new MysqlStorage(
        "localhost",                    //Servidor MySQL
        "freezer",                      //Usuario
        "passw0rd",                     //Contraseña
        "freezer",                      //Base de datos
        3306,                           //Puerto
        MysqlStorage::ENGINE_INNODB));  //Motor MySQL

A partir de ahí, podemos usar el objeto $storage de la misma forma que el Object Freezer original, con CouchDB, ya que es la misma API.

Object Freezer-Relational está disponible en SourceForge. Puedes descargarlo y probarlo, echar un vistazo al código o leer la documentación si te interesa. Y por supuesto, comentar qué te parece la idea de guardar objetos en una base de datos MySQL :-)

Mejor rendimiento de Drupal con GraphicsMagick

Un pequeño (y espero útil) apunte antes de que penséis que he abandonado completamente el blog :-(

Se trata de un consejo para mejorar el rendimiento de nuestro sitio Drupal. El sistema utiliza por defecto la biblioteca GD para manipular imágenes (por ejemplo, generar miniaturas). El módulo ImageAPI inserta una capa de abstracción en Drupal que permite elegir qué biblioteca gráfica usar, GD o ImageMagick. Es mejor utilizar ImageMagick, ya que es una biblioteca independiente de PHP y, por ello obtendremos mejor rendimiento total en Drupal, y además es más estable (si falla GD puede caer todo el motor de PHP, sin embargo, si falla ImageMagick no caerá, ya que es un binario diferente).

Pero aún mejor: existe un proyecto llamado GraphicsMagick, que es un fork de ImageMagick y que es más estable y, sobre todo, con mejor rendimiento, ya que consume menos memoria y es más rápida. Y lo que es mejor, tiene la misma API que ImageMagick (el comando

convert), con lo cual podemos engañar a ImageAPI diciéndole que use ImageMagick cuando en realidad tenemos instalado GraphicsMagick.

Para lograr esto no tienes más que instalar GraphicsMagick y el módulo ImageAPI de Drupal, en dos sencillos pasos. Supongamos que trabajamos con un servidor Debian/Ubuntu (en otros sistemas operativos no debería ser muy diferente):

  1. Instalamos GraphicsMagick:
    apt-get install graphicsmagick-imagemagick-compatPodemos probar que GraphicsMagick funciona escribiendo convert en la consola:

isra@salon:~$ convert
GraphicsMagick 1.3.5 2009-01-26 Q8 http://www.GraphicsMagick.org/
Copyright (C) 2002-2009 GraphicsMagick Group.
Additional copyrights and licenses apply to this software.
See http://www.GraphicsMagick.org/www/Copyright.html for details.

Usage: convert [options ...] file [ [options ...] file …] [options ...] file

[más opciones]

  • Instalamos el módulo ImageAPI y lo activamos en /admin/build/modules (módulos ImageAPI e ImageAPI ImageMagick).
  • Accedemos a la configuración de ImageAPI en Administración > Configuración del sitio > ImageAPI (/admin/settings/imageapi) y veremos el siguiente mensaje: “The ImageAPI ImageMagick module is the only enabled image toolkit. Drupal will use it for resizing, cropping and other image manipulations“.
  • Si también hemos activado el módulo ImageAPI GD2, nos dará a elegir (seleccionamos ImageAPI ImageMagick como opción por defecto):

¡Y listo! Fácil y rápido. Podemos comprobar que funciona accediendo a Administración > Configuración del sitio > ImageAPI > Configurar (/admin/settings/imageapi/config), lo que nos mostrará información sobre GraphicsMagick (versión, tipos soportados, etc):

¿He hecho benchmarks para comprobar la ganancia de rendimiento con respecto a ImageMagick?

Pues no, lo siento. Pero los chicos de GraphicsMagick sí los han hecho, y son bastante jugosos.

Pero… ¿no es necesaria la extension imagick de PHP?

No, no es necesaria, ya que ImageAPI interactúa con ImageMagick/GraphicsMagick a través del binario
convert

Iré escribiendo algunos artículos más sobre técnicas fáciles para optimizar el rendimiento de Drupal.

Primeras experiencias con WordPress… y muchas nueces ;-)

Web de Nueces San Ignacio
Todo desarrollador web debe saber trabajar con uno o varios sistemas de gestión de contenidos (CMS). Estos programas nos ahorran reinventar la rueda cada vez que tenemos que publicar contenidos en la web, gestionar usuarios y la administración del sitio, organizar nuestro código de acuerdo a un estándar, etc, etc, etc.

Personalmente siempre he sido aficionado a los CMS, pero a nivel de usuario. Me encanta conocer y probar los gestores de contenido, aunque hasta hace poco no había desarrollado proyectos —proyectos de verdad— con una de estas herramientas, por vagancia para afrontar la curva de aprendizaje y por afán de reinventar la rueda (puede ser divertido y muy pedagógico, pero no es práctico si queremos buenos resultados).

El caso es que hace un par de meses comencé un proyecto web para un amigo que cultiva nueces y me animé a probar WordPress, animado por la experiencia de los chicos de Atracciona, que utilizan este gestor de blogs para hacer webs corporativas. Mi proyecto era dar presencia web a la Nueces San Ignacio y captar clientes a través de Internet, por lo que a nivel técnico las exigencias eran mínimas (unas cuantas secciones de texto rico, fotos, un formulario de contacto y poco más).

La experiencia con WordPress ha sido impresionante. A pesar de que no me gustan sus tripas (algunos fragmentos de código son verdadero spaghetti code), diseñar un theme con WordPress es increíblemente fácil y rápido. Una vez tuve el diseño en HTML/CSS, pasarlo a WordPress fue cosa de una noche. No toma más esfuerzo que copiar un tema (por ejemplo, Kubrick) e ir modificando las plantillas, adaptando el CSS y cambiando el marcado que sea necesario.

El resultado, una web corporativa con un panel de administración muy potente, la disponibilidad de miles de plug-ins y el respaldo de un software probado en millones de servidores.

Logo de Nueces San IgnacioMás allá de la programación, también diseñé la web, el logotipo —y las tarjetas de visita, y un dossier comercial, todo ello con software libre e imágenes libres— y todo lo relativo a márketing en redes sociales, SEO y SEM. Y aunque el mercado en el que se mueve la empresa no depende en gran medida de Internet (el objetivo es vender toneladas de nueces, y el público objetivo hoy en día son distribuidores y grandes superficies), poco a poco la estrategia web va dando fruto. La experiencia ha sido gratificante, porque no es lo mismo hacer un proyecto para un cliente (con la exigencia de calidad y la concentración de sólo programar) que para un amigo (he tenido total libertad para diseñar, desplegar, redactar, etc). Te lo tomas con más calma, le dedicas las horas que puedas y el resultado acaba siendo muy satisfactorio, porque de un modo u otro me he involucrado en la empresa.

Conclusión, WordPress es un muy buen gestor de blogs que también puede ser usado como gestor de contenidos genérico para sitios web pequeños, con una rapidez en la creación de themes que nunca antes se había visto. No obstante, cuando tenga tiempo he de revisar otros CMS para sitios web corporativos. Hace algún tiempo probé CMS Made Simple, pero no me convenció. Sin embargo, MODx promete bastante.

Cuestiones todas a resolver en 2010. Feliz Navidad y que el año que se avecina sea el mejor de tu vida :-)