Jquery – la potencia sin control no sirve de nada !!

Yo soy de esos programadores web que están disfrutando con las bondades que nos ofrece JQuery desde su aparición. Esta librería nos simplifica enormemente nuestros desarrollos con JavaScript y los hace mucho más productivos.

Pero hasta ahora realmente no había aprovechado todo su potencial y es precisamente en  esta situación cuando me ha defraudado un poco.

Me explico:

He querido tratar todo un interfaz de usuario con JQuery para optimizar la presentación y evitar las idas y venidas de la página para consultar los datos. Para eso recupero la información para rellenar un control, desde mi capa de datos utilizando un método de página y formato Json, de esta manera se evita enviar la información innecesaria de la página.

Estos datos tienen una estructura mas o menos compleja o al menos más compleja que una simple tabla, porque se tiene que representar en diferentes niveles.

  • Fechas[n]
    • Identificadores[n]
      • Propiedades[n]
        • Valor

test11

Para representar estos datos correctamente en la tabla he generado unos bucles que recorren los datos y los presenta dependiendo de algunas condiciones.

No voy a poner todo mi código pero tendría más o menos este aspecto:

  • Varios bucles anidados para recorrer los registros y generar la tabla.
$($("#" + tabla + " tr:first")[0].cells).each(function() { 

        var diaCell = this;
        diaCell.innerText = result[pos].Key.charAt(0);

  • Modificación del DOM para agregar y eliminar datos de la tabla.
var rowHabitaciones = $("#" + tabla + " tr [hab]");
var reg = "<td>"+name +"</td>";
$(RowHab).after(reg);

Todo perfecto y encantado de lo simple que me ha quedado el código de cliente que tiene que tratar tanta información.

Peroooooo!!! si hay un pero.

Al ejecutar el código está tardando mucho más de lo esperado. Llego a tardar tanto en pintar la tabla que hasta el propio explorador me avisaba de este problema.

test

la potencia sin control no sirve de nada !!

Tenemos que tener en cuenta que Jquery es una librería que encapsula el lenguaje JavaScript para simplificar su uso, eso significa que para nosotros recorrer el DOM es ahora mucho más fácil, pero internamente sigue ejecutando complicadas sentencias para que nuestro código funcione por ejemplo en diferentes navegadores sin problemas.

Por ese motivo tenemos que seguir unas cuantas reglas para que nuestro código sea lo más optimo posible.

Antes de la optimización de mi código he testeado la velocidad que tarda el script en representar los datos inicialmente.

Primera prueba sin optimizar: 17,366 segundos !!!!!

test1

Realmente es impensable tener un script que tarde 17 segundos en pintar una tabla en el cliente.

Ahora voy a seguir unas simples reglas para el uso adecuado de Jquery haber si realmente ganamos algo en eficacia.

  1. Iteraciones: Es recomendable utilizar en lo posible las funciones nativas del navegador y evitar utilizar directamente los objetos del DOM en estas. Es más preferible utilizar texto y añadir este al final de la iteración.
  2. Añadir elementos al DOM: Siguiendo el anterior consejo, si tenemos que agregar una gran cantidad de objetos al DOM, es mejor añadir todos los objetos de una vez que irlos añadiendo progresivamente.
  3. NO abusar de los selectores: Es muy fácil abusar de los selectores por su gran potencia. Utilizar variables con los resultados de los selectores para su reutilización.

Muchos más consejos en improve-your-jquery-25-excellent-tips.aspx

Después de limpiar, reorganizar, no abusar de los objetos DOM y utilizar for en decremento de los cómodos each este es el resultado.

Segunda prueba con el código optimizado: 0,361 segundos !!!!!

test2

Realmente si cuidamos un poco la forma de utilizar Jquery sumado con el clásico JavaScript podemos tener un código mucho más optimizado para utilizar con nuestro interfaces de usuario.

Yo al menos en esta práctica me he ahorrado 17 segundos ni más ni menos y mi control está funcionando al 100%.

CrossPosting http://lonetcamp.com

Evento Seguridad Web XSS y buenas prácticas

Para los despistados o los que no se hayan enterado aún del evento, mañana Martes 17 de Noviembre de 2009, los chicos de secondnug con sus ya famosos  webCasts, me han pedido que repita la charla que hice en el CodeCamp 09 sobre como podemos evitar los típicos ataques web XSS, Inyección SQL, etc.

Si os interesa el tema no os podéis perder esta introducción 100% práctica de la seguridad web con buenas prácticas.

Apuntaros antes de que se cierren las inscripciones !!!

2f39cfe4-77da-4b2a-a322-b9a6ee133e7a

Microsoft Facebook en mi Windows Mobile 6.1

scr_facebook01

Hace poquito tiempo que he estrenado un nuevo teléfono con Windows Mobile 6.1

Tengo que reconocer que no tengo mucha experiencia con este sistema y me ha costado un poco configurar el acceso a datos del dispositivo.

Pero lo bueno ha sido cuando he querido instalar la versión de Facebook que Microsoft a creado para Windows Mobile para las versiones 6.*

No ha habido manera que utilizará la conexión correctamente y se conectara a internet, he reinstalando una y otra vez la versión castellana, ingles y porque no tenía el chino. Pero finalmente después de navegar mucho he encontrad la versión que conecta y me deja disfrutar de esta aplicación en mi móvil.

Os adjunto los ficheros necesarios.

Aplicación images     Idioma Castellano  images

¿Existe la columna con DataReader?

En mi empresa desde un principio hemos utilizado una herramienta propia para generar la capa de lógica de negocios, adaptada  al 100% a nuestras necesidades  y que ha ido creciendo con el tiempo. Eso nos ha beneficiado en tener controlado en todo momento nuestros objetos de negocio y nos ha evitado tener que hacer un salto obligatorio para utilizar alguno de los ORM que existen en el mercado, como puede ser: Entity Framework, NHibernate, etc.

Nuestra capa de acceso a datos “DAL” encapsula toda la lógica de conexiones a datos independientemente del proveedor y hay una de las funciones que retorna un lector de datos para poder personalizar la lectura de los datos desde la capa de lógica de Negocios.

 /// <summary>
 /// Ejecuta el comando creado y retorna el lector.
 /// </summary>
 /// <returns>El resultado de la consulta.</returns>
 public DbDataReader EjecutarConsulta(string cmd, CommandType tipo)
 {
     this.comando.CommandText = cmd;
     this.comando.CommandType = tipo;
     this.Conectar();
     return this.comando.ExecuteReader();
 }

Eso facilita la carga del objeto de negocio y optimiza la lectura.

DbDataReader reader = null;
Using (Dal dal = new Dal())
{
  string command = "select id, nombre, descripcion from productos";
  reader = dal.EjecutarConsulta(command, CommandType.Text);
  while (reader.Read())
  {
    ...

Pero uno de los problemas habituales que nos encontraremos con el objeto DataReader es que si no nos gusta leer los datos por posición, como es mi caso y preferimos controlar la columna que deseamos leer. Nos podemos encontrar con el horrible error que no se encuentra la columna que estamos intentando leer.

Ya podemos intentar validar si el objeto es null, pero no funciona:

capas

O si el dato está vacio:

capas2

Para poder validar si la columna que estamos consultando existe podemos tener una función en nuestro DAL que valide esta situación utilizando el propio esquena de la tabla:

public bool ValidarColumna( DbDataReader reader, string nombreColumna)
{
   reader.GetSchemaTable().DefaultView.RowFilter = 
     "ColumnName= '"  + nombreColumna + "'";
   return (reader.GetSchemaTable().DefaultView.Count > 0);
}

Finalmente cuando queramos hacer la consulta de los datos utilizaremos el validador para evitar errores no controlados en el acceso a datos.

 using (Dal dal = new Dal())
 {
    string command = @"select id, nombre, descripcion 
";
        from productos
    reader = dal.EjecutarConsulta(command, CommandType.Text);
    while (reader.Read())
    {
      ProductoData produc = new ProductoData();
      produc.ID = (dal.ValidarColumna(reader, "ID") 
        && reader["ID"] != DBNull.Value)?(int)reader["ID"]:0;
      produc.Nombre = (dal.ValidarColumna(reader, "Nombre")
        && reader["Nombre"] != DBNull.Value)
        ?reader["Nombre"].ToString():string.Empty;
      listaProductos.Add(produc);
    }
}

Es una forma un poco rebuscada, pero no conozco ninguna otra forma de verificar esta información.

Espero que os sea útil.

CrossPosting de http://lonetcamp.com