Migrar código de Windows 8 a Windows Phone 8

Como he comentado en alguna entrada anterior, recientemente tuvimos la ocasión de liberar aTareado para Windows 8.

Una de las primeras tareas a llevar a cabo, incluso antes de abordar nuevas funcionalidades, consiste en re-organizar el código y dejarlo preparado para poder sacar el máximo provecho en Windows Phone 8 al trabajo realizado en Windows 8. De esta manera, las nuevas funcionalidades estarán disponibles con más rapidez en ambos sistemas y podremos disponer de una versión en ambos sistemas con la mayor cantidad de código compartido posible.

aTareado surgió como un ejercicio de aprendizaje para crear aplicaciones de la Tienda de Aplicaciones de Windows, así que algunas decisiones de diseño (y me refiero a diseño técnico de la aplicación) han sido tomadas sin tener más propósito que el mero aprendizaje. En consecuencia, tras revisar un poco dichas decisiones, hay algunos problemas que habrá que tratar (en concreto para aTareado, que es muy sencillo, la lista puede variar de una aplicación a otra)

  • El modelo de la vista está en el mismo proyecto que la vista, lo que va a dificultar la reutilización del mismo en un proyecto de Windows Phone. Será necesario sacarlo a una biblioteca portable para su reutilización en ambas versiones.
  • El almacenamiento se encuentra demasiado acoplado a la fuente de datos. En Windows 8 y Windows Phone 8 el sistema de almacenamiento es diferente, con lo que este acoplamiento es bastante poco recomendable. Habrá que crear abstracciones para el repositorio que nos permita sacar versiones diferentes para ambos sistemas operativos.
  • El modelo de la vista hace uso de clases comunes que están demasiado relacionadas con clases de utilidad de Windows 8, así que para reutilizar el modelo de la vista en una versión de Windows Phone 8 habrá que crear algún tipo de abstracción para definir funcionalidades generícas, existentes en sistemas operativos diferentes.

Por otro lado, hay algunas decisiones que pueden simplificar la reutilización del código entre las versiones de Windows 8 y Windows Phone 8.

  • Parte del aprendizaje estaba enfocado en el patrón de diseño MVVM con lo que ya existe una separación clara entre la vista y el modelo de la vista, lo cual facilitará reutilizar este último en una versión de Windows Phone 8.
  • De entre de las posibles implementaciones de MVVM escogimos MVVM Light, que tiene versiones portables que pueden reutilizarse con facilidad en Windows 8 y Windows Phone 8.
  • La implementación de MVVM hace uso extensivo del patrón de diseño de Inversión de Control (IoC) lo que simplifica enormemente aprovechar abstracciones ya creadas para implementar versiones en sistemas operativos diferentes sin necesidad de tocar demasiado el código. Además la utilización de este patrón simplifica las pruebas unitarias y con poco esfuerzo podremos aprovechar el trabajo ya hecho para probar las clases nuevas que creemos para la versión de Windows Phone 8.
  • Para la serialización de datos se ha utilizado la biblioteca Newtonsoft.Json que también tiene sus versiones portables.

Reutilización W8 /WP8

La siguiente lista no es exahustiva, de hecho se limita a enumerar las consideraciones que hemos tenido que tener en cuenta al tratar de sacar el máximo provecho al código de aTareado.

Separación de Responsabilidades en la Vista

Si quieres sacarle el máximo provecho a tu aplicación en ambos mundos, empieza planteándote que un patrón de diseño que separe claramente la presentación de la lógica de presentación va ser de enorme ayuda, al fin y al cabo el XAML de Windows 8 y el XAML de Windows Phone 8 no son iguales. En este mundillo, esto lo consigues (con más o menos facilidad) utilizando MVVM.

Es buena idea que te lleves el modelo y la vista del modelo a bibliotecas portables de clases ya que con ese sencillo planteamiento ya tienes una buena base que compartir entre tus diferentes proyectos (W8 y WP8)

Es decir, partimos de algo parecido a esto:

image

Para terminar en algo similar a esto otro:

image

En realidad, parece que la cosa se ha complicado mucho (y es cierto) pero sólo porque el punto de partida era casi trivial.

A la hora de llevarnos el modelo y el modelo de la vista a bibliotecas portables partiendo de una versión en W8, la utilización de la versión portable MVVM Light ha sido de gran ayuda, pero tampoco ha estado exenta de problemas. El mayor problema encontrado aquí deriva de un pequeño bug en NuGet.

Cuando haces referencia a la MVVMLight (PCL) a través de NuGet, se realiza un cambio en la configuración de tu biblioteca de clases introduciendo una referencia al Runtime que no debería de introducirse. La solución es sencilla, simplemente elimina dicha referencia del fichero de configuración (puedes comprobar más detalles aquí).

Abstracción de Funcionalidades del SO

Por otro lado la utilización de patrones como IoC favorece enormemente el desacoplamiento entre clases. Así que, es una magnífica idea que construyas una biblioteca de clases portable donde definir todas las abstracciones (interfaces, fundamentalemente) y una biblioteca específica por Sistema Operativo donde implementen los servicios que se definen en la biblioteca de abstracciones. Tal y como se indicada en el gráfico anterior, parece que la cosa se ha complicado bastante. Pues bien, se ha complicado, pero esta complicación no es muy grande y simplifica enormemente el mantenimiento de ambas versiones.

Si ya estás utilizando MVVM Light en tus proyectos, seguro que estás familiarizado con la clase ViewModelLocator que es la que hace un uso exahustivo de los contenedores y localizadores de dependencias; además se encarga de registrar la correcta implementación del modelo de la vista. El ViewModelLocator puede registrar también las correctas implementaciones de las abstracciones (es decir, el ViewModelLocator registrará las versiones de W8 o de WP8 de dichas abstracciones). Hay un buen ejemplo aquí, donde pueden encontrarse ejemplos simples de estos conceptos.

Mensajes, mensajes, mensajes

Como sabéis, MVVM consigue desacoplamiento mediante un par de elementos fundamentales. Uno es el DataBinding y el otro es el itercambio de Mensajes entre los diferentes elementos del diseño.

No solo se utilizan como parte del DataBinding para avisar a la Vista que una propiedad ha cambiado, también pueden (deben) ser utilizados para comunicar algunos objetos sin que haya acoplamiento entre ellos.

Un Ejemplo de Mensaje

Supongamos que necesito un temporizador que dispare un evento de forma periódica. Cada sistema operativo suele disponer de clases que implementan estos temporizadores, además estas clases suelen venir por “duplicado” según estén diseñadas para interactuar con las vistas (ya que se ejecutan en el hilo de UI) o bien si están diseñadas para temporizar alguna acción que ha de ejecutarse en un hilo separado de la presentación.

Para evitar un diseño complicado y reutilizable en dos sistemas operativos diferentes, es perfectamente posible definir una clase que represente un mensaje de temporización. MVVM Light contiene una clase encargada de propagar mensajes de manera muy sencilla y desacoplada. Así pues, si nuestro modelo de vista tiene que reaccionar a mensajes del temporizador, simplemente lo subscribiremos a dichos mensajes y en la implementación específica del sistema operativo, nos limitaremos a lanzar dicho mensaje en cada pulsación del temporizador. De esta manera, el temporizador estará definido en una biblioteca de clases específica para el sistema operativo y la comunicación con el modelo de la vista se realizará, de forma desacoplada, a través del Messenger.

Este tipo de diseños permiten el desacoplamiento, pero vienen a un coste en la mantenibilidad ya que es muy difícil dar seguimiento a qué objetos se suscriben/desuscriben a qué mensajes y bajo qué condiciones lo hacen. De esta manera realizara pruebas unitarias que validen este comportamiento no es trivial.

En Resumen

Conseguir una versión “portable” de aTareado no ha sido complicado, pero ha requerido cierto esfuerzo de pruebas y refactorización. Las mayores dificultades han venido de un par de problemas relacionados uno con el diseño del código de aTareado y otro con un bug en NuGet, la mayor parte del trabajo ha venido a la hora de probar todo de nuevo.

Si tienes previsto crear una aplicación para WP8 o para W8, antes de comenzar hazte una sencilla pregunta. ¿La quiero para ambos sistemas operativos? Si la respuesta es sí, toma como referencia estos sencillos pasos a la hora de hacer el diseño y te simplificará la vida. Si la respuesta es no, hazte otra pregunta: ¿Seguro?

Subiendo aTareado al App. Store

Ha habido cierta cantidad de trabajo por detrás, pero aTareado ya está disponible en el App. Store.

846x468

aTareado se trata de una pequeña aplicación que nació con la única intención de permitirme practicar para aprender algunos de los entresijos de la programación de Aplicaciones de la Tienda de Windows 8 (Windows 8 AppStore Applications).

Permite realizar una gestión muy sencilla de tareas personales, añadiendo nuevas tareas, permitiendo su clasificación (¡hasta 100 categorías diferentes!) y seguimiento de forma sencilla e intuitiva.

screenshot_05032013_092430

Esta aplicación es fruto del trabajo de varias personas que han aportado sus ideas (gracias  a los amigos Rafa, Íñigo, Dannan y Javi) y también su esfuerzo como es el caso de Dannan que, además de aportar sus ideas, se ha encargado del diseño de la interfaz y del logotipo y que, en mi humilde opinión, ha realizado un excelente trabajo. O el propio Rafa que está aprendiendo por su lado la programación en Android utilizando: ¡aTareado!

screenshot_05032013_092722

screenshot_05032013_092748

Lecciones aprendidas

Primero de todo: organización.

Por mucho desarrollo amateur que se trate, hacer las cosas bien puede tener cierto coste relativo a tiempo y esfuerzo en una primera etapa.

La utilización de un control de código fuente ha sido fundamental. En mi caso, he hecho uso del Team Foundation Service, que es una mágnifica herramienta gratuita (para equipos reducidos) disponible en la nube.

Uno podría pensar que en situaciones tan triviales como las del desarrollo de una aplicación como esta, en las que las personas que desarrollan son uno mismo, hacer uso de una herramienta como TFS es innecesario. Pero no es así.

TFS permite no sólo realizar una magnífica gestión del código fuente de tu aplicación, también proporciona herramientas para la planificación y seguimiento del ciclo de vida de tu aplicación (ALM, o Application Lifecycle Management). En este caso, ha sido de gran utilidad para que un grupo de amigos documente de manera muy sencilla los requisitos que nuestra pequeña herramienta va a utilizar, genere seguimiento de los mismos (el avance lo vamos a dejar de lado, porque la vida profesional y personal deja poco espacio para este tipo de aficiones) así cómo la creación y seguimiento de nuevas incidencias (parte en la que Rafa ha resultado ser un auténtico crack)

Segundo: el conocimiento

Programar aplicaciones Windows 8 del App Store no es difícil, pero requiere cierta curva de aprendizaje.

El Framework

Si bien programas aplicaciones de la Tienda de Windows utilizando el Framework .NET 4.5, la realidad es que no tienes al alcance de tu mano el Framework Completo si no un subconjunto y un no tan pequeño recubrimiento alrededor del mismo.

No puedes hacer todo lo que estás acostumbrado a hacer. Muchas cosas tienen planteamientos diferentes y, en general más restrictivos (como, por poner un ejemplo, el acceso a ficheros) y otros aspectos sencillamente están fuera de tu alcance con este subconjunto de APIS que se pone a tu disposición como programador. ¿Es esto malo? Bueno, la discusión está bastante manida y no tengo nada nuevo que añadir a la misma, pero es la dicotomía entre la “protección” del usuario frente a la “libertad” del programador.

Me permito el lujo de poner “protección y “libertad” entre comillas ya que son aspectos un tanto controvertidos. ¿Nececsita el usuario ser protegido? Y, si es el caso, esta protección ¿no puede llevar fácilmente a una sobre-protección y, en consecuencia a una limitación de lo que el usuario puede hacer con la máquina y el sistema operativos que ha pagado? Y, por el otro lado. ¿Tiene el programador la “libertad” de hacer lo que quiera? Dejadme que os ponga un ejemplo: ¿Cuántas veces habéis tenido que aceptar que una aplicación acceda a tu localización y a internet sin que haya una causa funcional que justifique dichas capacidades? ¿Para qué quiere el programador acceder a mi localización y a internet si la aplicación lo único que hace, en principio, es encender el led de mi terminal?

El Lenguaje Visual y el Diseño

Es de sobra sabido que Windows 8 incluye un nuevo lenguaje de diseño, entendido como el conjunto de reglas, guías y prácticas a seguir para mostrar la información al usuario y para facilitarle al mismo el acceso y modificación de los datos que muestra su aplicación.

Este lenguaje, conocido como Modern UI tiene sus ventajas, pero también sus limitaciones ya que obliga a plantearse cosas de manera muy diferente a cómo un diseñador lo ha venido haciendo previamente (y si no que se lo digan a Dannan).

Comprender este lenguaje y crear un diseño partiendo de él es uno de los primeros puntos a tener claros.

El Lenguaje de Programación para la Interfaz Gráfica

Ahora sí, estamos hablando de XAML. Mi experiencia como programador no me ha llevado a cruzarme con este lenguaje de marcado hasta que no me he metido en esta pequeña aventura. La primera consecuencia de este punto es que el 80% de mi tiempo se ha ido en tratar de averiguar cómo hacer esto o aquello con XAML.

Si además le sumamos el hecho de que algunas características disponibles en WPF o Silverlight no lo están en el subconjunto de XAML que nos proporciona Windows 8, el desafío se ha presentado todavía más interesante.

Conclusión, si no sabes XAML y estás interesado en realizar Aplicaciones de la Tienda de Windows 8 debes de plantearte dos alternativas:

HTML + Javascript: Si ya dispones de esos conocimientos, probablemente tu curva de aprendizaje se reduzca.

XAML /C# XAML /VB.NET o XAML /C++: Esta alternativa requiere conocimientos en ambos lenguajes de cada pareja. En mi caso, la elección fue esta sencillamente por los prejuicios (fundados, siempre desde mi punto de vista, por supuesto) que tengo sobre Javascript. Si no conoces XAML asume que tu curva de aprendizaje será pronunciada en cuanto quieras que tu aplicación se distinga de alguna manera del resto.

Tercero: Las Ganas

Aprender es un reto, y sin ánimo de entrar en filosofías baratas, también es una forma de plantearte tú vida. Sin aprendizaje hay estancamiento y el estancamiento es una situación que en ocasiones puede resultar cómoda, pero que en el medio plazo (por no decir en el corto) lleva a un único sitio: “a ninguna parte”.

Evidentemente realizar aplicaciones es apasionante, pero también requiere esfuerzo. Sin la energía y las ganas, es muy difícil sacar cualquier proyecto adelante.

¿Y ahora qué?

Pues que aTareado ya está en el Store y, como no puede ser de otra manera, tiene bugs (algunos pequeños y otros no tanto). Además, ahora mismo proporciona una funcionalidad completa, pero sencilla en extremo. ¿No sería bueno poder organizar las tareas en listas? ¿Quizá poner avisos? ¿O integrarlas con el calendario? ¡Eh, que no hemos puesto tareas recurrentes! ¿Oye, y si pudiéramos hacer GTD con aTareado? ¿Y ponerle un módulo de Pomodoro? ¿Para cuándo la versión de Windows Phone y de Android?

Como véis, hay ganas.

¿Habrá tiempo?