Merece la pena

[...] he participado en dos tipos de proyectos: Aquellos en los que se invierte algo de tiempo en usar tests automatizados (Unit Testing u otros..) que al final se acaba recuperando con creces además de hacer un producto o un sitio web bastante más estable, y aquellos en los que no hay “tiempo para esas cosas”, pero sí hay horas y horas (y días y días) para arreglar en un servidor de producción los problemas que unos pocos tests hubieran detectado un mes antes cuando alguien tuvo un mal día y tocó la línea de código equivocado.

Jose A. Reyero

¿Quieres más razones para hacer unit testing? Aquí tienes doce.

Si te animas, aquí tienes algunos recursos para empezar a hacer unit testing en PHP:

¿Y tú, ya automatizas tus tests?

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

Todo lo que deberías saber sobre APC (II)

Configurar APC: directivas de configuración Aviso: si no has leído antes el primer artículo de la serie deberías hacerlo.

CONFIGURANDO APC para una óptima optimización optimizada

Como ya sabrás, las directivas de configuración se pueden cambiar en los ficheros .ini de configuración de PHP y sus extensiones. En el caso de Linux, probablemente el fichero esté en /etc/php5/apache2/conf.d/apc.ini, aunque también puedes añadir directivas en php.ini o cualquier otro fichero .ini del directorio conf.d/, ya que todos son cargados por el motor de PHP.

De todas las directivas de configuración que APC ofrece, creo que estas son las más jugosas:

  • apc.stat: indica si APC debe comprobar, a cada petición, si el archivo solicitado ha cambiado. En un servidor de producción es interesante desactivar esta opción ya que nos ahorraremos esa llamada al sistema. Pero ¡cuidado con los cambios de código! Para recompilar un script debes limpiar manualmente el APC o bien reiniciar Apache (con FastCGI no serviría).
  • apc.stat_ctime: comprueba que un archivo ha cambiado a través de los inodes, en lugar de con mtime.
  • apc.shm_size: especifica la memoria reservada para APC, en MB. Por defecto es 30.
  • apc.max_file_size: tamaño máximo de script cacheable.
  • apc.lazy_functions y apc.lazy_classes: cargan las funciones y clases de los includes sólo cuando son necesarios.
  • num_files_hint: aproximadamente cuántos scripts tienes en tu servidor. Ayuda a APC a optimizar sus índices internos. Si no estás seguro, mejor dejarlo a 0.
  • user_entries_hint: aproximadamente cuántas entradas de usuario guardarás. No estás seguro, mejor déjalo en 0.
  • apc.cache_by_defaultapc.filters: si pones apc.cache_by_default = 1, APC sólo cacheará los scripts cuyo nombre coincida con la expresión regular que especifiques en apc.filters. Interesante si tienes algunos scripts que sabes que van a cambiar muy frecuentemente (por ejemplo, durante un período de actualización) y has sido tan machote de desactivar apc.stat.
  • apc.include_once_override: se trata de una característica experimental, que se supone que optimiza las llamadas include_once y require_once para que consuman menos recursos. Dentro de algún tiempo tendremos más información sobre esta funcionalidad.

La extraña pero maravillosa directiva apc.rfc1867

Entre todas estas directivas de configuración destaca rfc1867, que obviamente hace referencia al documento RFC 1867, el cual especifica la subida de ficheros por HTML/HTTP. Pero ¿esto a qué viene?

Pues viene a que con APC, además de cachear los opcodes y guardar valores en la cache, también puedes controlar el progreso de las subidas de ficheros.

Sí, amigos. Si activamos la directiva apc.rfc1867, por cada fichero que se suba a tu servidor APC creará e irá actualizando una user entry con información sobre la subida. Esta entrada contendrá algo así como:

Array
(
    [total] => 1142543
    [current] => 1142543
    [rate] => 1828068.8
    [filename] => test
    [name] => file
    [temp_filename] => /tmp/php8F
    [cancel_upload] => 0
    [done] => 1
)

Es decir, el tamaño total del fichero, los bytes transferidos (current), la velocidad de subida (rate) y otros parámetros. Con esta valiosa información puedes hacer una bonita barra de progreso para indicar a tus usuarios cómo van sus subidas. Si quieres más detalles sobre cómo utilizar esta característica, te remito a este artículo y, como siempre, al manual oficial.

Si te has quedado con ganas de más

  • apc@facebook: presentación de 2007 donde se explica el funcionamiento de APC y se exponen los valores de configuración en los servidores de Facebook. Además explican su interesantísimo sistema para distribuir configuraciones en múltiples servidores a través de APC.
  • 2bits cuentan un caso interesante con Drupal y la discusión es también muy rica.
  • ¡El manual! No me canso de decirlo.

Esto no termina aquí

Te toca a ti. ¿Tienes experiencia con APC? ¿Has notado la mejora de rendimiento en tus servidores de producción? ¿Cómo lo has configurado? ¿Me das la contraseña de root?

Todo lo que deberías saber sobre APC (I)

Una de las formas más fáciles, a la vez que efectivas (un 300% de media), de hacer que tu sitio web PHP sea más rápido es usar un opcode cache. Hay varios en el mercado: APC, eAccelerator, XCache… vamos a ver APC por ser libre, el más fácil de manejar, extendido y el que mejores resultados arroja en los benchmarks.

Pero… ¿qué es un opcode cache?

Diagrama de flujo de APCComo seguramente sabrás, PHP es un lenguaje interpretado. Esto significa que cada vez que se solicita la ejecución de un script (o sea, cuando el usuario navega a una página concreta), este se compila y se ejecuta de forma automática, dando la sensación de que “no hay que compilar PHP”. Es un mito bastante extendido que PHP no se compila. Falso. PHP sí se compila, pero de forma automática. “Just In Time” (JIT), que dicen los anglosajones.

Este sistema de compilación JIT tiene la ventaja de una gestión más simple, sobre todo cuando tienes un script ya funcionando en el servidor y quieres modificarlo. Con PHP simplemente tienes que sustituir el fichero… y listo, la próxima vez que alguien acceda ejecutará la nueva versión.

Pero también tiene una desventaja: a cada visita se debe compilar el script. Y es una pérdida de tiempo, ya que si todos los visitantes de tu web ejecutan el mismo script, ¿para qué compilarlo una y otra vez? ¿No sería mejor compilarlo la primera vez, guardar ese script compilado (opcode) y ejecutarlo cuando alguien lo solicite?

Pues eso es exactamente lo que hacen los opcode cache: compilan el script la primera vez, lo guardan en memoria (RAM), y cuando se solicita, simplemente ejecutan el script compilado, logrando un aumento de velocidad bastante considerable.

Me has convencido. ¡Usemos APC!

APC (Another PHP Cache) es un sistema automático que compila los script sólo cuando es necesario. Viene empaquetado como una extensión de PHP, así que su instalación es sencilla. Y más si estamos usando Ubuntu o Debian Linux:

$ sudo apt-get install php-apc

Con sólo instalar este paquete (suponiendo que ya tengamos instalados Apache y PHP) ya tendremos APC funcionando correctamente. Si quieres más información sobre la instalación de APC puedes ir a la documentación oficial o en Google. Si tu proveedor de hosting no te ofrece APC… lo siento, es lo que tiene el hosting compartido :-P

Para saber si APC está funcionando correctamente, ejecutamos phpinfo():

APC como cache genérico

Además de “cachear” los scripts, APC sirve como almacenamiento genérico en memoria. Esto quiere decir que puedes guardar datos en la memoria de APC que estarán en RAM (por tanto, será de más rápido acceso que si los guardas en el disco duro o en una base de datos) y que podrás recuperar en cualquier momento. Eso sí, recuerda que si reinicias Apache o el sistema operativo, todos los datos que APC haya guardado en memoria se eliminarán.

Para almacenar una variable en la cache de APC puedes usar la función apc_add(), y para leerla, apc_fetch(). Por ejemplo:

/*
 * AVISO: este código tiene fines exclusivamente didácticos, y no debe ser
 * utilizado en aplicaciones reales en producción
 */

function leerPerfil() {
    $idUsuario = intval($_GET['idUsuario']);

    /**
     * Lee de la BD los datos del usuario $idUsuario. Si los datos están en cache,
     * no hacemos la consulta. Si no están, hacemos la consulta y guardamos los
     * datos en cache
     */
    if (empty($datosUsuario = apc_fetch("perfil_$idUsuario"))) {
        $query = mysql_query("SELECT * FROM usuarios WHERE id = '$idUsuario'");
        $datosUsuario = mysql_fetch_assoc($query);
        apc_add("perfil_$idUsuario", $datosUsuario);
    }

    return $datosUsuario;
}

Este sistema te permite hacer optimizaciones adicionales en tus aplicaciones (por ejemplo, guardar el resultado de una consulta a la base de datos para no tener que hacerla dos veces), pero tendrás que currártelas a mano. Tú eliges qué almacenar en APC. Pero ojo, si vas a hacer un uso intensivo de la caché, es mejor que uses un sistema de caché diferente al de los scripts. Por ejemplo, el famoso memcached (usado por sitios como Google o Facebook), que es un sistema de caché genérico, muy eficiente y muy fácil de usar (en serio, es muy fácil). Más información sobre funciones de APC en el manual de PHP.

Monitorizar APC

Otra de las ventajas de APC es que tiene un precioso panel de control. Es un script PHP al que puedes acceder haciendo un enlace desde tu directorio www público hasta la ubicación del script (en los directorios del sistema de PHP):

gunzip -c /usr/share/doc/php-apc/apc.php.gz > /var/www/apc.php

Si no funciona, o si no usas Linux puedes leer la documentación para instalar el panel de control de APC. Si no encuentras el script en tu sistema de ficheros puedes sencillamente descargarlo desde el Subversion de APC.

Aviso de seguridad: este script permite ver el estado de APC, revelando alguna información sobre el servidor que puede ser sensible por temas de seguridad. Es tu responsabilidad proteger el acceso al panel de control a través de configuraciones del servidor web, etc.

El panel de control tiene algunas opciones “públicas” y otras a las que sólo puedes acceder iniciando sesión con nombre de usuario y contraseña. Para cambiar el nombre de usuario y la clave puedes editar el propio script del panel de control, apc.php:

Cambiar la contraseña al panel de control de APC

El panel de control nos ofrece tres apartados:

  1. View Host Stats, donde tenemos un cuadro de control de APC con gráficas de consumo de memoria, información del sistema y datos de uso del cache.
  2. System Cache Entries: la lista de scripts cacheados, así como el número de hits (ejecuciones) que han tenido, su tamaño y fechas de último acceso/última modificación/creación.
  3. User Cache Entries: las variables que se hayan guardado en APC.

Configurar APC: panel de control

En el próximo artículo explicaremos más detalles sobre el panel de control de PHP y cómo interpretar los datos que nos brinda de cara optimizar aún más nuestro sitio web. Aunque si has llegado hasta aquí y has instalado APC en tu servidor ya has conseguido un gran ahorro de recursos en tu servidor :-)

Os presento a Kanpress

¡Hola! Estas últimas semanas he estado desarrollando una idea que surgió de una necesidad real: coordinar el trabajo de los cerca de diez redactores que escriben en Caminayven –se trata de una revista católica que funciona con WordPress–. Si nuestro trabajo es escribir artículos y un artículo puede estar en estado propuesto, en desarrollo o pendiente de revisión… ¿por qué no usar la metodología Kanban?

Así surgió la idea de Kanpress, un plug-in de WordPress que acerca los tableros Kanban al mundo editorial. Un artículo, una tarea. Proponer, asignar, desarrollar, revisar. Si quieres saber más sobre Kanpress, te remito a la página del proyecto. Aquí contaré brevemente cómo está siendo la gestión de un proyecto de software libre non-profit, pequeño pero con vocación de crecer en usuarios y características.

El comienzo del proyecto fue sencillo: la idea, el prototipo sobre papel y una implementación rápida de las funcionalidades más básicas: crear tarea, asignarla, mover su estado, etc. En cuanto tuve una primera y muy verde versión beta, la subí a Caminayven para que los compañeros la probaran, detectando errores y recibiendo de ese feedback la priorización de las siguientes funcionalidades a implementar.

Boceto de Kanpress en papel

El siguiente hito fue la Betabeers, reunión de programadores en Murcia, que aproveché para presentar Kanpress a un selecto grupo de espartanos que acogieron la idea con mucho interés. Para poder llegar al día de la presentación con algo decente trabajé en un sprint de dos días dedicados casi en exclusiva a mejorar la interfaz y pulir errores. Dos días en los que, por cierto, la técnica del pomodoro tuvo una importancia capital.

Es destacable el dato de que, cuando presenté Kanpress en la Betabeers (el pasado 8 de febrero), ni siquiera traía las rutinas de instalación necesarias para que el público pudiese probar Kanpress. Sólamente funcionaba en mi portátil y en caminayven.com. Pero funcionaba y tenía una interfaz decente, lo que me permitió causar buena impresión y captar algunos colaboradores. Pragmatismo en estado puro.

Cuando se celebró la Betabeers era demasiado pronto para que Kanpress rompiera el cascarón, pero las oportunidades hay que aprovecharlas. Los días siguientes fueron más de documentar y preparar Kanpress para su distribución que de agregar nuevas funcionalidades, así como de darle un poco de bombo (algunos blogs se hicieron eco de la existencia de Kanpress).

El tercer hito fue enviar Kanpress al repositorio oficial de plug-ins de WordPress, que fue aceptado al día siguiente. Esto suponía, principalmente, dos cosas: que Kanpress tenía que hablar inglés, y que debía usar el repositorio Subversion que me proporcionaba WordPress (y esto era un problema porque desde el principio trabajé con GitHub).

Así que últimamente me he esforzado por internacionalizar Kanpress (inglés, español y gallego son los idiomas soportados actualmente) y he decidido dejar de usar GitHub, ya que no he conseguido de forma elegante sincronizar ambos repositorios. También he procurado hacer completa y atractiva la página del plug-in en WordPress.

En resumen:

  • Implementa la idea lo más rápido que puedas y pide opinión a gente (mejor si es gente que entienda).
  • Pónselo fácil a los usuarios: haz una buena página, bonita y atractiva.
  • Internacionaliza: seis mil millones de cabezas piensan más que 300 millones de hispanohablantes.

¿Algún comentario? ¿Gestionas algún proyecto de software libre? ¡Comparte tu opinión en los comentarios!

PUFW8V3HXSQF