Patrones de arquitectura de software para iOS

Podemos definir la arquitectura de software como un conjunto de patrones que proporcionan una serie de guías para la creación de un programa. Permite a los programadores, analistas y todo el equipo de desarrollo compartir la misma línea de trabajo para poder alcanzar de manera más productiva todos los objetivos de la aplicación. Es considerada el nivel más alto en el diseño de diseño del software ya que establecen la estructura, funcionamiento e interacción entre las partes del software.

Una buena arquitectura de software permite:

  • Distribución bien balanceada de responsabilidades entre las entidades con roles estrictos. 
  • Permite realizar tests unitarios con facilidad y eficacia, con todo lo que ello implica.
  • Facilita el mantenimiento de la aplicación.

Explicar cada uno de los patrones de arquitectura llevaría mucho tiempo y espacio, por ahora solo voy a hacer una somera descripción de los más utilizados -que son con los que me he topado en mi trabajo-.

MVC: Modelo - Vista - Controlador

Es el patrón clásico por excelencia. El Modelo se encarga de los datos, la vista se encarga de la parte visual y el control de las interacciones entre la vista y el modelo.

Es el modelo aplicado por Apple por defecto aunque la aplicación que hacen de él no es un MVC real ya que la vista y el controlador actúan de una manera enrevesada entre ellos de tal manera que terminan actuando como un ente único de cada al modelo.

Este tipo de patrón se conoce en el mundillo como Massive View Controller por la cantidad de flujo y código extra que genera.

Esta estructura provoca también que sea muy complicado crear tests unitarios en un tiempo razonable y con una cobertura.

El desarrollo con este patrón es muy rápido, pero olvídate de crear tests decentes en un tiempo razonable.

MVP: Modelo - Vista - Presentador

Realmente este patrón es mucho más parecido al MVC real que el Cocoa MVC de Apple.

La vista en este caso es completamente pasiva. El Presentador actualiza la Vista e interacciona con el modelo.

En este patrón el UIViewController es solo una vista, perfectamente "mockeable" desde el Presentador, lo cual es genial para programar los tests.

La vista, el presentador y el modelo están en tres ficheros distintos. Los datos y los eventos se vinculan de manera manual, lo cual lleva bastante trabajo.

La distribución de responsabilidades queda claramente determinada, es mucho más fácil desarrollar tests y aunque este patrón te obliga a programar más código es más sencillo de mantener.

MVVM: Modelo - Vista - VistaModelo

El modelo y la vista son similares a los patrones anteriores, aquí la novedad está en la VistaModelo que cumple las funciones de mediador entre los otros dos.

La VistaModelo contiene una representación de la Vista, está vinculado (bind) con ella de tal manera que cualquier cambio que se ejecuta en la VistaModelo se actualiza de manera automática en la Vista. Estos cambios vienen provocados por la interacción de la VistaModelo con el Modelo.

MVVM no está bien soportado por Cocoa así que se utiliza ReactiveCocoa para permitir su implementación. Cuidado con React, te puede complicar mucho las cosas en iOS.

La distribución de responsabilidades también está bien definida, aunque la Vista tiene más responsabilidades que en MVP. Al ser la vista una capa abstracta para la VistaModelo es sencillo hacer tests. Por último sigue siendo sencillo mantener el código y en este caso gracias a los "bindings" el código escrito será menor.

VIPER: Vista - Interactuador - Presentador - Router - Entidad

La Vista cumple la misma función que en el resto de patrones, en este caso el papel lo ejerce el UIViewController o el UIView.

El Interactuador contiene la lógica de negocio de las entidades y de las conexiones con el Router

El presentador contiene toda la lógica de la parte visual e interacciona con el Interactuador y con la Vista.

Las entidades son conjuntos de datos planos.

El router se encarga de las conexiones entre los segues de VIPER.

Con este patrón en una sola pantalla podemos construir una aplicación intercambiando los diferentes elementos como si fuesen piezas de Lego. La responsabilidad de la navegación entre secciones cae de lleno en el Router.

Las responsabilidades en este patrón están muy distribuidas, los tests son muy sencillos de desarrollar y el mantenimiento es sencillo, el problema es que desarrollar una app con VIPER lleva mucho más trabajo que con los patrones anteriores.

Si quieres usar este patrón te recomiendo que uses Generamba para generar un proyecto vacío desde el que partir.

Estos patrones de arquitectura pueden ser utilizados también en proyectos para Android, de hecho, cuando el proyecto está en las dos plataformas es una buena manera de mantener organizado el mismo.

Hay muchos más patrones que se utilizan en otras ramas del software como el cliente-servidor,  maestro-esclavo, etc. Normalmente al principio suponen trabajar más lento, pero luego se agradacen mucho cuando el proyecto está en producción y hay que mantenerlo o ampliarlo.

A la hora de elegir el patrón debes evitar que el collar sea más grande que el perro. Es decir, si te piden una prueba de concepto de una app con 4 funcionalidades no te líes la manta a la cabeza con los patrones más complejos, utiliza un MVC para la prueba y listo. Por desgracia es muy habitual matar moscas a cañonazos con tal de realzar nuestro ego como desarrolladores.

Para el resto de los casos vamos a necesitar hacer tests así que habrá que utilizar MVP, MVVM o VIPER.

Comentarios