Autor: jmgomez (página 1 de 4)

Alguien voló sobre el nido del Phoenix

Phoenix es un Framework Web basado en Ruby On Rails, el padre de todos los Frameworks Web modernos. Está escrito en Elixir que es un lenguaje dinámico y funcional que corre sobre la Máquina virtual de Erlang.

BEAM o la Máquina Virtual de Erlang es una increíble pieza de ingeniería. Lleva entre nosotros 30 años y aunque para el público mainstream ha pasado desapercibido durante mucho tiempo, su robustez está más que contrastada. Sin ir más lejos, se estima que el 50% de los switches telefónicos mundiales corren sobre ella. Otro caso de éxito ha sido WhatsApp (artículoartículo), con un backend potenciado por BEAM.
También le debemos el cada vez más utilizado modelo de actores, sobre el que escribí un post no hace mucho tiempo. Algo que me resulta particularmente interesante, es que al contrario que JVM o .NET, la ErlangVM fue construida con Erlang en mente, un lenguaje funcional. Lo que implica que la librería estándar es funcional. En el caso de .NET si usamos F# terminamos arrastrando idiosincrasia del mundo de C#.

Elixir es un lenguaje de programación dinámico y funcional con una sintaxis claramente inspirada en Ruby. Como en el resto de lenguajes funcionales el concepto de objeto no existe. Los datos no mutan, se transforman. Elixir tiene un sistema de macros para extender el lenguaje, es interoperable con Erlang. Tiene un REPL, IEx. Y Mix como build tool. Incluso tiene un sistema de tipos gradual.

Si me sigues en twitter, sabrás que doy mucho las lata con los “typed-functional langs”. Desafortunadamente, aunque hay varios intentos, no hay ningún lenguaje production-ready en la BEAM con esta característica. Si te interesa estar al día con los lenguajes que corren sobre BEAM, este repo está genial.

Apoyándose sobre los hombros de BEAM, Phoenix facilita enormemente la construcción de Webs, APIs y Channels (canales de comunicación en tiempo real) sin inmiscuirse -demasiado- en nuestra aplicaciones. Dando como resultado aplicaciones relativamente mantenibles en el tiempo, o al menos más mantenibles de lo que nos ofrece un Framework Web promedio. Y es que, si nos quitamos Ecto de en medio, muchas veces da la sensación de estar usando una librería más. Esto es posible porque Phoenix está construido entorno al concepto de transparencia referencial que básicamente viene a decir que, para una misma entrada siempre habrá una misma salida o en otras palabras, tenemos garantía de que nuestras funciones no modifican el estado fuera de su ámbito. Con este nivel de aislamiento es muy simple testear o abrir un REPL y construir la aplicación por partes. Plug nace apoyándose en este concepto, y está en el corazón de Phoenix.

Plug

Según su propia documentación (). Plug es:

  1. Una especificación para componer módulos entre aplicaciones.
  2. Adaptadores para diferentes tipos de servidores en la máquina virtual de Erlang .

Un plug se puede ver como una función* con la siguiente firma:

    conn -> conn

Es decir, recibe como parámetro una conexión y retorna una conexión. La conexión en realidad es un diccionario. O sea, el plug recibe una conexión y retorna una transformación de dicha conexión. En Phoenix los plugs están en todas partes: controladores, router (que además es un pipeline de plugs), autenticación, logs… Hay muchísimas aplicaciones de terceros que siguen la especificación Plug, por lo que pueden ser consumidas desde Phoenix sin trabajo adicional.

*En realidad son dos funciones: init y call. Pero para el caso es lo mismo.

Hello World

Vamos a escribir el típico Hello World (en realidad iba a crear una app de notas, pero por extensión la voy a dejar para la siguiente entrada) Lo primero es hacer el setup de nuestro entorno.

Abrimos una terminal en la carpeta en la que queramos instalar el proyecto y ejecutamos:

mix phoenix.new hello_world

Mix nos preguntará si queremos descargar las dependencias. Obviamente diremos que sí, nos movemos al directorio hello_world y ejecutamos

mix ecto.create

El comando anterior creará la base datos

mix phoenix.server

Esto levantará un servidor, si vamos a http://localhost:4000 veremos nuestra flamante nueva app.

Si ahora editamos el fichero web/pages/index.html.eex con el texto “HelloWorld!” y salvamos. Al volver a la página, veremos como se actualiza automáticamente.

helloWorld

Click para ver (perdón por la calidad, el limite es 1MB)

La vista se acaba de recompilar (sí, phoenix soporta la compilación en caliente)  al salvar y gracias a que en el entorno de desarrollo por defecto hay un socket escuchando, los cambios en nuestros ficheros la página se actualiza automáticamente sin necesidad de herramientas externas.

Estructura 

La estructura de un proyecto Phoenix es la siguiente:

── config

── deps

── lib

── priv

── test

── web

── mix.exs

config: aquí irán los archivos de configuración del proyecto. Por defecto habrá un archivo de configuración por cada entorno: Dev, Prod y Test.

deps: todas las dependencias de nuestra aplicación ( que se encuentra en mix.exs) serán instaladas aquí.

lib: dentro de lib está el punto de entrada de nuestra aplicación.

priv: normalmente se utiliza para lo relacionado con los datos. Por ejemplo, los archivos de localización, las migraciones o el repositorio.

test: directorio de tests por defecto.

mix.exs: es el punto de entrada para Mix. Define entre otras cosas, las dependencias del proyecto.

web: es el lugar dónde estará nuestra aplicación. Y tienen la siguiente estructura:

── channels

── controllers

  └── page_controller.ex

── models

── static

── router.ex

── templates

  ── layout

    └── app.html.eex

  └── page

      └── index.html.eex

└── views

|   ── error_view.ex

|   ── layout_view.ex

|   └── page_view.ex

└── web.ex

channels: tendemos un archivo por cada channel. Recordamos que un channel es un punto de entrada en nuestro servidor que permite comunicación en tiempo real y *con estado* con un cliente.

controllers: como prácticamente en todos los frameworks MVC, la carpeta de los controladores.

models: se suele utilizar para definir el esquema de los datos y las funciones de transformación (behaviours). Recordemos que en Elixir no hay objetos y el patrón ActiveRecord se ha reemplazado por Repository.

static: assets

router.ex: archivo de definición de rutas

templates: Phoenix hace diferenciación entre Views y Templates. Templates es el equivalente a Razor, es decir, un DSL para generar HTML. Por convención, tendrá un directorio por cada controlador y un fichero para cada acción.

views: aquí irán las funciones de transformación necesarias para dejar nuestros datos listos para que la Template sea lo más “tonta” posible. Separarlo es conveniente porque muchas de las transformaciones pueden ser aplicadas no sólo a templates sino también a APIs o Channels.

web.ex: aquí podemos incluir las definiciones de nuestros modulos. Por defecto incluye para rutas, modelos, controladores, vistas y canales.

Conclusión

Phoenix tiene todas las papeletas para convertirse en el primer framework web funcional mainstream. Creo que las apps y webs de los próximos años consumirán canales y Phoenix los incorpora out of the box. Hay cosas que no me terminan de convencer como el acoplamiento de Ecto o que Elixir sea dinámico. Aún así creo que la ErlangVM va a dar mucho que hablar durante los próximos años.

Parallelizing algorithms with the Actor Model

The idea of this post is to illustrate how to apply the Actor Model, by taking advantage of its concurrence model to solve parallel problems. The kind of parallel problems that we can solve with the Actor Model are the same kind of problems that we can solve while using MPI systems.

Seguir leyendo

Curso online Xamarin

El próximo mes estaré dando un curso online de Xamarin en la nueva plataforma online OnCampusTraining. En el curso se tratará el desarrollo de aplicaciones nativas para iOS y para Android, comprendiendo así la idiosincracia de cada una de las plataformas. Para en el último tramo del curso aumentar exponencialmente nuestra productividad utilizando la nueva API de Xamarin.Forms y diversas técnicas de desarrollo multiplataforma, aprendiendo por citar un ejemplo, a crear nuestra propia librería de controles o a compartir el código de acceso a los sensores.

Trataré de compartir la experiencia acumulada durante estos últimos años en el desarrollo de aplicaciones móviles para distintos clientes alrededor del globo. En síntesis, lo que te aportara el curso si ya sabes como desarrollar para alguna de las plataformas, es un aumento de la productividad sin pérdida de control y si no has desarrollado para ninguna plataforma pero conoces C#, aprenderás a desarrollar para cada una de las plataformas entendiendo la distinta filosofía de cada una de ellas y, sobre todo, como reutilizar tus conocimientos de .NET

 

 

Por otra parte, a pesar de que Xamarin es una tecnología de pago, durante el curso disfrutaras de una licencia de estudiante sin limitaciones. Recordad que para la parte de iOS es necesario tener acceso a un Mac.

Si te interesa inscríbete cuanto antes porque esta semana se cierra el plazo.

¡Nos vemos pronto!

 


On Tail Recursion

 

La recursión es una forma de resolver problemas típicamente asociada a los lenguajes de programación funcionales, donde en ocasiones se carece de estructuras tipo bucle. La idea de la recursión se fundamenta en resolver un problema mediante pequeñas instancias del mismo problema. 

 

En FSharp, dada la herencia de OCAML y la utilización del algoritmo de inferencia Hindley-Milner, se utiliza la palabra reservada rec para definir una función recursiva.  

 

Aquí un ejemplo de función recursiva:

 

let rec count n =
    if n = 1000000 then
        printfn «done»
    else
        if n % 1000 = 0 then
            printfn «n: %i» n
 
        count (n + 1)
        ()

 

La función anterior muestra por pantalla los múltiplos de mil y cuando ha terminado escribe el mensaje ‘done’.

 

Sin embargo, si tratamos de ejecutar el código anterior obtendremos una excepción indicando un desbordamiento de pila, pero entonces, ¿cómo podemos definir la función anterior de forma que no desbordemos la pila? Algunos compiladores, como el de FSharp, poseen una característica denominada Tail Recursion o recursión de cola que nos permitirá evitar el desbordamiento grabando en la pila la posición de retorno, así cuando continue lo hará directamente en dicha posición. 

 

El problema que tenía la anterior función es que la última instrucción en ejecutarse, el retorno de la unidad, en realidad crea una operación diferida. La idea es básicamente que la última operación sea la llamada recursiva. Nuestra función recursiva de cola quedaría así:

 

let rec tailCount n =
    if n = 1000000 then
        printfn «done»
    else
        if n % 1000 = 0 then
            printfn «n: %i» n
 
        tailCount (n + 1)

 

Ahora sí, si la ejecutamos no tendremos desbordamiento de pila. El compilador se encargará automáticamente de optimizar la función y a efectos prácticos será igual que un loop. No tratéis de hacer esto en CSharp, porque al menos en la versión actual, no soporta tail recursion.

 

Edit: @gulnor comenta en twitter que en algunas situaciones excepcionales el compilador de CSharp sí hace Tail Recursion. Aquí un hilo algo más detallado: https://roslyn.codeplex.com/discussions/545455 

 

 

 

Creando un TypeProvider


En la entrada anterior vimos qué era un TypeProvider y cómo funcionaba. Ahora vamos a ver cómo crear uno.
Lo primero que tenemos que tener en cuenta a la hora de crear un TypeProvider es tener un esquema de datos, y que además, este sea fijo y no cambie a lo largo de la ejecución de nuestro programa.
Teniendo esto claro, podemos proceder a crear una nueva solución y le añadimos un proyecto de librería. Hay un paquete en nuget que nos ayudará a crear nuestro TypeProvider, Fsharp.TypeProvider.StarterPack Lo añadimos al proyecto y por último añadimos un nuevo fichero de código *al final* de nuestro proyecto. Como veis los que lo habréis intentado tiempo atrás, ahora es mucho más sencillo configurar el entorno para crear nuestros propios TypeProviders.
Implementando un TypeProvider simple
En el fichero que añadimos, escribimos el siguiente código:

namespace TypeProvidersGeeksMs
 
open System 
open System.Reflection 
open ProviderImplementation.ProvidedTypes 
open Microsoft.FSharp.Core.CompilerServices 
open Microsoft.FSharp.Quotations 
 
 
 
[<TypeProvider>]
type SampleTypeProvider(config: TypeProviderConfig) as x = 
    inherit TypeProviderForNamespaces()
 
    let ns = "Geeks.SampleTypeProvider"
    let asm = Assembly.GetExecutingAssembly()
    
    let doASimpleType() = 
        let t = ProvidedTypeDefinition(asm,ns,"NombreDeLaClase",Some typeof<obj>)
        t.IsErased <- false
        //Propiedad estática
      let staticProp = ProvidedProperty("StaticProperty",typeof<string>,IsStatic=true,GetterCode= 
                                          (fun args -> 
                                          <@@ "Hello Geeks!" @@>))
       t.AddMember staticProp
       //Un constructor
       let ctor = ProvidedConstructor(parameters = [ ], 
                                       InvokeCode= (fun args -> 
                                       <@@ "The object data" :> obj @@>))
 
       t.AddMember ctor
 
       let prop = ProvidedProperty("InstanceProperty",typeof<string>,IsStatic=false,GetterCode= 
                                          (fun args -> 
                                          <@@ "Hello Geeks! Desde una propiedad de instancia" @@>))
 
       t.AddMember prop
 
 
        t
 
 
    let types = [doASimpleType()]
 
    do x.AddNamespace(ns,types)
    
[<assembly:TypeProviderAssembly>]  
do()



Estamos definiendo una clase que sigue un protocolo especifico: hereda de TypeProviderForNamespaces, y está marcada con el atributo TypeProvider.
Si ignoramos por un momento la función doASimpleType(), veremos que definimos dos valores previos, el espacio de nombres y el ensamblado. También declaramos un valor types (que contendrá una lista con los tipos que generará) nuestro TypeProvider y por último, dentro del mismo tipo del TypeProvider en sí, lo añadimos al namespace. Finalmente, fuera del tipo principal, añadimos un atributo de ensamblado para indicar que estamos creando un TypeProvider.
La función que genera los tipos es doASimpleType, en el primer método empezamos a definir el tipo en sí, que como vemos es una función que recibe un ensamblado, namespace, un nombre para el tipo (la clase se llamará “NombreDeLaClase”) y un option (aka maybe monad) type del tipo base, en este caso Object. Posteriormente, lo marcamos como generativo, indicando que no es erased (ver entrada anterior). Y a partir de este momento, comenzamos a añadirle miembros. Añadimos una propiedad estática, un constructor y una propiedad de instancia, el procedimiento es muy similar en todos los casos: definimos el miembro y sus parámetros (en caso que sea necesario) el código que utilizará vía quotations o “expresiones de código delimitadas» (más adelante hablaremos de esto, http://msdn.microsoft.com/es-es/library/dd233212.aspx). Y finalmente, nuestro método devuelve el tipo que hemos creado. 
He intentado mantenerlo muy simple para no perdernos demasiado en los detalles, aunque como os imaginaréis esto es solo la punta del iceberg. Se quedan muchas cosas en el tintero,como que también es posible añadir miembros a posteriori (aquí un ejemplo http://www.solveet.com/exercises/Maquina-de-Turing-en-el-sistema-de-tipos/278/solution-1912)

Consumiendo el TypeProvider 
Añadimos un nuevo proyecto de Fsharp de consola y referenciamos la dll compilada (seguramente nos salte un diálogo alertandonos de problemas de seguridad). Lo siguiente que debemos hacer es referenciar el namespace (Geeks.SampleTypeProvider) y crear un alias del tipo (para indicar al compilador que emita el código del TP) 
type AliasForNombredeLaClase = NombreDeLaClase
[<EntryPoint>]
    let main argv = 
        let sample = AliasForNombreDeLaClase()
        printfn "%A" sample.InstanceProperty
        0 
Si todo ha ido bien el código anterior no debería de marcar ningún error. En teoría para consumir el TP desde CSharp bastaría con referenciar este último proyecto. 
Un detalle a tener en cuenta, es que cada vez que queramos cambiar el TP, vamos a tener que cerrar VisualStudio y eliminar la carpeta bin del proyecto que contiene el TP.

Conociendo los Type Providers


¿Qué son?

Muy resumidamente, los Type Providers (TP) son componentes que exponen metadatos al compilador de F# de forma que sean visibles como tipos, métodos y propiedades de .NET. En el fondo es un proceso de Generación Automática de Código (GAC) pero con algunas diferencias de como se ha venido haciendo tradicionalmente:
  • El TP es invocado implícitamente durante la compilación. A diferencia de la GAC tradicional que generalmente el código es generado explícitamente antes de ser usado. 
  • Los TP están integrados en el lenguaje. A nivel práctico esto significa que los ensamblados que contengan referencias a TPs pueden ser referenciados desde otros ensamblados y, como he citado anteriormente, ser usados como tipos normales de .NET.
  • La generación de código en los TP es perezosa (lazy) o lo que es lo mismo, sólo genera el código que se usará. Esto es importante porque reduce dramáticamente el tamaño del código a ser generado. 
  • Como consecuencia directa de que el código es generado en tiempo de compilación, siempre estará sincronizado con el resto del código. Este es sin duda uno de los grandes problemas de la GAC tradicional. 
En síntesis, un TP nos ayudará como desarrolladores eliminando la necesidad de escribir código boilerplate haciendo un wrapper por nosotros de la fuente de datos a la que queremos acceder.
Desafortunadamente los TP sólo pueden ser creados de F#. Dado que C# suele ir algo por detrás, quizá en futuras versiones sea posible crearlos desde C# también pero a no ser que hayan cambios en el roadmap, no será en C# 6. La buena noticia, es que puesto que genera tipos de .net ¡pueden ser consumidos de C#!

Generative Type Providers vs Erasing Type Provider

La realidad es que no es del todo correcto que puedan ser consumidos desde C#, lo cierto es que los GTPs sí generan tipos de .NET no siendo el caso para los ETPs. A diferencia de los GTP los ETP en lugar de generar tipos, generan fakes de los tipos, que le dicen al compilador de F#, por ejemplo, que miembros deben de ser llamados. Pero cuando el compilador los compila, los “fakes” son reemplazados por otro código. Y es por esto, que los ETP no pueden ser consumidos desde CSharp, porque los tipos que utilizarías desde C# ¡serían los fakes!

Usando un Type Provider para consumir la API de GitHub.

En la actualidad hay un considerable número de TP y de la más diversa índole. Desde los más básicos que pueden consumir CSV, XML o JSON hasta TP que pueden interactuar con lenguajes como R o en Python (en fase de desarrollo) pasando por TP para consumir datos estáticos de bases de datos. Para no extenderme demasiado, no será hasta la próxima entrada que no veamos cómo hacer un TP (y generativo para que pueda ser consumido desde C#). Pero para tampoco irnos con las manos vacías, veamos como utilizar un TP, en concreto el de JSON,  para acceder a una API REST cualquiera, por ejemplo ésta de GitHub: https://api.github.com/repos/fsharp/fsharp
Para usar el JSON TP bastaría con instalar el paquete de NuGet FSharp.Data y abrirlo.
type ApiGit = JsonProvider<«https://api.github.com/repos/fsharp/fsharp«>  
let user = «fsharp«
let repoName = «fsharp«
let repo =  ApiGit.Load(«https://api.github.com/repos/«+user+«/«+repoName)  

En la primera línea definimos el tipo, es necesario que le pasemos un sample de la estructura de los datos para que la pueda inferir. El sample puede ser: un fragmento de JSON directamente como cadena, el path de un fichero que contenga la estructura (en mi opinión la mejor opción) o lo que hemos hecho ahora: una dirección web que contenga la estructura. Es importante matizar que debemos pasar un literal constante, no podemos especificar variables en la dirección a la estructura del fichero. 
En la última línea, evidentemente podremos parametrizar la url que contendrá los datos ( además de Load, tenemos AsyncLoad que nos permite procesar los datos asíncronamente). 
Podremos ver el TP en acción con visualizar los miembros de repo a través del Intellisense.
 
¡El TP acaba de generar por nosotros todos los miembros que expone la API y su tipo! Pero lo más fascinante es que esto es sólo un ejemplo y se puede aplicar a muchos más tipos de datos e incluso, como veremos, podremos crear nuestros propios TP. 
Por cierto, hace un par de meses @acasquete y yo estuvimos en un webcast introduciendo F# si te lo perdiste o quieres repasar algunos conceptos, aquí tienes el video: http://vimeo.com/88283954

MvvmCross: Manejando notificaciones locales en Android

El Manejo de notificaciones locales en Android es diferente que en iOS, por lo que el código no es multiplataforma. En MvvmCross me gusta manejar ese tipo de escenarios en un Plugin propio , pero esta vez , para mantener el post breve voy a dejar el código en la Activity que generó la notificación (puedes leer la entrada en inglés aquí: http://jmgomez.me/mvvmcross-handling-notification-clicks).

 

Digamos que queremos mostrar una notificación cuando algo sucede en nuestra aplicación y, a continuación , redirigir al usuario a un ViewModel personalizado.

 


void SetBackgroundAlert(Route route) {
            var intent = GetRouteViewIntent(route);
            var pendingItent = 
                PendingIntent.GetActivity(this, 0,intent, PendingIntentFlags.UpdateCurrent);

            var notificationManager = (NotificationManager)this.GetSystemService(Context.NotificationService);
            var notification = new Notification.Builder(this)
                .SetContentTitle(«Alarm«).SetContentText(RouteView.offRouteMessage)
                .SetContentIntent(pendingItent)
                .SetSmallIcon(Resource.Drawable.notification_icon).Notification;

            notificationManager.Notify(1, notification);
        
        }

Nada nuevo por ahora, acabamos de crear una notificación desde NotificationBuilder , la clave es el método GetRouteViewIntent . Hemos recuperado un Intent específico que se pasa al PendingIntent, a continuación, cuando el usuario hace clic en la notificación , se redirige a nuestro ViewModel . El método GetRouteViewIntent es el siguiente :


static Intent GetRouteViewIntent(Route route) {
            var request = new MvxViewModelRequest();
            request.ParameterValues = new System.Collections.Generic.Dictionary<stringstring>();                        
            request.ParameterValues.Add(«idRoute«, route.IdRoute.ToString());
            request.ParameterValues.Add(«fromRating«false.ToString());
            request.ViewModelType = typeof(RouteViewModel);
            var requestTranslator = Mvx.Resolve<IMvxAndroidViewModelRequestTranslator>();
            return requestTranslator.GetIntentFor(request);
        }

Acabamos de crear un Request ( con sus parámetros ) y luego creamos nuestro Intent como MvvmCross hace internamente.

 


Programación funcional en CSharp, algunas pinceladas:

 

Sí, es cierto que si tenemos que clasificar a CSharp en un paradigma, este sería orientado a objetos. Pero desde .NET 3.5 con la inclusión de LINQ, o incluso antes, en .NET 2.0 (si no recuerdo mal) con la inclusión de los genéricos, el lenguaje ha ido añadiendo más componentes del paradigma funcional. En este post voy a intentar describir algunas (y sólo algunas) de las ventajas del paradigma funcional aplicado a CSharp, sin intención de sembrar cátedra.



Funciones de orden superior

Una función de orden superior grosso modo es una función que acepta como parámetro otra función. Esto lo podemos ver de LINQ. Una de las sobrecargas de lacláusulaa Where acepta una función de parámetro T y que devuelve un booleano.

Una de las mejores formas de añadirlas en nuestro código, es precisamente como lo implementa Linq. Es decir, a través de métodos extensores.


public static class FooExtensions{

public static void DoFoo(this Foo foo, Action DoSomething){

DoSomething();

}

}


Otro punto muy interesante de las métodos extensores es que nos facilitan la vida para crear apis fluidas, ahí ya entramos en el siguiente punto.


Expresividad


Aunque la expresividad no esté catalogada como característica de un lenguaje funcional, sí que es cierto que suelen ser más expresivos. En esto las apis fluent tienen mucho que decir, ya que pasamos de hacer las cosas en un modo imperativo (ordenando) a uno más declarativo (pidiendo).


Suele considerarse buena práctica definir constantes para hacer nuestro código más expresivo cuando trabajamos con cadenas. ¿Por qué no hacer lo mismo con funciones? Este es un ejemplo de código sacado de un proyecto real en el que estoy trabajando:


SettingsViewModel.ShowWebCommand.Execute(url);


No parece muy ofensivo, simplemente ejecuta un comando desde una vista (iOS) a un ViewModel (MvvmCross) que no puede ser bindado por características de implementación. Lo que es seguro es que si tienes que escribirlo varias veces, como es el caso, acaba siendo un poco desagradable a la vista. ¿Cómo hacerlo más conciso? Simplemente,asignándole a una función que recibe como parámetro un string y no devuelve nada:


Action<string> OpenWeb = (url) => SettingsViewModel.ShowWebCommand.Execute(url);


Las llamadas serían OpenWeb(url);


Mucho más simple no? Seguro que hay casos donde se maximiza aún más la expresividad.


Inmutabilidad

La inmutabilidad es una de las características más importante de los lenguajes funcionales. Es en realidad un concepto muy simple, viene a decir que las variables no almacenan estado (la mayoría de bugs suelen ser problemas de estado). Esto quiere decir que no asignamos valores a variables, en su lugar se definen símbolos que no podrán ser cambiados a posteriori. En CSharp trabajamos con variables en lugar de símbolos, por lo que en principio no podemos hacer el mismo procedimiento. Pero sí que es posible marcar variables como inmutables con readonly, e incluso hay librerías con colecciones inmutables out of the box.


Sinceramente, creo que la mejor forma de evitar el estado, sobre todo en el dominio (en UI y BBDD evidentemente es inevitable) es intentar reducir tanto como sea posible las declaraciones de variables a nivel de clase. Y si lo hacemos, modificarlas o bien con funciones void que prácticamente sólo hagan dicha modificación o bien si estamos construyendo una api fluent que se reciba como parámetro dicha variable, se modifique y se devuelva (aunque entonces no tendría mucho sentido almacenar el estado de la variable en cuestión :P)



Clousures


Un Clousure, aunque suene cool, no es más que una función definida en un ámbito en el que hay variables en el mismo ámbito, a las cuales la función podría acceder. Más claro aún:


void SomeFunction(){

var whatever = new Whatever();

var foo = new Foo();

foo.GetAllFoos().Where(f=>f.whatever==whatever);

}


El clousure sería el predicado del where, porque la estamos declarando en el ámbito de Whatever y por tanto, podemos acceder a Whatever. Pero si en lugar de definir el Where ahí, usaramos un Func<Foo,bool> previamente definido (como el action openWeb anterior), ya no sería un Clousure. Hay que tenercuidadoo con los Clousures si se usan en un contexto iterativo, porque al usar la variable del mismo ámbito, ésta tendrá el valor de la última iteración siempre (si es que cambia).



Continuará

No sé cuándo, pero escribiré otra entrada sobre esto con algún puñado de conceptos más. Espero que haya resultado útil a alguien. 🙂

Alcanzando la nirvana: MvvmCross + FSharp + iOS Development

Introduccion 

En este ocasión quiero mostrar de la manera más simple posible cómo combinar tres de mis tecnologías favoritas: MvvmCross, Xamarin.iOS y Fsharp.

 

Mi intención es mantener el ejemplo lo más simple posible, así que me he basado en el ejemplo más simple de mvvmcross que podemos encontrar en CSharp (link)

You can read this article in English here: jmgomez.me

Configurando el entorno

 

Lo primero que debemos hacer es configurar el entorno, el IDE que utilizaremos será Xamarin Studio. Puedes ver cómo tener FSharp funcionando en iOS aquí  también es posible que necesites descargar el último addin de F# Binding más info aquí (http://stackoverflow.com/questions/16412407/xamarin-studio-fails-to-open-f-files) gracias a @7sharp9

 

Una vez tenemos FSharp funcionando en iOS, tenemos que añadir manualmente las referencias de MvvmCross que podéis encontrar aquí . Actualmente las dll para mac y windows son distintas, en el futuro esto no será así.

 

Manteniendo la convención de MvvmCross, vamos a crear un proyecto de tipo librería para iOS (no portable) llamada ReachingNirvana.Core y con nombre de solución ReachingNirvana. Le añadiremos las siguientes librerías: Cirrious.CrossCore.dll, Cirrous.MvvmCross.dll, Cirrious.MvvmCross.Localization.dll. Lo siguiente será crear un nuevo proyecto llamado ReachingNirvana.Touch del tipo SingleViewApplication. Añadiremos las referencias Cirrious.CrossCore.dll, Cirrious.CrossCore.Touch.dll, Cirrious.MvvmCross.dll,Cirrious.MvvmCross.Touch, Cirrious.MvvmCross.Binding.dll, Cirrious.MvvmCross.Binding.Touch.dll y por último añadimos la referencia de nuestro proyecto ReachingNirvana.Core.

 

 

Haciendo la magia

 

Una vez configurado el entorno debemos añadir un fichero .fs a nuestra solución llamado App.fs con el siguiente contenido:


namespace ReachingNirvana.Core

open System

open Cirrious.CrossCore.IoC

open Cirrious.MvvmCross.ViewModels


type FirstViewModel() = 

    inherit MvxViewModel()

    let mutable hello : string = «Hello MvvmCross»

    member this.Hello

        with get () = hello

        and set (value) =         

            hello <- value 

            this.RaisePropertyChanged(«Hello»)

type App ()  = 

    inherit Cirrious.MvvmCross.ViewModels.MvxApplication()

    override u.Initialize() = 

        u.RegisterAppStart<FirstViewModel>()



 

Como se puede observar hemos definido varios tipos en el mismo fichero, esto no es necesario puedes separar cada tipo en un fichero si lo deseas pero recuerda que el orden de los ficheros en el proyecto importa. Si quieres cambiarlo abre el archivo de configuración del proyecto. 

 

Lo primero que definimos es la clase FirstViewModel que hereda de MvxViewModel y defimos una propiedad llamada Hello con el get y set. Como nota he preferido mantener la simplicidad/legibilidad usando un magic string en «Hello» porque de otra manera habría que hacer castings y queda algo sobrecargada la sintaxis.

 

Por otra parte, definimos el tipo App que hereda de MvxApplication y sobreescribimos el método Initialize, notése que no he registrado nada en el contenedor IoC porque para este ejemplo no es necesario, pero este sería el lugar para hacerlo.

 

Ya hemos terminado con con el proyecto Core, ahora es el turno de Touch. Lo primero es sustituir el código del AppDelegate.fs por este:

 

namespace ReachingNirvana.Touch


open System

open MonoTouch.UIKit

open MonoTouch.Foundation

open Cirrious.MvvmCross.Touch.Platform

open Cirrious.MvvmCross.Touch.Views.Presenters

open Cirrious.MvvmCross.ViewModels

open Cirrious.CrossCore

open ReachingNirvana.Core


type Setup (applicationDelegate:MvxApplicationDelegate, presenter: IMvxTouchViewPresenter) = 

    inherit MvxTouchSetup(applicationDelegate,presenter )

    override u.CreateApp() = 

        new App():> IMvxApplication

 

[<Register («AppDelegate»)>]

type AppDelegate () =

    inherit MvxApplicationDelegate ()


    let window = new UIWindow (UIScreen.MainScreen.Bounds)


    // This method is invoked when the application is ready to run.

    override this.FinishedLaunching (app, options) =

        let presenter = new MvxTouchViewPresenter(this,window)

        let setup = new Setup(this,presenter)

        setup.Initialize()

        let startup = Mvx.Resolve<IMvxAppStart>()

        startup.Start()

        

        window.MakeKeyAndVisible ()

        true


module Main =

    [<EntryPoint>]

    let main args =

        UIApplication.Main (args, null, «AppDelegate»)

        0




 

Aquí estamos definiendo tres clases, Setup AppDelegate y Main. El código es muy similar a la versión de CSharp (aunque mucho más bonito) la diferencia más notable es que debemos hacer casting explícito desde App a IMvxApplication en lugar de implícito. 

 

Por último definiremos nuestra vista, FirstView. Puedes cambiar el nombre a la que proporciona la plantilla de Xamarin Studio o borrarla y añadir una nueva, en el último caso, ¡recuerda que debes cambiar el orden de los ficheros!

 

En FirstView tenemos el siguiente código:

 

namespace ReachingNirvana.Touch

open System

open System.Drawing

open MonoTouch.UIKit

open MonoTouch.Foundation

open ReachingNirvana.Core

open Cirrious.MvvmCross.Binding

open Cirrious.MvvmCross.Binding.BindingContext

open Cirrious.MvvmCross.Touch.Views



[<Register («FirstView»)>]

type FirstView () =

    inherit MvxViewController ()

   

    let  label = new UILabel()

    let textBox = new UITextField() 

    

    // Release any cached data, images, etc that aren’t in use.

    override this.DidReceiveMemoryWarning () =

        base.DidReceiveMemoryWarning ()


    // Perform any additional setup after loading the view, typically from a nib.

    override this.ViewDidLoad () =

        base.ViewDidLoad ()

        this.View.BackgroundColor <- UIColor.White

        label.Frame <- new RectangleF((float32)0,(float32)0,(float32)320,(float32)50)

        this.Add(label)

        textBox.Frame <- new RectangleF((float32)0,(float32)70,(float32)320,(float32)50)

        this.Add(textBox)

        

        let set  =  MvxBindingContextOwnerExtensions.CreateBindingSet<FirstView,FirstViewModel>(this)

        set.Bind(label).To(«Hello») |> ignore

        set.Bind(textBox).To(«Hello») |> ignore

        set.Apply()

        

        

    // Return true for supported orientations

    override this.ShouldAutorotateToInterfaceOrientation (orientation) =

        orientation <> UIInterfaceOrientation.PortraitUpsideDown

 

 

Como se puede observar, es una vista simple que tiene dos controles, un UILabel y un UITextField. En el método ViewDidLoad inicializamos algunas propiedades de los controles y creamos los bindings:

 

CreateBindingSet es un método extensor, que no es más que un método estático que puede ser llamado desde la clase que lo implemente y pásandole por paramétro explicitamente la instancia que lo utiliza. A la hora de crear el binding, tenemos un caso análogo al de llamar a RaisePropertyChanged, bajo mi punto de vista en la versión de FSharp la sintaxis queda muy sobrecargada por lo que he preferido utilizar la sobrecarga con el magic string (internamente mvvmcross llama a este método desde la otra sobrecarga).

 

Ahora ejecutamos y podemos apreciar la armonía de nuestra primera app funcionando con MvvmCross y FSharp. 

 

 

Conclusión

 

Esto ha sido un primer contacto, habría que pensar si nos compensa usar FSharp en lugar de CSharp en todas partes por el poco soporte que tienen las tools (sobre todo por parte de Microsoft), quizá sería más sensato mantener la vista en csharp y cambiar el resto. Lo que está claro es que FSharp tiene muchas ventajas claras sobre CSharp y Csharp también tiene algunas ventajas sobre FSharp, como sabes, de «the right tool for the right job»

 

El código está aquí

 

Novedades de la Xamarin Evolve

 

Hoy ha terminado la Xamarin Evolve, o al menos lo más interesante, las novedades. No suelo escribir noticias, pero sin que sirva de precedente, esta vez los resultados bien valen la pena mencionarlos a bombo y platillo.

 

C# 5

O lo que es lo mismo, ¡Mono 3 disponible para todas las plataformas! Esto es genial porque como sabéis Mono 3 incluye c# 5 que a su vez incluye como mayor feature async/await. Aún más fácil escribir código asíncrono y sobre todo, compartir la mayor cantidad de código con Windows 8 y Windows Phone. 

 

Podéis encontrarlo en el canal beta, que no os de miedo la palabra beta porque aseguran que a no ser que hagas cosas sin sentido (anidando asyncs como si no hubiera mañana) no debería fallar. Supuestamente pasará mucho tiempo ahí.

 

Diseñador para iOS

Sin duda una de las mayores novedades y algo que nadie se esperaba. Un diseñador que permite diseñar para iOS gráficamente sin tocar XCode. Ahora mismo sólo admite StoryBoards, pero en breve se extenderá el soporte para el resto de Views. Cuando lo haya probado en profundidad le dedicaré un artículo entero. 

 

Podéis encontrarlo en el canal Alpha (sí, da un poco de miedo).

 

Soporte para F#

Una de las cosas que me esperaba y que, valga la redundancia, más estaba esperando. Ahora podemos desarrollar nuestras vistas en F#. ¿Quién no tiene ganas de ver cómo la programación funcional juega de aliado perfecto con MonoTouch.Dialog para generar interfaces? 

 

Testing Cloud

Plataforma de tests automáticos que permite testear tus aplicaciones en cientos de dispositivos distintos. Estaremos atentos a los precios. 😉

 

¿Y soporte oficial para PCL?

Esta es otra de las cosas que más estaba esperando pero desgraciadamente aún no está listo. Según Miguel de Icaza en un mes aproximadamente estará en el canal Alpha, así que toca seguir esperando.

 

Seguro que se me quedan cosas en el tintero, pero para mí estas han sido las novedades más importantes. 

 

 

Antiguas entradas