miércoles, 23 de septiembre de 2009

Algunos fallos tontos en el desarrollo web con PHP

¿A qué desarrollador web no le ha pasado alguna vez tener algo que no funciona, probar mil cosas y luego darse cuenta que era un error o fallo trivial? Para tirarse de los pelos, ¿verdad? Voy a relatar algunos.

  • ¿Por qué no entra por el if?
    Este es típico: un if que controla una sóla condición. Ejemplo en PHP, pero aplicable a cualquier lenguaje -excepto Python :-)
    loQueSea();
    if ($varControl)
    hazAlgo();
    otraCosa();

    Al cabo de un rato piensas que  si entra por el if, además debes cambiar otra variable y escribes:
    loQueSea();
    if ($varControl)
    hazAlgo();
    $otraVarControl = true;
    otraCosa();

    Y nunca consigues que otraVarControl se quede a true. ¿Qué pasa aquí? Fácil: no hemos puesto llaves al if.
    Conclusión: aunque el if sólo controle una sentencia, mejor con llaves siempre. Al final siempre va a haber más de una sentencia bajo ese if:
    loQueSea();
    if ($varControl) {
    hazAlgo();
    $otraVarControl = true;
    }
    otraCosa();


  • ¡No pilla los cambios!
    Es la típica llamada de un cliente (o un jefe): ¡me has dicho que cambiaste el XXX y no lo veo, sigue como antes!
    Nuestro XXX puede ser un fichero .js, un .css, una imagen o cualquier otro tipo de recurso que estamos seguros que hemos actualizado y que aún así, nos dicen que no lo ven.
    A los desarrolladores web no nos gustan mucho las cachés, ni proxies, etc, y además nos conocemos todos los típicos trucos para hacer un refresco completo de la página, pero nuestros jefes, clientes y usuarios sí que utilizan cachés (en el navegador, en su proxy). Además no se saben esos "mágicos" atajos de teclado que utilizamos sistemáticamente (Ctrl-Shift-R, Ctrl-F5 en IE) para ver cómo va nuestro trabajo en el navegador.
    Solución: forzar el refresco. Supongamos el siguiente HTML que incluye un .js sobre el cual hemos hecho cambios importantes:



    ...

    Subimos el fichero actualizado al hosting o servidor de producción, hacemos la llamada o enviamos el correo de rigor ("oye, ya está hecho") y al rato tenemos el típico "yo lo veo como antes".
    Nuestro fallo: presuponer que el entorno del usuario es el mismo que el nuestro. Puede que esté navegando a través de un proxy (suelen guardar en caché los elementos que le solicitan), su navegador puede estar configurado para que también "cacheé" algunos recursos, etc.
    La solución más fácil es añadir un "query string" a la llamada al recurso. Esto nos garantiza que será tratado como un fichero diferente y cargado de nuevo:



    ...

    Nos da igual cuál es esta "query string", simplemente lo que queremos es que todos los proxies, navegadores y demás clientes entiendan que es un recurso diferente. Este truco es válido para CSS, imágenes, swf. Por ejemplo, en la regla CSS:

    div.cabecera {background-image: http://mi.servidor.com/img/fondo.png?r=1}

    Si se tiene todo el trabajo integrado en un sistema de control de versiones, es muy útil configurar nuestro "deploy" para que este "parámetro" tome siempre el número de versión. Si estamos desarrollando la aplicación todavía, el truco infalible para que el navegador siempre lea los recursos como "nuevos" es hacer las llamadas así en nuestro fichero .php:



    <script src="fichero.js?version=" type="text/javascript">
    <link href="fichero.css?version="  rel="stylesheet" type="text/css" />

  • Página en blanco, no se ve nada. ¿Qué falla?
    Este típico error suele pasar cuando PHP está configurado para no mostrar ningún error (lo más recomendable en producción). Las soluciones son dos:

    • Editar el php.ini y cambiar el ajuste "display_errors" (nada recomendable).

    • Escribir la siguiente instrucción para saltarnos este ajuste para un "script" en concreto:
      <?php
      ini_set('display_errors', 1);
      // Sigue nuestro script

      La función ini_set() permite ajustar parámetros de configuración para un script determinado. Es muy útil cuando algo falla y no vemos dónde.



  • Los usuarios de mi aplicación no pueden hacer "login", o unos acceden al perfil del otro.
    Este es un error bastante insidioso y puede tener diferentes orígenes. Hay que conocer cómo maneja PHP las sesiones: PHP asigna al usuario una 'cookie' única con el identificador de sesión. En el servidor se guardan ficheros de sesiones en un directorio, un fichero para cada sesión 'asignada' a un usuario. Problemas potenciales:

    • El usuario no está aceptando cookies: en este caso es imposible que PHP asocie una sesión y sus datos con un usuario. Se puede configurar para que PHP mande el identificador de sesión en la URL, pero no es nada recomendable. Se puede comprobar si el usuario acepta cookies intentando enviarle una y leyéndola a continuación. Si no la tenemos, sacamos una advertencia al usuario.

    • El directorio del servidor donde se guardan las cookies no está accesible (problemas de permisos, falta de espacio, etc).

    • Si tenemos una configuración con balanceo de carga (varios servidores atendiendo a la misma URL) tenemos que asegurarnos que una vez que un usuario 'entra' por un servidor, sigue siempre en el mismo servidor. Otra solución es guardar las sesiones en una base de datos en vez de almacenarlas como ficheros.




Hay muchísimos más fallos tontos que nos podemos encontrar, pero éstas son algunas de las que más tiempo me han hecho perder ;-)

martes, 21 de julio de 2009

Selectores CSS: la intersección entre diseño y programación

El uso de selectores CSS en los "frameworks" para JavaScript más conocidos ha permitido lo que hace unos años era impensable: los diseñadores entienden el código de los programadores y los programadores pueden comprender el CSS de los diseñadores.

jQuery es especialmente adecuado: no distingue entre selectores "por id" ni selectores por "clase" (Prototype tiene dos funciones diferentes, $() y $$(), para estas tareas).

$('.lateral a.externo').click(function(ev) {
// Código  a ejecutar
})


Este sencillo código es fácil de entender y un diseñador al verlo rápidamente intuye que en todos los tags A dentro de la "capa" lateral que tengan la clase externo se hará algo al hacer click.

.lateral a.externo {color: red; padding: 5px; margin: 0;}


Este fragmento de CSS afecta a los mismos elementos que el javascript anterior. Un desarrollador enseguida ve también a qué elementos afecta.

Lo bueno es que si el diseñador y el programador hablan en el mismo lenguaje (selectores CSS), el desarrollo es muy fácil y se puede trabajar en paralelo fácilmente.

miércoles, 15 de julio de 2009

Probando Android en un PC

Gracias al proyecto Live Android podemos probar en nuestro emulador favorito (VirtualBox, VMWare, ...) el sistema operativo para dispositivos móviles de una forma muy cómoda.

En mi caso he configurado en VirtualBox una máquina "Linux 2.6" con 256 Mb de RAM y 8 Mb de memoria de vídeo. Arrancamos desde la imagen ISO y ¡voilá!: ya tenemos Android en nuestro escritorio. Es un poco complicado usarlo con sólo las teclas, así que ahí va una "chuleta" (lo he encontrado aquí):

Arrows -> navigation
Enter -> confirm
Left Windows key -> home
Escape -> back
Menu key (next to right Windows key) -> application menu
+ F1 -> Console mode
+ F7 -> Graphical mode

(En el Mac no tengo tecla "Win" y la "manzanita" izquierda me "echa" del emulador. Ya lo miraré con más detenimiento).

He estado jugueteando un rato y la verdad, es un sistema muy apetecible no sólo para móviles, sino también para portátiles. A mi Aspire One le sentaría muy bien, tiene todo lo básico (correo, mensajería, cámara, álbum de fotos, reproductor de música, etc).

[gallery link="file" columns="4"]

miércoles, 24 de junio de 2009

Gasto de memoria en navegadores

Seguimos haciendo algunas pruebas con los navegadores mas recientes: Chrome 3 para Mac (beta), Safari 4, Firefox 3.5 beta y Opera 10 beta.

En la entrada anterior evaluábamos como se comportaban ante los tests de JS, hoy vemos el consumo de memoria. Chrome es un navegador multiproceso, así que la medida del consumo no es tan simple como sumar la memoria que consume cada proceso, aunque puede darnos una idea.

Estos son los datos que he obtenido en mi MacOSX:

[caption id="attachment_349" align="aligncenter" width="300" caption="Consumo de memoria con 7 pestañas abiertas"]Consumo de memoria con 7 pestañas abiertas[/caption]

[caption id="attachment_350" align="aligncenter" width="300" caption="Consumo de memoria con 12 pestañas abiertas"]Consumo de memoria con 12 pestañas abiertas[/caption]

Las pestañas que teníamos abiertas eran variadas: Gmail, Google Calendar, Youtube, un par de periódicos "online", ...

Conclusiones:

  • El "plugin" de Flash causa muchos problemas y provoca unos picos de consumo de CPU en todos los navegadores en general.

  • Chrome beta no puede usar plugins todavía, así que sus resultados están un poco falseados.

  • Firefox 3.5 [impresión subjetiva] parece que se mueve un poco mas ligero, pero sigue siendo bastante glotón.


Como he comentado en muchas ocasiones: si sigo utilizando Firefox, es por Firebug.

martes, 9 de junio de 2009

"Benchmarkeando" navegadores

En la siguiente dirección, la gente que desarrolla el motor de JavaScript para el navegador Chrome tiene una serie de pruebas para medir el rendimiento de JavaScript de un navegador.

Como es previsible (es parte interesada, ¿no?), Chrome obtiene la mejor puntuación y el nuevo Safari 4 también obtiene una muy buena puntuación.

Lo curioso es que el resto de navegadores sacan mucha peor puntuación, como un orden de magnitud menos. A ver si busco más "benchmarks" de JavaScript y paso otra batería de pruebas.

[gallery link="file" columns="4"]

También he incluido una captura de los IE 7 y 8 a título anecdótico. Se cuelgan en el test.

Actualizacion: he pasado el conjunto de "tests" que proponen en la web de Dromadeo con algunos navegadores. Ahora es Safari 4 el que gana, despues, Chrome.

Actualización II: Firefox 3.5beta gana bastante en rendimiento.