Desarrollo de aplicaciones híbridas con Ionic Framework

El día de hoy, presentamos los conceptos básicos y las diferentes tecnologías con las que se puede construír una aplicación híbrida para Android/iOS/WP.

Video: http://www.youtube.com/watch?v=cytsFgCHqyM

Links últiles:

ionicframework.com
https://cordova.apache.org/
http://ngcordova.com/
https://nodejs.org/
https://angularjs.org/
http://gulpjs.com/
http://bower.io/
http://sass-lang.com/
http://yeoman.io/
https://github.com/mwaylabs/generator-m

Parámetros globales en peticiones Ajax con jQuery

jQuery nos permite realizar peticiones Ajax a través del método $.ajax(), o alguna de sus versiones más cortas ($.get(), $.post(), etc.). En algunas ocasiones, suele plantearse la necesidad de agregar parámetros de datos globales a todas las peticiones de una misma página. Para resolver este tipo de situaciones, jQuery nos provee el método $.ajaxSetup().

Cabe aclarar que, si bien en este post se menciona al método $.ajaxSetup() como un medio para agregar parámetros de datos globales, también se puede utilizar con otros fines, como por ejemplo, para ejecutar cierto código previo al envío de las peticiones.

Ahora bien, veamos cómo agregar parámetros de datos globales. Una de las opciones es utilizar lo siguiente:

$.ajaxSetup({
    beforeSend: function(jqXHR, settings) {
        settings.data = $.extend(settings.data, { say: 'hello' });
        return true;
    }
});

Uno de los problemas que presenta esta solución, es que no está considerando el tipo de mensaje de la petición. Podemos mejorar un poco el código previo, y hacer lo siguiente:

$.ajaxSetup({
    beforeSend: function(jqXHR, settings) {
        if(settings.type === 'GET') {
            settings.url = ...; // agregar parámetro a la url
        }
        else {
            settings.data = $.extend(settings.data, { say: 'hello' });
        }
        return true;
    }
});

Si bien ahora se están cubriendo más casos, agregar parámetros a peticiones de tipo POST no suele ser tan directo. En definitiva, nuestra solución puede mejorarse para que se aproxime al comportamiento esperado, pero supone trabajar aún más e introducir código.

Vemos así, que recurrir al método beforeSend no nos provee una solución directa, sino que debemos considerar varios casos puntuales. Ahora bien, jQuery nos provee una alternativa más que, a comparación de la solución anterior, es más directa y sencilla.

La otra alternativa consiste en utilizar:

$.ajaxSetup({
    data: {
        say: 'hello'
    }
});

Curiosamente, este método se ejecuta de manera acumulativa y no sobreescribe los datos que tiene la petición, sino que agrega los parámetros de nuestra petición (al final de la URI en caso de un GET). A continuación se pueden ver dos capturas con ejemplos. Una de ellas representa un GET y la otra un POST.

Espero que les sirva de ayuda. Saludos!

 

JavaScript Tip #4–Llaves

Algo que en JavaScript sí importa es la forma en cómo escribimos el texto que hace al código. En este caso, más allá de la sintaxis, la gramática es importante.

function A() {
   return
   { valor = 123 };
}

En el código anterior, algo que podría ser tomado como natural o posible en otros lenguajes, en JavaScript puede ser un problema. Si llamamos a la función A, esta, al finalizar, en vez de retornarnos un objeto con una propiedad llamada “valor”, retornará undefined.

function A() {
   return {
      valor = 123
   };
}

El código anterior puede verse idéntico desde la perspectiva de funcionalidad, pero el colocar la llave de apertura inmediatamente después del return hará que el código funcione como se espera.

Es importante, entonces, siempre colocar las llaves en la misma línea a la cual pertenece.

JavaScript Tip #3–Igualdades

Si estamos acostumbrados a otros lenguajes de programación, en especial aquellos con raíz en C o C++, les puede resultar extraño ver código JavaScript donde aparecen no dos iguales (==) sino tres (===) en el análisis de las condiciones.

JavaScript, para este caso, incluye el operador === (Junto a la variante !==) el cual es recomendado a la hora de comparar dos elementos:

var a = ‘1’;
var b = 1;
if (a == b) { … }

En el ejemplo anterior, a y b serán iguales, ya que JavaScript deberá hacer las conversiones necesarias para poder comparar los dos lados de la igualdad. Esto, por supuesto, consume tiempo.

if (a === b) {
   …
} else {
   …
}

En este caso, la condición será falsa, ya que el tipo de dato no es igual y no se realizarán conversiones para verificar la igualdad.

JavaScript Tip #2–Clases

Sí, sabemos que (Aún) las clases como tales no existen, y tampoco una sintaxis o nomenclatura. Por lo que, para hacer algo similar, usamos funciones que contiene otras funciones dentro.

El siguiente suele se un caso típico:

function ClaseA() {
   this.funcion = function () {
   };
}

Luego, al crear una instancia de ClaseA obtenemos un objeto más o menos clásico si lo vemos desde la óptica de lenguajes tipados.

Pero JavaScript tiene otra forma de hacer las cosas que es más… JavaScript.

var ClaseA = (function () {

   var claseA = function () { };

   claseA.prototype.funcion = function () { };

   return claseA;
})();

El modelo anterior hace uso de prototype para crear nuevos puntos de entrada y encapsula de mejor forma (Además de se más óptimo) la pseudo clase y las funciones dentro de ella.

Windows Azure: Independizando del ambiente la configuración WIF en el “service package”

Supongamos el siguiente escenario:

  • tenemos un WebRole configurado con WIF para usar wsFederation
  • tenemos la sección “identityModel” del web.config de la siguiente manera:

<system.identityModel>
<identityConfiguration>
<certificateValidation certificateValidationMode=”None” />
<issuerNameRegistry type=”System.IdentityModel.Tokens.ValidatingIssuerNameRegistry, System.IdentityModel.Tokens.ValidatingIssuerNameRegistry”>
                            <authority name=”https://youracsdev.accesscontrol.windows.net/”>
                                <keys>
                                      <add thumbprint=”AAAAAABBBBBBCCCCCDDDDDEEEEEFFFFFFGGGGG” />
                                </keys>
                                <validIssuers>
                                    <add name=”https://youracsdev.accesscontrol.windows.net/” />
                                </validIssuers>
                           </authority>
                   </issuerNameRegistry>
           </identityConfiguration>
</system.identityModel>

  • creamos el “service package” (*.cspkg) para el ambiente de “staging” de nuestra cuenta de Azure
  • desplegamos el paquete. Luego de hacer un “smoke test” sobre la aplicación, “movemos” el paquete al entorno productivo
  • allí, queremos cambiar nuestro ACS: es decir, re-apuntarlo al ACS productivo

Aquí es donde el SDK de Azure no nos brinda opción alguna para realizar esto. Desde una perspectiva de “configuration management”, no podemos cambiar el web.config de las instancias (salvemos el poco prolijo caso de remotear la instancia y cambiarlo a mano directamente en disco). Lo que nos brinda la Azure Management Console
es acceso para modificar el llamado “Service definition file” (.csdef), ingresando a “Cloud services” en el menú de la izquierda, ingresan luego al cloud service que desean configurar,  y después click en “configure”. Esto les brinda una UI para poder modificar los valores que existen en el Service definition file (reiniciando el rol una vez que esto ocurre).

Pero este archivo no tiene un esquema definido para configurar WIF.

La solución?

Debido al pipeline de ejecución del WebRole al momento de iniciarse, podemos, en el RoleEntryPoint.OnStart modificar el web.config, es decir, modificar los nodos de “system.identityModel” (usando el namespace System.Xml.Linq, por ejemplo), basándonos en el “service definition file” correspondiente para el ambiente en el que estamos ejecutando el deploy.

Así, podemos tener en el .cscfg, tres settings como estas:

<Setting name=”TrustedIssuersThumbprint” value=”AAAAAABBBBBBCCCCCDDDDDEEEEEFFFFFFGGGGG” />
<Setting name=”TrustedIssuerName” value=”https://youracsdev.accesscontrol.windows.net/” />
<Setting name=”ValidIssuerName” value=”https://youracsdev.accesscontrol.windows.net/” />

y estas settings cambiar según el ambiente: *.dev.cscfg, *.qa.cscfg, etc.

Luego de ejecutado el OnStart, el web.config quedará con los valores correspondientes, listo para la ejecución del HttpApplication.Application_Start

Extendiendo objetos en JavaScript

Muchos lenguajes cuentan con la posibilidad de extender la funcionalidad de objetos nativos o creados por programadores.

Por ejemplo, en C#, podemos “inyectar” funcionalidad mediante los Extendend Methods (http://msdn.microsoft.com/en-us//library/bb383977.aspx) a objetos pre existentes. Pero es necesario remarcar que esta característica (En el caso de C#), es solo una forma de alivianarle el trabajo al desarrollador mientras escribe código, ya que por detrás, el código se ejecuta de la misma forma que lo haría si llamásemos a una función dentro de una clase estática.

Veamos un ejemplo:

class Program
{
    static void Main(string[] args)
    {
        string text = “”;
        Console.WriteLine(text.ToSomething());
        Console.WriteLine(Ext.ToSomething2(text));
        Console.ReadLine();
    }
}

public static class Ext
{
    public static string ToSomething(this string data)
    {
        return data + “Hola”;
    }

    public static string ToSomething2(string data)
    {
        return data + “Hola”;
    }
}

En este caso, si vemos el código en la clase Program, todo apuntaría a que tenemos una mejora con el método extendido, ya que no necesitaríamos conocer la función en cuestión, misma que es provista desde el tipo de dato y, por otro lado, la función “ToSomething” queda incorporada al tipo.

Pero, si miramos un poco más adentro, esto es, el código IL, veremos que en realidad, no pasa nada de nada. Todo sigue funcionando como si hubiésemos llamado a una función común.

IL_0000:  nop
IL_0001:  ldstr      “”
IL_0006:  stloc.0
IL_0007:  ldloc.0
IL_0008:  call       string Extendend.Ext::ToSomething(string)
IL_000d:  call       void [mscorlib]System.Console::WriteLine(string)
IL_0012:  nop
IL_0013:  ldloc.0
IL_0014:  call       string Extendend.Ext::ToSomething2(string)
IL_0019:  call       void [mscorlib]System.Console::WriteLine(string)
IL_001e:  nop
IL_001f:  call       string [mscorlib]System.Console::ReadLine()
IL_0024:  pop
IL_0025:  ret

O sea, no hemos enriquecido el objeto, solo hemos agregado soporte visual.

En JavaScript, por el contrario, es posible inyectar funcionalidad a los objetos y que estas sean parte del objeto, tanto para uno particular como para todas las “instancias” del mismo tipo.

Esto podemos conseguirlo con el uso de “prototype”. Pero veamos un ejemplo:

var arr = [];
//Llenamos el array


//Buscar un elemento
for (var i = 0; i < arr.length; i++) {
   if (arr[i] === …) {
     founds.push(arr[i]);
   }
}

En el ejemplo, lo que intentamos hacer es obtener un elemento de un array basados en un criterio particular. La lógica resulta simple, y podría ser encapsulada en una función y así usarse tantas veces como se requiera.

Por supuesto, podríamos hacer esto, o extender el objeto Array para que contenga esta funcionalidad.

if (Array.prototype.where === undefined) {
    Array.prototype.where = function (selector) {
        var result = [];
        for (var i = 0; i < this.length; i++) {
            if (selector(this[i])) {
                result.push(this[i]);
            }
        }
        return result;
    }
}

La principal diferencia, comparada con una función y con el ejemplo de C# es que, en este caso, efectivamente el objeto Array posee, ahora, una función llamada “where”, y cualquier instancia de Array contendrá la misma, no repitiendo el código si no, incorporándolo al objeto.

En resumen, en JavaScript, es posible modificar los objetos y tipos más allá de un cambio visual de cara al desarrollador. Esto nos otorga mayor flexibilidad para desarrollar ya que no es necesario tener un conjunto de funciones para tareas sobre objetos específicos, si no que podemos enriquecer estos objetos de forma directa.

Objetos eficientes en JavaScript

Hablemos de objetos

En JavaScript resulta relativamente fácil crear objetos. Sin tanta sintaxis decorativa, una simple función puede hacer el trabajo:

var A = function () {
}

var B = new A();

Y con esto, ya tenemos una “instancia” de A en B. Nada complicado en absoluto. Pero veamos que pasa a medida que agregamos algunas funciones internas.

var A = function () {
var self = this;
this.f1 = function () {};
}

var B = new A();
var C = new A();

En este caso, tal vez no notemos diferencia alguna, pero existen, y pueden ser causantes de pequeños grandes problemas que no notemos hasta que sea tarde, y que no nos demos cuenta de cómo solucionarlos.

El problema

El problema radica en que, para el puntero “f1”, estamos asignando una función anónima particular. Esto quiere decir que B y C tendrán, cada una de ellas, su propia función anónima apuntando a f1, por lo que, mientras más objetos de A creemos, más funciones anónimas tendremos. Aunque la función sea exactamente la misma.

Una forma de resolverlo

Podemos resolver este problema con algo de sintaxis más orientada a JavaScript y menos a la programación orientada a objetos clásica.

La clave es “prototype”. Aunque no pretendo meterme en el fango tratando de explicar todo lo relacionado a este concepto (Tal vez en otro momento), si lo usaremos para solucionar el problema planteado.

var A = (function() {
var _a = function () {};

_a.prototype.f1 = function () {};

return _a;
})();

De cara a la instanciación de nuevos objetos no tendremos que hacer nada. Ahora, el truco está dentro de la función que hemos creado.

En este caso, la variable A, que contendrá la firma de nuestra “clase”, recibe el resultado de la ejecución de una función anónima. Notemos que la función está contenida entre paréntesis y al final de la misma se ejecuta su contenido con el uso de (). Este tipo de declaraciones hace referencia a funciones auto ejecutadas. Las mismas se ejecutarán una única vez, alojando su contenido en la variable A. Por lo que instancias de A no generarán una sobrecarga de ejecuciones.

Entonces, JavaScript ejecutará la función anónima en el mismo momento que lea el código, retornando _a.

_aes una variable interna que representa el objeto en sí. O sea, el que posee la firma de nuestra clase. En la primer línea vemos que _a apunta a una función anónima. Teniendo esto, y mediante el uso de prototype, podemos crear entradas a _a, que serán compartidas por todos los objetos creados de A.

En definitiva, al usar prototype solo tenemos UNA única función y todas las instancias de A usan la misma referencia o apuntan a ella sin duplicar la funcionalidad.

Como resumen rápido podemos decir que, cuando trabajamos con JavaScript, podemos caer fácilmente en el consumo de memoria sin necesidad, sin que nos demos cuenta. Y que necesitaremos conocer algunos trucos para poder optimizar nuestro código.

En este caso, la palabra clave es “prototype”, que no solo nos salvará en estos casos, si no que en muchas otras.