lunes, 28 de septiembre de 2015

El Patrón Model - View - ViewModel ( MVVM )

Este año Google IO introduce un nuevo framework que parece impresionante para los desarrolladores de Android ,y que permite la "unión" de las vista a los campos en un 
objeto arbitrario. Cuando un campo se actualiza, el framework se da cuenta y la vista se actualiza automáticamente.

Este sistema es muy potente, y nos permitirá utilizar un modelo de desarrollo que se ha utilizado en el mundo de Windows durante algún tiempo llamado Model-View-ViewModel (MVVM). 
Antes de saltar a cualquier código, es importante entender los conceptos básicos de esta arquitectura, y la forma en que usted y su aplicación puede beneficiarse.

El patron Model - View - ViewModel fue concebido por John Gossman allá por el año 2005 en un post de su blob titulado "Introduction to Model/View/ViewModel pattern for building WPF apps"(http://blogs.msdn.com/b/johngossman/archive/2005/10/08/478683.aspx), siendo este una adaptación del patrón Presentation Model (http://martinfowler.com/eaaDev/PresentationModel.html) propuesto por Martin Fowlers para tecnologías .NET como XAML (como se conoce ahora al conjunto de herramientas para desarrollar en Windows 8), WPF y Silverlight. 

Este patrón junto a otros mas conocidos como MVC o MVP tiene por objetivo simplificar las tareas de desarrollo y mantenimiento del software escrito con estos a través de la división de ocupaciones, por lo cual alguien que ya haya trabajado previamente con alguno de los patrones previamente mencionados, le parecerá bastante familiar MVVM.

El patrón MVVM consta de tres partes:

a) Modelo - Representa la lógica empresarial
b) View - Lo que muestra el contenido
c) ViewModel - El objeto que une los dos puntos anteriores juntos

Model
El modelo, dentro de MVVM es el encargado de representar el modelo del negocio, proveyendo de esta manera la base necesaria para la manipulación de los datos de la aplicación, además parte del modelo se lo puede usar como clases POCO (Plain Old CLR Objects) para poder usarlas con Entity Framework Code First o algún otro ORM. Cabe resaltar que en el modelo, no debería de existir ninguna lógica de negocio o código que afecte a como se visualizan sus datos en pantalla.

View
La vista es la parte encargada de la parte visual de nuestra aplicación, no teniéndose que ocupar en ningún momento en el manejo de datos. En MVVM la vista tiene un rol activo, esto significa que en algún momento la vista recibirá o manejara algún evento (Clic en un botón, alguna tecla presionada, etc.) y tendrá que comunicarse con el modelo, para poder cumplir el requerimiento. 

ViewModel
El ViewModel (modelo de vista en español) es el encargado de ser la capa intermedia entre el modelo y la vista, procesando todas las peticiones que tenga la vista hacia el modelo, además de tener que ocuparse de manejar las reglas del negocio, la comunicación con aplicaciones externas o consumir datos desde alguna fuente (Bases de Datos, Web Services, Sensores, etc.). Para la comunicación entre el View y el ViewModel, utilizamos los enlaces de datos que nos permiten tener un código bastante limpio (Bindings http://msdn.microsoft.com/en-us/library/ms752347.aspx)


Observaciones
Trabajando con este patrón y migrando cientos de líneas de código Espagueti al patrón, he visto algunas practicas o concejos que pueden ser de bastante utilidad al menos al momento de comenzar a usar el patrón.
- El Code-Behind no tiene que existir: He escuchado bastante de eso por todo ello, y le cuento que es un tanto falso, para entender mejor como funciona el code-behind dentro del patrón MVVM, hay que pensarlo como si fuere el patrón MVC, donde la vista este escrita en HTML y el JavaScript que maneja todo lo referente a la vista(cambiar un color, redimensionar un control, etc.); ciertamente el Code-Behind hay que usarlo con cautela, pero a la vez prescindir por completo de el puede llevarnos demasiado tiempo, por regla, si algo que nos puede tomar un par de minutos con Code-Behind, nos toma horas sin el, entonces estamos yendo por mal camino.
- La vista debe ser 100% desacoplable de ViewModel: Esto al igual que el punto anterior hay que pensar primero en la dificultad que realizar esto conlleva, por que ciertamente no es a función principal del patrón, si es un aditamento, si es que es posible implementarlo en un lapso de tiempo corto y sin tener que crear una mayor estructura para que se lleve a cabo.
- No es necesario usar un Framework para MVVM: Esto es completamente cierto, ya que usando un par de clases escritas por nosotros o por terceros podemos tener nuestro proyecto con MVVM al 100%.
- MVVM es solo para aplicaciones grandes: Muy falso, MVVM funciona perfectamente bien para proyectos grandes y pequeños, inclusive por las características de una Aplicacion Android , Silverlight o XAML el desarrollo de toda aplicación es mas simple usando el patrón. En todo caso, al igual que el punto 2 el tiempo y la complejidad nos dirán si estamos aplicando de manera correcta el patrón, ya que perder horas montando la infraestructura para un proyecto que no requiere mas de unos minutos, no es lo correcto.

Es un tema para profundizar, pero el primer paso en entender la arquitectura, para luego trabajar con el Framework de DataBinding .

lunes, 14 de septiembre de 2015

Qué es Data Binding

El anuncio de Android M, la nueva versión del sistema operativo móvil de Google, en Google I/O no fue tan relevante para los usuarios, pero sí lo fue para los desarrolladores. Y esto se debe a la presentación de una de sus herramientas, que podrá cambiar el futuro del desarrollo para esta plataforma. Su nombre es Data Bindig.
Entre muchas cosas, el Data Binding nos permite dejar de preocuparnos por la actualización de las vistas cuando los datos cambian. Y para los que no se atreven con Android por culpa de Java, no hay que preocuparse, con Data Binding se escribe muchísimo menos código Java.

Qué necesito para empezar

Para poder usar Data Binding es necesario tener instalada la última versión de Android Studio 1.3. Además necesitaremos el preview del SDK de Android M, que se puede instalar desde el SDK Manager. Por último, es necesario contar con Android M. Es posible descargar una imagen de Android M para emularlo o actualizar tu Nexus con la preview.
Lo siguiente será configurar las dependencias del proyecto. Un nuevo proyecto de Android Studio tiene dos archivos build.gradle. Uno pertenece al proyecto y el otro pertenece al módulo de la aplicación. Vamos a modificar primero el gradle.build del proyecto.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:1.2.3'
        classpath "com.android.tools.build:gradle:1.3.0-beta4"
        classpath "com.android.databinding:dataBinder:1.0-rc1"
    }
}
 
allprojects {
    repositories {
        jcenter()
    }
}
Pero también es necesario añadir la configuración necesaria al archivo build.gradle del módulo, aplicando el plugin de Data Binding con el siguiente código:
Tampoco hay que olvidar que trabajamos sobre la preview del SDK de Android M.
1
2
apply plugin: 'com.android.application'
apply plugin: 'com.android.databinding'
Tampoco hay que olvidar que trabajamos sobre el preview del SDK de Android M.
1
compileSdkVersion 'android-MNC'
1
2
minSdkVersion 'MNC'
targetSdkVersion 'MNC'

El modelo

Antes que cualquier cosa, necesitaremos crear un modelo que usaremos en la aplicación. Este deberá contar con las siguientes características:
  • Extender de BaseObservable
  • Los getters de los atributos necesitan la anotación @Bindable
  • En los setters deberemos notificar que los datos han cambiado connotifyPropertyChanged
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class User extends BaseObservable {
    private String firstName;
 
    public User(String firstName) {
        this.firstName = firstName;
    }
 
    @Bindable
    public String getFirstName() {
        return this.firstName;
    }
 
    public void setFirstName(String firstName) {
        this.firstName = firstName;
        notifyPropertyChanged(com.stanete.databinding.BR.firstName);
    }
}

¿Y la interfaz?

Data Binding cambia la forma en la declaramos los layouts o vistas. Ahora debemos especificar qué tipo de datos reciben las vistas y qué objeto va a proveer estos datos.
Por esta razón, los layouts se componen de dos partes:
  • Un parte en la que especificaremos las variables que usaremos
  • Una segunda parte en la que declararemos las vistas
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
    xmlns:tools="http://schemas.android.com/tools"
    tools:context=".MainActivity">
 
    <!-- Las variables que usaremos -->
    <data>
        <variable
            name="user"
            type="com.stanete.databinding.User" />
    </data>
 
    <!-- Las vistas -->
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:orientation="vertical">
 
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{user.firstName}"
            android:textSize="18sp" />
 
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="changeData"
            android:text="HACER MAGIA" />
    </LinearLayout>
</layout>

El toque final

Aquí es cuando ocurre la magia de Data Binding. En la Activity no vamos a hacer referencia a las vistas, Data Binding elimina eso por completo. Ya no encontraremos ningún findViewById ni ningún onClickListener.
Antes de seguir, es necesario hacer Rebuild del proyecto. La librería de Data Binding generará una clase Java por cada *bindable layout. El nombre de las clases Java se llamarán en función del nombre de tus vistas, añadiéndole el sufijo Binding. De tal forma que, si tu layout se llama activity_main.xml, la clase se llamará ActivityMainBinding. Y esta clase será la que usaremos para enlazar los datos con las vistas.
Necesitamos añadir un par de líneas al código de la Activity, para enlazar los datos con la vista. Aquí también añadiremos un método changeData que se ejecute cuando hagamos click en un botón.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class MainActivity extends AppCompatActivity {
 
    User user;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
 
        ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
 
        user = new User("Freddy");
        binding.setUser(user);
    }
 
    public void changeData(View view) {
        user.setFirstName("Christian");
    }
}
Ya podemos ejecutar la aplicación en cualquier emulador o dispositivo con Android M. Al pulsar el botón los datos cambiarán, y como consecuencia, la vista se actualizará.

Data Binding nos permite crear aplicaciones Android de una manera más sencilla y rápida. Es una nueva forma de desarrollar Android, que cambia el paradigma de las arquitecturas actuales.