El futuro es de Javascript

El gran ruido de la invasión en el lado servidor de Javascript empezó en el año 2009 con Node.js: no era el primer proyecto que lo intentaba pero sí el primero que lo lograba, y su logro aportó más que poder disponer del mismo lenguaje en el cliente y en el servidor. Por otro lado, sobre las posibilidades que ofrece actualmente Javascript en el navegador gracias a los compiladores JIT, ya he hablado en otro artículo.

Aunque el creador de Node.js, Ryan Dahl, abandonara su proyecto hace ya años, dejando de lado la web para pasar a proyectos más interesantes de Machine Learning, afirmando que Go es una mejor herramienta para servidores web con gran volumen de carga, creo que la inercia que tiene Javascript a día de hoy, le garantiza el dominio en los próximos años.

Desde luego que Javascript dista de ser un gran lenguaje de programación, pero la historia de la informática está plagada de casos en los que no se impuso lo que técnicamente era mejor, pues pesaron más factores relacionados con el mundo de los negocios. En mi opinión, el impulso que está cogiendo Javascript en los últimos años, hará que la palabra de moda en el personal de recursos humanos sea «Javascript». Si trabajas en la industria deberías tenerlo en cuenta.

Encuesta stackoverflow 2018

Tecnologías más populares en la encuesta de Stackoverflow del presente año.

Por supuesto, los programadores en lenguajes «tradicionales» del lado servidor, como PHP, Java o Python, van a seguir teniendo trabajo los próximos años, aunque sólo sea, en el peor de los casos, por los millones de líneas de código en producción que alguien va a tener que seguir manteniendo; aunque a día de hoy no creo que se llegue a ese extremo; seguro que -todavía- se desarrollarán proyectos nuevos en estos lenguajes.


Editado el 18/4/2018:

Google Brain ha llevado a Javascript su librería de TensorFlow: TensorFlow.js Es decir, llega a los navegadores, y por lo tanto a los ordenadores, móviles y tablets, el machine learning y las redes neuronales.

Cómo comentar el código

En la lista de libros frecuentemente citados y raramente leídos, probablemente encontraríamos desde «El fin de la historia y el último hombre», de Francis Fukuyama, hasta «Code Complete», de Steve McConnell. Este último es el que voy a citar aquí, sin haberlo leído para seguir la tradición, concretamente su muy extendida afirmación de que los comentarios no tan solo no son necesarios sino que pueden conseguir el efecto contrario: un código complejo que el programador no trabaja para simplificarlo por tener a su disposición el camino, inicialmente más breve, de los comentarios.

En mi humilde opinión, aunque estoy de acuerdo en gran parte con la opinión de McConnell y otros, los comentarios sí son necesarios. Estos deben describir el porqué o describir qué se está haciendo, no el cómo, pues es el cómo lo único que puede delegarse a un código claro y descriptivo. Cuando el proyecto carece de documentación o no se mantiene actualizada, los comentarios que explican el porqué son aun más necesarios.

A continuación, veamos algunos ejemplos prácticos para ilustrar mi opinión:

class Model_Session
{

   /**
    * Sigue el patrón singleton para encapsular la sesión.
    * No extiende Model_Signia_Abstract porque debe definir construct privado.  
    */
   private $calledClass;

   protected function __construct($options)
   {
      $this->calledClass = explode('_', get_called_class())[1];
   }

   final static function getInstance($options = null)
   {
      static $instances = array();

      $calledClass = get_called_class();

      if (!isset($instances[$calledClass])) {
         $instances[$calledClass] = new $calledClass($options);
      }

      return $instances[$calledClass];
   }

   public function __clone()
   {
      trigger_error("An instance of the class " . __CLASS__ . " already exists.", E_USER_ERROR);
   }

   protected function set($value)
   {
      $_SESSION[$this->calledClass] = $value;
   }

   public function get($value)
   {
      if (isset($_SESSION[$this->calledClass][$value])) {
         return $_SESSION[$this->calledClass][$value];
      } else {
         return false;
      }
   }

   public function isLogged()
   {
      return isset($_SESSION[$this->calledClass]);
   }
   
   public function delete($key)
   {
      unset($_SESSION[$this->calledClass][$key]);
   }
   
   public function logout()
   {
      unset($_SESSION[$this->calledClass]);  
   }
   .
   .
   .
}

Algunos consideran que singleton es un antipatrón de diseño, pero este código está ahora mismo solucionando necesidades reales de empresas y soy de la opinión de que la teoría existe para ayudarnos, no para interferir en aquello por lo que nos pagan. En la misma línea, aunque trigger_error debería evitarse, en los métodos mágicos prefiero lanzar un error a lanzar una excepción. Aclarado esto, regresemos al tema que ocupa este artículo. Con la primera línea del comentario explico por qué y para qué uso el patrón:

Sigue el patrón singleton para encapsular la sesión.

La segunda línea está pensada para responder tanto el porqué que me pueda plantear yo cuando revise el código tiempo después y no recuerde por qué lo programé así, como el que se pueda plantear otro programador que vea esta clase por primera vez:

No extiende Model_Signia_Abstract porque debe definir construct privado.

El resto de la clase no tiene más comentarios y tampoco le hacen falta, pero, ¿qué sucede cuando los nombres de las variables y métodos no son descriptivos? Que nos vemos obligados a crear comentarios que clarifiquen cómo funciona la rutina. Comparemos estos dos métodos:

function permsM($m)
{
      $perms = [];
      
      foreach (['add', 'view', 'edit', 'delete'] as $a) {
         if (isset($this->get('permissions')[$a]) && in_array($m, $this->get('permissions')[$a])) {
            $perms[] = $a;
         }
      }

      return $perms;
}

Probablemente el ejemplo esté un poco forzado, pero sin duda demuestra que, o bien añadimos comentarios por doquier, o bien usamos nombres descriptivos:

public function getPermissionsForModule($sModule)
{
      $aPermissions = [];
      
      foreach (['add', 'view', 'edit', 'delete'] as $action) {
         if (isset($this->get('permissions')[$action]) && in_array($sModule, $this->get('permissions')[$action])) {
            $aPermissions[] = $action;
         }
      }

      return $aPermissions;
}

Cuando tenía unos 9 años hice mi primer «programa», lo sufrió un Zx Spectrum 128, su cantidad de memoria estaba contenida en su nombre, en Kilobytes. Con semejante restricción, entiendo que en la época tenía lógica optimizar el consumo de memoria incluso recortando el nombre de las funciones y variables, pero a día de hoy eso no tiene ningún sentido. Además, tanto los IDE como sencillos editores (por ejemplo Notepad++), disponen de la funcionalidad de autocompletar texto, que nos ayuda a recordar y escribir correctamente los nombres de variables, funciones, métodos y clases sin importar cuán largos sean. Por lo tanto, a día de hoy no hay excusas para no usar nombres descriptivos.

En este sentido, las constantes ayudan enormemente:

if ($file['error'] === 0 { //¿Mande? ¿Fue bien o mal?

if ($file['error'] === UPLOAD_ERR_OK {

Podemos llegar a ser más papistas que el Papa con el código que se explica a si mismo:

if ($file['size'] > 5242880) { // 5 MB

if ($file['size'] > 5*1024*1024) {

Otros comentarios necesarios

– Cuando, por falta de tiempo, se ha tenido que programar de forma poco óptima, indicarlo ayudará más adelante, cuando el proyecto haya sido entregado, a reconocer las partes que necesitan refactoring más urgentemente.

– Existen expresiones que son complejas y no hay azúcar sintáctico que las simplifique, como por ejemplo las expresiones regulares; en estos casos, comentar qué se está buscando aumentará la productividad de todo el equipo.

– Finalmente, cuando hemos copiado un código con licencia que lo permita, es de caballeros citar el autor y la fuente (si es que no estamos obligados directamente por la misma).

En definitiva, si cada vez que escribimos un comentario nos preguntamos si es realmente necesario o, si por el contrario, está encubriendo un código poco legible, conseguiremos elaborar software más fácil de mantener, tanto para nosotros como para quienes vengan después. Si describe cómo procesa, lo más probable es que nos estemos haciendo trampas.

Adiós a Firebug

Firebug ha sido definitivamente enterrado con la llegada de Firefox Quantum. Este plugin fue el primero que nos permitió a los desarrolladores inspeccionar y editar código HTML y CSS, así como depurar Javascript.

Hace ya casi 13 años de la primera versión y durante todo este tiempo ha sido una herramienta de uso casi diario para todos los desarrolladores web, independientemente del lenguaje que emplearan en el lado servidor. Este plugin llegó a tener tanto éxito que contó con numerosas extensiones propias.

Firebug

¡Todos los bugs fueran como este!

Hoy en día nadie se lanza a desarrollar aplicaciones web sin tener a su disposición las herramientas que proporcionaba Firebug. Por ello, desde hace años todos los navegadores han integrado sus funcionalidades, ese ha sido el legado de Firebug.

Modificar imágenes desde la línea de comandos con ImageMagick

ImageMagick es un completísimo paquete de programas multiplataforma para el tratamiento de imágenes. A diferencia de programas como Photoshop o Gimp, los programas que lo componen se ejecutan desde la línea de comandos, aunque también dispone de un sencillo entorno para X Window en Linux.

Entorno gráfico de ImageMagick en Linux

Tiene numerosas herramientas que, entre otras cosas, permiten:

  • Convertir entre una gran cantidad de formatos de imágenes.
  • Manipular la paleta de colores de una imagen.
  • Añadir tramados.
  • Crear un gif animado a partir de varias imágenes.
  • Superponer una imagen encima de otra.
  • Añadir texto a una imagen.

En la documentación se puede ver un listado detallado.

En la web es frecuente que el gestor de contenidos cree automáticamente réplicas de diferentes tamaños a partir de una imagen subida por el usuario para su correcta visualización en diferentes páginas. Por lo tanto, sin duda lo más usado para la web es su capacidad de reescalar imágenes, para lo que usa el algoritmo de «liquid rescaling«. Ademas la modificación de tamaño es muy flexible, permitiéndonos lograr la modificación que estemos buscando.

Tal vez algún lector se esté preguntando que habiendo programas con entorno gráfico como los citados más arriba, para qué trabajar en el modo texto de la shell de Linux/Unix. Veamos entonces un caso en que sería conveniente. Resulta fácil que una web acabe teniendo miles de imágenes distribuidas en cientos o miles de directorios, pues, por cada imagen que el administrador del contenido sube se van a crear varias copias con diferentes tamaños. Fácilmente el total de imágenes de un catálogo de productos, por ejemplo, se vuelve inmenso. Imaginemos que un cambio de diseño o la necesidad de hacer la web responsive hace necesario modificar el tamaño de una de las copias que se estaba guardando de cada imagen. En vez de modificarlas una a una con nuestro programa de edición de imágenes favorito, se puede crear un shell script como este:

ls *jpg | while read i
do
f=`basename $i .jpg`
convert $i -resize 200x200 smaller-$f.jpg
done

Lo que hace es buscar todas las imágenes jpg del directorio y gracias al comando convert de ImageMagick crea una copia más pequeña reescalada a 200×200 píxeles cuyo nombre será la cadena «smaller-» concatenada al nombre del fichero original. Fácilmente se podría modificar el script para que recorriera recursivamente todos los subdirectorios.

Todo lo que nos ofrece ImageMagick se puede utilizar desde diferentes lenguajes de programación y no solo porque desde éstos se pueda invocar comandos en la shell* y por lo tanto a ImageMagick, si no que el paquete ha sido portado. Está disponible en Java, .NET, Ruby, Pearl, Python, Php, etc. Aquí hay una lista detallada de todos.

En el caso concreto de PHP existe la extensión nativa IMagick. Sin duda es GD la extensión más extendida, valga la redundancia, en PHP. A pesar de su mayor propagación, y como es tan frecuente en el mundo de la informática, IMagick presenta algunas ventajas sobre GD que la convierten en una mejor extensión para trabajar con imágenes. Aquí un artículo con una comparación entre ambas.


* Como hace Drupal, el extendido CMS en PHP.


Aunque la palabra comando es un calco de inglés y en español es más correcto usar orden o instrucción, uso el término que usamos habitualmente en nuestro trabajo.


 

Chuck Norris también en el HTML

Chuck Norris, el único hombre, perdón, Hombre, que ha contado dos veces hasta infinito, también dispone de un color en HTML, un rojo probablemente inspirado por las pasiones que despierta:

Chuck Norris

Como si fuera el valor «green» o «yellow» para el atributo bgcolor, «chucknorris» es un color más, concretamente el #C00000

Este es el código del ejemplo:

<table>
   <tbody>
      <tr>
         <td align="center" bgcolor="chucknorris" width="100%">Chuck Norris</td>
      </tr>
   </tbody>
</table>

Él


Aclaración para navegantes:

Obviamente esto es una broma. El color chucknorris no está definido en el estándar. Funciona, o algo parecido, tomándolo por rojo, por como el navegador interpreta los códigos hexadecimales de los colores.

Máscaras de bits

Una máscara de bits son datos para operaciones a nivel de bits. Por ejemplo para el conjunto de los 10 primeros números naturales:

U = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}

La máscara que marca los impares es:

M = [1, 0, 1, 0, 1, 0, 1, 0, 1, 0]

Mediante la operación NOT sobre la máscara obtenemos los pares:

M = [0, 1, 0, 1, 0, 1, 0, 1, 0, 1]

Dadas dos máscaras, A y B, la operación OR (∨) nos proporciona la unión de ambas A ∪ B mientras que AND (∧) la intersección A ∩ B :

A = [0, 0, 0, 0, 0, 1, 1, 1, 1, 1]

B = [1, 0, 1, 0, 1, 0, 1, 0, 1, 0]

A ∧ B = A ∩ B = [0, 0, 0, 0, 1, 0, 1, 0]

A ∨ B = A ∪ B = [1, 0, 1, 0, 1, 1, 1, 1, 1, 1]

Las máscaras de bits tienen diferentes usos.

Sirven para definir rangos de IPs y ACL

ACL es el acrónimo de listas de control de acceso. En el protocolo TCP/IP las direcciones IP vienen acompañas de su máscara. Si ejecuto ifconfig en mi ordenador aparece la siguiente información:

ifconfig

IP y máscara

Es gracias a la máscara que los demás ordenadores de esta red pueden saber si el mío pertenece a la misma red local o a una red remota. Veamos como lo hace:

11000000.10101000.00000001.01100111 => 192.168.1.103 IP

11111111.11111111.11111111.00000000 => 255.255.255.0 Máscara de red

Mediante ceros las máscaras de red indican qué octeto es el significativo para identificar al ordenador, en este caso es el último octeto, cuyo valor es 103. Mientras que con unos indica el identificador de la red, que en este ejemplo es el de las redes locales o redes de clase C: 192.168.1

Sirven para gráficos 2D

En los juegos de no hace tantos años, antes de la llegada de las 3D, mediante una máscara de bits se indicaba que parte del sprite debe transparentar con el fondo por el que se mueve.

Sprites y máscaras de bits

Sprites y máscaras de bits

Aún hoy en día se siguen usando, por ejemplo cuando hace pocos meses Google añadió este juego a Google Maps:

Ms Pac-Man paseando por Madrid se encuentra la sede del PP…

cazando corruptos

¡Y no puede evitar ponerse cazar fantasmas corruptos pululando por la calle Génova!

Sirven para hacer código más legible

Se usan en funciones y métodos que esperan varios parámetros booleanos. La principal ventaja es simplificar el uso de la función, secundariamente se consigue una menor carga de la pila. Si tenemos en PHP la función:

function func ($param1, $param2, $param3, $param4)

Cuando la invoquemos lo más probable es que no nos acordemos de los parámetros y su orden. Es más práctico algo como esto:

const BIT_1 = 0b0001; // 1
const BIT_2 = 0b0010; // 2
const BIT_3 = 0b0100; // 4
const BIT_4 = 0b1000; // 8

function func ($bits) {
  if ($bits & BIT_1) {
    // Haz esto.
  }
  if ($bits & BIT_2) {
    // O esto otro.
  }
  if ($bits & BIT_3) {
    // También esto.
  }
  if ($bits & BIT_4) {
    // Y esto si también te lo piden.
  }
}

func(BIT_1 | BIT_3);

En PHP los operadores de bit AND y OR son & y | respectivamente. Muchas de las funciones incluidas en PHP usan está técnica, al igual que en otros lenguajes. He aquí unos ejemplos:

filter_var($string, FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_HIGH | FILTER_FLAG_STRIP_LOW)

html_entity_decode($string, ENT_QUOTES | ENT_XML1, 'UTF-8')

El error_reporting para especificar el nivel de errores en php.ini y la función error_reporting() para modificarlo en tiempo de ejecución.

Sirven para el control de permisos

Usar máscaras de bits y operaciones a nivel de bit para controlar los permisos de usuarios o de los grupos a los que pertenecen puede llegar a ser inviable en aplicaciones realmente grandes, pero donde sea cómodo aplicarlas se conseguirá una velocidad y reducción del tamaño de la base de datos sin igual. En el caso de la base de datos permiten pasar de tener una o más tablas donde almacenar los permisos a un solo campo en la tabla de usuarios, permitiendo olvidarnos entonces de costosas consultas con Joins.

Aunque su uso para estos menesteres no sea recomendable, veamos a modo de curiosidad cómo funcionan. La siguiente tabla presenta unos permisos mapeados para un gestor de contenidos:

cambiar permisos crear perfil editar perfil borrar perfil crear borrador
512 256 128 64 32
editar entrada borrar entrada publicar entrada editar entrada borrar entrada
16 8 4 2 1

Si en la campo «permisos» de un usuario tenemos el número 14, sabemos que este en binario es 1110. También sabemos que el número máximo es 512, 1000000000 en binario, por lo tanto concatenemos por la izquierda los ceros que faltan: 0000001110. Sigue siendo 14 en binario y si ponemos cada dígito en la tabla donde mapeamos los permisos, tendremos que con 1, es decir, activos, están los que permiten editar, borrar y publicar una entrada. A los demás permisos les corresponde un cero y por lo tanto el usuario no los tiene. Un usuario con todas las concesiones sería 1111111111, por lo tanto en el campo correspondiente de la tabla «usuarios» tendría almacenado el número 1023.

Antes hemos visto como implementa PHP los operadores bit a bit; realmente todos los lenguajes los implementan, observemos ahora la siguiente consulta SQL en MySQL:

SELECT * FROM usuarios WHERE 512 & permisos

Esta consulta nos daría todos los usuarios que tienen el 512, «cambiar permisos», activado. El operador a nivel de bits & devolverá verdadero sólo en los casos en que sean 1 los bits a su izquierda y lo sean también en la misma posición a la derecha. Recordemos que 512 en binario es 1000000000 por lo que la condición del WHERE será sólo verdadera en los registros cuya columna «permisos» el bit más significativo (el de la izquierda) valga 1. Por supuesto también se pueden usar otros operadores lógicos, no sólo AND.

Como hemos visto, aunque las operaciones a nivel de bit parezcan más de tiempos en los que los recursos de los ordenadores, RAM y CPU, eran muy limitados, siguen teniendo su utilidad.