Knockout: bindear booleano a radio button

Knockout JS es un framework realmente útil para hacer páginas web dinámicas. Últimamente he tenido la oportunidad de utilizarlo bastante y, siendo un total inexperto, puedo decir que facilita mucho las cosas y tiene una excelente documentación.

Sin embargo, recientemente me encontré en una situación en la que tuve que invertir bastante tiempo para conseguir hacer funcionar un binding entre un par de radio buttons, una propiedad JavaScript del viewModel de Knockout y la correspondiente propiedad en el modelo MVC que recibía mi acción del controlador.

El error

El error se manifestaba simplemente no funcionando el binding entre mi propiedad JS del viewModel y los correspondiente radio buttons. En un primer momento el binding parecía ir bien, pero al enviar la página de vuelta al servidor y retornar al mismo punto por existir algún error en la validación del modelo MVC, el binding no saltaba y los radio buttons no se marcaban según los valores que el usuario hubiera elegido.

La razón

Los radio buttons definen sus valores como strings mientras que la propiedad del modelo MVC era booleano. Entre medias Knockout intentaba “lidiar” entre ambas, pero al recibir el modelo MVC de vuelta tras la validación, su valor booleano no bindeaba correctamente con los radio buttons por ser sus valores cadenas en lugar de booleanos también.

La solución

Probablemente haya múltiples, pero en mi caso la más sencilla fue utilizar un binding custom entre los radio buttons con valores string y la propiedad JS del viewModel.

https://gist.github.com/javierholguera/7bad4fa6e6a4e1aa2ffb

Utilizando un interceptor entre los valores que llegan de los radio buttons y la propiedad, podemos convertir en ambos sentidos entre booleanos y strings convenientemente.

El custom binding se aplica sobre el binding “checked” habitual de los radio buttons, de forma que podemos reaprovechar todo el mecanismo ya existente.

Referencias

StackOverflow – Knockoutjs (version 2.1.0): bind boolean value to select box

Por qué hacemos self = this en JS?

Cuando empecé a utilizar Knockout JS, descubrí que existía una cierta convención según la cual, al crear la función Constructor del modelo que se “bindea” con Knockout, la primera línea siempre era la siguiente:

var self = this;

No tenía ni idea de porqué se hacía esto, pero entendía que era necesario para, posteriormente, poder definir y añadir los distintos métodos y propiedades que formaban el modelo.

Ahora, gracias a los vídeos de “JavaScript The Good Parts” de Douglas Crockford en Pluralsight, por fin sé el porqué de esta misteriosa pero indispensable línea. Y las razones son realmente dos.

Una función anidada no tiene acceso al this externo

Como bien explica Douglas, cuando dentro de una función definimos otra función, la función anidada no tiene acceso al puntero this que la función externa ha recibido.

Para superar esta limitación, en ocasiones veremos código en el que se define una línea como la siguiente.

var that = this;

Con esto lo que conseguimos es capturar en la función superior el puntero this, para posteriormente permitir a la función anidada acceder a la variable that que contendrá el mismo valor que contenía this cuando fue capturado.

Exactamente la misma técnica es la que estaremos aplicando al capturar this en una variable de nombre self. De esta forma las distintas funciones que crearemos como parte de la definición del modelo, podrán acceder al this que originalmente recibió la función constructora.

Pero, por qué querríamos acceder a ese this original que la función constructora recibe? Aquí entra en juego el segundo principio que define esta técnica.

La función constructora recibe el nuevo objeto en this

Esta es la otra clave de esta técnica. Cuando una función se invoca con el operador new (como hacemos al crear el modelo), se crea un nuevo objeto y se asigna al puntero this que recibe la función que estamos invocando con el operador.

Esto a efectos prácticos significa que el this que recibiremos en la función constructora es el propio nuevo objeto al que estaremos añadiendo propiedades y métodos como parte del código de dicha función.

De este peculiar modo nuestra función constructora no sólo inicializa el objeto como haría un constructor de un lenguaje estático como Java o C#, sino que también añade la propia funcionalidad al asignar funciones y propiedades.

Routing with WCF

Today we face a problem in Production environment. We needed to route some WCF requests from one “publicly visible” server to an internal one. A typical routing scenario.

Fortunately these requests were received in a WCF service and this technology has a built-in routing feature since 4.0 version. To use it we don’t need to change any code, it is enough to modify the app.config/web.config of the services. Here we can see how to use it, step by step. All these XML code will be place inside system.serviceModel tag

First Step – Define the new Service

We have to define a new Routing service that will receive all the requests. It will, later, internally dispatch them depending on certain routing rules. The XML necessary is:

<services>
  <service name="System.ServiceModel.Routing.RoutingService" behaviorConfiguration="routerConfig">
    <endpoint address=""
              binding="basicHttpBinding"
              contract="System.ServiceModel.Routing.IRequestReplyRouter"
              name="reqReplyEndpoint" />
  </service>
</services>

Two things that we may notice:

  • The services needs a behavior configuration. In this configuration, later, we will define the routing table.
  • We don’t define an address because we assume the service will be deployed in a IIS server. If we want to do some tests with Casinni, we will need to define an address.

Second Step – SVC hosting file for the new service

Since WCF 4.0 we don’t need the SVC files to host a WCF service, we can define them in app.config/web.config and the internal plumbery of WCF/IIS is smart enough to allow us calling the corresponding URL as if the SVC file really exists. This is the XML necessary for that:

<serviceHostingEnvironment>
  <serviceActivations>
    <add relativeAddress="RiskManagementServiceUAT.svc" service="System.ServiceModel.Routing.RoutingService, System.ServiceModel.Routing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
  </serviceActivations>
</serviceHostingEnvironment>

Two more points to consider:

  • The relative address must contain an extension. For example, if we define it as “RiskManagementService.UAT”, without SVC extension, it will fail.
  • The service needs to specify the complete qualify name in this case, but it is not usual. In other projects that we have used this “virtual SVC” system, it was not necessary. Apparently there is some kind of limitation with the RoutingService.

Third Step – Service behavior configuration

We referenced a service behavior when we defined the service in step 1. Below we can see that configuration, that will need to indicate what routing table we have to use.

<behaviors>
  <serviceBehaviors>
    <behavior name="routerConfig">
      <serviceMetadata httpGetEnabled="true" />
      <serviceDebug includeExceptionDetailInFaults="true" />
      <routing routeOnHeadersOnly="false" filterTableName="routingTable" />
    </behavior>
  </serviceBehaviors>
</behaviors>

Things to consider here:

  • Be sure the name of the behavior matches what you set when defined the service.
  • serviceMetadata may not be necessary in a production environment, if you don’t expect new clients to be created from your service WSDL.
  • serviceDebug MUST NOT be activated in production environment. It is a security risk.
  • In the routing tag we will indicate the name for the routing table to be used in this RoutingService service.

Fourth Step – Routing table

We are getting close to the end… We need to define the routing table. There is complex patterns that we may want to follow, like taking into account headers or contents in the messages. It is really useful for versioning, load-balancing and similar stuff. However, in our concrete scenario we only want to redirect all messages to the internal server, so we didn’t need a complex solution. This was our table:

<routing>
  <filters>
    <filter name="matchAll" filterType="MatchAll" />
  </filters>

  <filterTables>
    <filterTable name="routingTable">
        <add filterName="matchAll" endpointName="RiskService" />
    </filterTable>
  </filterTables>
</routing>

Three important points here:

  • Under filters tag we will define all possible filters. In this case we use the MatchAll filter. In bibliography there is a link for all filter types in WCF.
  • Under filterTables tag we define all the possible tables. We may have different tables for different routers. In our case, we define a “routingTable” in the service behavior in Step 3 and here it is.
  • As part of every table we will bound filters with endpoints. This is a very flexible approach, we can define as many possible filters as we may need for all our endpoints and later just correlate them in the filter table.
    • filterName will be the name of the filter to apply.
    • endpointName will be the name of the endpoint where the message will be routed when the filter is matched. This endpoint corresponds to a new element defined in the next step.

Fifth Step – Client endpoints

The router is a sum of input messages, routing logic and destination services. We have defined 2 of 3. In this point we will define what services will receive the messages once the routing is done. Here it is is the XML.

<client>
  <endpoint name="RiskService"
            address="http://appserver5/RiskManagementTool/RiskManagementService.svc"
            binding="basicHttpBinding"
            contract="*" />
</client>

So what do we have here? Just being “client” of the service where we want to send messages under certain criteria defined in Step 4. Pay attention to the name that we give to the endpoint, because this name must match the value for endpointName in the entries of the filter table defined in Step 4.

Conclusions

WCF is not a easy technology, but it is really powerful and, with enough knowledge and patience there is a great number of scenarios that you can cover with just defining appropriate XML configuration. No coding, no compiling, no deploying, just playing with the app.config/web.config and you get a very powerful Routing Service that is able to route base on headers, message content, protocol, etc.

Bibliography

8 señas de una Aplicación Metro (II)

Siguiendo con la serie iniciada hace un par de días sobre las señales de identidad de una aplicación Metro, hoy continuo con la segunda entrega.

Rapidez y Fluidez (Fast & Fluid)

Este es uno de los aspectos más importantes del diseño de una Aplicación Metro y, en general, de una aplicación táctil. Se basa en cuatro importantes bases.

El rendimiento es más importante todavía en una aplicación táctil, puesto que no existe un nivel de indirección como ocurre con el ratón o con el teclado. Una aplicación táctil que no responde inmediatamente hace sentir al usuario que su máquina está muerta.

También es muy importante el uso de animaciones para elevar la percepción de calidad de la aplicación por parte del usuario. Permite elaborar interfaces fluidas en las que los elementos vienen de algún lugar y van a otro. Por suerte contaremos con una amplia colección de animaciones en WinRT, con las que gratis y sin complicaciones podremos añadir ese toque de calidad a nuestras aplicaciones Metro.

El tercer y último punto donde se asientan el principio de Fast & Fluid es la definición de un nuevo lenguaje para la interfaz táctil. Utilizar estos gestos bien conocidos ayudará al usuario a familiarizarse con la interfaz de la aplicación muy rápidamente, lo que redunda en beneficio de la propia aplicación. En la imagen inferior podemos ver los nuevos gestos.

image

Para terminar, las aplicaciones Metro se deben diseñar pensando primero en el interfaz táctil. Por otra parte, si se utilizan los controles estándar que aparecen con Windows 8, será posible tener también una interfaz 100% usable con teclado y ratón, “gratis”. Es importante, sobretodo, no separar las interfaces táctil y de ratón, creando bases de código distintas para ambas.

Otras entregas

8 señas de una Aplicación Metro I: Diseño con Estilo Metro (Metro style design)

[Metro] Diseño Metro–Principios y Personalidad

Rebuscando por los muchos e interesantes vídeos que hay en Channel 9 del Build de Septiembre ‘11 encontré éste, en el que se describen los principios sobre los que se fundamenta el estilo de diseño Metro.

En el vídeo se explica que Metro tiene 3 influencias clave:

  • Diseño Moderno (Escuela Bauhaus), que se centra en eliminar todo lo que resulta innecesario en un diseño se centra en la funcionalidad. En su momento esta corriente surgió como reacción ante el sobre-adorno, algo que podría justificarse también hoy en día viendo el nivel de “glossy” de algunas interfaces.
  • Estilo tipográfico internacional (Diseño Suizo): en este aspecto son 4 las razones a destacar.
    • Tipografía clara, limpia, alto contraste, colores planos
    • Simetrías y jerarquías
    • Lenguaje universal
    • Fotografías en lugar de ilustraciones o gráficos, para aportar realidad
  • Diseño en Movimiento (Motion), que permite darle vida al resultado.

Estas 3 influencias clave terminan fundamentando los 5 principios sobre los que se sustentará Metro:

  • Orgullo del trabajo detallista, casi artesanal.
  • Rapidez y fluidez.
  • Auténticamente digital. El mejor ejemplo lo tenemos en los nuevos iconos.
  • Hacer más con menos.
  • Ganar como uno, adaptándose, por ejemplo, a las estructuras que predefine Windows 8. Aporta homogeneidad y coherencia.

En fin, si queréis saber más de cada punto, tendréis que ver el vídeo Smile

8 señas de una Aplicación Metro (I)

Durante el Build Jesen Harris, del equipo de Experiencia de Usuario de Windows, impartió una de las charlas más interesantes. En ella explicó las 8 señas de identidad de una Aplicación Metro.

Estas 8 señas son las siguientes:

  • Diseño con estilo Metro
  • Rapidez y fluidez
  • Partirse y redimensionarse con belleza
  • Utilizar los contratos adecuados
  • Invertir en un gran “Tile”
  • Sentir la aplicación conectada y viva
  • Mover datos a la nube
  • Abrazar los principios de Metro

En este post y sucesivos posts iremos analizando qué significan estos principios y cómo se traducen tanto desde un punto de vista de diseño, como de programación.

Diseño con Estilo Metro (Metro style design)

Las aplicaciones Metro van a tener una “silueta” común, entendida como una serie de principios y guías de estilo que todas deberían respetar para evitar que el usuario sienta incomodidad al pasar de una a otra.

Seguir este estilo resultará sencillo gracias a las plantillas y otros recursos que vamos a tener a nuestra disposición. Bellas tipografías, espacios entre elementos estándar, etc. Todo ello podremos lograrlo con poco esfuerzo. Con estas plantillas tendremos aplicaciones armoniosas con el estilo Metro y entre ellas.

Otro punto importante de las aplicaciones Metro es primar el contenido sobre el “chrome” o marco, entendido como la ventana y toda su decoración y elementos. Este tipo de aplicaciones clásicas de Windows seguirán teniendo su espacio para aplicaciones ricas orientadas a escritorio, teclado y ratón.

Otro punto a considerar son los bordes de la aplicación, que van a coincidir con los bordes de la pantalla puesto que las aplicaciones Metro se ejecutan a pantalla completa por defecto. Los bordes izquierdo y derecho van a ser para el sistema operativo, siendo el izquierdo el encargado de mostrarnos las ventanas ya abiertas y el derecho los “charms” principales.

Sin embargo los bordes superior e inferior son para que la aplicación haga el uso que crea conveniente de ellos. En estos bordes las aplicaciones deben poner la mayoría de sus comandos en barras en estos bordes, barras que aparecerán y desaparecerán dinámicamente y que evitarán estropear el contenido. Por supuesto aquellos comandos que tengan un uso muy habitual deben ir a la ventana principal como siempre.

Otro aspecto a tener en cuenta es que estas aplicaciones van a utilizarse en muchas ocasiones con los dedos a través del interfaz táctil, por lo que es recomendable seguir algunas pautas, como colocar controles en los bordes, que son lugares mucho más accesibles según los estudios de usabilidad realizados por Microsoft.

Otras Entregas

8 señas de una Aplicación Metro II: Rapidez y Fluidez (Fast & Fluid)

Instalar Windows Developer Preview

Ahora que se acerca el lanzamiento de la nueva versión de Windows 8 (sorprendentemente bautizada como Windows Consumer Preview, ¿dónde han quedado las “betas”?) es un buen momento para recapitulizar cómo podemos instalar una de estas versiones de evaluación junto con nuestro Windows 7 de trabajo diario, sin llorar por la pérdida de información.

Distintas opciones

Existen varias opciones para instalar Windows Developer Preview, tal como nos enumera Scott Haselman en este post de su blog. A la sazón serían:

  • Solución de virtualización, como VMWare o Virtual Box.
  • Instalarlo en una máquina en solitario.
  • Quitarle el disco duro a una máquina y meter uno nuevo para instalar en él.
  • Arranque dual.
  • Arrancar con hardware real usando VHD (Virtual Hard Disk).

Coincido con Haselman en que la última es la mejor de todas las opciones, puesto que es la única que nos garantiza un rendimiento muy cercano al de una instalación directa contra el “hierro”, al tiempo que nos ahorra todos los inconvenientes de hacer una instalación 100% real.

Pasos

Veamos qué pasos tenemos que seguir para hacer esta instalación con tecnología VHD

Paso 1 – De ISO a USB

Lo primero será descargarse la ISO y pasarla a formato USB para que podamos pincharla en la máquina antes de empezar su instalación. Microsoft tiene una aplicación para hacer este paso muy sencilla y funcional llamada “Windows 7 USB/DVD download tool”. No os dejéis engañar por su nombre rimbombante, no es más que una aplicación que “descomprime” ISOs en un pinchos USB para poder usarlos en instalaciones de estas características.

Choose Media Type

Paso 2 – Crear el fichero VHD

VHD funciona con ficheros que simulan un disco duro sobre el que se realizar toda la instalación y funcionamiento del sistema operativo. Desde una consola de MS-DOS lanzada con privilegios de Administrador tendríamos que escribir “diskpart” para lanzar la consola de creación de ficheros VHD, que tendrá un aspecto similar al siguiente.

image

Una vez en esta consola estos son los comandos que tenemos que introducir:

// maximum indica la cantidad máxima de GBs del disco

create vdisk file=d:VMsWin8.vhd type=expandable maximum=60000

 

// seleccionamos el nuevo "disco" para trabajar con él

select vdisk file=d:VMsWin8.vhd

 

// nos "atachamos"...

attach vdisk

 

// ... y creamos una partición primaria

create partition primary

 

Con estas pocas líneas ya tendríamos preparado el disco en formato fichero sobre el que vamos a realizar la instalación. Es importante que lo creemos en un disco duro real en el que tengamos espacio suficiente para la máxima expansión que puede alcanzar. De lo contrario tendríamos errores en tiempo de ejecución cuando el VHD intente expandirse en el disco duro real y no exista espacio disponible.

Paso 3 – Instalación

Los siguientes pasos son los habituales: pinchar el USB, seleccionar el arranque desde el pincho en el correspondiente menú que todas las BIOS nos ofrecen y esperar a que Windows termine de cargar los ficheros que necesita para empezar la instalación. Tan pronto lleguemos a la pantalla en que se los da a elegir dónde queremos instalar el sistema operativo, tendremos que pulsar “MAYUSCULAS” seguido de “F10”. Esto hará aparecer una consola en la que podremos seleccionar nuestro fichero VHD creado anteriormente y “cargarlo” para que se convierta en una de las unidades disponibles para la instalación. En las siguientes fotos nos lo enseñaba bien Haselman. Primero, el listado de las unidades disponibles para la instalación antes de cargar el VHD.

foto_instalacion_antes

En la ventana de Consola que se ve en la imagen introduciríamos los siguientes comandos para “cargar” el VHD.

// seleccionamos el disco con la ruta que creamos antes

select vdisk file=d:VMsWin8.vhd

 

// nos "atachamos"

attach vdisk

 

Una vez hayamos hecho esto, volvemos a la ventana de selección de unidad y refrescamos con el botón correspondiente. Y tal como se puede ver en la siguiente imagen, tendremos una nueva unidad disponible para hacer la instalación sobre ella; la unidad representada por el fichero VHD.

foto_instalacion_despues

Seleccionaríamos esta unidad y continuaríamos con el proceso normalmente, incluso aunque recibamos algún aviso sobre la posibilidad de que no se pueda arrancar el sistema desde la unidad seleccionada. No debemos preocuparnos por esto, debemos seguir adelante hasta que se nos solicite reiniciar, momento en el que retiraremos el pincho USB y procederemos.

Paso 4 – Arranque Dual

Windows Developer Preview es lo suficientemente listo para instalarse como gestor de arranque y dejarnos asombrados al comprobar que, por fin, Windows tendrá un sistema de arranque gráfico y vistoso, no basado en consolas de MS-DOS como hasta ahora. En la siguiente imagen puede verse.

booting

Conclusión

La instalación no puede ser más sencilla y es, además, muy rápida, como todo lo que viene con Windows Developer Preview. No esperes más para empezar a “cacharrear” con el sistema operativo más esperado en los últimos años.

Bibliografía

Scott Haselman – Guide to Installing and Booting Windows 8 Developer Preview off a VHD (Virtual Hard Disk)

Cómo suprimir errores en proyectos de DB

Últimamente estoy teniendo que pelearme mucho con proyectos de bases de datos de Visual Studio y no puedo decir que lo esté disfrutando.

Sin embargo he de reconocer que una de las cosas más interesantes que tienen es la posibilidad de compilar y analizar estáticamente el código TSQL de estos proyectos, como si se trata de código C# o VB.NET.

Siendo como es una ventaja para escribir código primero correcto y, posteriormente, más óptimo y, en general, de mejor calidad, en ocasiones cabe la posibilidad de que queramos hacer caso omiso a los warnings y errores que nos lanza.

A diferencia de sus equivalentes en código procedural, con los proyectos de base de datos no tenemos ni directivas pragma ni atributos SuppressMessage que nos permitan ignorar estas advertencias. Sin embargo no estamos perdidos del todo, tenemos dos posibles estrategias a seguir:

Fuerza bruta

Si eres de los que no le importa usar la fuerza bruta para resolver sus problemas lo más rápido posible, ésta es tu opción: simplemente eliminar todos los errores del tipo para todo el proyecto.

En la siguiente imagen se pueden ver las propiedades del proyecto de base de datos, en concreto la pestaña de Build. En ella podemos introducir los números correspondiente a las reglas que queremos ignorar para el proyecto completo.

image

El modo preciso

La desventaja clara de la opción anterior es que perderemos ese tipo de avisos para posteriores errores que pudiéramos introducir en el proyecto. Sería mucho más práctico si pudiéramos reducir el alcance de la supresión a, por ejemplo, un único fichero, sabiendo que en los proyectos de bases de datos cada fichero contiene un único objeto de la base de datos.

Pues bien, por suerte es posible y además es muy sencillo. Basta con pinchar en el fichero deseado y mostrar las propiedades del mismo. Veremos una caja de texto denominada “Suppress Warnings” en la que podremos introducir el código que representa la regla a suprimir. En la siguiente figura se puede ver.

image

Gracias a esta opción podremos seguir recibiendo los avisos de este error en otros ficheros en los que nos equivoquemos.

El Patrón Promise

El patrón Promise es precisamente nuevo, pero está creciendo en popularidad a raíz del gran uso que se hace de él en la API de WinJS, el wrapper JavaScript para hacer a la nueva API WinRT en Windows 8. El objetivo de este patrón es facilitar el modelado de procesos asíncronos, de forma que el código que consuma operaciones que no van a retornar inmediatamente sea lo más legible y fácil de escribir posible.

Escenario actual

La asincronía está de moda. La Nube, aplicaciones “responsivas”, etc. Todo parece empujar a los desarrolladores a hacer un uso cada vez mayor de este tipo de construcciones programáticas. Microsoft ha decidido hacer una apuesta decidida por la asincronía en las aplicaciones Metro con Javascript, por muchas razones.

En primer lugar hay que tomar en consideración también el hecho de que JavaScript sea un lenguaje de ejecución basado en un único hilo, lo que hace que cualquier tarea de larga duración congele la interfaz gráfica, con la consiguiente mala imagen para la aplicación frente al usuario. Además, la visión de Microsoft con respecto a las aplicaciones Metro se basa en fluidez, rapidez de respuesta y sensación de inmediatez, de ahí que la asincronía pase de ser una característica deseada a una obligación absoluta.

Por estas razones Microsoft ha decidido ofrecer versiones asíncronas de la gran mayoría de llamadas al sistema que WinRT pone a disposición de los desarrolladores. Estas llamadas van a implementar, en su gran mayoría, el patrón Promise, para simplificar su uso asíncrono.

Pero, ¿cómo es este patrón? ¿Qué características tiene y cómo podemos usarlo? Veámoslo.

El Patrón

Promises/A es el nombre del estándar detrás de este patrón. En él se propone que los objetos Promise tengan una propiedad then que será una función con tres parámetros:

  • Handler para gestionar el resultado satisfactorio.
  • Handler para gestionar los errores.
  • Handler para gestionar el progreso de la operación.

Al retornar un objeto promise la función estará “prometiendo” retornar un valor en algún punto del futuro próximo.

Esta implementación del estándar es exactamente la misma que ha hecho Microsoft en su librería. En el siguiente fragmento de código

myWebService.get("http://www.javierholguera.com")
    .then(
       function(result) { /* gestionar resultado correcto */},
        function(error) { /* manejar error */},
       function(progress) { /* informar sobre avances */}
     );

Para terminar uno de los principales beneficios del patrón es la facilidad para componer unos promises con otros. Por ejemplo, imaginemos que queremos realizar un proceso asíncrono A y cuando hayamos terminado dicho proceso satisfactoriamente, quedemos ejecutar un segundo proceso asíncrono B. Con el siguiente fragmento de código podemos ver cómo lo haríamos.

procesoA.ejecutar("http://www.javierholguera.com")
    .then(function(result) {
         // gestionamos el resultado de A ejecutando el proceso B
        // esta funcion retorna el promise del proceso B
        return procesoB.ejecutar(result);
    })
    .then(function() {
        // gestion del exito del proceso B
        console.log('B finalizo correctamente');
    }, function(error) {
        // gestion del error del proceso B 
        console.log('B finalizo con errores');
    });

Podemos apreciar en el código como el segundo .then está ejecutándose sobre el resultado retornado por el primer .then, que es en realidad el promise correspondiente al proceso B. En este caso he omitido, por claridad, el handler para el error en el promise del proceso A, pero podría haberse añadido perfectamente justo a continuación del manejador para el resultado exitoso del proceso A.

Conclusión

Promise es un patrón sencillo pero que nos ayuda a gestionar la asincronía de una forma fácil y limpia. Este patrón tiene una larga vida por delante, como parte fundamental de la API de WinJS en Windows 8, por lo que cuanto antes lo dominemos, antes empezaremos a escribir co´digo asíncrono como las aplicaciones Metro nos exigen.

Move y Merge en TFS

El equipo en el que trabajo está mejorando sus políticas de branching e intentando ser más riguroso a la hora de hacer Scrum.

Recientemente nos vimos en una situación que, aunque debería ser marginal, ocurre en todos los sprints (y probablemente en los de todos los equipos, para ser sinceros): un Product Backlog Item no se completó en el sprint.

Nuestra política de ramas es “un branch por característica”, por lo que tenemos tantos branches como PBIs. Además, para ser un poco más organizados, creamos carpetas padre para los PBIs que se hicieron en un sprint. Por eso, si el sprint es “Release 1 – Sprint 2”, tendremos una carpeta R1S2 que contendrá todos los branches correspondientes a los PBIs de ese sprint.

Solución 1: Llevar a Main

No podemos llevar el código inestable que hay en la rama original a Main y de ahí crear una nueva rama, puesto que estaríamos “rompiendo” Main. Además, tampoco tendría mucho sentido esta duplicidad.

Solución 2: Branch de Branch

Otra posible opción sería hacer un branch del branch original, en la nueva carpeta. Por ejemplo, hacer un branch de R1S2PBIXXX a R1S3PBIXXX, donde XXX es el ID del PBI no completado. El problema de esta solución es que, a la hora de llevar los cambios a Main, nos obligaría a ir hacia atrás en el tiempo, de la última rama a la anterior, y de ahí a Main. También nos obligaría a mantener “viva” la rama original, a la espera de recibir los cambios para poder, después, merguearse a Main y “morir”.

Solución 3: Move del Branch

Está creíamos que era la mejor solución: mover la rama de la carpeta original a la nueva. Por ejemplo, de R1S2 a R1S3. De este modo mantendríamos la rama “enganchada” a Main y podemos hacer el branch directamente desde la nueva posición.

Sin embargo, aquí viene TFS con las rebajas: al hacer el merge de vuelta a Main, interpreta TODOS los ficheros como mergeables, por haber sido movidos. Lo peor es que, si confirmamos el checkin, la historia de ese fichero refleja dicha entrada, aun cuando no hay diferencias reales en su contenido.

Parece ser que este comportamiento es premeditado y probablemente existan buenas razones para ello, pero a nosotros nos obliga a prescindir de esta solución, para no convertir el History de los ficheros en un pequeño caos.

Conclusiones

No existe una buena solución, pero tendremos que tirar con la Solución 2 porque es la única viable a día de hoy.