domingo, 20 de abril de 2008

Paralelizando conexiones más allá de los límites del navegador

Últimamente he estado lidiando con el asunto del límite de conexiones de los navegadores trabajando bajo HTTP 1.1. En esta versión del protocolo no se permiten, en principio, más de 2 conexiones simultáneas. Ésto es un problema en aplicaciones que precisan sacar el máximo rendimiento de las descargas como puede ser el envío de imágenes, que ya de por sí es información pesada.

Aquí cuentan que un cliente no debería mantener más de 2 conexiones con cualquier servidor o Proxy. Muy bien; eso coménteselo a los de Google y su Google Maps, o a Microsoft y su Maps Live, a ver qué opinan del asunto (ellos lo resuelven como detallo más adelante). Y todo por seguir "el estándar", dicho sea de paso.

Microsoft ya ha tomado medidas con su 'Explorer 8' para aumentar por defecto el número de conexiones simultáneas a 6. El caso es que como siempre, cada navegador irá "a su bola" y al final nos tocará lidiar con estos problemas a los programadores (para ganarnos el sueldo, y tal...). Menuda chusta!

Googleando se puede encontrar cómo resolver este asunto de forma más o menos elegante (sin intervención por parte del usuario) con la inclusión de múltiples dominios que apunten a una misma IP encargada de resolver las peticiones al cliente. Con este "Hack" la verdad es que se consiguen unas velocidades de descarga potentes (siempre dependiendo del ancho de banda). Prueba de ello es el visor que tenemos publicado para GeoMadrid.

En diversos Blogs que he estado leyendo opinan que este tipo de triquiñuelas puede reventar Internet. Yo opino que todo en su justa medida... Los servidores deben estar preparados ofreciendo escalabilidad pues las aplicaciones de hoy demandan grandes volúmenes de información. La Web tiene su talón de Aquiles en el ancho de banda pero eso no debe ser un impedimento para desarrollar aplicaciones que saquen el máximo provecho de los recursos disponibles.

miércoles, 12 de marzo de 2008

Desarrollador 5 Estrellas

Recientemente he obtenido la 5ª Estrella del curso online de capacitación para tecnologías relacionadas con .NET. Actualmente trabajo con ese Framework, de ahí que decidiera enrolarme principalmente por ampliar conocimientos y obtener material actualizado. Mis impresiones al respecto:

- Lo mejor de todo que es gratuito.
- Es una buena oportunidad de iniciarse en .NET si aún no lo conoces y/o te pica la curiosidad.
- Buen material aunque no me agrada que la parte final sean vídeos y más vídeos. Además, la calidad del sonido es mediocre.
- Conoces tecnologías que aún no trabajando con ellas a diario, te pueden servir para proyectos futuros (p.e. Workflows).
- No es complicado aprobar exámenes, aunque alguno es algo "puñetero".
- Con tanta estrella al final eres capitán general, como poco ;-)

En breve abordaré el Desarrollador Gold y posteriormente, si todo va bien, el Platinum. Aquí como el Lute, camina o revienta...

sábado, 1 de diciembre de 2007

Dale aire al navegador exprimiendo el Javascript

Una parte muy importante de la Web actual es la visualización de animaciones. Ofrecen un añadido importante a cualquier interfaz de usuario siempre que se usen en su justa medida. En el ámbito Web podemos utilizar principalmente GIFs animados para el keyframing o generar animaciones de forma dinámica orientadas, en principio, a movimiento de objetos. Ésta segunda opción es muy interesante y flexible, aunque requiere codificar un pequeño Framework.

Las animaciones dinámicas requieren como mínimo de un Timer para ir notificando las actualizaciones de cada objeto. Javascript tiene este soporte aunque la resolución del Timer en la mayoría de los navegadores deja bastante que desear. De cualquier modo, si se utiliza una estrategia inteligente podemos aprovechar sus recursos de manera óptima.

Cuando se precisa animar algo siempre recurrimos al socorrido setInterval o setTimeout. Tendemos a crear uno por cada grupo de objetos que se van a mover al unísono. Esto no es beneficioso para el comportamiento del navegador principalmente porque se empieza a saturar la ejecución de hilos por cada Timer instanciado (ésto también depende del intérprete del navegador y su gestión interna de hilos).

A mí me gusta siempre extrapolar el diseño de algunas partes de una aplicación (sea Web o de escritorio, orientada a gráficos o incluso bases de datos) al campo de los videojuegos y en este caso tengo una buena piedra de toque. La idea es utilizar una clase manager que notifique a todos los objetos afectados del momento en que tienen que actualizar su estado interno. Este manager utilizará únicamente un Timer, con el ahorro de procesamiento para el navegador que eso conlleva. Si piensas que puede ser lento o no sincronice correctamente los objetos visuales afectados, permíteme que te diga que funciona como un reloj ;-)

La base del diseño lo forman simplemente una interfaz IAnimatable (debería darle una vuelta a este nombre :-D ) y una clase AnimatorManager. IAnimatable debe implementarla toda clase que necesite actualización en base a una frecuencia. Por su parte, AnimatorManager será la clase maestra encargada de manejar a su antojo a todos los implementadores de la interfaz, notificando cuando corresponda.


//Interfaz para todo componente susceptible de ser animado vía Timer
WebDock.IAnimatable = function() {}
WebDock.IAnimatable.Prototype = {
    onTick: function(){}
}
WebDock.IAnimatable.registerInterface('WebDock.IAnimatable');
 
//Manager de animación que controla el Timing de todos los implementadores de IAnimatable
WebDock.AnimatorManager = function(fps) {
    this._items = new Array();

    this._frameTime = 1000/fps;

    this._isprocessing=false;
    _oThis = this;
}

WebDock.AnimatorManager.prototype = {
    run: function() {

        this.timerID = setInterval(this.pump, this._frameTime);

    },
    
    add: function(animatable) {
        this._items.push(animatable);
    },
    
    remove: function(animatable) {
        for (var i=0;i<this._items.length;i++)
        {
            if (animatable==this._items[i])
            {
                this._items.splice(i, 1);

                i=this._items.length; //es más rápido que 'break'
            }
        }
    },
    
    //llama a la actualización de todos los componentes de animación registrados
    pump: function() {
        if (!_oThis._isprocessing) //establecemos contención para mantener sincronización correcta de cada frame
        {
            _oThis._isprocessing=true;
            for(var i=0;i<_oThis._items.length;i++)

            {
                var animatable=_oThis._items[i];
                animatable.onTick();
            }
            _oThis._isprocessing=false;
        }

    },
    dispose: function() {
    }
}
WebDock.AnimatorManager.registerClass('WebDock.AnimatorManager', null, Sys.IDisposable);


Por si a alguien le resulta raro el código Javascript anteriormente expuesto, simplemente apuntar que está desarrollado utilizando el Framework AJAX de ASP.NET. Éste permite herencia, interfaces, enumeraciones, eventos, etc. muy útiles a la hora de orientar a objetos en Javascript.

domingo, 25 de noviembre de 2007

Balancea tu Software

¿Cuántas veces hemos pensado que el diseño de nuestra aplicación, que en un principio era cojonudo, ahora no lo es tanto? ¿Cuántas otras nos hemos dado cuenta que después de un tiempo sin tocar nuestros desarrollos es complicado su entendimiento y mantenimiento?

Dependiendo del tipo de aplicación o componente Software que estemos diseñando, debemos tener en cuenta qué prima en el desarrollo del mismo. Por un lado tenemos el crear un buen diseño que permita desarrollos futuros sin desestabilizar lo ya realizado. Por otro está el siempre desquiciante tema de las optimizaciones que todo programador "tunea" de forma continua para hacer el algoritmo más rápido o el sistema más eficiente. Ésto es especialmente notable en tecnología gráfica y Networking.

El tema del rendimiento normalmente implica un pequeño caos en el desarrollo debido a que se tiende a concentrar mucho las operaciones que realiza una tarea determinada. Cuantas menos llamadas a funciones mejor; cuantas menos capas de clases mejor, etc. Prefiero tratar directamente con tipos primitivos locales que con Wrappers o adaptadores que no hacen otra cosa que llamar y llamar a otros de su calaña para obtener un mismo resultado a costa de una pérdida de rendimiento... Bien, todo esto está muy bien para secciones críticas del código y/o pequeños programitas pero no es muy recomendable en desarrollos de cierta envergadura.

Sólo hay que pensar un poco en el desarrollo en equipo de cualquier empresa del negocio del Software para darse cuenta que se precisa el trabajo coordinado de muchos para que cada parte/componente del sistema se integre correctamente y sea fácilmente mantenible por cualquier otro que esté especializado en ese área de desarrollo concreto. Aún así, sobrediseñar tampoco es bueno pues tiende a complicar un sistema que podría resolverse con menos abstracciones/subclasificaciones y yendo al grano en ciertas partes del mismo.

¿Dónde está el umbral entre un buen diseño y un código eficiente? Las mejores armas que tenemos a nuestro alcance es la experiencia y el profundo conocimiento de las herramientas utilizadas para lograrlo.

Ahí va una pildorita.