miércoles, 3 de diciembre de 2014

Se ha publicado Symfony 2.6

El pasado 29 de noviembre se publicó la nueva versión 2.6 del popular framework PHP Symfony [EN]. Dicha versión incluye multitud de novedades como por ejemplo la inclusión de las llamadas AJAX en la barra de depuración [EN], el nuevo tema para formularios basado en Bootstrap 3 [EN], el nuevo instalador de Symfony [EN] y así hasta 100 cambios, mejoras y correcciones. Puedes consultar la lista completa de cambios de Symfony 2.6 [EN] y las actualizaciones necesarias para pasar de Symfony 2.5 a 2.6 [EN]. Symfony 2.6 se actualizará hasta julio de 2015 y tendrá soporte hasta enero de 2016.

Siguiendo con Symfony recientemente se ha dado a conocer la hoja de ruta para los próximos Symfony 2.7 [EN], con fecha de lanzamiento prevista en mayo de 2015, que será LTS con soporte hasta mayo de 2019 y la última versión de Symfony 2; y el futuro Symfony 3 [EN] que romperá la compatibilidad con las versiones anteriores pero que no supondrá un cambio trágico como lo fue el paso de Symfony 1 a Symfony 2. Las principales novedades que se conocen de Symfony 3 son que se aumentará el requisito de versión de PHP mínimo a PHP 5.5 o PHP 5.6 y que se eliminará código obsoleto, rompiendo compatibilidad con las versiones anteriores.

Referencias

jueves, 13 de noviembre de 2014

PepePhone, la seguridad informática y los diseños inconsistentes

Pepephone es el operador virtual de telefonía móvil mejor valorado por sus usuarios según diversas encuestas. La principal característica de este OMV, más allá de la competencia de precios, es tener los operadores del servicio de atención al cliente en España (concretamente en Palma de Mallorca). Además según la propia Pepephone sus operadores están entrenados para resolver todos los problemas en una llamada y tienen permisos para hacer todos los cambios en el contrato que pida el cliente, pero en cambio tienen prohibido tratar de venderte nada u ofrecerte cambios de tarifas ni nada parecido. La segunda parte no la discuto ya que jamás ningún operador ha de Pepephone ha intentado colarme un cambio de contrato ni nada similar. En cambio eso de que los operadores están entrenados para resolver los problemas del cliente es... ¡discutible!

Contaré mi caso. El pasado 1 de noviembre tuvimos que dejar la empresa sin actividad (congelada) por problemas que no vienen al caso por lo que llamo al 1212 para solicitar un cambio de titular para poner la línea móvil a mi nombre y cambiar la cuenta bancaria. El operador amablemente me informa que tengo que hacerlo desde el área de cliente de la web de Pepephone. Fallo mío. Acostumbrado a tratar con Movistar, Vodafone o Endesa por ejemplo desde cuyas webs se puede hacer de todo menos lo que necesitas (sea lo que sea), no lo había mirado. Cuelgo y voy al área de clientes de Mi Pepephone. Localizo la opción del cambio de titular enseguida, introduzco todos los datos incluido la fotocopia de mi DNI y meeeeeeeeeeeeec: "el email introducido ya está en uso". Vaya por dios. El email es clave única.

Desde el punto de vista del diseño informático, hacer que el email sea clave única y con ello obligar a cambiar el email al cambiar el titular es algo que yo no haría por diversos motivos, pero cosas más raras se han visto. En fin como no me da la gana cambiar de email, uso una cuenta de GMail y sé que puedo alterar la dirección y seguir recibiendo el correo normalmente, lo que hago es poner nombre.apellidos@gmail.com en lugar de nombreapellidos@gmail.com. El email es distinto para el sistema y yo sigo recibiendo emails en la misma cuenta. Le vuelvo a dar a "enviar" y no ocurre nada. Ni un mensaje de confirmación de envío ni un mensaje de error. ¡Nada! ¿Lo habrá enviado? Vuelvo a pulsar enviar y entonces aparece un mensaje de error: "Solicitud ya en curso".

Confuso. Mucho. Un simple mensaje de "formulario enviado" habría bastado para saber si todo iba bien o sino un email de confirmación. Pero no. Nada de nada. Al día siguiente, mosqueado, repito el proceso con el mismo resultado: la primera vez que pulso el botón no hace nada (el formulario queda con todos los datos en modo edición como si no hubiera hecho nada). La segunda vez me muestra el mensaje "Solicitud ya en curso".

Decido dar un voto de confianza a Pepephone, esperando un par de días con la esperanza de que todo funcione bien. Y... sorpresa: ¡lo hace! Un par de días después recibo un email "Te confirmamos que la solicitud de cambio de titular se ha completado con éxito". Y me mandan las nuevas credenciales de acceso, ya con el email nombre.apellidos@gmail.com. Accedo al área de cliente y meeeeeeeeeeeeec: "707 usuario no autorizado". Mi gozo en un pozo. Decido esperar un día más por aquello de que uno es informático y sabe que a veces esas cosas se arreglan "solas" por la noche (cuando pasa el batch, quiero decir). Pero no... ni al día siguiente ni al otro consigo acceder a mi cuenta con las credenciales que me han dado. ¡Aquí nada funciona a la primera!

¿Qué hago ahora? Lo primero será llamar a esos super-operadores de Pepephone, ¿no? Llamo, explico mi problema y el operador empieza a preguntar: DNI, email, número de teléfono, dirección,... número de cuenta. "¿Número de cuenta? Pues ni idea. Estoy en la calle y en estos momentos no tengo forma de saber el número de cuenta". "Pues si no me dice el número de cuenta no puedo resetearle el password, señor". "¿Y no tienes alguna otra forma? Ya te he dado el email, el teléfono, el dni... y lo único que quiero es que me mandéis otra password". "Pues no, señor. Si no me dice todos los datos yo no puedo hacer nada, pero si quiere puede enviar un mail a pepephone@pepephone.com y pedírselo a mis compañeros".

¿Un email? ¡Ya! ¡Seguro que sí! Venga, no pierdo nada: Escribo el email y lo envío. Nos vamos a reír. Cuatro horas después me contestan (se han dado prisa): "Lamentablemente, en la solicitud que nos han remitido, el email solicitado pertenece a otro cliente ya existente. Con el fin de poder atender a la petición que nos habían remitido le agradeceríamos que nos indicasen un correo electrónico alternativo para incluir en su perfil de usuario". Esta vez me lo esperaba. Si no escribo "desde" nombre.apellidos@gmail.com no me resetean el password.

Cabreado ya entro en Mi Pepephone, busco la opción de he olvidado mi contraseña, introduzco ***sólo*** el DNI y el email y dos minutos después recibo el email con la nueva clave de acceso. Y funciona.

Lo que he escrito hasta aquí no es más que un mensaje-pataleta digno de ForoCoches.com. Desde luego llamar al 1212 sin haber buscado antes en Internet fue un error de looser deluxe. Nota mental: borrar el 1212 de la memoria del teléfono (para lo que sirve). Ahora viene la moraleja:

Lo que quería ilustrar con este ejemplo es como algunas empresas pueden complicar innecesariamente un proceso sencillo como es el asignar una nueva clave de acceso, mareando al usuario y haciéndole perder el tiempo. Si para resetear el password desde Internet sólo necesito el email y el dni, ¿Por que para pedirlo por teléfono me tienen que pedir el número de cuenta? Y respecto al email, ¿Qué más da la dirección desde la que escriba? Como si eso no se pudiera simular. ¿Por que los procesos empresariales no son consistentes? Según mi experiencia eso ocurre por falta de coordinación entre departamentos. Es más que habitual que en una empresa relativamente grande no haya nadie que tenga una visión de conjunto de los procesos empresariales relacionados con las TIC (tecnologías de la información y la comunicación) de forma que el mismo proceso funcione de forma diferente dependiendo de que departamento lo ejecute. Y eso es un error.

Las causas de esa descoordinación entre departamentos pueden ser muchas, pero yo apuesto como culpable principal por la externalización salvaje de los servicios de las TIC. A corto plazo puede suponer un ahorro considerable para el empresario, pero si externalizas todo el departamento de informática pierdes conocimiento funcional porque el personal externo suele tener una rotación más elevada que el personal interno. Externalizar la programación por ejemplo puede estar bien siempre que mantengas a los jefes de proyecto y analistas en nómina. No digo que ese haya sido el caso de Pepephone. Hablo de experiencias personales.

domingo, 2 de noviembre de 2014

Symfony 2 avanzado: Cómo pasar el 'locale' a un servicio

Muchas aplicaciones Symfony 2 son multiidioma gracias a la capacidad del popular framework para manejar las traducciones. En este contexto la variable locale contendrá el identificador del idioma. Desde el controlador es muy sencillo obtener el locale a partir del request; basta pedirlo: $this->get('request')->getLocale(). En cambio no es tan sencillo inyectar el locale en el constructor de un servicio debido a los diferentes ámbitos (scopes) que pueden tener los servicios.

Sin embargo hay un truco para hacerlo:

<service
    id="mylocale"
    class="Symfony\Component\HttpFoundation\Request"
    factory-service="request"
    factory-method="getLocale">
</service>

<service
   id="myservice"
   class="%myservice.class%">
   <argument type="service" id="mylocale" on-invalid="null" />
</service>

Es decir, primero creamos un service factory que acceda al Request para obtener el locale y luego inyectamos el service factory en nuestro servicio. el parámetro on-invalid="null" es muy importante para solucionar aquellos casos en que el Request no existe; como por ejemplo los comandos de consola. Al implementar la clase hay que tener en cuenta que es posible que recibamos null en lugar del locale.

class MyService
{
    /**
     * @var string
     */
    private $locale;

    /**
     * @param string $locale
     */
    public function __construct($locale = null)
    {
        $this->locale = $locale;
    }

    // (...)
}

viernes, 31 de octubre de 2014

Javascript avanzado: objetos, clases y prototipos. Introducción

Javascript es un lenguaje muy completo y muy complejo de aprender, sobre todo la parte referente a objetos, clases, herencia, prototipos, etc. Y esto es porque si bien Javascript no soporta de forma nativa esos conceptos de la orientación a objetos que tan claros están en otros lenguajes como Java, C++ o PHP, todos ellos pueden simularse con las funciones nativas del lenguaje.

Por ello voy a iniciar una serie de artículos sobre Javascript Avanzado.


Creación de un objeto simple

var stack = {
    elements: [],
    push: function(elem) {
        this.elements.push(elem);
    },
    pop: function() {
        var elem = this.elements.pop();
        return elem;
    }
};

En Javascript se puede usar la notación JSON para crear objetos sin tener que crear antes una clase. En el ejemplo creamos un objeto llamado stack que tiene un array de elementos y dos métodos: push() y pop(). La variable resultante es directamente un objeto. La mayoría de los lenguajes orientados a objeto no permiten crear objetos sin haber creado antes una clase, pero Javascript sí.

NOTA: Es innecesario crear un objeto stack en Javascript pues la clase Array ya tiene las funciones push() y pop() de forma nativa, pero me sirve para ilustrar el ejemplo.

stack.push(1);
stack.push('string');
stack.push({ id: 1, name: 'test' });
console.log(stack.pop());

Como se ve podemos usar directamente los métodos del objeto stack, pero en cambio no podemos crear nuevos objetos stack, ya que stack es un objeto y no una clase. Por lo tanto el siguiente código dará error:

var s = new stack;

Además en este tipo de objetos simples todos los métodos y miembros son públicos, lo cual quiere decir que podríamos acceder directamente a la lista de elementos elements, lo cual no suele ser correcto desde el punto de vista de la programación orientación a objeto.


Añadiendo miembros y métodos a un objeto simple

Javascript, a diferencia de otros lenguajes de programación orientados a objetos más tradicionales permite añadir nuevos miembros y métodos a un objeto simple tras su creación. Por ejemplo:

stack.top = function() {
    if(this.elements.length < 1) {
        return null;
    }
    else {
        return this.elements[this.elements.length - 1];
    }
};

Así añadimos el método top() al objeto stack que funcionará exactamente igual que si lo hubiéramos puesto desde el principio.


Creación de una clase

En Javascript no podemos crear una clase como tal, pero sí que podemos simularlo mediante una función. Sí, sí... has leído bien: una función. Esa función además funciona como constructor de la clase. Veamoslo con el mismo ejemplo:

var Stack = function() {
    var elements = [];
    this.push = function(elem) {
        elements.push(elem);
    },
    this.pop = function() {
        var elem = elements.pop();
        return elem;
    }
};

En el constructor de la clase Stack inicializamos un array de elementos y definimos las funciones push() y pop(). Ahora Stack es una clase, no un objeto y por lo tanto no podemos hacer lo siguiente:

Stack.push('elem1');
console.log(Stack.pop());

La forma correcta de hacerlo sería creando primero un objeto de clase Stack.

var st = new Stack;
st.push('elem1');
console.log(st.pop());

Además se da el caso de que ahora el miembro elements es privado lo cual significa que no puede ser accedido desde fuera de la clase.


Añadiendo miembros y métodos a una clase Javascript

Anteriormente vimos como añadir métodos a un objeto Javascript. Aquí también podemos añadir miembros y métodos directamente al objeto st, pero como la variable elements no es un miembro de la clase no podremos acceder a ella. Tendríamos que hacer que la variable elements fuera un miembro de la clase

var Stack = function() {
    this.elements = [];
    this.push = function(elem) {
        this.elements.push(elem);
    },
    this.pop = function() {
        return this.elements.pop();
    }
};

var st1 = new Stack;

st1.top = function() {
    if(this.elements.length < 1) {
        return null;
    }
    else {
        return this.elements[this.elements.length - 1];
    }
};

st1.push('e1');
console.log(st1.top());

Hemos añadido el método top() al objeto st que funcionará como si se hubiera añadido en la definición de la clase (función constructora). Sin embargo ese método es exclusivo del objeto st y no estará disponible para otros objetos Stack. ¿Y podemos añadir un método a una clase? Sí; a través del prototipo:

Stack.prototype.top = function(){
    if(this.elements.length < 1) {
        return null;
    }
    else {
        return this.elements[this.elements.length - 1];
    }
};

Ahora tanto st1 como cualquier otro objeto de clase Stack creado con posterioridad tendrán top() entre sus métodos.


Herencia de clases en Javascript

El concepto de la herencia en Javascript también es extraño si estas acostumbrado a otros lenguajes orientados a objeto. Al no existir clases como tales tampoco hay palabras clave como extends o implements. La herencia se hace asignando el prototipo de una función (clase) a otra. Pero la explicación detallada la vamos a dejar para otro artículo.


Referencias

miércoles, 22 de octubre de 2014

Más sobre Composer

El otro día os hablaba de Composer el gestor de dependencias para proyectos en PHP que permite incorporar a nuestros proyecto en PHP multitud de librerías, gestionando sus dependencias de forma magistral. Pues hoy he encontrado el artículo Composer, gestor de dependencias para PHP que amplía la información que yo mismo puse aquí. Os recomiendo su lectura.

Actualización (23/10/2014): Los chicos de desarrolloweb.com han publicado hoy una segunda parte del artículo de Composer llamada Cómo Instalar Composer, donde se detallan las distintas formas de instalar Composer en los más populares sitemas poerativos: Windows, Linux, Max OSX, ...

jueves, 16 de octubre de 2014

Función javascript para formatear un número de teléfono

El título de este artículo lo dice todo: Función javascript para formatear un número de teléfono. Así pues ahí va:

String.prototype.formatPhone = function(sep) {

    if(typeof sep == 'undefined') {
        sep = ' ';
    }

    var num = this.replace(/[^\d\+]/g, '');
    var len = num.length;

    if(len < 7) {
        return num;
    }
    else if(len < 10) {
        return num.replace(
            /(\d{1,3})(\d{3})(\d{3})/,
            '$1' + sep + '$2' + sep + '$3'
        );
    }
    else {
        return num.replace(
            /(\d+)(\d{3})(\d{3})(\d{3})/,
            '$1' + sep + '$2' + sep + '$3' + sep + '$4'
        );
    }
};

Y para usarlo...

    var phone = '[+34] 93 6665544'.formatPhone(' ');
    document.write(phone);

Resultado: +34 936 665 544.

lunes, 13 de octubre de 2014

Manual de buenas prácticas en Symfony2

Me acabo de enterar a través del fabuloso blog Symfony.es de Javier Eguiluz de la presentación del manual oficial de buenas prácticas para desarrollar aplicaciones en Symfony2. Si estás interesado puedes descargarlo en formato PDF en inglés o en español, aunque el propio Javier advierte que el contenido cambiará en los próximos días pues por ahora sólo se ha publicado una versión preliminar. También puedes consultar on-line el manual en Español.

Se trata de una serie de reglas que configuran un conjunto de buenas prácticas que recomiendan desde SensioLabs y que han sido aprobadas por el propio Fabien Potencier. Puedes estar de acuerdo o no con esta guía por lo que si eres desarrollador experto no es necesario que las sigas. Tampoco es obligatorio modificar un proyecto existente para seguirlas. Sin embargo me parece una gran ayuda especialmente para principiantes y para proyectos nuevos. Personalmente no estoy totalmente de acuerdo con todas pero me parece muy interesante especialmente las recomendaciones sobre como crear el bundle de aplicación, y donde poner los recursos como las vistas o las traducciones.

jueves, 28 de agosto de 2014

Herramientas para desarrollo web: Composer

Composer es una de las herramientas fundamentales para desarrollar aplicaciones y páginas web en lenguaje PHP, ya que permite administrar las dependencias de nuestro proyecto con las distintas librerías externas que necesitemos usar. Composer instala las librerías que el proyecto necesita en una carpeta del propio proyecto. Vamos a ver como funciona con un ejemplo:

Supongamos que nuestro proyecto PHP necesita generar archivos Excel. En lugar de crear todo el código necesario desde cero, miramos en Packagist si alguien ha creado una herramienta open-source que haga lo que necesitamos y vemos que existe una librería llamada PHPExcel. Esa librería a su vez necesitará otras, probáblemente. En lugar de descargar el código fuente de la librería y buscar las dependencias dejamos que sea Composer el que resuelva el problema.

Para ello lo primero será tener instalado Composer en el PC, ya sea de forma global o en el directorio raíz del proyecto. Composer es un programa escrito en php que descargaremos y ejecutaremos.

$ curl -sS https://getcomposer.org/installer | php

Obtendremos un archivo llamado composer.phar que luego para instalarlo globalmente podemos moverlo a un directorio del path como /usr/bin o /usr/local/bin, dándole permisos de ejecución.

$ mv composer.phar /usr/local/bin/composer
$ chmod a+x /usr/local/bin/composer

Una vez tenemos Composer instalado de forma global, creamos el archivo composer.json en la raíz de nuestro proyecto:

{
    "require": {
        "phpoffice/phpexcel": "dev-master"
    }
}

Y entonces usamos composer para que resuelva las dependencias:

$ composer install

La ejecución de composer crea la carpeta vendor y descarga automáticamente la librería phpexcel y las dependencias de ésta si las hay. También crea un archivo llamado autoload.php que será necesario incluir en nuestro proyecto para usar las librerías creadas por composer.

<?php
require __DIR__ .'/vendor/autoload.php';

Requerimientos:

Al ser un programa escrito en PHP Composer es multiplataforma por lo que funciona tanto en Linux como en OSX y en Windows. Necesita una versión de PHP 5.3.2 o superior y puede requerir modificar alguna configuración en php.ini, pero el propio instalador informa de cualquier incompatibilidad. Además es conveniente tener instalado Git, Svn u otras herramientas para el control de código fuente.


Enlaces:

martes, 29 de julio de 2014

Silex, un micro-framework para PHP basado en Symfony2

Symfony2 es uno de los frameworks para PHP más completos, versátiles y potentes que existen actualmente en el mercado. Pero, ¿Qué ocurre si no necesitamos tanta potencia? ¿Que hacemos si queremos desarrollar una pequeña página corporativa donde la potencia de Symfony2 es más un estorbo que una ayuda? En esos casos en lugar de usar Symfony u otro framework potente como Zend se suele optar por personalizar un Wordpress, un Joomla o cualquier otro CMS. El problema entonces es que perdemos el control del desarrollo en temas como gestión de permisos, teniendo que adaptar nuestros requerimientos a lo que pueda hacer el CMS elegido. Sin embargo existe una tercera vía: El uso de un micro-framework que sin ser tan potente como un Symfony o un Zend nos proporcione la suficiente versatilidad para desarrollar una pequeña página web de forma ágil. Y en este caso la propia SensioLabs y Fabien Potencier, creadores de Symfony, nos dan la solución: Silex.

Silex es un micro-framework para lenguaje PHP basado en componentes de Symfony2. Funciona con PHP 5.3 o superior y tiene licencia MIT (código fuente libre). La gran potencia de Silex es que aprovecha gran parte de los componentes del núcleo de Symfony2, que están sobradamente probados, pero en cambio en mucho más fácil de usar que Symfony2. El paquete básico de Silex permite desarrollar páginas web desde cero, proporcionando un sencillo sistema de definición de rutas propio y poco más. Sin embargo es posible añadir a Silex multitud de componentes externos que también usa Symfony: desde Twig hasta Doctrine, pasando por Swiftmailer y algunos de los componentes más potentes de Symfony como sus formularios, su sistema de validación, su sistema de traducciones, etc.

La documentación de Silex es muy completa, en la línea de los otros productos de SensioLabs.


Ejemplo: Hola mundo en Silex

require_once __DIR__ . '/../vendor/autoload.php';

$app = new Silex\Application();

$app->get('/', function() {
    $output = 'Hola mundo.';
    return $output;
});

$app->run();

viernes, 11 de julio de 2014

Nueva imágen corporativa y nueva web

Este mes estamos de celebración en iFraktal pues estrenamos, logotipo, imagen corporativa y página web. El diseño y las tendencias están en constante cambio y eso nos obliga también a nosotros a seguir esa ola de renovación constante.

Nosotros somos los primeros en aconsejar a nuestros clientes que una vez la página web está acabada, lo que hay que hacer es un proceso de renovación constante, algo que atraiga siempre la atención hacia su carta de presentación, es decir, su página web. Es por ello que nosotros nos hemos aplicado nuestro própio consejo y "nos hemos lavado la cara".

Así mismo hemos inaugurado un nuevo blog corporativo integrado dentro de la nueva página web, dejando este blog, que también renovaremos estéticamente, como herramienta de soporte técnico para desarrolladores internos y externos. Seguiremos por supuesto publicando información técnica, artículos y trucos siempre que podamos.


Enlaces de interés

miércoles, 28 de mayo de 2014

Software a medida

El software a medida es un producto de Ingeniería de Software desarrollado especialmente para un cliente, teniendo en cuenta los requerimientos del mismo y las políticas de su empresa u organización.

El software estándar por su parte está orientado un uso masivo por clientes con necesidades similares. Algunos productos de software estándar permiten también ciento grado de personalización de forma que con un desarrollo particular pueden adaptarse a las necesidades del cliente, aunque es difícil que se adapte exactamente a los requerimientos y políticas del mismo. Un ejemplo serían los diversos CMS (sistemas de gestión de contenidos) como Wordpress, Joomla, Prestashop, Drupal, ... Otros productos de software estándar no permiten ningún tipo de personalización.

A priori el software a medida siempre es más caro porque requiere más trabajo, pero cumple exactamente con las necesidades del cliente. Sin embargo en ocasiones las adaptaciones de software estándar a las necesidades de un cliente pueden costar tanto como hacer el software a medida desde cero. Todo depende de lo que el producto inicial se adapte a los requerimientos del cliente.

Como analogía entre software a medida y estándar se puede usar, con restricciones, el caso de un traje a medida frente a otro comprado en un centro comercial. Muchos clientes tendrán bastante con un traje del centro comercial al que le hacen unos mínimos arreglos. En cambio si el cliente tiene necesidades especiales por ser por ejemplo muy alto es difícil que encuentre un traje que le sirva en el centro comercial y tendrá que pedir a un sastre que se lo confeccione a medida. Otra posibilidad sería comprar el traje más grande del centro comercial y luego pedir a un sastre que se lo alargue. El coste del arreglo generalmente será menor que el traje a medida pero el resultado tampoco será el mismo.


Ventajas del software a medida:

  • Se adapta perfectamente a las necesidades del cliente.
  • No requiere un cambio en la forma de trabajar de la empresa u organización.
  • Se puede modificar y ampliar fácilmente.
  • Posibilidad de entregas modulares.
  • El software es propiedad del cliente.

Desventajas del software a medida:

  • Generalmente es más caro que el software estándar.
  • La implementación es más costosa y por lo tanto más lenta.

¿Cuando conviene desarrollar software a medida?

Una empresa u organización preferirá desarrollar software a medida cuando las necesidades de sus sistemas de información no se adapten exactamente a ningún producto comercial, personalizable o no, ya sea porque tienen requerimientos especiales o porque no deseen cambiar sus procesos de gestión. Los requerimientos especiales pueden ser cualquier cosa: desde informes especializados hasta procesos de gestión no habituales. La decisión de desarrollar software a medida puede afectar a la competitividad del cliente a medio plazo, por lo que es una decisión que hay que meditar bien antes de tomar una decisión definitiva.

jueves, 22 de mayo de 2014

PHP avanzado: Llamadas recursivas en funciones anónimas (closures)

PHP

Una closure es una función sin nombre que puede por ejemplo asignarse a una variable o pasarse como parámetro a otra función. PHP soporta closures desde la versión 5.3 con una restricción importante: El ámbito de las variables es totalmente privado. Esto quiere decir que desde dentro de la closure no se puede acceder a variables externas a no ser que sean variables globales y las declares con la palabra clave global. Una excepción a esto son las variables superglobales. Además desde PHP 5.4 se puede acceder a $this si la closure se declara dentro de un método de una clase. Esa restricción no es un problema por si mismo, pero restringe el uso de variables locales cuando declaras la closure dentro de una función o de un método de una clase. Para solucionar eso se usa la palabra clave use. Entonces si queremos hacer una llamada recursiva a la closure tendremos que pasar una referencia a la propia closure a través de la palabra clave use. Por ejemplo (*):

$factorial = function( $n ) use ( &$factorial ) {
    if( $n == 1 ) return 1;
    return $factorial( $n - 1 ) * $n;
};

(*) Ejemplo sacado de Stack Overflow.

martes, 20 de mayo de 2014

Añadir métodos a una clase en Javascript

Javascript es un lenguaje de programación que está cada vez más en alza debido a sus enorme flexibilidad y a sus muchas posibilidades. Una característica que los principiantes en este lenguaje no suelen conocer es que se puede añadir y modificar el comportamiento de los métodos de una clase posteriormente a la declaración de la misma. Y esto puede hacerse tanco con clases propias como con clases nativas del lenguaje.

Por ejemplo la clase String, que es nativa de Javascript, tiene muchos métodos útiles como pueden ser trim(), substring(), indexOf() o replace(); pero carece por ejemplo de un método stripTags() que elimine las etiquetas HTML de una cadena de texto. Sin embargo podemos añadirlo fácilmente:

String.prototype.stripTags = function() {
    return this.replace(/<(?:.|\n)*?>/gm, '').trim();
}

Una vez declarado podemos hacer lo siguiente:

var x = "<p>Hola <b>mundo</b>.</p>";
x = x.stripTags();
document.write(x);

El resultado será "Hola mundo" sin los tags HTML.

martes, 22 de abril de 2014

Cual es el mejor IDE para programar en PHP

Un IDE (Integrated Development Environment) o entorno de desarrollo integrado es la herramienta que los programadores usamos para programar. En realidad los programadores somos gente simple: lo único que de verdad necesitamos para programar es un buen editor de texto. Luego si queremos probar nuestro desarrollo necesitaremos el compilador o intérprete del lenguaje de programación que estemos usando y dependiendo del caso igual algunas herramientas adicionales como un servidor web o la máquina virtual de Java. Pero de entrada lo único imprescindible es un editor de texto.

Como editor de texto nos vale casi cualquier cosa: desde el inútil bloc de notas de Windows hasta el complejo EMACS de GNU, pasando por el Notepad++ o el Ultra Edit en Windows, el gEdit en Ubuntu o el VI o el Nano en cualquier distribución Linux. Los programadores que ya peinamos canas recordamos aun los tiempos en que los IDE no se habían generalizado y la nuestra única herramienta era un editor de textos.

¿Que es un IDE?

Un IDE es un conjunto de herramientas integradas en un único paquete que proporciona a los programadores un marco para el desarrollo de aplicaciones informáticas. Un IDE puede servir para programar en un único lenguaje, en varios lenguajes o ser de propósito general (para cualquier lenguaje, generalmente añadiendo plugins).

Un IDE puede tener algunas de las siguientes herramientas (o todas ellas):

¿Cual es el mejor para programar en PHP?

Y ahora que ya he explicado que es un IDE, ¿Cual es el mejor para programar en PHP? Pues la pregunta es complicada. Cada programador tendrá sus preferencias, pero personalmente después de haber probado varios tanto en Windows como en Linux me quedo con PhpStorm.

PhpStorm es un IDE comercial multiplataforma de JetBrains que incluye editores para PHP, HTML y JavaScript, análisis de código en tiempo real, prevención de errores y mucho más. A mi me gusta sobre todo porque es muy rápido y bastante intuitivo de usar. He probado otros IDE como Eclipse y NetBeans, ambos gratuitos y open source, pero prefiero la rapidez de PhpStorm.

martes, 15 de abril de 2014

iTherm, una app para controlar la fiebre infantil

Hoy quiero dar difusión a un proyecto de un amigo que está buscando financiación. Se trata de iTherm un brazalete termómetro para niños que se conecta vía bluetooth con un dispositivo móvil (iPhone o Android) para realizar una medición constante de la temperatura del niño, pudiendo configurarse alertas para que avise si la temperatura supera un cierto límite. Dejo a continuación el vídeo de la entrevista que le han hecho recientemente La Vanguardia.

lunes, 14 de abril de 2014

El experto

Hoy voy a publicar un vídeo que he visto en Microsiervos. El vídeo se titula The Expert (el experto). Es una parodia perfecta de aquellas reuniones de trabajo en las que los jefes llaman a un empleado experto en cierto campo pero luego no tienen en cuenta sus opiniones. Como nota final decir que yo me he encontrado más de una vez en situaciones como esta, algunas igual de surrealistas y que en cierta ocasión tras una reunión así tuve yo otra reunión con mi manager donde me acusó de actitud negativa y falta de visión comercial. Mi campo es el desarrollo de aplicaciones informáticas, pero este se puede aplicar a casi cualquier trabajo de oficina. El vídeo está en inglés pero se entiende bien y además se pueden activar los subtítulos que funcionan perfectamente.

viernes, 28 de marzo de 2014

Symfony2 avanzado: Usando un objeto Query para crear un QueryBuilder

Este caso es un poco difícil de explicar. Vamos a suponer lo siguiente: Tenemos una entidad Factura y un repositorio FacturaRepository que tiene una función findFacturas(). Dicha función recibe un parámetro obligatorio $usuario de clase Usuario y otro opcional $filtros que por defecto es un array vacío. La mencionada función, que está perfectamente testeada y no desea cambiarse, prepara dinámicamente una query DQL teniendo en cuenta los permisos del usuario y un montón de filtros y devuelve un objeto de clase Query que al ejecutarla devuelve la lista de facturas del usuario.

namespace Company\ContabilidadBundle\Entity;

class Factura {
  //...
}

class FacturaRepository {
  public function findFacturas(Usuario $usuario, $filtros = array( )) {
    //...
    return $query;
  }
}

Por otro lado, en otra parte de la aplicación, tenemos un formulario en el que necesitamos poder seleccionar una de las facturas del usuario mediante un cuadro de selección (combobox). Para ello lo más lógico es añadir al formulario un campo de tipo entity. El problema es que que no podemos aprovechar la query que tenemos en nuestro repositorio porque los campos entity se cargan con un QueryBuilder.

Hoy me he encontrado con este mismo problema. Quedaba totalmente descartado Convertir en un QueryBuilder una query DQL de dos palmos y medio de largo, perfectamente testeada, por su complejidad (y porque no me daba la gana), así que me he puesto a investigar si había alguna forma de convertir o cargar un objeto Query en un objeto QueryBuilder. No ha sido fácil pero lo he conseguido...

Este es el resultado:

namespace Company\ContabilidadBundle\Form\Type;

class FormularioFormType extends AbstractType {

  //...

  public function buildForm(FormBuilderInterface $builder, array $options) {

    //...

    $builder->add(
      'factura',
      'entity',
      array(
        'class' => 'CompanyContabilidadBundle:Factura',
        'query_builder' => function(EntityRepository $repository) use($usuario) {

          $query = $repository->findFacturas($usuario);
          $qb = $repository->createQueryBuilder('f');
          $qb->where($qb->expr()->in('f', $query->getDql()));
          $qb->setParameters($query->getParameters());
          return $qb;
        }
    ));
  }
}

Veámoslo paso a paso:

  1. En primer lugar obtenemos el objeto Query del repositorio. Dicho objeto estará listo para ser ejecutado devolviendo el resultado que deseamos.
  2. En segundo lugar extraemos la sentencia DQL y los parámetros del objeto Query con las instrucciones $query->getDql() y $query->getParameters().
  3. En último lugar creamos un nuevo objeto QueryBuilder y simulamos una subquery como esta: SELECT * FROM Facturas f WHERE f IN (...), poniendo la sentencia DQL original en el lugar de los puntos suspensivos.

Es rebuscado pero funciona perfectamente.

sábado, 1 de marzo de 2014

Symfony 2: Añadiendo bundles externos

Esta es la tercera parte del mini-curso de Symfony 2 que empecé hace tiempo. En el último capítulo creamos nuestro primer proyecto Symfony 2. El proyecto recién creado traerá todas las dependencias necesarias para empezar a programar con el framework Symfony. Sin embargo una de las grandes ventajas de Symfony 2 es que es fácilmente ampliable mediante librerías externas programadas por terceros llamadas bundles.

Hay bundles para todos los gustos: unos añaden características nuevas a Symfony 2, otros mejoran su seguridad, otros amplían funcionalidades, etc. La forma de instalar un bundle externo es nuevamente mediante el uso de composer. Para ello hay que añadir las dependencias en el archivo composer.json que encontraremos en la raíz de nuestro proyecto Symfony de la siguiente forma:

{
    "require": {
        "vendor/package": "version",
    }
}

En este caso vendor y package forma el nombre del bundle mientras que version es el número de versión (por ejemplo: 1.2.3 o 1.2.* o >1.2.3 o >1.2.3,<1.3, etc. Para buscar bundles compatibles podemos ir a Packagist, que es el repositorio de paquetes instalables vía Composer.


En ejemplo: añadiendo Bootstrap

Vamos a verlo con un ejemplo. Supongamos que queremos añadir el framework CSS Bootstrap a nuestro proyecto Symfony. Podríamos descargarnos la librería de Bootstrap y añadirla manualmente a nuestro proyecto, pero en Symfony siempre que sea posible preferiremos hacerlo vía bundle externo. Buscando en Packagist encontramos que hay varios bundles que añaden Bootstrap a Symfony. Yo he elegido Mopa Bootstrap porque lo conozco de antes, pero además es uno de los que más descargas y mejor valoración tienen en Packagist. Visitamos la página web oficial del proyecto Mopa Bootstrap en Github y allí la sección de instalación nos indica como añadir el bundle a Symfony 2; hay que añadir el siguiente código en el archivo composer.json:

{
    "require": {
        "mopa/bootstrap-bundle": "v3.0.0-beta3",
        "twbs/bootstrap": "v3.0.0"
    }
}

Una vez hecho esto hay que ejecutar composer update desde el directorio principal del proyecto para que se actualicen las dependencias y se descarguen las librerías.

$ composer update
Loading composer repositories with package information
Updating dependencies (including require-dev)
  - Installing mopa/composer-bridge (v1.3.0)
    Downloading: 100%

  - Installing mopa/bootstrap-bundle (v3.0.0-beta3)
    Downloading: 100%

  - Installing twbs/bootstrap (v3.0.0)
    Downloading: 100%

Como podemos ver además de los dos bundles indicados nos ha instalado un tercero: mopa/composer-bridge (v1.3.0). Esto es porque Composer sabe que es necesario instalarlo o sino mopa/bootstrap-bundle (v3.0.0-beta3) no podrá funcionar. Ahora ya podemos empezar a usar Bootstrap en nuestro proyecto web. Pero, ¿Como se usa mopa/bootstrap en Symfony? Para saber eso hay que leerse la documentación.


Mini-curso de Symfony 2

  • Primeros pasos: Conceptos y definiciones sobre Symfony 2.
  • Primer proyecto: Como empezar un proyecto Symfony 2.
  • Añadiendo bundles externos: Agregar dependencias a composer.json.

martes, 11 de febrero de 2014

Google Adwords (i)

¿Como consigo visitantes en mi nueva tienda on-line? ¿Por qué nadie visita mi página? ¿Qué hago para ser "popular" en Internet? Estas cuestiones y otras similares las hemos escuchado decenas de veces de los clientes. Básicamente hay dos formas de conseguir visitantes para una página web y ambas se conocen por sus acrónimos: SEO y SEM. Las dos se basan en lo mismo: conseguir aparecer bien posicionado por una o varias palabras clave en los principales buscadores (Google, Yahoo, Bing, etc). La diferencia es el camino que toman para conseguir el objetivo.

SEO (Search Engine Optimization) es un conjunto de técnicas encaminadas a la optimización de una página web para que sea mejor considerada por un buscador (por ejemplo: Google, Yahoo, Bing, ...) de forma que aparezca mejor posicionada en los resultados de búsqueda para un conjunto de palabras clave.

SEM (Search Engine Marketing) es una de las formas que existen de hacer publicidad de una página web. Consiste en insertar anuncios patrocinados entre los resultados de búsqueda de un buscador (por ejemplo: Google, Yahoo, Bing, ...) para un conjunto de palabras clave a cambio de dinero. Existen muchos programas de SEM pero el más popular es Google Adwords.

Resumiendo, SEO es optimizar la página web para hacerla atractiva a los buscadores y SEM es pagar para aparecer en los resultados de búsqueda. La compra de enlaces patrocinados es una muy buena estrategia para complementar el SEO sobre todo en páginas web que empiezan.

Ya hemos comentado que Google Adwords es el programa de publicidad SEM de Google para sitios web. Adwords se utiliza para hacer publicidad patrocinada y cuenta con enormes cantidades de clientes con sitios web de todo tipo y de todas partes del mundo. Se trata de anuncios que se muestran de forma relevante en los resultados de la búsqueda del usuario. Google permite pagar para que un sitio web aparezca por determinadas palabras claves en los resultados de búsqueda.


Primeros pasos con Google Adwords

Usar el programa Adwords es muy sencillo: Sólo se necesita una cuenta Google y un navegador. Tanto si se dispone de cuenta Google como si no la primera vez hay que acceder al programa Adwords, seleccionar la zona horaria y la moneda y confirmar la creación. A partir de este momento ya se puede crear la primera campaña publicitaria, pero ésta no comenzará a publicarse hasta que se indiquen las preferencias de facturación.


Como configurar una campaña Adwords de éxito

Mucha gente que crea su primera campaña Adwords se encuentra con que si sigue los consejos que la apropia aplicación Adwords le ofrece, lo que consigue son unas pocas visitas muy caras que no siempre soy visitas útiles. Esto ocurre porque si bien Google trata siempre de que todos los anuncios de los clientes aparezcan en los resultados de las búsquedas, su objetivo principal es maximizar sus propios beneficios por lo tanto los anuncios que más clics reciban serán los que más aparezcan hasta agotar el presupuesto del cliente. Por ello diseñar una campaña Adwords de éxito no es sencillo y se requieren ajustes continuos. El objetivo de Google es que haya los máximos clics posibles mientras que el objetivo del cliente suele ser realizar las máximas ventas desde su página web. Una campaña Adwords tiene que conseguir que tanto Google como el cliente alcancen sus objetivos. Y eso no es fácil de hacer.

Así, lo primero que se debe hacer al crear una campaña de Google Adwords es preguntarse, ¿Que busco conseguir con mi campaña? ¿Ventas? ¿Registros? ¿Visitas? Dependiendo del objetivo final la campaña será totalmente diferente y el precio máximo por clic que deberá pagarse será muy distinto

Por ejemplo el objetivo de la campaña de una web de venta de productos será realizar las mayores ventas, pero no a cualquier precio. Si el precio pagado por los clics de la campaña supera el margen de beneficio de los productos el usuario estará perdiendo dinero. Según nuestra experiencia en el mejor de los casos el rendimiento de una campaña Adwords (relación entre clics y ventas) nunca superará el 10%. Pero ese es el mejor de los casos. Una buena campaña debe tener como objetivo tener un rendimiento de entre el 3% y el 5%. Así supongamos que tenemos un rendimiento esperado del 3% y que el margen de beneficio medio por producto es de 3€. En este caso si el precio pagado por clic supera los 0,09 € el usuario perderá dinero.

En cambio si el objetivo del usuario fuera el de conseguir registros el cálculo del precio máximo por clic sería muy diferente. Por ejemplo tuvimos un cliente que ofrecía a través de su web muestras gratuitas de un producto y su objetivo era el de conseguir nuevos clientes. En este caso a priori no podíamos calcular con exactitud el precio máximo por clic ya que dependía de la aceptación del producto y de otros factores más subjetivos. En ese caso la experiencia en hacer campañas Adwords es muy importante. Un porcentaje elevado de los clientes que pidieron muestras gratuitas se convirtieron en clientes en los siguientes meses y la campaña fue un éxito.

Pero no sólo es importante el precio máximo por clic. Hay muchos otros factores que influyen en el éxito de una campaña Adwords como la elección de las palabras clave y la construcción de los anuncios... pero eso lo dejaremos para otros artículos.