Archivos de la categoría Trabajo

Debug remoto

Estoy probando una aplicación en el iPad que básicamente es una UIWebView que accede a una página de Internet que es la que realmente tiene la aplicación.

En el navegador de escritorio todo funciona perfectamente, pero a la hora de probarlo en el iPad he detectado un comportamiento distinto y necesito saber qué es lo que pasa y por dónde va el flujo de ejecución.

Para ello existen muchas soluciones, bastante complicadas desde mi punto de vista, que pueden servir para ver qué es lo que está pasando como por ejemplo: Enabling Remote Debugging via Private APIs in Mobile Safari.

Pero no me acaba de convencer, así que he optado por otra solución, que leí hace un tiempo y no recuerdo dónde.

La idea es redefinir el objeto console para que realice una petición a un servidor enviando el contenido con el que se le ha invocado, algo así como un log remoto.

Para ello con el siguiente código se puede conseguir:

(function(window, undefined) {
    var console_old = window.console,
        console = {};

    console.log = function() {
        var xhr = new XMLHttpRequest();
        
        xhr.open('POST', '/console.php', true);
        xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
        xhr.send('log=' + JSON.stringify(arguments[0]));

        console_old.log(arguments[0]);
    };

    console.info = console.log;
    console.warn = console.log;

    window.console = console;

})(window);

El código en el servidor sería el siguiente:

 exec("echo '".$_POST['log']."' >> /tmp/console.log");    

Con todo lo anterior ya podemos poner debugs por el código y ver en tiempo real por dónde está pasando la aplicación y qué problemas tiene.

Ni que decir tiene que aplicar esto a un desarrollo web o aplicación nos puede servir para poder saber qué tipos de errores les da a los usuarios, eso sí habría que mandar un poquito más de información para poder resolver incidencias que les ocurran.

Números y rendimiento

Sigo buscando que mis aplicaciones hechas en javascript se ejecuten más rápido, para ello recientemente he descubierto unos trucos para para poder acelerar la conversión de strings en números.

Para ello, en vez de usar parseInt y parseFloat que son increiblemente lentos, uso el operador unario ‘+’:

//var numero = parseInt('12');
var numero = +('12');

//var numero = parseFloat('12.1');
var numero = +('12.1');

La razón de que el operador uniario sea más rápido es que éste no realiza una comprobación de los límites superiores e inferiores del número, eso sí hay que tener cuidado de que el string sea un número válido.

Referencias:

http://monkeyandcrow.com/blog/js_coercion_performance/
http://jsperf.com/parsing-vs-coercion

Expansión de objetos con variables y métodos privados

Continuando con el apasionante mundo de la creación de objetos en javascript y después de haber aprendido a usar los getters y los setters, me he puesto a definir objetos y quería que todos ellos tuvieran la función de vincularse unos con otros.

Al hacer esto me he visto repitiendo una y otra vez el mismo código para realizar esa vinculación, lo cual no es buen sintoma. Así que me he parado a pensar cómo podría hacer para crear un objeto genérico con esas propiedades para que los demás objetos, por así decirlo, hereden esas propiedades.

Me he puesto manos a la obra y lo primero que he hecho ha sido crear la definición de ese objeto genérico que va a contener, de momento, solo la funcionalidad de vincular.


var Objeto = function() {
    var self = this;

    self._binds = {};

    self.clase = {
      bind: function(v, o, f) {
        self._binds[v] || (self._binds[v] = []);
        self._binds[v].push({
          obj: o,
          func: f
        });
      }
    };

    self._bind = function() {
      self._binds['value'] && self._binds['value'].forEach(function(e) {
        e.func.apply(e.obj, [self.clase]);
      });
    };
  };

Después de tener el objeto genérico y sabiendo que no voy a instanciar ningún objeto real con él, sino que lo voy a usar para crear otro objeto el cual sí será la clase que usaré para instanciar los demás objetos, me he puesto a buscar información sobre constructores, prototipos y demás.

Al cabo de un buen rato he dado con una solución válida para mi problema, ya que yo quiero mantener ciertas variables y ciertos métodos privados; y con la información que había obtenido de mi búsqueda siempre tenía todas las variables a la disposición de la instancia que creaba.

La solución es la siguiente:

var miObjeto = function() {
    var self = this,
        _value = 0;

    // Cogemos las propiedades genéricas

    Objeto.apply(this);

    // Definimos los getters y los setters

    self.clase.__defineGetter__('value', function() {
      return _value;
    });
    self.clase.__defineSetter__('value', function(v) {
      _value = v;
      self._bind(); // Llamamos a la función de vinculación
    });

    return self.clase; // Devolvemos únicamente la clase
  }

Como los constructores en javascript son funciones y todas las funciones tienen el método call, lo que se me ha ocurrido es llamar a la función/constructor Objeto sobre miObjeto, con lo que se consigue que se definan dentro de miObjeto todas las propiedades y métodos que estaban presentes en Objeto.

Luego utilizo la otra manera de definir getters y setters, que tienen javascript, para definir las demás propiedades de miObjeto y por último devuelvo el objeto clase que contiene los métodos públicos que deseo que tenga la instancia que utilice dicha clase.

El uso de estas nuevas clases es igual que en el artículo anterior, con la diferencia de que si ahora creo, por ejemplo, un miObjeto2, no tengo que volver a implementar la funcionalidad de vincular ya que la puedo heredar de Objeto.

var miObjeto2 = function() {
    var self = this,
        _enable = 0;

    // Cogemos las propiedades genéricas

    Objeto.apply(this);

    // Definimos los getters y los setters

    self.clase.__defineGetter__('enable', function() {
      return _enable;
    });
    self.clase.__defineSetter__('enable', function(e) {
      _enable = e;
      self._bind(); // Llamamos a la función de vinculación
    });

    return self.clase; // Devolvemos únicamente la clase
  }
  var miObjetoReal = new miObjeto();
  var miObjetoReal2 = new miObjeto2();
  miObjetoReal.bind('value', miObjetoReal2, function(e) {
    (e.value != '') && (this.enable = 1) || (this.enable = 0);
  });

También a estos objetos se les podría añadir la vinculación con un elemento DOM, como en el artículo anterior, y tendríamos unos objetos con los que trabajar sin preocuparnos de las actualizaciones de la interfaz.

Referencias

http://www.webdeveloper.com/forum/showthread.php?t=243971
http://www.3site.eu/doc/
http://stackoverflow.com/questions/6039676/copying-javascript-getters-setters-to-another-prototype-object

Getters, Setters y vinculación de objetos

Recientemente he estado leyendo algunos artículos de javascript en los que se explicaban las bondades de los getters y los setters y cómo podemos utilizarlos para darles más funcionalidad a nuestras clases.

Un Ejemplo sencillo sería el siguiente:

  var MiClase = function() {
    var _value = 0;
    var clase = {
      get value() {
         return _value;
      },
      set value(v) {
         _value = v;
      },
    };
    return clase;
  };

Lo definido arriba es equivalente a esto:

  var MiClase = function() {
    this.value = 0;
  };

Pero claro, ¿para qué hacer algo más complicado si no se obtiene ningún beneficio?, la respuesta está en que al ser los getters y los setters funciones, podemos añadir más acciones dentro de estas a parte de las de devolución y asignación de variables.

Uno de los usos que se le puede dar es vincular un objeto que creemos a través de la clase con un objeto DOM, como por ejemplo una caja de texto:

  var MiClase = function(t) {
    var _value = 0,
        _obj = document.getElementBy(t);

    var clase = {
      get value() {
         return _value;
      },
      set value(v) {
         _value = v;
         _obj.value = v;
      },
    };

    _obj.addEventListener('blur', function() {
      clase.value = this.value;
    }, false);

    return clase;
  };

  var miObjeto = new MiClase('micaja');

Con el código de arriba conseguimos vincular el objeto miObjeto con la caja de texto de identificador micaja, de manera que siempre que introduzcas algo en la caja de texto se actualizará la propiedad value del objeto miObjeto y viceversa.

Podemos complicar un poco más la definición de la clase para añadir vinculación entre objetos, es decir, yo quiero vincular dos objetos a través de una propiedad de uno de ellos, de manera que cuando actualice la propiedad en el objeto origen en el objeto destino se realicen una serie de acciones. Para todo esto, la clase quedaría de la siguiente manera:

var MiClase = function(t) {
    var _value = 0,
        _obj = document.getElementBy(t),
        _binds = {};

    var clase = {
      get value() {
         return _value;
      },
      set value(v) {
         _value = v;
         _obj.value = v;
         var self = this;
         _binds['value'] && _binds['value'].forEach(function(e) {
           e.func.apply(e.obj, [self]);
         });
      },
      bind: function(v, o, f) {
        _binds[v] || (_binds[v] = []);
        _binds[v].push({
          obj: o,
          func: f
        });
      }
    };

    _obj.addEventListener('blur', function() {
      clase.value = this.value;
    }, false);

    return clase;
  };

Lo que hemos hecho ha sido añadir un objecto que contiene un array de vinculaciones, _binds, y una función bind que nos permite asociar objetos. También hemos añadido en el setter la ejecución de las funciones de vinculación que pueda tener el objeto pasando como parametro el propio objeto para que puedan interactuar con él.

Ahora el código para realizar las vinculaciones:

  var miObjeto1 = new MiClase('caja1');
  var miObjeto2 = new MiClase('caja2');

  miObjeto1.bind('value', miObjeto2, function(e) {
    this.value = e.value + '(copia)';
  });

Con el código de arriba lo que hemos hecho ha sido vincular las cajas de texto caja1 y caja2 con los objetos miObjeto1 y miObjeto2 respectivamente y después hemos vinculados los dos objetos entre sí por medio de la propiedad value de miObjeto1 de manera que cuando ésta cambie se llamará a la función de vinculación. En este ejemplo sencillo, cada vez que se cambia la propiedad value de miObjeto1 se le asigna a la propiedad value de miObjeto2 el mismo valor más el texto “(copia)”.

Dentro de la función de vinculación, this hace referencia al objeto destino, en nuestro ejemplo, miObjeto2 y el parámetro e hace referencia al objeto origen, en el ejemplo, miObjeto1.

Referencias
JavaScript getters and setters: varying approaches
Javascript getters and setters for dummies?
Working with objects

Copia de un array en Javascript

En casi todos los desarrollos es común el uso del tipo array para almacenar elementos. Muchas veces queremos guardar una copia de una array por si lo necesitamos restaurar de nuevo a su estado inicial. En tal caso haríamos algo similar a esto:

var a = [1, 2];
var b = a;

Ahora si modificamos un elemento de a:

a[0] = 3;

Podremos restaurar de nuevo nuestro array que teníamos en b, ¿No?

a = b;

La respuesta es NO, ya que si vemos el contenido de b comprobaremos que el elemento 0 también se ha modificado. Lo que ha sucedido con la asignación entre dos variables, una de las cuales es de tipo array, es que hemos creado un puntero al mismo objeto y por tanto no hemos guardado un array con los valores iniciales.

Para conseguir nuestro objetivo tendremos que recurrir a un pequeño truco que crea un nuevo array:

var b = [].concat(a);

El código de arriba lo que hace es crear un nuevo array que es el resultado de concatenar a un array vacío el array a. De esta manera, modificando los valores del array a conseguimos que los valores del array b queden inalterados.

Procedimientos en 3D

Como dice el refrán: “En todas partes cuecen habas”, y mi empresa no es la excepción. Como es normal todas las empresas tienen unos procedimientos internos a través de los cuales se ejecutan la mayoría de las tareas del día a día. En mi empresa, estos procedimientos no están reflejados en ningún documento interno ni están en un tablón de anuncios ni nada por estilo. Son procedimientos que a veces se han pasado en formato de correo electrónico con contenido totalmente críptico e ilegible o se han transmitido de boca en boca como los cuentos populares.

La desventaja de todo esto es que nadie comprende bien los procedimientos ya que según la situación, el cliente y el procedimiento en sí la cosa cambia y bastante. Esto da lugar a enfados y personas descontentas ya que no tienen un lugar de referencia claro para poder saber como actuar en cada momento.

El otro día mientras despotricábamos en la comida varios compañeros y yo, se me ocurrió la idea de que los procedimientos en mi empresa se podrían expresar como una tabla de tres dimensiones: Tarea, época y cliente.

La explicación de esto es la siguiente: Los procedimientos que sigue una empresa para realizar una misma tarea dependen, de la tarea en si, la época del año en que nos encontremos y el cliente para el cual se tenga que realizar la tarea.

Por este motivo, si tenemos que realizar la tarea T para el cliente A en la época del año E1 utilizaremos el procedimiento P(T,A,E1) pero esa misma tarea T para el cliente B utilizará el procedimiento P(T,B,E1).

Como una empresa tiene muchos clientes y una tabla de estas dimensiones sería algo intratable, lo mejor que se puede hacer es definir tipos de clientes: A, B, C, … y asignar a cada cliente un tipo, de está manera la tabla tendrá muchos menos registros y será más fácil de visualizar.

Igual con esto he re-inventado la rueda, pero creo que mi empresa funcionaría mucho mejor teniendo una tabla de este tipo a disposición de todos los empleados.

Adictos a los feeds

Ayer esta leyendo los titulares de las noticias pendientes de menear en meneame.net y llegue al blog de desarrollo personal llamado El inconformista, tenía varios artículos interesantes, así que me dispuse a leerlos.

Entre ellos cabe destacar uno que me llamo bastante la atención: ¿Por qué nos convertimos en adictos al e-mail?

En el se explica la situación de las personas que son adictas al email, personas que están todo el rato chequeando el correo en busca de nuevos correos a los que poder contestar o los que poder leer.

Hoy estando en el trabajo mientras instalaba unas fuentes en un servidor me he puesto a pensar en es artículo y he visto que en mi trabajo no se puede aplicar el concepto de adicto al email ya que todos nosotros lo utilizamos como herramienta de trabajo y es muy difícil estar sin leer el email durante más de una hora ya que la mayor parte de las peticiones que nos hacen los clientes se hacen por email.

Después de analizar un poco más la situación y observar ciertos de mis hábitos en el trabajo, me he dado cuenta de que lo que se puede aplicar a las personas como yo es la adicción a los feeds. Siempre tengo abierto el lector de feeds y en cuanto tengo un lapso de tiempo, por pequeño que sea lo dedico a ver si hay artículos nuevos en los sitios a los que estoy suscrito.

Por todo lo anterior creo que se podrían utilizar los Trucos para reahablitar a un adicto al e-email pero aplicados a los feeds.

Intentaré no leer los feeds en cuanto llegan y hacerlo solo unas pocas veces al día, aunque hay veces que tienes tantos lapsos a lo largo del día que esto se hace una tarea bastante difícil.

Mail con adjuntos por consola

Hace unos días estaba yo paseando a la hora de la comida por los demás departamentos de mi empresa y al pasar por el de badcrc, le vi a él y a otro compañero muy enfrascado en algo, me pico la curiosidad y me acerque. Lo que estaban haciendo era intentar enviar un fichero adjunto a través del comando mail de la consola de Unix, pongo aquí el comando por si a alguien le sirve:

cat kk.zip | uuencode kk.zip | mail -s “Mi asunto con adjunto” micorreo@midominio.com

Oracle express edition

Ayer tuve una cena con algunos antiguos compañeros de trabajo y estuve hablando con uno de ellos sobre Oracle y Java, tecnologías que yo personalmente no uso mucho. La razón de esto es que en mi trabajo del día a día lo que necesito es desarrollar aplicaciones rápidamente y no tengo tiempo para configurar e instalar correctamente estas tecnologías, a parte de que la curva de aprendizaje de ambas es bastante grande comparada con el PHP y el MySQL.

A lo que ibamos, me comento que existía una versión de desarrollo de Oracle, llamada Oracle Express Edition, la cual era muy sencilla de instalar y configurar y que era la que ellos usaban como entorno de desarrollo. La verdad es que la idea de que Oracle saque una versión de desarrollo de fácil instalación y configuración me parece muy buena, ya que así pueden intentar competir con MySQL a la hora de desarrollar pequeñas aplicaciones.

Yo si tengo algún rato libre intentaré instalar y hacer alguna que otra pruebecilla, pero que conste que sigo decantandome por el PHP+MySQL ya que las experiencias que he tenido con Oracle y con Java no han sido muy satisfactorías, ya que para hacer cosas sencillas hay que dar muchas vueltas. Esto no quita que en un futuro intente aprender más sobre configuración de Oracle y programación en Java, pero me da que esto no sucederá a no ser que me cambie de trabajo.

Codificación de los feeds

Hoy estaba desarrollando un feed para un portal y me he encontrado con que tenía el feed con codificación UTF-8 y mi servidor estaba configurado para entregar US-ASCII.

Como no quiero tocar el servidor, lo que he hecho ha sido meter el una cabecera Content-type:

Content-type: application/xml

Lo normal hubiera sido poner text/xml, pero poniendo application/xml lo que haces es forzar a que te coja la codificación que le estás indicando en el fichero, no la del servidor.