Tag Archives: programación

Resolviendo Shikaku

Esta es una práctica que realicé (y comenté) en diciembre de 2008 para la asignatura de Programación III de la UNED.

La práctica se basaba en realizar un sistema para resolver tableros de shikaku, mediante el algoritmo de vuelta atrás. Mi solución es óptima pero no del todo correcta desde un punto de vista académico, ya que el uso del algoritmo (de backtracking) es menos usado de lo que debería.

Para poder ver el código, este puede descargarse a través de un cliente de Subversion, en sistemas Unix/Linux es tan fácil como:

svn co http://project.bosqueviejo.net/svn/shikaku/trunk

Explicación del código

Bueno, tengo que reconocer que, después de algo más de un año de haberlo hecho, he tenido que releer y revisar de nuevo todo para acordarme (y reaprender) cómo hace lo que hace.

Por ello, voy a escribir una documentación básica sobre el código en sí, para tenerla como referencia, cuando tenga que volver al mismo otra vez, y para que sirva a todos aquellos que lo necesiten.

En principio, el código se divide en las siguientes clases:

  • shikaku.tablero.Combinacion: esta clase se encarga de almacenar combinaciones. Una combinación es un rectángulo que se sitúa ocupando un espacio de X*Y=N. La combinación debe de tener en alguna de sus casillas el número contenido, por lo que se almacena también la ordenada de N para comprobaciones.
  • shikaku.tablero.Ordenada: es cada uno de los números que aparecen en el tablero. Se almacena su posición dentro del tablero y la representación numérica del mismo.
  • shikaku.tablero.Tablero: almacena las dimensiones del tablero, la lista de combinaciones fijas (las que solo tienen una combinación válida detectada) y la lista de soluciones posibles para el tablero.

Una ejecución de shikaku tiene los siguientes pasos:

  1. Entra en main de la clase shikaku, donde se detecta el origen de datos, hasta saber de donde se va a cargar el tablero.
  2. En run se crea una instancia del tablero, y se ejecuta, para cada punto del tablero, el generador de la clase Combinacion.
  3. El generador se encarga de buscar combinaciones válidas para el punto dado, dentro del tablero y validando su posición dentro del tablero (es decir, que no haya parte del rectángulo fuera) y con respecto al resto de puntos (que no tenga contenido nada más que el punto del que tiene que hacer la combinación).
  4. El último paso para la resolución, es llamando a buscaSoluciones, de la clase Tablero, que se encarga de realizar el algoritmo de vuelta atrás para buscar las soluciones al tablero.

Estos son los pasos más importantes dentro del código para resolver el tablero de shikaku.

La depuración

Uno de los motivos por los que el algoritmo no es del todo de tipo vuelta atrás, es precisamente por el uso de tres algoritmos voraces que se ejecutan antes que el último, de vuelta atrás. Estos algoritmos realizan una criba sobre las combinaciones basándose en tres premisas que debe cumplir cada combinación para ser válida:

  1. Que no haya nada fuera del tablero: esto se realiza mediante una simple validación a la hora de generar las combinaciones. Es simple y rápida, y quita mucho procesamiento al algoritmo final.
  2. Combinaciones con un solo número: esto se refiere a que dentro del rectángulo que conforma la combinación, solo esté contenido el número objeto de la combinación y ningún otro. Esta validación también está incluida a la hora de generar las combinaciones, para lo que se necesita, en el generador, pasar todos los puntos del tablero.
  3. Eliminar combinaciones imposibles: imposibles, además de las que se descartan en los puntos anteriores, son las que colisionan con todas y cada una de las combinaciones posibles de otro número vecino. Si la combinación de un número colisiona con todas las combinaciones posibles de otro número, como es lógico, no podrá ser posible.

Ciertamente, con estos algoritmos se llega a resolver un alto porcentaje de los tableros básicos, sin necesidad de realizar el algoritmo de vuelta atrás. Solo los tableros grandes y con dificultad alta, necesitan, además de estos algoritmos voraces, el de vuelta atrás.

Mejoras

En sentido académico, teniendo en cuenta uno de los requisitos que se pide, que es que sea un algoritmo de vuelta atrás, quizás sea más correcto que la depuradora actúe solo a nivel de rama y no en profundidad.

Hay que tener en cuenta que esto penalizaría el rendimiento y empeoraría en lo que a gestión de memoria se refiere, pero prima más cumplir con los requisitos ;-)

Programación para Administradores de Sistemas

Cuando estuve estudiando el título de Administración de Sistemas Informáticos es cuando me acerqué a los lenguajes de scripting (por el año 2002), y fue cuando comencé a aprender lenguajes como PHP, Python, Ruby y Perl.

El lenguaje Perl me llamó la atención, sobre el resto, porque había sido un lenguaje creado por Larry Wall, un administrador de sistemas… ¡en un mes!, supongo que lo que creó fue la parte más básica del sistema, pero al mismo tiempo la más importante, ya que, como él mismo comenta, Perl fue la simplificación del uso de herramientas como awk, sed, shell script y C.

En la mayoría de trabajos que he tenido, después de eso, cuando un administrador de sistemas desarrollaba algún proyecto, alguna aplicación o decía que programaba, lo hacía en Perl. No en vano, ha sido considerado por muchas distribuciones, empresas y comunidades, como el lenguaje de facto para las actividades típicas de administración de sistemas, entre las que se encuentran tareas tan vitales como: la instalación del sistema, asistentes de configuración, pasarelas intermedias (como amavis)…

Uno de los grandes miedos de la gente que programa en este lenguaje, es la mítica frase de que Perl es un lenguaje write-only, es decir, de los que se usan solo para escribir código que no hace falta mantener (o de usar y tirar), aunque proyectos grandes y la comunidad en sí manteniendo y ampliando el lenguaje, han demostrado que Perl es un gran lenguaje de programación en el que se pueden desarrollar grandes cosas y darles mantenimiento sin problema ni riesgo.

Programming Perl (3rd Edition)
Larry Wall, Tom Christiansen, Jon Orwant; O'Reilly Media, Inc. 2000

El libro que aconsejo para adentrarse en el mundo de Perl es el que escribió su creador, Larry Wall, aunque a partir de su tercera edición, que está acompañada de mucho más contenido aportado por autores como Tom Christiansen, uno de los primeros que se sumó al mundo y comunidad de Perl; y Jon Orwant, el editor de The Perl Journal, cuya publicación cesó hace ya algunos años.

El libro es algo extenso y asusta al primer vistazo, no en vano son 1070 páginas. Pero una vez se ha abierto y visto el índice, se entiende su extensión y deja de asustar. Realmente, el libro se parte en cinco apartados bien diferenciados:

  • Introducción… bueno, esta la podemos leer a modo informativo, o podemos obviarla. Son unas 50 páginas.
  • Los detalles desagradables… un título un poco extraño, pero se entiende, porque son los detalles del lenguaje en sí, lo que permite, lo que se puede hacer con él, la sintaxis, los elementos… todo. Es la parte más importante del libro, en mi parecer. Unas 350 páginas, más o menos.
  • Perl como Tecnología, nos adentra en lo que hace el intérprete internamente, cómo se puede optimizar su uso, el depurador, los hilos, interfaz con C… sería la parte avanzada del lenguaje. Unas 150 páginas.
  • La Cultura de Perl, es el uso de CPAN, el administrador de paquetes, prácticas comunes, seguridad, haciendo Perl portable entre plataformas, documentación, etc. Un poco de Perl en la comunidad y cómo compartir código en la forma en la que lo hacen muchos. Unas 100 páginas.
  • Material de Referencia… como no podía faltar, toda la referencia de los paquetes básicos de las librerías que trae consigo Perl. Esta quizás es la parte más extensa del libro, pero la que más se puede emplear en el día a día, realmente.

Una lectura muy recomendable para todos aquellos que quieren adentrarse en la programación de Perl de una forma más íntima, conociendo la comunidad, cómo compartir código, cómo aprovechar el código que ya está disponible para Perl y las mejores prácticas de programación en este lenguaje.

Los sectores del software

De siempre, se va viendo que las empresas de software se decantan por una forma de hacer las cosas, mientras que otras eligen otro camino distinto y, muy pocas, mezclan elementos de doctrinas tan establecidas y dogmáticas como son: el mundo del software libre, el mundo java o el mundo .net.

El mundo .NET

Como todo lo que tiene que ver con Microsoft, el mundo .NET se mueve, casi exclusivamente, con productos y herramientas desarrolladas por esta misma compañía. Funciona sobre Windows, con base de datos de Microsoft y se diseña con herramientas de Microsoft.

Lo bueno de Microsoft es que desarrollan los productos para un público general y sin conocimientos extensos. Los lenguajes suelen ser o muy fáciles (Visual Basic) o muy complejos (C++, C#), pero cumplen con todas las necesidades de los programadores a los que van dirigidas las herramientas. Así mismo, tienen un alto nivel de operatibilidad entre los diferentes productos, es decir, escribir código ASP con SQL Server es simple, gracias a ese nivel de compactación y simplificación.

Lo bueno de la simplificación lleva a lo malo de la complejidad también. Un programa que se hace de forma simple y fácil, siguiendo los pasos que Microsoft ha pensado para dar es simple, sencillo y rápido. Pero cuando la aplicación debe tener una forma específica o salirse un poco del camino típico, comienzan a surgir problemas solo saldables con código complejo.

Ximian, absorbida por Novell, ha realizado muchas aproximaciones a este mundo para portarlo al mundo del software libre a través de su escritorio Gnome y su proyecto Mono. No obstante, es un tema un poco espinoso, ya que quien usa software libre, por lo general, se aleja de las tecnologías propuestas por esta gran multinacional, por lo que, aunque es usada y tiene su cuota de mercado, Mono no llega a ser usado tanto como podría esperarse.

El mundo Java

El mundo de Java ha estado siempre en una lucha constante y abriéndose camino en el desarrollo de software, sin mucho éxito al principio, sobre todo en lo que respecta a las aplicaciones de escritorio. Esto fue debido a su naturaleza de pseudo-compilación y pseudo-interpretación, ya que es un lenguaje compilado e interpretado que se ejecuta sobre una máquina virtual, y las labores de interpretación de los bytecodes son algo costosos, en relación a código que se ejecuta de forma nativa.

No obstante, en la parte web, de interfaces, desde que comenzó, ha tenido una gran aceptación, puesto que permite el desarrollo de las aplicaciones en cualquier infraestructura (windows, linux, solaris, …) y se han desarrollado grandes herramientas para el desarrollo en este sentido.

Java siempre es el favorito y preferido de las consultoras (a menos en España), donde es empleado para el desarrollo de aplicaciones, tanto de escritorio como web en todos los sectores donde son contratados.

La mayoría de empresas que han tenido relación con Microsoft y han salido de malas con la grande, han terminado montándose al carro de Java y aportando a esta comunidad en modo de open source herramientas, conocimiento, etc. Además de Sun Microsystems (su fundadora), hay otras como IBM, RedHat, Oracle, etc. que se han sumado al carro de Java para el desarrollo y ampliación de esta comunidad.

Hay comunidades de software libre que se han sumado a la aportación de código para el mundo Java. Esto supongo que será erróneamente aportado como el voto útil, sin saber que en nada se beneficia al software libre en sí, sino solo al mundo Java que, aunque pueda parecer atractiva la idea de luchar contra el tirano, no es más que ayudar a una empresa a derrocar a otra. Esto puede ser muy discutible, sobre todo por los defensores de Java :-D

El mundo del software libre

Al margen de la guerra entre .Net y Java, surgen los entornos, sistemas y elementos de software libre. Pensar que todo el mundo tiene que ser Java o .Net es un craso error, ya que hay muchos elementos que se pueden combinar a gusto propio del desarrollador y emplearlos como mejor convenga para obtener los mejores resultados para una tarea concreta.

A este respecto, una de las comunidades con más auge es la de desarrolladores de PHP, por ejemplo, que es el lenguaje que más proyectos de software libre tiene desarrollados, y es el más usado para el desarrollo de sitios como Facebook, Menéame, WordPress, etc.

Otra de las comunidades más activa en los entornos web es la de Ruby, Ruby on Rails más específicamente, que tiene un entorno fácil y profesional para el desarrollo rápido de sitios web. También Python, con su framework Django. Ambos presentes en el mundo Java a través de JRuby y Jython, respectivamente.

Entornos también desarrollados en lenguajes más específicos como Perl, Erlang, Tcl, etc. hacen que se complete el abanico de posibilidades para el desarrollo de software a través de las soluciones que aporta el software libre.

La nota negativa, es que los elementos no son altamente cooperativos, es decir, aunque se basan en estándares, normas y todos son abiertos, hay que realizar desarrollos para poder tener funcionando cosas entre unos y otros, debido a que en el software libre, no todo está hecho o viene dado fácilmente. Pero la nota positiva sobre esto, es que la dificultad que eso entraña es mucho menor que la que entrañaría el desarrollar algo no hecho o no pensado para hacerse, en Java o .Net.

Conclusión

En principio, no te quedes solo con uno, esto no son tres equipos a los que haya que apoyar a muerte, estas son tres formas de ver la tecnología y puede convenir cualquiera de las tres según el contexto en el que haya que ponerse.

Por ejemplo, en una empresa que se haya invertido en infraestructura y software Microsoft, se tenga todo montado en SQL Server, con ASP e interfaces desarrolladas en Visual Basic, desarrollar cualquier nueva ampliación o una nueva herramienta, cabe pensar que será siempre más fácil si nos ceñimos a lo ya establecido que si comenzamos a cambiar lo que hay.

Igualmente, en otra empresa en la que se haya realizado una inversión para Java, incluso con servidores Solaris, y bases de datos Oracle, no conviene pensar en desarrollar nada con Visual Basic, ni PHP, sino pensar en agregar más aplicaciones de tipo J2EE, que será lo más fácil de implementar.

Por último, en una empresa pequeña, con aspiraciones a crecer, que tengan todo desarrollado en PHP y MySQL, se podría cambiar a un framework de desarrollo para PHP, así como agregar elementos más complejos en caso de ser necesarios (como memcached).

En definitiva, no intentar cambiar lo que ya hay si funciona. Otro caso es que no funcione o que haya que realizar adaptaciones y se pueda aprovechar para agregar elementos más generales o estándares.

Sistemas de Mensajes Encolados (MQ)

Hace poco me he encontrado con un problema. Tengo un entramado de servidores y comunicaciones entre cada uno de ellos. Cada servidor puede notificar, ya sea vía SOAP, HTTP, XMPP o mediante cualquier otro protocolo, un evento o una información a otro servidor del entramado, con lo que cada servidor se configura de una forma específica, con una serie de nombres de dominio o IPs.

El problema viene al querer aplicar escalabilidad al proyecto. Cuando no solo hay un equipo implicado, sino que existen dos o tres, los cuales hay que configurar bajo ciertas circunstancias.

Lo primero que pensé, es que, si le puedo notificar a la red de que sucede un evento en concreto, ya sea a una sola máquina o conjunto definido de estas (pero para todos los equipos la misma configuración), facilitaría la puesta en producción. Con lo que me puse a buscar y encontré MQ, message queue.

El encolado de mensajes

La comunicación de los equipos informáticos se basa en mensajes, en eventos, que deben de poder transmitirse de unos a otros cuando sucedan (si es que se quiere tener la máxima fiabilidad en la información que se trata).

Una forma es comunicar directamente al implicado, lo cual resulta un poco tedioso si los implicados son muchos y muy distintos.

Otra forma es mediante un sistema JMS o un MQ, como RabbitMQ.

El encolado de mensajes es un sistema que permite que un elemento perteneciente a un sistema de información, pueda comunicar un estado, evento o mensaje informativo o imperativo a otro conjunto de elementos dentro del sistema, para que interactúe con él.

Por ejemplo, si tenemos un servidor web, una interfaz, que controla un conjunto de máquinas encargadas realizar llamadas salientes, rastrear páginas de la web para almacenar información para un buscador o similar, y la interfaz quiere enviar parámetros nuevos de configuración a estas, puede hacerlo mediante el envío de un mensaje generalizado a ese conjunto de máquinas, y estas máquinas recibirán el mensaje en el momento que lo soliciten.

Esta utilidad es igualmente buena para cuando una interfaz web, por ejemplo de un estudio fotográfico, carga imágenes desde la web, las retoca con algún tipo de efecto, ajuste, etc. y más adelante permite su descarga. El sistema web puede enviar el evento al sistema de retocado de que hay una imagen disponible, y cuando la imagen ya está disponible, el sistema de retocado puede enviar otro mensaje de vuelta diciendo que ya está.

Quizás esto último podría hacerse mejor con una base de datos, pero con el sistema de mensajería, se eliminan los datos en el momento que ya no se necesitan, mientras que con la base de datos, esos datos podrían permanecer ahí de forma indeterminada.

Conclusiones

Los sistemas de encolado de mensajes tienen su utilidad, sobre todo, en sistemas formados por varias máquinas, con roles bien definidos y en las que se quiere afinar lo que son las conexiones y comunicaciones entre las máquinas.

La Historia de Erlang

He encontrado un documento (en inglés) que redacta la historia de Erlang contada por su desarrollador principal, en los laboratorios de Ericsson:

Erlang fue diseñado para escribir programas concurrentes que se ejecutasen eternamente. Erlang usa procesos concurrentes para estructurar el programa. Estos procesos no tienen memoria compartida y se comunican por paso de mensajes asíncronos. Los procesos de erlang son ligeros y pertenecen al lenguaje, no al sistema operativo. Erlang tiene mecanismos que permiten que los programas cambien on-the-fly (en vivo) así, esos programas pueden evolucionar y cambiar sin detener su ejecución. Estos mecanismos simplifican la construcción de software implementando sistemas non-stop (que no se detienen).

El desarrollo inicial de Erlang tuvo lugar en 1986 en el Laboratorio de Computación de Ericsson. Erlang fue diseñado con un objetivo específico en mente: proporcionar una mejor forma de programar aplicaciones de telefonía. En ese momento, las aplicaciones de telefonía eran atípicas del tipo de problemas que podían resolver los lenguajes de programación convencionales. Las aplicaciones de telefonía son, por su naturaleza, altamente concurrentes: un simple switch debe manejar decenas o cientos de miles de transacciones simultáneas. Tales transacciones son intrínsecamente distribuidas y el software se espera que sea altamente tolerante a fallos. Cuando el software que controla los teléfonos falla, sale en los periódicos, algo que no ocurre cuando fallan las aplicaciones de escritorio. El software de telefonía debe también cambiar on-the-fly, esto es, sin perder el servicio mientras se realiza una actualización del código. El software de telefonía debe también operar en tiempo real, con ajustados requisitos de tiempo para algunas operaciones, y más relajado tiempo en otras clases de operaciones.

Como puede leerse en el extracto, Joe Armstrong, fijó los requisitos de Erlang en solucionar los problemas de un entorno altamente concurrente, que no puede permitirse caer y que debe de actualizarse sin pérdida de servicio.

Actualmente, esta definición casa con casi la mayor parte de servicios en Internet.

PHP 5.3

Llego algo tarde, cosas del verano, pero voy a comentar algunas de las mejoras que vienen incluidas en la nueva liberación de PHP, la 5.3.

Para mi, esta versión, además de corregir fallos de la anterior, aporta características que le hacen acercarse aún más a la forma de programación profesional que viene dada con otros lenguajes como Java, C#, C++, Python, Ruby…

Espacios de nombres (namespaces)

Los espacios de nombres, llamados en otros lenguajes: paquetes, módulos, …; con esto, podemos tener organizado nuestro código, no solo en directorios, sino también bien delimitado su espacio de nombres mediante el uso del namespace.

Por ejemplo, si tenemos dos directorios: File y BD; que pertenecen a un programa y cada uno de ellos tiene un archivo para contener la clase Output, en las versiones anteriores de PHP habría que incluir uno u otro, o modificar el nombre para que fuese FileOutput y DBOutput, redundando la ruta con el nombre de la clase.

Ahora, con el uso de namespaces, se puede delimitar con solo agregar una sección de código como esta:

namespace File {
 
    class Output {
        /* ... */
    }
}
 
namespace {
    $f = new File\Output();
}

Static… ahora sí

En las versiones anteriores de PHP, los valores static no eran tratados del todo bien, no permitiéndose algunos usos que parecían lógicos y no produciéndose, sobre todo en la herencia, los resultados que se esperaban.

Ahora, ya se permite el uso de variables para contener el nombre de la clase a la que llamar de forma estática, es decir, ya se permite este uso:

class A {
    public static function say() {
        echo "Hola\n";
    }
}
 
$clase = "A";
$clase::say();

Así mismo, el uso del late state binding, es posible mediante la palabra clave static, de modo que, si se llama a un método estático como static::metodo() en lugar de como self::metodo(), se llama al método de la clase hija que haya sobrecargado al método que se llama. Un ejemplo:

class A {
    public static function who() {
        echo __CLASS__;
    }
    public static function test() {
        static::who(); // Here comes Late Static Bindings
    }
}
 
class B extends A {
    public static function who() {
         echo __CLASS__;
    }
}
 
B::test();  // output: B

Por último, la función especial __call no se llama cuando no hay un método de clase que no exista, en su lugar se llamará a __callStatic, de modo que se pueda hacer diferencia de cuando se está llamando a un método de objeto y cuando se llama a un método de clase.

Más de Late State Binding

Hasta ahora, cuando se quería hacer una clase abstracta que llamase a funciones de sus clases hijas, que aún no han sido declaradas, éstas debían ser abstractas. Pero si la clase no era abstracta y el método a llamar no constaba como abstracto, la llamada no se realizaba a esa función, sino a la del padre.

El sistema de late state binding, asegura que la llamada a métodos se hará siempre de abajo a arriba, es decir, si existe un método en la clase hija que se instanció, aunque el método en ejecución sea el del padre, el método que se llama es el de la clase hija. Más o menos lo que se vió con los métodos estáticos, pero esta vez con métodos.

Funciones anónimas

El uso de funciones anónimas (closures o lambda) es una técnica de programación que permite completar código escrito, mediante el desarrollo parcial de algún algoritmo. Imagina que quieres hacer un código en el que tengas que hacer algo, un paso inicial, un paso intermedio y, en cada iteración una ejecución específica, para terminar con un último paso tras esa iteración.

El código concreto dentro de la iteración puede variar… y de hecho variará en cada implementación, pero el resto no, el resto se mantiene de forma fija. Pues, se puede implementar el esqueleto del programa, y aceptar como parámetro de la función que se haga, una variable que contenga el código a ejecutar. La función que completaría nuestro código se puede hacer así:

$code = function ($dato1, $dato2) {
    echo $dato1 . "--" $dato2 . "\n";
};
 
algoritmo($code);
 
function algoritmo( $func ) {
    for ($i=0; $i<100; $i++) {
        $func($i, $i*$i);
    }
}

También se pueden emplear funciones como array_walk, preg_replace_callback, uasort, etc.

Esto permite realizar códigos como los que se realizan en Ruby o en los lenguajes funcionales y declarativos.

Recolector de Basura de Referencias Circulares opcional

Se deja al programador la decisión de si quiere activar el recolector de referencias circulares del garbage collector, o no. Por defecto viene activado y actúa de la siguiente forma, con este código:

class A {
    function __construct () {
        $this->b = new B($this);
    }
}
 
class B {
    function __construct ($parent = NULL) {
        $this->parent = $parent;
    }
}
 
for ($i = 0 ; $i < 1000000 ; $i++) {
    $a = new A();
    unset($a);
}
 
echo number_format(memory_get_usage());

Si se ejecuta desde consola, con una versión de PHP anterior a la 5.3, se verá en pantalla un error fatal, de que el límite de memoria se ha superado.

Esto es debido a que la liberación de memoria, cuando se va a proceder a liberar la clase B, ve que tiene una referencia a A, que ya va a ser liberada y crea un ciclo, con lo que, para evitarlo, no libera B. En las versiones de PHP 5.3 en adelante, se detecta este ciclo como tal y se liberan ambas.

También existe la posibilidad de desactivar este comportamiento o ver si está activo, con las funciones gc_enable, gc_enabled y gc_disable.

Nowdoc y Heredoc

Hasta ahora, los bloques de tipo heredoc eran los únicos que permitían escribir de forma libre un texto para después usarlo como variable. Ahora también disponemos de los nowdoc, que son iguales, salvo que no se hace parseo de variables. Un ejemplo:

$hola = "Hi, ";
 
$hd = < <<END
texto $hola
END;
 
$nd = <<<'END'
texto $hola
END;
 
echo $hd; // output: texto Hi,
echo $nd; // output: texto $hola

Constantes

Ahora, la palabra clave const puede ser empleada fuera del alcance de una clase, con lo que, en lugar de usar define se puede emplear esta forma:

// antes
// define("CONSTANTE", "Hola mundo!");
 
// ahora
const CONSTANTE = "Hola mundo!";

Operador Ternario simplificado

El operador ternario (expr1)?(expr2):(expr3) ahora permite dejar vacío el espacio correspondiente a (expr2) de modo que si (expr1) es verdadero, se retorna (expr1) y si es falso, se retorna (expr3).

Nuevos Módulos

PHPar

Al igual que JAR, PHPar sirve para empaquetar los PHP en un solo fichero, con lo que se mejora el despliegue de las aplicaciones, la organización del código, etc.

Intl

Mejores funciones de internacionalización para PHP. Hasta ahora, en PHP el único soporte de internacionalización que había disponible era gettext, ahora, con el uso de Intl y sus clases, se facilita internacionalizar una aplicación web, ya que tiene soporte para numeración, fecha, etc.

FileInfo

Da información sobre ficheros, usando la cabecera magic del propio fichero, intenta localizar de forma heurística su tipo, pudiendo retornarlo en formato MIME.

Etiquetas de Salto

Bueno, como en todo, hay avances y retrocesos, esto de proporcionar a PHP un elemento de código spaguetti como es el goto, no hace sino potenciar los malos usos, por lo que yo descartaría su uso.

Migración

Como cualquier liberación de lenguaje, PHP viene con mejoras, agregados y, además, cambios que implican que códigos anteriores puedan dejar de funciona, con lo que es aconsejable leerse bien la guía de migración, para ver los cambios que se introducen, lo que llega a ser deprecated, etc.

Conclusiones

Con esta liberación, PHP da varios matices que le hacen acercarse más a lenguajes como C++ y Java, agregando cosas como PHPar y los namespaces, así como mejorando su implementación de POO.

Considero que el cambiar a esta versión y desarrollar con las nuevas implementaciones hará que los códigos desarrollados sean más claros y, sobre todo, más organizados, por lo que es una buena baza para realizar el cambio.

Además, viendo la guía de migración, se deja entrever que los cambios de la versión anterior, 5.2.x, a esta nueva rama, son mínimos, con lo que, si se ha desarrollado código acorde a la versión anterior, realizar los cambios para adecuarse a esta versión, no es nada complicado.

Lenguajes Funcionales para el Desarrollo Web

La web concurrente, a prueba de fallos y distribuida ya va siendo más fácil de desarrollar gracias a dos iniciativas paralelas. Una de ellas es Erlyweb, el entorno desarrollado por Yariv Sadan que permite realizar de forma fácil sitios web en lenguaje Erlang. La otra es Lift, un framework de desarrollo web para otro lenguaje funcional: Scala.

¿Lenguaje funcional para la web?

Muchos se harán esta misma pregunta, si de siempre, los lenguajes imperativos han sido empleados para el desarrollo de aplicaciones web (Java, PHP, Ruby, Perl, C#, …), ¿por qué emplear un lenguaje funcional como Scala o Erlang?

Las ventajas son las siguientes:

  • El lenguaje funcional obliga a pensar lo que se programa, realmente, en este tipo de lenguajes también es posible cometer errores y hacer barbaridades, pero en menor medida. Por regla general, lo que se programa en un lenguaje funcional, suele ser meditado, pensado y puede ser probado de mejor forma.
  • Obliga a organizar el código, ya que todo gira en torno a crear funciones que se llamen unas a otras y a sí mismas, así como tener el código separado en módulos o bloques funcionales. Por ejemplo, en Erlang, para emplear OTP (gen_server, gen_event, gen_fsm…) se debe de crear un módulo para cada uno de ellos, con lo que todo queda bien organizado.
  • El código resultante es más corto y más legible, ya que el código funcional no reutiliza variables, se basa en listas y tiene menos estructuras de control que los lenguajes imperativos, sí, resulta más fácil de comprender el lenguaje en sí y el código, una vez se va leyendo.
  • Tienen ventajas cuando se habla de concurrencia, tiempo real y tolerancia a fallos. Obviamente, si no se permite la reasignación, no se permite cambiar el valor de un dato ya asignado y, por tanto, no hay cabida para la memoria compartida, con lo que la concurrencia se simplifica de forma sorprendente. Por otro lado, estos lenguajes han sido pensados y desarrollados para distribuirse en varios nodos y/o equipos, pudiendo migrar sus procesos entre nodos y sustituir al nodo principal en caso de no estar operativo.

En lo que respecta al lenguaje en sí, se ve claro y, hasta muchos pensarán: ¡mierda!, he perdido el tiempo aprendiendo y usando PHP (o Perl, o Ruby, o Java…); pero no hay que ser tan radical, estos lenguajes son muy útiles y ofrecen muchas ventajas a los lenguajes tradicionales web y, gracias a los frameworks desarrollados, las mejoras son increíbles.

Si tan bueno es… ¿por qué no se usa?

Seamos sinceros, la razón de uso de un sistema u otro se basa, íntegramente, en la popularidad, la costumbre y los malos usos. Cuando en tu entorno hasta 3 personas dicen que PHP es bueno para la web, ya sabes que es lo que hay que aprender si quieres hacer web, pero eso no debería de ser lo único a calibrar, y sobre todo si el conocimiento que se adquiera de PHP se usará para el desarrollo profesional de aplicaciones.

Erlang lleva muchos años usándose en el terreno de las telecomunicaciones y Yariv, el creador del framework Erlyweb, integra servicios desarrollados en Erlang para Facebook, con lo que, los grandes de Internet, ya se han dado cuenta de que hay que dar un paso hacia adelante. Por otro lado, Scala es usado en otros sitios como Twitter.

Ahora de verdad, ¿por qué usarlos?

El desarrollo de entornos web conlleva el uso de varias tecnologías que se usen de forma coordinada y limpia. Desarrollar un software en cualquier lenguaje mezclado con SQL y código en HTML con CSS incrustado y código JavaScript repartido por todos lados hace que el código sea difuso. Difícil de entender.

Sin embargo, con C# y Java se comenzaron a emplear soluciones que han ido trascendiendo a lenguajes de scriptting como Ruby, Python o PHP, en los que ya no se dejan ver consultas SQL, sino el uso de objetos y funciones, el código de presentación queda almacenado por separado con etiquetas especiales, helpers y otros añadidos, los códigos HTML validados, los CSS en sus respectivos ficheros aparte y agregados desde la sección pertinente e incluso el uso del JavaScript no intrusivo.

Llegados a este punto, nos encontramos con que, desarrollar web es, tan solo, desarrollar. Realizar el programa en un solo lenguaje y de forma fácil. Pero aún así, volvemos a encontrar lo que ya había tiempo atrás, nuestro lenguaje imperativo puede contener fallos lógicos y, si es un lenguaje de scriptting muy permisivo, algunos de esos fallos son difíciles de perseguir.

El uso de un framework como lift o erlyweb facilita el seguimiento de fallos, desarrollar en erlang y scala facilita el desarrollo propio de la aplicación y agrega factores determinantes de crecimiento de la misma, así como estabilidad, ¿qué más se puede pedir?

Escalado de Ruby on Rails

Después de liberar el primer proyecto escrito en Ruby on Rails, cuando lo pasamos a producción, nos dimos cuenta de que el sistema funcionaba realmente lento. En algunos casos, incluso, no respondía, con lo que buscamos información por internet y vimos:

Mongrel y Thin no son multi-hilo

Fue algo que nos sorprendió mucho, una aplicación servidora secuencial, que atiende las peticiones una a una y, en caso de que una petición se tarde un par de segundos (que las teníamos :-S ), el sistema se queda trabado durante todo ese tiempo.

Las soluciones posibles eran dos:

  • Phusion Passenger, también conocido como mod_rails, es un módulo para Apache que mantiene tantos hilos como peticiones se vayan gestionando, siempre con unos límites máximos y mínimos, tal y como apache suele hacerlo.
  • Ngnix + Thin, esta solución fue un poco más artesana, por decirlo de alguna forma, ya que consistía en configurar este servidor web como proxy inverso, para hacer el balanceo de peticiones entre todos los hilos de thin que se quieran cargar en el sistema. Descartamos en este punto a mongrel por comentarios que había leído en otros blogs.

Bien, por correr lo más posible, lanzamos tantos hilos como nos fue posible en la máquina que dedicamos al proyecto y, nos complació ver que podía aguantar hasta 40 hilos, sin que sus CPUs lo notasen apenas. Con lo que conseguimos un pool de 40 puertos dedicados a atender peticiones HTTP.

En otra máquina se configuró un proxy inverso. En el escenario de pruebas usamos nginx, aunque el tenerlo en la misma máquina y hacer pruebas masivas, nos dio como resultado que una cantidad importante de peticiones se perdían o transformaban en respuestas de tipo 500 por parte de nginx. Optamos entonces por un balanceador que tiene la compañía vía hardware, muy rápido y, a día de hoy el sistema web tira tan rápido y casi mejor que el que tenemos montado en PHP :-)

En el próximo artículo comentaré las configuraciones, arquitecturas y demás seguidas, sobre todo a nivel de nginx y thin, que es lo que realmente interesa.

Shoes: programación fácil de GUI en Ruby

Actualización: ver nueva entrada.

Cuando se realizan scripts para ciertas tareas para automatizarlas, pero que tienen que tomar datos del usuario, así como los datos que se presentan son útiles, tanto para rápida consulta, como para dar dicha información por teléfono o usarla en el código, otra interfaz, etc. surge el problema de que la consola se hace un paso como a otro mundo y resulta incómodo.

Una forma de ahorrar la pulsación de teclas, diseñando una interfaz que nos sea útil y presente la información, así como la toma de datos, de forma organizada y práctica, son las aplicaciones basadas en GUI, que se han comenzado a introducir en lo lenguajes de scripting… solo que, el uso de los mismos, se hace tan tedioso, que resulta incómodo realizar una interfaz para usuario en esos sistemas.

Hace poco, en un curso de Ruby on Rails que estaba dando Dani, un colega muy versado en Ruby y su mundo, nos enseñó un juguetito bastante gracioso para hacer GUI desde Ruby: Shoes.

Lo instalé para GNU/Linux y lo comencé a probar… en cuestión de una hora tenía una pequeña aplicación que tomaba información de un ActiveRecord, hacía una consulta según los datos de entrada que le introducía y rellenaba el resto del formulario con los datos de salida… muy útil en esos momentos para la resolución de incidencias, ya que suelen venir con datos incompletos y la resolución debe de ser rápida (y ya estaba cansado de ir a golpe de consulta SQL… mucho que teclear para obtener solo un par de datos :-P )

En la misma página hay un tutorial y, bajando el código, se pueden ver ejemplos donde hay desde programitas simples de reloj, hasta videojuegos en 3D :-) … lo recomiendo, a mi me ha ayudado mucho.

La liebre y la tortuga

En este cuento voy a intentar explicar lo que significa programar rápido y lo que significa programar de forma ágil. La primera forma sería la que se considera comenzar lo antes posible, para terminar lo antes posible… pero ciertamente, sin planificación, dar palos de ciego a ciertos niveles de implementación, es más lento que planificar la estrategia de desarrollo a priori. Vamos a verlo con el cuento de…

La liebre y la tortuga

En Silicon Valley, había un programador tan rápido que podía escribir cientos y miles de líneas de código en cuestión de pocas horas, trabajaba rápidamente y, por ello, era conocido como la liebre. Aunque era un poco alocado, se lanzaba directamente a programar y no planificaba bien los proyectos.

No obstante, todos lo admiraban por lo rápido que hacía aparecer código en tan poco tiempo.

Por otro lado, estaba otro programador, algo más lento, que planificaba en papel y lentamente todos sus desarrollos, con lo que en un día obtenía muy pocas líneas de código. Este programador era conocido, por esto mismo, como la tortuga.

La liebre y la tortuga trabajaban en la misma empresa y, ante la fuerza que la admiración del resto ejercía sobre el primero, por su característica totalmente opuesta a la del segundo, la liebre instigaba e intentaba siempre perjudicar a la tortuga.

En la sala de trabajo, un día, cuando la tortuga ya se cansó de tanta hostilidad, aprovechó la oferta de un trabajo de programación importante, con un nivel de desarrollo importante y grande, para retar a la liebre: tú que eres tan rápido, te desafío a desarrollar este programa más rápido que yo.

Toda la sala quedó estupefacta, salvo el director de proyectos, que disimuladamente sonrió, agregando: sería interesante verlo. A lo que el resto de la sala agregó más risas.

El director de proyecto se dirigió a la liebre y le preguntó: ¿serías capaz de desarrollar este proyecto en menos tiempo que la tortuga? A lo que la liebre respondió sin dudar: ¡claro que sí! Pues os doy a ambos una semana para el desarrollo del proyecto, quien antes lo termine cumpliendo con los requisitos especificados, será el ganador.

La liebre comenzó a reir, aceptó el trato, al igual que la tortuga y fue a seguir riendo con sus compañeros durante largo rato mientras la tortuga marchó a su puesto de trabajo. La tortuga analizó el proyecto e inmediatamente localizó una serie de patrones claros que seguir, tomó los requisitos y trazó los diagramas que le harían cumplir con los mismos de la mejor forma, para seguir con una planificación ajustada al tiempo que tenía para cumplir con el proyecto. Se puso manos a la obra y comenzó el diseño.

Mientras tanto la liebre, se tomaba su tiempo y, mientras hablaba con sus compañeros decía: si ya sé cómo lo voy a hacer, es una chorrada de proyecto, ¡muy fácil!

En el segundo día, la tortuga terminaba su diseño con diagramas de UML, marcaba la división y los patrones que integrarían cada una de las clases, así cómo los detalles del diseño de interfaz y otras características a tener en cuenta en diagramas de secuencia.

Al tercer día, la liebre comenzó a codificar, en poco tiempo, tenía un trozo de código que cumplía los primeros requisitos y reía a gusto creyendo saber que conseguiría su propósito. Mientras, la tortuga, acababa de sentar el esquema de clases y la estructura básica, la arquitectura de soporte y preparaba todo para comenzar la codificación al día siguiente.

En el cuarto día, la liebre comenzó a encontrarse los primeros problemas, algunos requisitos chocaban directamente con muchas de las partes ya desarrolladas y en funcionamiento, así como datos ya implementados en la base de datos, con lo que se veía obligada a rehacer la estructura de datos, eliminar todo el código que no le servía y volver a escribir código nuevo. La tortuga comenzaba la codificación con la estructura de clases autogenerada por las herramientas CASE que usaba y trazaba las líneas de código de acceso a datos y lógica de negocio, escribía las pruebas unitarias para asegurar que todo salía bien y seguía adelante.

El quinto día, para la liebre, comenzaba el stress, la desesperación, se acerca el final del proyecto, aún no están todos los requisitos y se han vuelto a encontrar problemas. Como no hay una visión global, no sabe cuantos problemas más puede llegar a encontrar y, para los ya encontrados, la recodificación es algo pesada. Con lo que parece que solo lleva, de forma constante la mitad del proyecto. Por otro lado, la tortuga ha terminado la parte de lógica de negocio y manejo de datos, así como la parte de seguridad y acceso, el controlador, con lo que solo le restan las vistas, con las pruebas funcionales para acabar el proyecto.

El sexto día, cuando se había previsto la entrega del proyecto, la liebre había pasado toda la noche en su puesto de trabajo, intentando, con chapuzas, terminar a tiempo el proyecto, haciéndolo de forma muy deficiente y sin probarlo. Sin embargo, la tortuga, ya acababa la vista, haciendo siempre la ejecución de las pruebas de regresión para probar la integración de cada una de las partes, junto con las funcionalidades pedidas y el entorno en sí.

A la entrega del proyecto, la liebre presentó un proyecto con fallos, que no terminaba de funcionar y que tenía implementados los requisitos solicitados de forma dudosa, mientras que la tortuga entregaba un proyecto bien pensado, con un resultado limpio y funcional.

Ante los resultados, el director de proyectos se dirigió a la liebre y le dijo: no es cierto que es más rápido quien más rápido programa, sino quien, con menos código y menos trabajo, consigue hacer lo mismo en menos tiempo; y con ello, la tortuga ha demostrado, que es más rápido que la liebre.

Conclusión: usar metodologías ágiles acelera realmente el desarrollo, porque optimiza el proceso de creación.