viernes, 30 de noviembre de 2012

[Off-Topic] Javascript – Desde cero hacia las mejores prácticas (Materiales de la charla)


El pasado día 29 de noviembre tuve el placer de dar una charla en el comité sobre JavaScript con el título “Javascript – Desde cero hacia las mejores prácticas”

Aquí os dejo los materiales de la charla por si os pueden resultar de interés.

Descargar materiales

Un saludo

Andoni Arroyo

lunes, 23 de julio de 2012

Como desarrollar con Javascript y no morir (ni matar) en el intento – III


En JavaScript el concepto de Objeto representa un papel clave. Si tenemos en cuenta que no existe el concepto de clase que manejamos en otros lenguajes, es el objeto sobre el que recae la responsabilidad de definir el modelo y almacenar el valor de la instancia.

Una vez interiorizado este concepto, (superado el shock…) debemos tener en cuenta que en JavaScript disponemos de cinco tipos primitivos por valor que son: number, string, boolean, null, y undefined. Todo lo demás son objetos (más o menos especializados)

Estos tipos por valor (exceptuando null y undefined) poseen lo que se conoce como primitive wrapper objects. Los objetos wrapper pueden ser creados utilizando los constructores predefinidos Number(), String(), y Boolean()

Veamos este código al respecto:

   1:          //// number (primitivo)
   2:          var n = 100;
   3:          console.log(typeof n); // "number"
   4:          // objeto Number 
   5:          var nobj = new Number(100);
   6:          console.log(typeof nobj); // "object"

Estos objetos exponen una serie de métodos que nos ayudan a trabajar con la naturaleza de los datos a los que representan. Por ejemplo el objeto Number expone métodos como toFixed() o toExponential o el objeto String los métodos substring(), charAt() o toLowerCase().

Como hemos comentado alguna vez JavaScript es muy propenso a interpretar de la mejor manera que pueda el código e intentar hacer que funcione, con resultados algunas veces imprevistos.

¿Que os parece si os digo que estos métodos pueden ser aplicados también sobre los métodos primitivos por valor?

Pues en principio lo menos que os puede parecer es raro… Bueno, lo que esta ocurriendo detrás de la escena es que JavaScript promociona puntualmente el tipo primitivo a su correspondiente objeto, ejecuta el método y a continuación descarta el objeto creado. Lo dicho, buenas intenciones pero si no conocemos este comportamiento, puede provocar más de un dolor de cabeza…

Por ejemplo, como se nos ocurra la idea de aumentar un tipo primitivo, el interprete de JavaScript no nos arrojará ningún error, puesto que desde el punto de vista sintáctico todo está correcto, pero la propiedad incluida lo será sobre el objeto que se descartará automáticamente con lo que mal negocio hemos hecho.

Veamos un código que ilustra este ejemplo:

 
   1:          // string primitivo
   2:          var enterprise = "Plain Concepts";
   3:          // El primitivo es convertido a un objeto con el fin
   4:          // de ejecutar el método split()
   5:          console.log(enterprise.split(' ')[0]); // "Plain"
   6:          // Si intentamos aumentar un tipo primitivo no es un 
   7:          // error
   8:          enterprise.CIF = "XXXXXXXXXX";
   9:          // pero como el objeto es decartado automaticamente después de
  10:          // la promoción, la propiedad se pierde...
  11:          console.log(enterprise.CIF); // "undefined"​​





Este comportamiento, no ocurriría si instanciamos un objeto del tipo concreto (String(), Number(), Boolean()… ), por lo que si estamos pensando en aumentar el objeto creado no es buena idea usar los primitivos. 

También podríamos usar el constructor Object que incluye cierta lógica para crear el tipo derivado apropiado en base al valor recibido. (Una especie de factory)
 
Por ejemplo:
 

   1:           var n = new Object(3);
   2:           console.log(n instanceof Number); // True


 
Esta característica es un arma de doble filo puesto que nos puede llevar a errores o comportamientos inesperados cuando empleamos tipos dinámicos, por lo que en general se desaconseja su empleo siendo mas aconsejable (por sencilla y certera) emplear la notación literal.
 


 

miércoles, 18 de julio de 2012

Como desarrollar con Javascript y no morir (ni matar) en el intento – II


Cuando trabajamos con JavaScript una de las características que más quebraderos de cabeza nos pueden dar es el ámbito de las variables. Así como en otros lenguajes tenemos la capacidad de definir un ámbito dentro de varios elementos (por ejemplo en C# dentro de una clase, método, usign…) en JavaScript el único elemento que nos permite definir ámbito es el objeto function. (Y digo objeto porque en JavaScript una función es un Objeto, es decir puede tener propiedades y métodos…)

Hoy vamos a analizar un efecto conocido como Hoisting. Este efecto ocurre porque en JavaScript podemos dispersar las declaraciones de nuestras variables a lo largo de nuestra aplicación.

Veamos el siguiente código:

   1:          var name = "global name";
   2:          // global variable 
   3:          function func() 
   4:          {    
   5:              console.log ('name value: ' + name);   // undefined   
   6:              var name = "local name";    
   7:              console.log('name value after assign value: ' + name);  
                                                          //local name
   8:          };
   9:          func(); 

Como podéis ver en este código tenemos una variable “name” con el mismo nombre en el ámbito global y dentro de la función. Como hemos comentado antes, la función nos permite definir ámbito de variables, por lo que la variable “name” es diferente dentro y fuera de la misma.
Si analizamos el código anterior podemos observar que en la línea 5 se accede a la variable “name”. Sería lógico espera que dicha variable tenga el valor “global name” pero aquí entra en juego la característica de JavaScript llamada Hosting

Con este nombre, JavaScript nos permite colocar múltiples “var” en cualquier punto de la función de tal manera que ellos funcionen como si hubiesen sido declarados al principio de la función.

Lo que tenemos que tener en cuenta es que la declaración de la variable se promociona al tope de la función (como si “var name” se colocase antes de la fila 5) pero la inicialización de la misma se ejecuta en el punto definido (la línea 6 en el código anterior). Es por eso que ocurre el efecto comentado anteriormente, es decir, en la línea 5 la variable “name” de la función (“var name”) se ha ejecutado pero no la inicialización de la misma. (Por eso el valor undefined)

Una vez entendido como funciona y con el fin de evitar errores un tanto confusos que disparen el coste de mantenimiento, un buen hábito es asumir la convención de definir todas las variables que vamos a usar al principio de la misma.

martes, 17 de julio de 2012

[Material del evento] Porque debería automatizar mis pruebas?

Os he dejado en mi skydrive el material del evento Porque debería automatizar mis pruebas? que vimos en el Centro de Innovación Social de Bilbao.

Espero que os resulte interesante, un saludo.

Como desarrollar con Javascript y no morir (ni matar) en el intento


Cada día son más las aplicaciones que cuentan con JavaScript como lenguaje de programación.
El motivo de este éxito anunciado es, entre otro, la ubicuidad de este lenguaje, y es que correr en “casi” todos los navegadores instalados a lo largo y ancho del mundo no es poca cosa.

La Web actual requiere cada vez una mayor carga de programación en cliente, hace un uso cada vez más intensivo de las capacidades del mismo (manejo del DOM, AJAX, Almacenamiento en local…) Además existen otros tipos de escenarios donde tradicionalmente JavaScript no tenía presencia (las aplicaciones nativas para Windows, aplicaciones para dispositivos móviles…) que también van convirtiéndose en terreno abonado para JavaScript.
Un claro ejemplo de este cambio ha sido confirmado con la aparición de Windows 8 y su Interfaz Metro. En él, JavaScript se presenta como un lenguaje de cliente de primera clase para desarrollar aplicaciones. Esto lo hace comparable a los hasta ahora intocables lenguajes manejados como C# o VB presentes en WPF o Silverlight.

Este cambio ha sido posible gracias en gran medida a incluir ciertas características que antes formaban  parte de .NET a nivel del Sistema Operativo y, por lo tanto, consumible desde un entorno no manejado como en el que se ejecuta JavaScript. (Internet Explorer)

Además de Metro, en las aplicaciones móviles también JavaScript es bastante común para conseguir reutilización entre plataformas, contando con ciertas artistas invitados como Phonegap

Y es por todo esto que las comunidades de desarrolladores muy versadas en entornos muy avanzados de programación (como la gente de .NET o Java) van aterrizando en JavaScript y en la mayoría de ocasiones su primera sensación viene a resumirse en la muy común frase “vaya m***** es JavaScript”

Bueno pues la realidad es que sin estar al nivel de los lenguajes y marcos de trabajo modernos tampoco es tan malo como al principio creemos. Lo que si es necesario es realizar el esfuerzo de entender las aproximaciones con las que JavaScript afronta algunos de los problemas comunes. Esta tarea es la que vamos a realizar en esta serie de entradas ayudándonos a encajar los conceptos básicos.
Una de las primeras cosas que debemos tener en cuentas es:

“El problema con las variables globales”

Las variables globales (como su nombre indica) son compartidas a través de todo el código de tu aplicación JavaScript o página Web. Esto quiere decir que la superficie de colisión de dichas  variables es sencillamente: toda tu aplicación, con lo cual es relativamente probable definir diferentes variables globales con el mismo nombre pero diferentes propósitos.

Para entender este problema debemos ser conscientes de que JavaScript es esencialmente propenso a ayudar a que nuestra aplicación funcione a costa de no ser (a veces excesivamente) riguroso en sus validaciones (algo mejorado con el uso del strict)

Se dan dos características para la propensión a este problema:
  • En JavaScript podemos utilizar una variable que no hayamos definido
  • Cualquier variable que no hayamos declarado se convierte automáticamente en la propiedad del objeto global
Veamos un ejemplo:

(Tened en cuenta que en JavaScript el unico elemento que nos permite definir ámbito es el objeto fuction)

   1:   
   2:          function sum(x, y) {
   3:              result = x + y;
   4:              return result;
   5:          }
   6:          console.log(sum(2, 4));  // 6
   7:          console.log(result);  // 6

Como podemos observar aunque el ámbito de la variable result se desea limitar a la function sum en la que se emplea sigue viva fuera de la misma.
La regla de oro es aplicar siempre la palabra reservada var. Este mismo código declarando resutl con un var por delante nos daría un bonito:

Uncaught ReferenceError: result is not defined al ejecutar el código de la línea 7

Sencillo ¿verdad?

Veamos otro código muy similar al anterior pero incluyendo el var que aun  así no funciona como esperamos:

   1:          function foo() 
   2:          {    
   3:              var a = b = 0;
   4:          }
   5:          foo();
   6:          console.log(b);

En este caso lo que está ocurriendo es que solo se aplica el var a la variable a, que se está inicializando con el resultado de la asignación de b = 0. Pero con b nos está ocurriendo lo mismo que en el ejemplo anterior, la estamos usando antes de declararla por lo tanto es un variable global
Hay muchos aspectos sobre los que podemos ir comentando particularidades de JavaScript así que estad atentos.

jueves, 12 de abril de 2012

Evento: Porque debería automatizar mis pruebas?


El próximo día 17 de Abril a las 19:00 tengo el placer de dar una charla con el título ¿Porque debería automatizar mis pruebas? dentro del marco de actividades del grupo WebDev Bilbao en el Centro de Innovación Social de Bilbao.

En la misma hablaremos, entre otras cosas, sobre:

  • Cuales son los aspectos más importantes a la hora de automatizar nuestras pruebas.
  • Que podemos aspirar a conseguir con dicha automatización.
  • Candidatos a la automatización.
  • Porque automatizar las pruebas es más que una técnica.
  • Terminología del mundo de las pruebas.
  • Economía de la automatización de pruebas.
  • ROI.
  • Características del buen test.
  • Problemas comunes.
  • Como organizar nuestros tests.
  • Métodos de diseño de tests.
  • Tipos de tests (que no solo existen test unitarios!!)
  • Estrategias de verificación.

Vamos, de todo un poco sobre un tema tan interesante como es el de la automatización de nuestras pruebas.

Os espero por ahí para hacer el evento lo más interesante posible.

lunes, 6 de febrero de 2012

Cambios y expectativas (Plain Concepts +1)

Es tiempo de cambios para mí. Dejo de trabajar en Panda Security para comenzar una nueva etapa en Plain Concepts.

Haciendo balance de mi paso por Panda Security, el resultado es francamente positivo. He aprendido mucho, trabajando en equipos formados por gente muy diferente (alemanes, cubanos, americanos…) lo cual me ha permitido evolucionar como profesional y como persona. Tópico, pero verdad…

Entonces, por que cambiar?

Pues porque es mucho lo que espero de mi nueva empresa:

  • Gestión ágil (de verdad), con todo lo que eso implica.
  • Proyectos interesantes, avanzados tecnológicamente y con requerimientos exigentes.
  • Compañeros motivados, capaces de compartir sus conocimientos y estar abiertos siempre a la mejora. Conozco hace tiempo a mucho de ellos de la comunidad, eventos y otro saraos. Son el tipo de gente con el que da gusto trabajar.
  • Conocer un montón de gente interesante de la que aprender, tanto dentro como fuera de la empresa. Trabajando duro para ser el peor, como comentaba Dawn Cannan en su articulo: Be the Worst en Agile Record)

Un sitio definitivamente donde poder trabajar con alta motivación, que me ayude a evolucionar aportando mi esfuerzo y plantee retos que sean beneficiosos para ambas partes.

Estoy seguro que esto y mucho más va a ser lo que voy a encontrar allí.

Estamos en contacto.

martes, 31 de enero de 2012

Invocando un servicio WCF desde una aplicación Metro (desde la misma máquina!!)


El otro día hablábamos de las limitaciones de comunicación entre aplicaciones Metro y Desktop hospedadas en la misma máquina establecidas en Windows 8. De hecho, hablábamos de la “NO” comunicación entre Metro y Desktop. Los pistoleros más rápidos dirán que donde dije Digo ahora digo Diego, pero esperar un poco antes de apedrearme en la plaza pública…

Comentábamos que por diseño, invocar desde una aplicación Metro a un servicio WCF expuesto en la misma máquina, no está permitido. Esto puede ser una restricción demasiado estricta (y totalmente injustificadas) si estamos desarrollando en la misma máquina el servicio y la parte Metro que la consume.

Para este tipo de casos (y no para saltarnos el control, que no tenéis una idea buena...) contamos con una herramienta de línea de comandos llamada CheckNetIsolation. Podemos leer un poco más al respecto aquí http://msdn.microsoft.com/en-us/library/windows/apps/hh452759.aspx

Acorde a dicha restricción, al acceder a dicho servicio, la aplicación Metro (sin ningún tratamiento previo) recibiremos una excepción del tipo EndPointNotFopundException con un mensaje tal que así:

{"There was no endpoint listening at ... that could accept the message. This is often caused by an incorrect address or SOAP action. See InnerException, if present, for more details."}

Ok, a menos de que creas que la gente de Microsoft va de farol, es lo esperado, no?

Ahora viene lo interesante. Para permitir este tipo de comunicación (recuerda que la limitación solo se aplica a la misma máquina) debes seguir estos pasos:

Lo primero que debemos hacer es buscar en el registro la clave de la aplicación Metro con la que deseamos hacer la excepción. Para ello, abrimos el Regedit y buscamos la clave de la aplicación que cuelga de:

HKEY_CURRENT_USER\Software\Classes\Local Settings\Software\Microsoft\Windows\CurrentVersion\AppContainer

Fíjate en el valor de la propiedad displayname para poder identificarla.
Una vez que sepamos la rama concreta, puedes seleccionarla con el botón derecho y copykeyname y selecciona el nombre de la carpeta del mapping (desde S-1-15... hasta el final). Este <keyname> nos permitirá establecer la excepción más adelante.

A continuación, abre el “Developer Command Promp” y escribe “CheckNetIsolation” para acceder a la utilidad. Pégate una leidita el enlace anterior para evaluar un poco mas en detalle las capacidades de la herramienta.

En nuestro caso debemos escribir:

  • Para ver el listado de las aplicaciones ya excluidas del bloqueo de loopback:
    CheckNetIsolation.Exe LoopbackExempt –s
  • Para incluir nuestra aplicación como una excepción:
    CheckNetIsolation.exe LoopbackExempt -a -p=<keyname>
  • Para comprobar que ya ha sido correctamente incluida, pues vuelve a ejecutar el comando anterior (nunca te lo hubieses imaginado, verdad?)
    CheckNetIsolation.Exe LoopbackExempt –s

Una vez hecho esto, ya podremos consumir servicios de la misma máquina sin recibir la excepción comentada al principio del post, comprobado!!

miércoles, 25 de enero de 2012

Windows 8 y la “NO” comunicación entre Metro y Desktop

Windows 8 va cogiendo forma, y lo que vamos viendo nos confirma que la gente de Redmond está haciendo una apuesta muy fuerte por evolucionar su sistema hacia diferentes dispositivos. Un único sistema operativo para ordenadores y tabletas (dejemos los teléfonos de momento…) implica un profundo replanteamiento del mismo, desde sus cimientos.

Por un lado tenemos un gran hito para Windows 8 es la necesidad de correr sobre procesadores ARM. Por otro lado, Microsoft tradicionalmente se aplica en  maximizar la compatibilidad hacia atrás. Este es un compromiso que tradicionalmente le ha diferenciado de la competencia digamos más “intrépida” en sus evoluciones/revoluciones.

El resultado de aplicar este par de fuerzas, en principio opuestas (compatibilidad hacia atrás VS evolución hacia la ligereza) implica casi tener dos sistemas operativos en uno. Es muy interesante la lectura de este post Windows 8 – A Tale of Two Platforms al respecto.

Siempre que se produce un cambio profundo como este, se generan por un lado un buen montón de riesgos a mitigar así como otro montón de oportunidades a aprovechar. Cuando comenzamos a evaluar la posibilidad de que nuestras aplicaciones corran sobre Windows 8 siempre comenzamos a pensar en los componentes que la conforman y en como ir migrándolos hacia la nueva plataforma.

Quien más quien menos ha oído o va a oír al respecto:
“Este servicio lo dejo igual y desde la interfaz metro lo invoco y...”

Pero en esta aproximación hay un demonio escondido: crea un dependencia de la parte de aplicaciones “Metro” hacia la parte “Desktop” y ese no es el camino que Microsoft fomenta. Tengamos en cuenta que si todos los desarrolladores aplican ese proceso, la parte “Metro” de Windows 8 nunca podrá correr sin la parte “Desktop”. Ese es el precio a pagar por dicha dependencia.

Podemos ver esta división en el siguiente gráfico:
image

Comprobamos que no existe un canal de comunicación oficial por encima del Kernel de Windows (que obviamente, comparten) para realizar comunicaciones entre aplicaciones “Metro” y “Desktop”.

La pregunta (muy común y cada vez más) es clara:
¿Como puedo comunicar entre aplicaciones Metro y Desktop?

La respuesta no es tan clara, pero desde luego no es algo que en principio Microsoft fomente.
El modelo de procesamiento en la nube y clientes ligeros es el candidato por todas las grandes a la hora de llegar a diferentes dispositivos y es también es el que Microsoft promociona. Este escenario ha demostrado su éxito en la competencia y algo sabe esta empresa de aprender de los demás.

Una posible solución (por supuesto depende de la naturaleza de cada aplicación) es llevar toda la lógica de tu aplicación a tu proveedor de Cloud (Azure, Amazon, GAE…) y dejar un cliente bien ligero en “Metro” que consuma de manera optimizada dichos servicios. (Debemos tener en cuenta que en Metro solo se ha migrado la parte de cliente de WCF!!).

Obviamente este modelo también tiene su problemática a resolver, como por ejemplo como comportarse en caso de no tener comunicación.
Con el fin de confirmar las limitaciones de comunicación entre aplicaciones “Metro” y “Desktop” podemos leer:

  • Ale Contenti comentaba que la comunicación entre aplicaciones de ambos mundos es a nivel de archivo. (aunque también dice que es muy pronto para confirmarlo)
    http://channel9.msdn.com/Events/BUILD/BUILD2011/TOOL-789C
  • Otra idea podría ser montar un Servicio Web en la parte Desktop:
    Respecto a eso, podemos leer a Jeff Sanders en los foros de soporte de Microsoft:

    “You cannot access a WebService on the same machine. The WebService would need to be external to the machine ... In Metro you cannot use IPC except with Metro Style applications that are in the same package.”Otro día hablamos de CheckNetIsolation.exe, prometido!
  • Pero estas restricciones de comunicación no solo existen a alto nivel. Podemos leer a Pavel Minaev:

    ”… Named pipes aren't there, for example, nor are memory mapped files. There are sockets (including server sockets), but when connecting to localhost, you can only connect to the same app. You could use normal files in one of the shared "known folders" (Documents, Pictures etc), but that is a fairly crude hack that necessitates polling and is visible to the user.”

A buen entendedor pocas palabras bastan. Podemos ver claro que este canal de comunicación no es el deseado. Y esto es comprensible, puesto que si pensamos un poco en los diferentes escenarios sobre los que deseamos corra Windows 8 podemos observar que:
  • PCs Legacy corriendo Windows 8 donde se ejecutarán aplicaciones Legacy pero no van a aprovechar las bondades de las aplicaciones basadas en interfaces táctil (Metro/WinRT)
  • Tabletas x86 donde podrán correr aplicaciones Legacy que por otro lado, si sacaran el máximo a las aplicaciones metro. Eso si, tendremos que tener en cuenta temas como peso, vida de la batería, coste...
  • Tabletas basadas en ARM donde las aplicaciones Legacy (salvo que Microsoft se saque algo de la chistera...) no van a correr, pero sacarán el máximo de Metro.
Resumiendo podemos decir que Windows 8 tiene dos caras, es muy importante comprender esto para poder afrontar las migraciones y nuevos desarrollos con la perspectiva adecuada al nuevo panorama que se nos presenta.

miércoles, 4 de enero de 2012

POCOs con piel de cordero

Reconozcámoslo, automatizar cualquier proceso es gratifícateme pero no siempre es fácil. Todos alguna vez hemos aparcado muy buenos propósitos (como los año nuevo…) debido a los impedimentos encontrados por el camino.

He sufrido este fenómeno recientemente en una empresa que todos conocemos (y no puedo nombrar ;)) hace bien poquito con un intento de aplicar TDD en los equipo de desarrollo debido a los plazos de entrega tan ajustados que se manejaban.

Sintiéndolo mucho, debemos decir que esto es lo normal.

Afortunadamente igual de normal tener el deseo de mejorar y eso nos impulsa hacia caminos que sabemos van a ser ventajosos. Uno de ellos es automatizar las pruebas en nuestros proyectos. En torno a un 40% del tiempo destinado a un proyecto se dedica a probar, así que invertir en este campo parece una apuesta segura.
Centrándome en el propósito del post (que me voy por las ramas) hace poco he estado trabajando con un equipo que tenía algunas dudas frente a como automatizar las pruebas sobre algunas clases de una determinada funcionalidad.

Poco más o menos la queja era:
Tenemos una clase que no podemos desacoplar (como nos has dado la paliza 100 veces) puesto que .NET me obliga a que herede de otra puesto que lee del fichero de configuración...
Por no entrar a demasiado detalle digamos que tenían unas clases que ellos creían POCO, pero que realmente no lo eran, puesto que tenían unos bonitos atributos que se habian pasado por alto.
La solución del problema fue crear un mock la clase directamente (los frameworks de Mock “modernos” nos permiten hacer esto) y mockear de ciertas propiedades que se estaban consumiendo desde el código para conseguir el nivel de aislamiento necesario y poder realizar las prueba unitaria. Por supuesto, desde la prueba unitaria tuvimos que añadir los mismos atributos que tenía el código real y conseguimos que el test funcionara correctamente.
Lo más interesante de todo esto son las conclusiones que podemos extraer de la experiencia:
Cuando en DDD hablamos de que las clases deben ser POCO es por algo. Todo lo demás es infraestructura. La tecnología es infraestructura. En este ejemplo, esos atributos tan inofensivos, son tecnología y hacen que esas clases aparentemente POCO no lo sean. (se mapean de un fichero de configuración!!)
Por eso digo en el título que estos POCO son lobos con piel de cordero.
La siguiente pregunta es ¿Debemos probar el código de infraestructura?
Pues la respuesta es SÍ. Es parte de nuestra aplicación y debemos probarlo, pero probablemente tengamos una política de testeo diferente. Debemos en la medida de lo posible, hacer que dichos “adaptadores” sean lo más sencillos posibles facilitando su testo.

Podemos decidir alcanzar una cobertura menor en pruebas unitarias y realizar un mayor esfuerzo en pruebas de integración.
Como siempre, la clave del éxito radica ajustar la relación del esfuerzo que nos supone desarrollar (y mantener) una batería de pruebas optima para en contexto (Core Business / Infraestructura…) en el que nos encontramos, con el retorno de valor que de la mismas obtenemos.
Por cierto, feliz 2012 ;)