Feb 17 2011

Quomai

tatai

Con este nombre, es como hemos bautizado a este nuevo proyecto y aventura en el que nos hemos metido. Quomai.

Logo de Quomai

Queremos que suene mucho y fuerte entre todos vosotros y estamos trabajando muy duro para que en breve veáis la idea en funcionamiento.

Y así para empezar… os gusta el nombre? Y el logo?

Stay tuned!

Estos son algunos de los sitios donde daremos guerra:


Nov 22 2010

El patito de goma como método de debug

tatai

Uno de los métodos más baratos y conocido para hacer debugging “en parejas” es el método denominado “el patito de goma”. Creo que esta es la primera vez que se habla sobre él.

Es realmente sencillo y he tenido he podido comprobar (conmigo y con otros) como la eficacia de este método es elevadísima. Hay que seguir unos sencillos pasos:

  1. Conseguir un patito de goma, preferiblemente variedad baño
  2. Colocar el patito cerca nuestra, en el escritorio por ejemplo e informarle que vais a ver un poco de código, a ver si está de acuerdo.
  3. Explicar al pato qué es lo que se supone que hace el código y tras esto, entrar en detalle explicándolo línea a línea.
  4. En algún momento le dirás al patito lo que se supone que es lo siguiente a hacer y te darás cuenta que eso no es lo que realmente está haciendo tu código. El pato se mantendrá sentado serenamente, contento de saber que te ha ayudado en tu tarea.

Existen variantes al patito de goma, como otro tipo de peluches y objetos, pero su efectividad no está tan demostrada como con el patito de goma.


Nov 22 2010

Problemas con mocks en PHPUnit

tatai

A petición de Mariotux, va este post sobre uno de los problemas que me he encontrado cuando he tenido que usar mocks en PHPUnit. Es uno de los errores ya reportados y se da al intentar comprobar llamadas a un método con distintos parámetros.

Supongamos que tenemos una clase como esta que queremos mockear:

class MyClass {
  public function check($param) {
    // Código
  }
}

En el caso concreto de querer comprobar si se realizan, por ejemplo, dos llamadas a esta función pasando $param = ‘one’ y una llamada con $param = ‘two’, es cuando nos encontremos el problema. Por ejemplo:

$mock = $this->getMock('MyClass');
$first = 'one';
$mock->expect($this->exactly(2))->method('check')->with($first);
$second = 'two';
$mock->expect($this->once())->method('check')->with($second);

Aunque la clase que programemos realice correctamente las llamadas, PHPUnit nos indicará que se esperaban 2 llamadas a check, pero se han realizado 3 y, por lo tanto, no pasará el test.

Esta misma semana comentaba con Carlos Ble y hay posibles soluciones, como es generar una clase intermedia que separe ambas llamadas, siempre teniendo en cuenta que podamos hacer ese código y quizás no sea tan sencillo con código legado o con mucho acoplamiento.

A ver si en los próximos releases de phpunit-mock-objects se soluciona este problema.


Nov 17 2010

Configurar el fichero hosts de Android Emulator

tatai

Es posible que te encuentres en la situación (doy un par de ejemplos más abajo) en los que necesites que tu Android Emulator haga caso a tu /etc/hosts en vez de al DNS. Para este caso, lo que tienes que hacer es seguir estos dos sencillos pasos:

  1. Crear un fichero hosts en tu ordenador (o usar el que ya tienes en /etc/hosts)
  2. Remontar el emulador y copiar el fichero anterior

La necesidad de remontar viene porque si no, el dispositivo está como sólo lectura y por lo tanto es imposible escribir nada en él.

Supongamos que tenemos partimos de nuestro /etc/hosts, iríamos al directorio donde tenemos las tools del SDK y teclearíamos:

adb remount
adb push /etc/hosts /system/etc/

También es posible coger el fichero hosts que tiene el emulador (por ejemplo, copiandolo a nuestro directorio /tmp):

adb push /system/etc/hosts /tmp

¿Y en qué casos nos puede hacer falta? Bueno, yo en concreto lo he necesitado cuando estaba desarrollando una aplicación que se alimentaba de un webservice. Realizaba el desarrollo del webservice en paralelo y por lo tanto no estaba (todavía) en la máquina de producción. De esta forma, gracias al fichero hosts obligaba al emulador a buscar en mi entorno de desarrollo en vez de ir al de producción, haciendo que la aplicación tuviese un comportamiento transparente, en código, sobre dónde atacar.


Nov 11 2010

Return no numérico en funciones bash

tatai

Por defecto en bash sólo se pueden retornar enteros. ¿Qué hay que hacer entonces para que retorne un valor no entero?

El truco está en hacer un echo del valor y asegurarnos en la llamada de la función que se asigna a una variable. Es decir, nuestra función sería:

function retorna_texto {
    echo -n "este es el valor a retornar"
}

Y la llamada:

VALOR=$( retorna_texto )

Ahora en ${VALOR} tendremos el texto tal y como queríamos


Feb 26 2010

Bash completion for symfony (autocomplete)

tatai

I have just pushed into GitHub a bash autocomplete script for symfony.

This script allows to autocomplete your first level option when calling to symfony script. It is easy to install (just copy one and call it manually if you do not have access rights). All steps and working issues are in the wiki. It also accepts custom actions.

This is a working example once script is corretly installed and invoked:

Assuming symfony is in current folder and [tab] y tab key press action, this is an example of how symfony_complete works:

$ ./symfony con[tab]figure:[tab][tab]
author    database
$ ./symfony doctrine:a[tab]uthor

We are pleased to know what you think and any issue you have. You can find us on GitHub.

Related links:


Feb 11 2010

XHP: una extensión para escribir PHP de forma distinta

tatai

Una de las noticias de esta semana en el mundo PHP es sin duda toda la información acerca de HipHop for PHP por parte del equipo de desarrollo de Facebook. Una de las extensiones que ha salido a la luz por parte del equipo de front-end es la que han llamado XHP y, como ellos mismos rezan, “a new way to write PHP” (una nueva forma de escribir PHP).

La explicación de cómo funciona es muy sencilla. Intentan evitar que al desarrollar la parte de frontal, cuando nos “pegamos” con el XHTML, tengamos que unir código XHTML y PHP. En el ejemplo que muestran se ve más claramente.

De un código como:

<?php
if ($_POST['name']) {
?>
    <span>Hello, <?=$_POST['name']?>.</span>
<?php
} else {
?>
    <form method="post">
    What is your name?<br>
    <input type="text" name="name">
    <input type="submit">
    </form>
<?php
}

Nos da como opción generar este otro:

<?php
// note: includes omitted
if ($_POST['name']) {
  echo <span>Hello, {$_POST['name']}</span>;
} else {
  echo
    <form method="post">
      What is your name?<br />
      <input type="text" name="name" />
      <input type="submit" />
    </form>;
}

No voy a negar que, de primeras, XHP parece más sencillo de seguir y de generar. Eliminar los tags de apertura y cierra de PHP aligera el código en gran medida. Además, eliminamos problemas con el XSS así como detectar problemas por malformación de XHTML en tiempo de parsing.

A mi personalmente me sigue gustando bastante más usar un motor de plantillas. Un motor real como XTemplates (sí, he dicho XTemplates, no smarty o similares). Separar el código PHP del HTML me parece bastante importante y necesito verlo con más claridad.

No obstante, hay que seguir el tema de cerca. Si es algo que la gente de Facebook ha visto que es necesario ya que aumenta el rendimiento, es evidente que en este tipo de entornos será uno de los puntos de referencia. Sin embargo, XHP como técnica para el resto de las webs donde no se reciban tantas peticiones como Facebook (si no recuerdo mal, sirven más doscientas mil millones de páginas al mes, sí, sí, 200.000.000.000), es posible que un objetivo que cumpla a primera vista es juntar el PHP con el HTML, algo que, repito, me parece bastante “sucio” si no hay una justificación clara. Pos supuesto, un motor de plantillas tiene sus desventajas, no vamos a negarlo :)

Lo dicho, XHP de momento me parece algo que puede provocar que el código sea más rápido pero a costa de hacerlo más guarro. Habrá que seguirle la pista para ver por dónde avanza, no lo descarto de primeras porque el objetivo de aumentar el rendimiento es muy importante, pero analizando el coste (ni monetario ni de recursos en este caso, jeje).

Enlaces:

Update: Muy muy muy interesante lo que comenta Rasmus en su web. Importante verlo.


Oct 21 2009

Trabajando con eficiencia

tatai

Muchas veces considero que es una obsesión, pero de lo que estoy seguro es que muchas más veces gano tiempo pensando un poco y haciendo las cosas mejor y más rápidas.

El caso que voy a presentar ahora es lo que yo considero “la forma más rápida de descargarnos un dump de una base de datos”. Añadamos como condición que tenemos que usar un protocolo cifrado, en este caso, SSL. Para cualquier de los dos ejemplos que voy a presentar, contamos que tenemos autentificación en el servidor remoto (ahora que sabemos cómo hacerlo).

Empecemos por el final. Cómo se nos ocurriría hacerlo directamente. Básicamente los pasos serían estos:

# Nos conectamos al servidor
ssh user@server.com
# Realizamos el dump de la base de datos
mysqldump -u mysqluser -p mysqldb > dump.sql
# Comprimimos los datos para reducir el tamaño de los datos a trasferir
gzip dump.sql
# Volvemos a nuestro ordenador
exit
# Copiamos el fichero a nuestro ordenador
scp user@server.com:dump.sql.gz .

He hecho una prueba con una base de datos pequeña. Si únicamente contabilizamos el tiempo en realizar cada uno de estos comandos y los sumamos (es decir, no tenemos en cuenta ni el ssh inicial ni los tiempos entre comandos, incluído si nos vamos a tomar un café mientras hace el volcado o lo comprime), salen los siguientes tiempos:

  • mysqldump: 2.2 segundos
  • gzip: 0.5 segundos
  • scp: 12.2 segundos
  • total método 1: 14.9 segundos

Veamos ahora otra forma. ¿Y cómo es? Pues bien sencilla… ¿y si te digo que puedes agrupar todos los comandos en únicamente uno?

¿Cómo? Pues aprovechando que se pueden ejecutar comandos de forma remota con el comando ssh y que lo que devuelva ese comando, se retorna mediante la consola estándar (stdin). Además, teniendo en cuenta que también podemos llamar a gzip en línea mediante una tubería (denominada en inglés pipe, representada por la barra vertical: |). Si unimos todo esto, nuestro comando queda (ejecutado directamente desde nuestra máquina):

ssh user@server.com "mysqldump -u mysqluser -p mysqldb | gzip" > dump.sql.gz

Si medimos el tiempo que le cuesta a este comando obtenemos para el método 2: 12.0 segundos

La diferencia puede parecer muy pequeña vista así, pero estamos hablando que es casi un 20% más rápido. Si este proceso (con el primer método) hubiese durado 4 horas (sí, os aseguro que se puede dar el caso), en algo más de 3 horas lo habríais terminado. Estos datos son muy variables, hay que tener en cuenta muchas cosas, pero que hagáis las pruebas que hagáis, en igualdad de condiciones, este nuevo método es mucho más rápido.

Y os aseguro que si hacéis la prueba con un proceso largo, en el que tendríais que esperar que terminase cada paso para iniciar el siguiente comando, ganaréis mucho tiempo sobre todo entre comando y comando.

La próxima vez que os toque algo como esto, usad este método y tomaros el café (o la comida) que os podréis tomar gracias a no tener que esperar, a mi salud.

Pensad un poco, esto es sólo un ejemplo, ¡hay muchas más opciones!


Oct 5 2009

Cuenta atrás/Countdown para mootools

tatai

Es posible que en la pasada Navarparty 7 participases en el concurso Date El Bit y te encontraras con que este año la primera fase de las preguntas se realizaba pregunta por pregunta y había una cuenta atrás para cada una de ellas.

Pantalla de ejemplo de Date El Bit de la Navarparty 7

Pantalla de ejemplo para Date El Bit de la Navarparty 7

Pues bien, para poder hacerla realicé una pequeña clase en javascript para Mootools que me permitiera poder visualizar la cuenta atrás que se puede ver en la imagen. Como estuve buscando por internet y no encontré nada que me gustase, me lancé a hacerlo, no podían ser muchas líneas.

Y así ha sido. Con tan sólo 98 líneas (incluídos comentarios en inglés), tengo el gusto de presentar la clase Countdown.

Esta clase tiene como objetivo realizar la cuenta atrás visualmente actualizando un elemento DOM que se le indique.

El ejemplo de utilización más sencillo es este, que nos crea una cuenta atrás de 10 a 0 en pasos de hasta 100 milisegundos que actualiza en el elemento con id=”counter”:

new Countdown($('counter')).start();

Podemos completarlo un poco más con el siguiente ejemplo:

new Countdown($('counter'), {
  'decimals' : '3', // para hacer que parezca un tiempo de la fórmula 1 :p
  'onComplete' : function() {alert('finalizado!');}, // muestra un alert cuando acaba la cuenta atrás
  'onStep' : function(target, show) {
    // Si el contador está por debajo de 5, poner en rojo, si no, en negro
    if(show < 5) {
      target.setStyle('color', '#f00');
    }
    else {
      target.setStyle('color', '#000');
    }
  }
});

Oct 2 2009

Una forma sencilla de hacer bien las cosas

tatai

Para romper este “silencio” de casi un mes debido a la Navarparty y al trabajo, volvamos a la carga con un pequeño post.

Quiero tratar el tema de “cómo hacer bien las cosas programando” con un sencillo ejemplo que pasó el otro día por mis manos. Y para ello contaremos con dos actores, un array y un if. Supongamos que tenemos los siguientes datos:

$a = array
  array('from' => 0, 'to' => 100),
  array('from' => 101, 'to' => 250),
  array('from' => 250, 'to' => 1000),
  array('from' => 1001, 'to' => 2000)
);

Nuestro sencillo código va a retornar el índice del array $a en el que se encuentra un número $b. Ahora bien, tenemos dos formas de hacerlo:

Opción a:

function getRange($b) {
  foreach($a AS $index => $actual) {
    if($actual['from'] <= $b && $actual['to'] >= $b) {
      return $index;
    }
  }
}

Opción b:

function getRange($b) {
  foreach($a AS $index => $actual) {
    if($actual['to'] >= $b && $actual['from'] <= $b) {
      return $index;
    }
  }
}

El único cambio es el if que, como se puede ver, cambia el orden de las condiciones.

Entonces, hacemos la pregunta, ¿cuál de las dos opciones es más eficiente? Es posible que no lo veas claro, pero si lo miras un poco veras como en la mayoría de los casos es la opción b. Únicamente son igual de eficientes cuando $b se encuentra entre los valores de la primera posición.

¿Y por qué es más eficiente la opción b? La respuesta es porque dentro del if, al tener un Y lógico (los dos ampersands &&) si la primera condición es falsa, la otra condición ni siquiera se evalúa. Es decir, nos ahorramos que el microprocesador tenga que hacer esa comprobación lógica. Y este caso se da si pensamos que $b = 150. Para la opción a el if tiene que ejecutar ambas condiciones (0 <= 150 && 100 >= 150) para descubrir que es false y pasar a la siguiente iteración, mientras que con la opción b bastaría con la primera comprobación (100 >= 150) para saber que es false y pasar a la siguiente iteración.

Si se hace este if una única vez estamos hablando de una parte muy pequeña de un segundo, pero si esta tarea es muy repetitiva o el array tiene muchas posiciones, el efecto es claramente favorable e incluso se puede notar directamente.

Este sencillo ejemplo demuestra como pensar un poco las cosas y cambios muy pequeños en tu código pueden hacer que tengas un código mucho más optimizado y que te de mayor rendimiento.

Y por si quieres rizar el rizo, la opción a puede ser más eficiente que la b, pero sólo en el caso de que se recorra el array de forma descendente o este ordenado de forma inversa.