Lesbian in the shell

Desde que instalé Debian por primera vez, hará ya unos 14 años, tengo la costumbre de llamar “Lesbian” a cualquier ordenador de mi propiedad que lleve Linux. Por cierto, casi siempre he usado la distribución Debian o una variante.

Lesbian in the shell

Shell in the Lesbian

Ghost in the shell

Ghost in the shell. De moda otra vez después de más de 20 años. Ahora Motoko Kusanagi sufre un whitening.

Simplificación de expresiones booleanas mediante álgebra de Boole

Cuando estamos repasando código podemos encontrarnos expresiones booleanas en condiciones lógicas más complejas de lo necesario que dificultan entender lo que el código hace. Esto puede ser debido a que la persona no tiene los conocimientos necesarios para hacerlo mejor (en esta profesión uno se encuentra hasta biólogos sin mayor interés en la profesión que el salario) o al constreñimiento que sufrió el programador cuando desarrolló el código que estamos repasando. Puede por lo tanto ser nuestro propio código el que incurra en esos errores que ahora, con más calma, descubrimos y nos preguntamos en qué estaríamos pensando cuando hicimos esos whiles y esos ifs.

Para reducir el total de términos de una expresión booleana existen técnicas como los mapas de Karnaugh o el método de Quine-McCluskey pero en programación generalmente es suficiente con las leyes del álgebra de Boole. Teniendo en cuenta que la condición lógica AND es el producto booleano, OR es la suma y NOT el complemento  , las leyes son:

  • Idempotencia:
    1. x + x = x
    2. x * x = x
  • Doble complemento:
    1. ¬x (doble negación) = x
  • Identidad respecto a la suma y el producto o elementos neutros de la suma y del producto:
    1.  x + 0 = x
    2. x * 1 = x
  •  Maximalidad de los elementos 1 y 0:
    1. x + 1 = 1
    2. x * 0 = 0
  • Leyes asociativas respecto de la suma y del producto:
    1. x + (y + z) = (x + y) + z
    2. x * (y * z) = (x * y) * z
  • Leyes distributivas respecto de la suma y del producto:
    1. x + y * z = (x + y) * (x +z)
    2. x * (y + z) = x * y + x * z

Esta última ley no es tan evidente pero se ve claramente con su tabla de verdad:

x y z y+z x*y x*z x*(y+z) x*y + x*z
0 0 0 0 0 0 0 0
0 0 1 1 0 0 0 0
0 1 0 1 0 0 0 0
1 0 0 0 0 0 0 0
0 1 1 1 0 0 0 0
1 0 1 1 0 1 1 1
1 1 0 1 1 0 1 1
1 1 1 1 1 1 1 1
  • Leyes de De Morgan:
    1. x + y = x * y
    2. x * y = x + y

También las podemos comprobar mediante sus tablas de verdad:

x y x y x+y x+y x*y
0 0 1 1 0 1 1
0 1 1 0 1 0 0
1 0 0 1 1 0 0
1 1 0 0 1 0 0

Estas leyes se pueden generalizar a más de dos variables. Además, podemos ver que x * yxy

  • Ley de absorción:
    1. x(x + y) = x

Su tabla de verdad es:

x y x + y x(x + y)
0 0 0 0
0 1 1 0
1 0 1 1
1 1 1 1

La ley de absorción también se concluye aplicando las leyes anteriormente mencionadas:

x(x + y) = (x + 0)(x + y) = x + 0*y = x + 0 = x

Aplicando las leyes booleanas se deducen las siguientes propiedades:

  • x + xy = x
  • x + xy = x + y
  • x + x = 1
  • x * x = 0

Si bien las dos últimas son evidentes, para las dos primeras podemos crear sus correspondientes tablas de verdad en caso de duda.

También es conveniente conocer un teorema acerca del complemento de una función booleana y  para ello hay que explicar qué es una función booleana. Una función booleana es algo tan sencillo como las tablas de verdad que hemos visto antes: dadas unas variables x, y, z… se obtiene un resultado F. El grado de la función es el número de variables. Este es un ejemplo de una función grado dos F2→F:

x y F(x, y)
0 0 0
0 1 1
1 0 1
1 1 1

La expresión booleana que produce tal resultado F es: x* y + x*y + x*y Aunque cómo encontrar la expresión booleana a partir de una tabla de verdad es otro tema. Ahora que ya sabemos qué es una función booleana, dejemos esta función de momento a un lado y volvamos entonces al teorema:

El complemento de una función booleana F se obtiene complementando todas sus variables e intercambiando las operaciones de suma y producto, es decir:

F(x1, x2, … xn,+,* = F(x1, x2, …,xn, *, +)

Por ejemplo el complemento de la función anterior F se podría expresar como:

F = (¬x + y) * (x + ¬y) * (x + y) A + B + C = A + B + C = (x+y) * (x*y) * (x*y)

Con los minterm y maxterm también se acaba viendo que toda función booleana puede expresarse tanto como un conjunto de minterms multiplicados, como un conjunto de maxterms sumados. Aunque los minterm, maxterm y las formas canónicas también podrían ayudarnos, con las leyes anteriores, propiedades y el último teorema no debería haber código que se nos resista a ser simplificado. Veamos algunos ejemplos de despistes que hacen el código poco legible y como quedarían simplificados:

if (($foo && myFunction()) || ($foo && $bar)) {

Con la ley distributiva quedaría: if ($foo && (myFunction() || $bar))

if (!($foo || $bar || myFunction())) {

La expresión booleana de este if sería x + y + z

Aplicando la propiedad asociativa: x + (y + z)

Reemplazando por a: x + a

Aplicando la ley de De Morgan: x * a

Deshaciendo el reemplazo: x * (y + z)

Otra vez De Morgan: x * y * z

Así que el if original quedaría if (!$foo && !$bar && !myFunction()) {

El operador lógico XOR, aunque no forma parte de las operaciones booleanas básicas, tiene tantas utilidades que está en toda clase de circuitos y lenguajes de programación. Su función booleana es:

XOR = x*y + y*x

Devuelve 1 sólo cuando x e y tienen valor diferente. Por lo tanto, el siguiente código:

if (($foo && !$bar) || (!$foo && $bar)) {

Quedaría:

if ($foo xor $bar) {

Ahora bien, si sabemos que ambas variables son booleanas, esto es exactamente lo mismo y según como hasta más legible:

if ($foo !== $bar) {


Nota:

Las leyes de álgebra de Boole están en estrecha relación con la lógica de predicados o de primer orden. Dos ejemplos: la ley de absorción es el modus ponens y las leyes de De Morgan también aplican a los conjuntos. Estas últimas son:

  1. A ∪ B = AB
  2. A ∩ B = AB

Veamos la segunda ley. Ésta nos dice que la intersección de todos los elementos que no son de A con la de todos los que no son de B equivale a la unión de todos los que no son de A con todos los elementos que no son de B. Su demostración es:

Se lee: Todo x tal que x no pertenece a la intersección de A con B

Demostración segunda ley de De Morgan

Probando servicios web con HttpRequester

Cuando se trata de probar un Web Service RESTful, ya sea nuestro o de un tercero, existe un addon para Firefox muy útil: HttpRequester

Método Options

Solicito al servidor las opciones disponibles (OPTIONS) y devuelve: GET, HEAD, PUT, PATCH, POST y DELETE

Cabecera del método Get

Get sobre la misma URL y a la derecha vemos la cabecera que devuelve el servidor

Cuerpo del método Get

Si hacemos doble click sobre la petición podremos ver el cuerpo de la misma

Método Delete

Borramos el post con ID = 1

Como se puede apreciar en los ejemplos, HttpRequester es una herramienta de Firefox bastante útil para un desarrollador de aplicaciones web.

Javascript ya no es un lenguaje de juguete

Hace años que Javascript ya no es un lenguaje de juguete con el que manipular con Dios y ayuda el DOM del navegador1 y para muestra un botón, ¡pero qué botón!

Emulador de PC con Javascript

También incorpora una versión reducida del compilador gcc

Se trata de un simulador de PC desarrollado en Javascript que puede ejecutarse perfectamente en tu navagador. Concretamente emula un procesador 486 (sin coprocesador matemático), RTC (reloj interno), puerto serie, disco duro, etc.

Además el emulador no viene solo sino que incorpora un Linux (Kernel 2.6.20) y una versión del compilador GCC que el mismo programador del emulador creó: Tiny C Compiler. Se trata de una versión mucho mucho más ligera y rápida que el compilador original.

El genial autor de esta obra es el francés Fabrice Bellard. Es un su web podéis encontrar otras muestras de su genio.

Desde que en 2008 los navegadores empezaron a incorporar compiladores JIT en vez de interpretar el código Javascript, la velocidad de ejecución dio un enorme salto. A medida que van mejorando (hoy en día son capaces incluso de optimizar código) siguen reduciéndose los tiempos. Esto ha dado más alcance a Javascript, por ejemplo Node.js funciona mediante una implementación en el lado servidor del compilador JIT para Chrome llamado V8.

Eso sí, a pesar de todas las librerías y software que ha crecido entorno a este lenguaje, y a pesar de su evolución, sigue teniendo características que hacen difícil la vida del programador:


1 Posiblemente las dificultades más que ser debidas a carencias de Javascript lo eran por los bugs de los navegadores a la hora de manipular el Document Object Model y a las diferencias entre ellos para implementar su manipulación (o el estándar no era muy concreto o era ignorado donde convenía implementarlo de otra manera, no lo sé). En todo caso, sobre Javascript recaían parte de las culpas con el consiguiente desprestigio.

En PHP un sistema de plantillas es prescindible

Si bien es cierto que PHP hace muchos años que dejó de ser un sistema de plantillas tampoco me parece que necesite implementar un sistema de plantillas de forma imperiosa. En su origen, PHP era un sencillo lenguaje, cuyo intérprete programó en C Rasmus Lerdorf, destinado a implementar su página personal, de ahí el acrónimo Personal Home Page. Mucho ha llovido desde entonces y hace tiempo que PHP es un lenguaje orientado a objetos bastante potente con muchas librerías a su disposición. A pesar de ello, un motor de plantillas me parece una sobrecarga innecesaria y mucho menos me convence el razonamiento de querer dotar al lenguaje de una especie de aura de seriedad. En casos concretos hace más bien que mal, pero hay 2 razones por las que en muchos casos me parece prescindible.

Primera: Un sistema de templates añade una sobrecarga no despreciable. El entorno más frecuente para PHP son los servidores web compartidos que alojan diversas webs. Los costes de alojamiento son reducidos por la poca carga que supone PHP, tanto en tiempo de CPU como RAM consumida. Poner en esos servidores mastodontes como Symfony tiene su peaje. El patrón MVC es conveniente, la sobrecarga no, y la V de vista no implica usar plantillas. Más sobre esto en mi segunda razón.

Hace ya años que PHP es usado también en grandes aplicaciones web, con miles de usuarios conectados simultáneamente y cuyo alojamiento no alcanza en un sólo servidor sino que se requiere de una server farm. Trabajé en una empresa así y recuerdo que la competencia de dicha empresa había apostado por Java, un lenguaje más “serio” (más empleado a nivel corporativo). El gasto en servidores de esa empresa multiplicaba en varias veces el de la nuestra y cuando se llega a cierto volumen los costes dejan de ser despreciables y empiezan a marcar diferencias. Que PHP, a diferencia de Java, no necesite ingentes recursos para declarar un simple entero es una poderosa razón por la que barrió a Java de la web.

Segunda: Algunos argumentan que PHP es demasiado “parlanchín” para ser empleado en la vista pero no estoy de acuerdo. Puede (o no) que esto:

{foreach $foo as $bar}

Sea mejor que esto:

<?php foreach($foo as $bar){ ?>

Pero es idéntico a los “short tags” que PHP sigue permitiendo. Además, PHP dispone de una sintaxis alternativa para las estructuras de control:

<? foreach($foo as $bar): ?>

Esto también es objeto de crítica:

<?php echo htmlspecialchars($var, ENT_QUOTES, 'UTF-8') ?>

¿Por qué no usar esto?

<?=htmlspecialchars($var, ENT_QUOTES, 'UTF-8') ?>

Para que nadie sufra del síndrome metacarpiano podemos encapsular en algún helper esa función, como hace CakePHP:

<?=h($var) ?>

La función sería algo así:

function h($text)
{
return htmlspecialchars($text, ENT_COMPAT | ENT_HTML5, 'UTF-8');
}

Así mismo se pueden crear fácilmente otras funciones para agilizar la programación de las vistas.

También se argumenta que diseñadores y maquetadores no tienen por qué saber acerca de temas de seguridad como los ataques XSS y CSRF y que para que ellos puedan programar las vistas con seguridad debe implementarse un sistema de plantillas. En estos casos sí sería necesario usarlo y sólo añadiría lo siguiente: he conocido muchos diseñadores y no he visto ninguno interesado en programar en el lado servidor. Iría más lejos: no he conocido ninguno interesado en programar. A lo sumo, sí en aprender Flash en sus años buenos. Frecuentemente, ni tan siquiera Javascript, a pesar de incluir ficheros en sus diseños. Obviamente les interesan las funcionalidades que aporta pero en general no están interesados en saber cómo funciona. En la industria que yo conozco, programar las vistas acaba siendo trabajo también del programador y éste sí conoce (o debería) las implicaciones de seguridad. Si en la empresa los diseñadores sí están por la causa sí sería conveniente usar un sistema de templates.

Otras casos en los que puede ser interesante usarlo es cuando se requiere una sandbox con un susbset de las funciones propias y/o de PHP. Por ejemplo si el usuario desde el back end ha de poder acceder a arrays con datos y a ciertas funciones para transformar y operar esos datos. Para estos casos hay sistemas de templates como Twig que proporcionan una sandbox y sería razonable usarlos en vez de reinventar la rueda programando uno propio.

A pesar de no ser necesario un sistema de plantillas en la mayoría de aplicaciones web, ya consiguen hacer negocio con ellos. ¿Necesidad real o creada?

La diferencia entre getElementById y el dolar de jQuery

Cuando atiendo las preguntas de un programador junior en problemas con su código Javascript me doy cuenta de que muchas son debidas a la confusión entre jQuery y un objeto del DOM. Los que empezamos a tocar Javascript antes de la llegada de librerías como jQuery vemos la diferencia claramente, pero hoy en día, cuando un programador novel se lanza a desarrollar en el lado cliente código Javascript estará usando, como mínimo, una librería como jQuery, por lo que lo raro sería que no confundiera ambos.

Vamos a ver en qué consiste la confusión. Cuando trabajamos con la librería jQuery podemos pensar que seleccionar un elemento por su ID:

$('#myVideo').....

Es equivalente a como lo hacíamos antes, cuando no existía la librería jQuery:

document.getElementById('myVideo');

Pero realmente es completamente diferente. El segundo devuelve un puntero al elemento DOM seleccionado que nos permite acceder a las propiedades y métodos propios del elemento mientras que el primero, jQuery, nos proporciona una envoltura (wrapper) sobre el elemento seleccionado (o conjunto de elementos ). Esa envoltura proporciona al programador unos elementos (comunes a todos los elementos del DOM) que facilitan su manipulación.

Esto se ve claramente con el tag <video> que incorpora HTML5 y que usaré como ejemplo. Este tag incorpora métodos no comunes a otros elementos como play() y pause(). El siguiente código Javascript funcionará perfectamente si a dicho elemento le ponemos “myVideo” como identificador:

var player = document.getElementById('myVideo');
player.play();

En cambio, el siguiente código todo cuanto hará será imprimir un error en la consola del navegador:

$('#myVideo').play();

Otro ejemplo para clarificar mejor es cuando queremos acceder a los hijos de un elemento del DOM pero disfrutando de los métodos de jQuery. Veamos el siguiente código:

$('div[id^="panel"] ol').each(function () {

Sirve para recorrer todos los hijos <li>, de un tag <ol>, que pertenece a varios elementos div cuyo id empieza por “panel”. Dentro de la función podemos referirnos a cada uno de ellos mediante this, pero el siguiente código sería incorrecto:

$('div[id^="panel"] ol').each(function () {
   this.hide();
}

El método hide lo incopora jQuery, por lo tanto, para poder invocarlo sería:

$(this).hide();

Mientras que para acceder al id sería:

$('div[id^="panel"] ol').each(function () {
   alert(this.id);
   $(this).hide();
}

Tengamos en cuenta además que $ es un alias para la función jQuery, función que nos da acceso a toda la librería jQuery. El dólar es equivalente y más rápido a escribir:

jQuery(this).hide();