Cuándo utilizar VIPER

Como os dijimos hace unos días, vamos a continuar con VIPER y vamos a profundizar un poco más. En esta publicación os contaremos en qué ocasiones utilizaremos VIPER y en qué momentos no.


3. ¿Cuándo debemos utilizar VIPER?

Al crear un proyecto que tiene un potencial de evolución, es importante pensar en una estructura que se adapte bien y que permita que muchos desarrolladores trabajen simultáneamente en él de la manera más perfecta posible. Por ello, en estos casos, la estructura MVC puede no ser suficiente para mantener un proyecto que esté debidamente organizado.

Es muy común que los desarrolladores se encuentren depurando una gran clase para buscar un error y se sientan como si estuvieran buscando una aguja en un pajar.

Con el desacoplamiento entre los objetos que VIPER propone, podremos ver que:

  • Es más fácil hacer un seguimiento de los problemas a través de informes de fallos (debido al Principio de Responsabilidad Única).
  • Añadir nuevas funciones es más fácil.
  • El código será más limpio, más compacto y reutilizable.
  • Hay menos conflictos con el resto del equipo de desarrollo.
  • Es más fácil escribir pruebas automatizadas (dado que su lógica de UI está separada de la lógica de negocios).
  • Cumple con los principios SOLID.

¿Cuándo NO debemos utilizar VIPER?

Dependiendo del tipo de proyecto, será mejor utilizar un tipo de arquitecturas u otra.
Debido a la cantidad de elementos involucrados, VIPER puede generar una sobrecarga cuando se inicia un nuevo proyecto (aunque en gran medida se amortiza a largo plazo). Por ello, puede ser una exageración para proyectos pequeños que no pretenden escalar.

Si el equipo no está completamente alineado con el mantenimiento de la estructura de VIPER, terminará con una combinación MVC-VIPER que puede causar dolores de cabeza, así que asegurémonos de que el equipo esté completamente sincronizado antes de seguir adelante con esta arquitectura.

Conclusiones

VIPER es un patrón de arquitectura para proyectos iOS realmente bueno, entre otros, como MVP y MVVM, que cumple con los principios SOLID, los más importantes en la programación orientada a objetos. Si tienes curiosidad por saber más sobre la arquitectura VIPER, existen más artículos relacionados en internet, pero nuestra recomendación es que te descargues repositorios que utilicen la arquitectura y que practiques a partir de ellos, (que incluso puedes montarte tus propios proyectos desde cero).

El uso de VIPER en la arquitectura de proyectos iOS

Al desarrollar una aplicación iOS es importante pensar qué arquitectura debemos utilizar.

La mayoría de los desarrolladores usan el patrón sugerido por Apple: la arquitectura denominada MVC (Model-View-Controller). Sin embargo, como muchos otros patrones, el MVC tiene sus fallos:

Por un lado, debido a su simplicidad, lleva incluso a los programadores más
experimentados a poner código que no pertenezca a una vista ni a un modelo en la lógica del controlador, generando otros de gran tamaño y vistas y modelos realmente compactos, o lo que es peor, muchas dependencias.

Por ello, en esta publicación veremos VIPER, una de las alternativas de tendencia a MVC que puede ayudarnos a superar sus limitaciones, así como a mantener nuestro código modular y bien organizado, mejorando el proceso de desarrollo.

¿Qué es VIPER?

VIPER son las siglas de View, Interactor, Presenter, Entity, Router.
Y es básicamente un enfoque que implementa el principio de responsabilidad única para crear una estructura más limpia y para modular un proyecto iOS.

La idea detrás de este patrón es la de aislar las dependencias de la aplicación, equilibrando la delegación de responsabilidades entre las entidades, lo que se logra utilizando la siguiente arquitectura:

En este diagrama se ilustra la arquitectura VIPER, en la que cada bloque corresponde a un objeto con tareas, entradas y salidas específicas.

Pensemos en estos bloques como si fueran trabajadores en una línea de ensamblaje: una vez que el trabajador completa su trabajo con un objeto, este pasa al siguiente empleado y así hasta que se termina el producto.
Las conexiones entre los bloques representan la relación entre los objetos y qué tipo de información se transmiten entre sí. Y la comunicación de una entidad a otra se da a través de protocolos, pero eso lo explicaremos un poco más adelante.

Arquitectura de proyecto iOS

Teniendo en cuenta el verdadero propósito de la arquitectura VIPER, lo importante es comprender primero un poco cómo es cada parte y cuáles son sus responsabilidades.

Para ello, desarrollaremos una aplicación básica que obtiene una lista de artículos de un API REST y los muestra por pantalla.

1. View

La View en una aplicación iOS con VIPER. Se trata de un UIViewController que contiene una subvista que puede implementarse mediante programación o utilizando el Interface Builder.
Su responsabilidad es la de mostrar lo que el Presenter le dice y manejar las interacciones del usuario con la pantalla.
Cuando este activa cualquier evento que requiera procesamiento, la View simplemente lo delega al Presenter y espera una respuesta que le indique qué se debe mostrar a continuación.

Así es como sería la View para nuestra visualización de artículos en Swift:

2. Presenter

El Presenter funciona como un puente entre las partes principales de un módulo VIPER. Por un lado, recibe eventos de entrada provenientes de la View y reacciona a ellos solicitando datos al Interactor.
Por otro lado, recibe las estructuras de datos que provienen del Interactor, aplica la lógica de vista sobre estos datos para preparar el contenido y, finalmente, le dice a la View qué debe mostrar.
Aquí hay un ejemplo de un Presenter para nuestra aplicación de visualización de artículos:

3. Interactor

Podemos pensar en este objeto como una colección de casos de uso dentro de un módulo específico. El Interactor contiene toda la lógica de negocios relacionada con las entidades y debe ser completamente independiente de la interfaz de usuario.
En nuestra aplicación de visualización de artículos, un ejemplo de caso de uso es buscar la lista de artículos del servidor.

Es responsabilidad del Interactor realizar las solicitudes, manejar las respuestas y convertirlas en una Entity (que, en este caso, es un objeto del artículo).
Una vez que el Interactor termina de ejecutar alguna tarea, notifica al Presenter sobre el resultado obtenido. Algo muy importante que se debe tener en cuenta, es que los datos enviados al Presenter no deben implementar ninguna lógica comercial, por lo que deben estar limpios y listos para usar.

En nuestra aplicación de visualización de artículos, el Interactor sería responsable de obtener los artículos de una API:

4. Entity

La Entity es probablemente el elemento más simple dentro de una estructura VIPER. Encapsula diferentes tipos de datos y, por lo general, se trata como una carga útil entre los otros componentes de VIPER.
Una cosa importante a tener en cuenta es que la Entity es diferente de la capa de acceso a datos, que debe ser manejada por el Interactor.

En nuestra aplicación de visualización de artículos, la clase de artículos sería un ejemplo de una entidad:

5. Router

El último y quizás el elemento más peculiar de la arquitectura VIPER es el Router, que es responsable de la lógica de navegación entre los módulos, y cómo deben suceder (por ejemplo, definir una animación para presentar una pantalla o cómo se debe realizar la transición entre dos pantallas). Recibe los comandos de entrada de los Presenter para indicar a cuál de estas debe dirigirse.

Además, debe ser responsable de pasar los datos de una pantalla a la otra. Debe implementar un protocolo que defina todas las posibilidades de navegación para un módulo específico (lo que permite una visión general rápida de todas las rutas que puede tomar una aplicación con solo mirar el protocolo del Router).

Debido a una limitación del marco de trabajo de iOS, solo los ViewControllers pueden realizar una transición entre pantallas, por lo que un Router debe contener una referencia al controlador del
módulo o a cualquiera de sus elementos secundarios.

Así es como se vería nuestro Router en la aplicación de visualización de artículos (hay que tener en cuenta además que al Router se le conoce como Wireframe).

En la próxima publicación seguiremos hablando de VIPER y explicaremos cuándo debemos utilizarla y cuándo no.

Comenzar un proyecto en Angular

En esta publicación vamos a explicar cómo comenzar un proyecto en Ángular de la mano de nuestro compañero Dani G.

Todo programador en algún punto de su vida se ha preguntado con qué lenguaje de programación utilizar a la hora de comenzar un nuevo proyecto. Normalmente, se suelen utilizar aquellos con los que ya se ha trabajado o que se conocen muy bien, pero son muchos más los valores que se deben tener en cuenta antes de escoger uno.

Para ello, tenemos que hacernos una serie de preguntas:

¿Tiene dicho lenguaje una documentación lo suficientemente detallada y clara como para resolver dudas?

¿Tiene comunidad que siga desarrollando extensiones y actualizaciones?

¿Sera fácil encontrar compañeros que conozcan este lenguaje?

¿La curva de aprendizaje sera rápida y sencilla?

¿Podré escalar mi proyecto llegado el momento?

¿Quien se encuentra detrás del lenguaje?

¿Alguna compañía “grande” lo usa?

Si con un par de búsquedas en google eres capaz de responder estas dudas de manera satisfactoria, puede ser que hayas escogido el lenguaje que buscas. En el caso de Dani, esta decisión fue Angular, y a continuación nos explica cómo comenzar un proyecto y sus posibilidades a futuro:

1-Iniciar el proyecto en Angular

Según mi experiencia personal, Angular-cli es la manera más rápida de trabajar. Además, en la propia web tenéis información muy detallada sobre cómo usarlo.

2-Diferenciar componentes en el proyecto

Partiendo de la base de que hemos definido nuestro proyecto y tenemos un diseño, aunque sea de servilleta, debemos trocearlo. Es decir, debemos convertirlo en un “lego” para comenzar a crear componentes (mínima unidad con funcionalidad propia). Un ejemplo de esta acción seria así:


Esto es un pequeño ejemplo que te ayudara a tener un proyecto sin acoplamiento, sin código duplicado y con una buena organización.

Con esta división podríamos empezar a crear “secciones” en nuestro proyecto tipo:

  • Componente Header
  • Componente Sidebar
  • Componente Buscador
  • Componente redes sociales
  • Componente menu mobile
  • Componente Párrafo con titulo
  • Componente Tarjeta
  • etc.

3-No reinventar la rueda

Angular ofrece DirectivasPipes y demás utilidades propias del lenguaje que podréis encontrar en su documentación.

También debéis tener en cuenta las librerías realizadas por terceros que están a vuestra disposición en NPM packages y que os agilizarán el trabajo, aunque tampoco se debe abusar.
Antes de añadir un paquete se debe investigar un poco sobre él (si tiene soporte, cuánta gente lo usa…) y se deben tener en cuenta las dependencias del mismo, ya que al incluirlo en nuestro proyecto las adquirimos, además de los posibles problemas a la hora de actualizar Angular cuando sea necesario.

Otro punto considerar es que a mayor numero de paquetes incluidos en el proyecto, mayor es el «peso» de nuestro proyecto y eso puede suponer un problema.

4-Optimización de Assets

Está claro que al añadir una imagen, vídeo o audio al proyecto se debe optimizar para que ocupe el menor espacio posible, aunque siempre sin bajar de la calidad impuesta por nosotros mismos.

5-A programar

Teniendo todo lo anterior, ya solo quedaría comenzar a crear el proyecto y ahora es cuando debemos preguntarnos: «¿sé programar en Angular?»:

Si sabes programar en javascript no tendrás ningún problema y en el caso de no tener ni idea tranquilo, existen miles de plataformas web que ofrecen cursos interactivos por un bajo o nulo coste. Como:

Optimizar el orden de los comandos en un Dockerfile

En nuestra primera publicación vamos a ver cómo se puede optimizar el orden de los comandos en un Dockerfile, 

De las primeras cosas que se explican a la hora de aprender a generar imágenes con Docker es cómo se componen de capas y cómo cada modificación provoca que se genere una capa nueva en la imagen sobre la anterior.

De esta forma si escribimos:

«`dockerfile

FROM alpine

RUN touch hello.txt

«`

Logramos tener una capa que es la imagen base de Alpine y una segunda capa con el archivo /hola.txt



A raíz de ahí se puede pasar a optimizar la gestión de dependencias.

Es evidente que los proyectos no suelen tener imágenes tan simples. Por ejemplo, un proyecto de PHP podría ser algo así:

«`dockerfile

FROM php:7.2-fpm-alpine

RUN curl -sS https://getcomposer.org/installer | php — –install-dir=/usr/local/bin –filename=composer \   

&& composer –version

 COPY . /app

 WORKDIR /app

 RUN composer install –no-interaction –no-progress –no-scripts

«`

 Los pasos para optimizar la gestión de dependencias son:

1.     Obtener la imagen base para PHP FPM

2.     Conseguir e instalar Composer

3.     Copiar el código que contiene composer.json y composer.lock

4.     Instalar las dependencias

Tras esto, el Dockerfile funcionará pero con un pequeño problema: cada vez que modifiquemos parte del código y queramos generar la imagen del último paso, habrá que instalar las dependencias de nuevo.

Esto ocurre al tomarse como base la última capa cacheada, que será la anterior a copiar nuestro código.

Por ello, para solventar este problema podemos pasar a modificar el Dockerfile de la siguiente forma:

«`dockerfile

FROM php:7.2-fpm-alpine

 RUN curl -sS https://getcomposer.org/installer | php — –install-dir=/usr/local/bin –filename=composer \

&& composer –version

COPY composer.* /app

 WORKDIR /app

RUN composer install –no-interaction –no-progress –no-scripts

 COPY . /app

«`

Primero copiamos los archivos de Composer donde están definidas nuestras dependencias y las instalamos. Posteriormente, copiamos los archivos de nuestro proyecto para conseguir que instale las dependencias solo cuando estas cambian.


En esta imagen se puede ver por ejemplo cómo se genera la carpeta vendor con las dependencias del proyecto.

Aquí vemos cómo en el último comando los únicos archivos que se añaden son los del proyecto.

¡EXTRA!

Para saber qué ocurre en una imagen de Docker hemos utilizado la herramienta Dive, os recomendamos que le echéis un ojo si no la conocíais antes.