8 cosas aprendidas de Android en el Codemotion 2014

En el pasado Codemotion 2014 pude asistir a varias charlas relacionadas con el desarrollo de aplicaciones para Android, en las que pude aprender y recordar algunos conceptos y herramientas que resumo en este pequeño artículo:

1. Model-View-Presenter

Fuente: Wikipedia DE
Fuente: Wikipedia DE

El patrón Model View Presenter es muy similar a Model View ViewModel en la base, ya que tanto el ViewModel como el Presenter notifican a la vista de los cambios, y reciben los comandos de la misma.

En el caso de Android, se propone el uso de Interfaces entre Presenter y la Vista, de manera que trabajamos, con clases abstractas, consiguiendo cierta independencia con las implementaciones.

2. Arquitecturas hexagonales

El uso de las clases abstractas con los MVP es lo que deriva en una arquitectura hexagonal, en la que mediante puertos (que es como se denominan estas interfaces) nuestra lógica de negocio se comunica con las diferentes abstracciones de la vista y diferentes servicios como comunicaciones o almacenamiento.

Fuente: VICTOR SAVKIN
Fuente: VICTOR SAVKIN

En el caso concreto de Android, la lógica de negocio puede estar completamente aislada en un módulo Java puro, lo que da una mayor independencia de la plataforma.

3. Documentación de calidad mantenida por la comunidad

android-guides

Los manuales de android guides, creados por los chicos de codepath, contienen (a fecha de hoy) más de 100 artículos con guías prácticas de desarrollo, cubriendo temas como fragments, persistencia, o guías completas como cómo empezar con gradle. Resultan verdaderamente interesantes y desde luego es un lugar a añadir a mi lista de favoritos.

4. Motores de Inyección de dependencias

De la misma manera que tenemos ninject en .NET o bien podemos crear nuestro propio motor, para Android tenemos Dagger (para inyección de dependencias en general) y Butterknife (para inyectar vistas), que nos permiten gestionar las dependencias de nuestros objetos (para implementar una arquitectura hexagonal como la que hemos definido anteriormente, por ejemplo).

5. Bases de datos y almacenamiento

url

En función de las necesidades que tengamos, hay dos proyectos que deberíamos tener en cuenta:

  • SugarORM, permite tener una base de datos local de manera extremadamente simple y manejable.
  • ORMLite compatible con cualquier proyecto de Java y permite una mayor personalización y estructuras un poco más complejas, además de estar más extendido en la comunidad.

Además, podemos o bien utilizar la clase ContentProvider para almacenar datos, o bien usar los adaptadores propios del sistema operativo, aunque se recomiendan las dos opciones anteriores.

Web: SugarORM (no confundir con SugarCRM): http://satyan.github.io/sugar/
Web: ORMLite: http://ormlite.com/

6. Testing

Para desarrollo Android tenemos muchas herramientas para hacer testing, desde JUnit que nos permite además de código Java estándar probar código específico para la plataforma, pasando por Mockito para crear artefactos para nuestros tests, y acabando con Espresso, para probar la UI de nuestra aplicación.

7. Programación reactiva

La programación reactiva o Reactive Programming es un paradigma que se basa en el flujo de datos, actualizando la visualización de los mismos a través del envío y recepción de mensajes. Es un tema verdaderamente interesante, ya que mezcla conceptos de programación funcional con patrones de lenguajes orientados a objetos como observer.

8. Otros lenguajes

Uno de los puntos fuertes de la JVM es la capacidad para ejecutar otros lenguajes más allá de Java, de esta manera podemos usar lenguajes como Kotlin (creado por Jetbrains), Groovy o incluso Clojure para hacer aplicaciones Android. El soporte para otros lenguajes es algo que está en proceso, pero que podemos tener en cuenta (Android Studio se lleva bastante bien con Kotlin, por ejemplo). Si nos vamos fuera de la JVM tenemos opciones como Xamarin que nos permite desarrollar apps para Android usando C#.

Conclusiones

Esta lista es solamente un resumen de varias charlas y conversaciones tenidas durante el evento. El ecosistema Android es muy interesante, no solo por todas las herramientas y técnicas disponibles, que una vez aplicadas se pueden llevar a otras plataformas, sino además por la comunidad que tiene, no solamente Android sino el lenguaje Java y los lenguajes basados en la JVM.

Nos vemos en la siguiente, aquí te dejo un recopilación de todas las charlas del Codemotion: https://docs.google.com/spreadsheets/d/14ZjJQ_VeT8mKmO8MANA1Os5zwRA3Pu_rpFdfyFtBZ4A/edit#gid=0

Creating a Dependency Injection Engine with C#

According to the Wikipedia, dependency injection is a software design pattern that implements inversion of control and allows a program design to follow the dependency inversion principle. This patttern is implemented in C# with engines that generate all the required dependencies for our objects like Ninject, an open-source engine with a simple syntax and plugins for ASP.net MVC and SignalR.

In this article, we will see how does a dependency injection engine works by creating our own, based on Ninject’s syntax and philosophy.

Introduction

Dependency injection helps us to separate the concerns between the different layers of our code, and improve the encapsulation and testability of our code. Let’s start with a simple code, a list of notes that allows us to add a note, and saves it by calling _dataStorage, an object initialized in the constructor:

public class NoteList
{
    private DataStorage _dataStorage;
    public NoteList()
    {
        _dataStorage = new DataStorage();
    }
    public void Add(string note)
    {
        if (string.IsNullOrEmpty(note))
        {
            throw new ArgumentException("Note cannot be empty");
        }

        _dataStorage.Save(note);
    }
}

DataStorage is a class that writes the content of the note to disk, and has the following code for the Save method:

internal void Save(string note)
{
    using (StreamWriter writer = new StreamWriter("db.txt"))
    {
        writer.WriteLine(note);   
    }
}

The test code is the following:

//Arrange
var noteList = new NoteList();
var noteText = "myCustomNote";

//Act
noteList.Add(noteText);

//Assert
using (StreamReader reader = new StreamReader("db.txt"))
{
    var all = reader.ReadToEnd();
    Assert.IsTrue(all.Contains(noteText));
}

As we can see, we are generating a dependency on DataStorage (they are coupled), so this means that we cannot test NoteList unless we also test the behavior of DataStorage.

Removing coupling

The first thing we can do is to abstract DataStorage in an interface called IDataStorage. The following step is passing it as an argument, instead of initializing on the constructor:

...
private IDataStorage _dataStorage;
public NoteList(IDataStorage dataStorage)
{
    _dataStorage = dataStorage;
}
...

The test code also changes, so we define the dependencies from outside the class:

...
var dataStorage = new DataStorage();
var noteList = new NoteList(dataStorage);
var noteText = "myCustomNote";
...

Building our injector

Now we have a class that receives the parameters as arguments. These parameters must be defined and initialized manually before calling our constructor, so the first step is generating the parameters by asking our Injector for a specific type. The first version of our injector is a static class with two methods and an internal dictionary to hold the mappings, and it looks like this:

private static Dictionary<Type, object> mappings
    = new Dictionary<Type, object>(); 

public static T Get<T>()
{
    return (T)mappings[typeof(T)];
}

public static void Map<T>(object o)
{
    mappings.Add(typeof(T), o);
}

Now we can request an object for the interface in our test:

Injector.Map<IDataStorage>(new DataStorage());
var dataStorage = Injector.Get<IDataStorage>();

This code has an issue, that is that we always return the same object, and we are still specifying the injector in the constructor. It would be easier if the injector returns a new copy of the object and if we could also request our object directly from the injector:

Injector.Map<IDataStorage>(new DataStorage());
var noteList = Injector.Get<NoteList>();

For having these results we need to do some heavy improvements to our Injector. The first thing we are going to do is to divide the Get method into a non-generic one, so we can use recursion someway later:

public static T Get<T>()
{
    var type = typeof(T);
    return (T)Get(type);
}

The second thing we are going to do, instead of storing the object in our dictionary, is store the type, so we change also the Map method, this way we make sure of not storing a specific object:

public static void Map<T, V>() where V : T
{
    mappings.Add(typeof(T), typeof(V));
}

And finally, we are going to change our Get method to invoke the constructor of the requested type, after some extra checks:

private static object Get(Type type)
{
    var target = ResolveType(type);
    var constructor = target.GetConstructors()[0];
    var parameters = constructor.GetParameters();

    List<object> resolvedParameters = new List<object>();

    foreach (var item in parameters)
    {
        resolvedParameters.Add(Get(item.ParameterType));
    }

    return constructor.Invoke(resolvedParameters.ToArray());
}

Let’s review this code step by step: The first thing it does is resolving the type, this means checking if we have any mapping available for the specific type, if not, it returns the same type:

private static Type ResolveType(Type type)
{
    if (mappings.Keys.Contains(type))
    {
        return mappings[type];
    }

    return type;
}

After being sure about using the correct type, the next step is retrieving the constructor for the specified type, and the list of its parameters (if any).

...
    var target = ResolveType(type);
    var constructor = target.GetConstructors()[0];
    var parameters = constructor.GetParameters();
...

If the constructor has parameters, then each parameter type it will try to resolve it individually, and if the resolution was successful, it is added to a list of resolved parameters (the order here is very important, as it must match the order of the constructor signature).

    foreach (var item in parameters)
    {
        resolvedParameters.Add(Get(item.ParameterType));
    }

Finally, the constructor is invoked with the parameter list and returns the created object.

    return constructor.Invoke(resolvedParameters.ToArray());

The final syntax for getting a new object from our dependency injector is the following:

Injector.Map<IDataStorage, DataStorage>();
var noteList = Injector.Get<NoteList>();

The result is a very convenient way of generating an object without caring about its dependencies, that may be defined at a way higher level.

Recap

Dependency injection is not an obscure term, it allows us to create uncoupled architectures, and engines like the one we just created allow us to create the required infrastructure at a higer level, so the rest of the classes have only the logic related to its own behavior, with the minimum set of dependencies. It’s also not a very complicated piece of software, although ninject has a way more features and is far more robust that what we have seen here, but this is just step one.

Also, C#’s language features allow us to do some metaprogramming by getting types, parameters of a constructor and invoking it at runtime, which is not bad for a strongly typed language. It would be interesting to see how we could create a version of this injector in a more dynamic, loosely typed environment.

Get the code and play with it!