Patrón de diseño VIPER en Swift para desarrollo de aplicaciones iOS.

Todo lo que tiene un principio, tiene un final: Gatama Buda. Fuente de la imagen: captura de pantalla tomada de la película

Los patrones de diseño son un regalo de Dios para los desarrolladores de software. Estas son técnicas que minimizan la duplicación de código, evitan un alto acoplamiento y estandarizan una forma común de escribir código que proporciona una solución general para situaciones recurrentes mientras se desarrolla un software. En esta historia nos familiarizaremos con un patrón de diseño llamado VIPER (View, Interactor, Presenter, Entity and Router) para el desarrollo de iOS.

Requisitos previos: antes de comenzar con VIPER, asegúrese de conocer el patrón de diseño arquitectónico y el patrón de delegación.

¿Qué es la víbora?

Viper es un patrón de diseño que implementa el paradigma de "separación de preocupaciones". Principalmente como MVP o MVC, sigue un enfoque modular. Una característica, un módulo. Para cada módulo, VIPER tiene cinco (a veces cuatro) clases diferentes con roles distintos. Ninguna clase va más allá de su único propósito. Estas clases son las siguientes.

Ver: Clase que tiene todo el código para mostrar la interfaz de la aplicación al usuario y obtener sus respuestas. Al recibir una respuesta, Ver alertas al presentador.

Presentador: Núcleo de un módulo. Obtiene la respuesta del usuario desde la Vista y funciona en consecuencia. Única clase para comunicarse con todos los demás componentes. Llama al enrutador para enmarcar el cable, Interactor para buscar datos (llamadas de red o llamadas de datos locales), ver para actualizar la IU.

Interactor: tiene las lógicas comerciales de una aplicación. Principalmente hacer llamadas API para obtener datos de una fuente. Responsable de hacer llamadas de datos pero no necesariamente de sí mismo.

Enrutador: hace la estructura de alambre. Escucha del presentador sobre qué pantalla presentar y la ejecuta.

Entidad: contiene clases de modelo simple utilizadas por el interactor.

A continuación se muestra un diagrama simple de VIPER

Arquitectura de la víbora

Viper con ejemplo

He creado un proyecto simple para explicar la víbora. Se puede encontrar en GitHub. Es una aplicación muy básica que muestra un titular de noticias obtenido de una API externa. (Qué inútil: p).

Viper es una arquitectura impulsada por la delegación. Entonces, la mayor parte de la comunicación entre las diferentes capas se ejecuta a través de la delegación. Una capa llama a otra a través de un protocolo. La capa de llamada llama a una función desde un protocolo. La capa de escucha se ajusta a ese protocolo e implementa la función.

A continuación explicaré cómo he implementado VIPER en uno de mis proyectos de muestra. Te sugiero que abras el proyecto en github y lo revises mientras lees la explicación.

Protocolos

He creado un archivo separado para todos los protocolos.

Se sigue una convención de nomenclatura para nombrar un protocolo. Por ejemplo, "viewToPresenterProtocol". Por lo tanto, es un "protocolo" que será implementado por "el presentador" para escuchar lo que la "vista" tiene que decir.

  • PresenterToViewProtocol: Presenter llama, Ver escucha. El presentador recibe una referencia de este protocolo para acceder a Vista. Ver se ajusta al protocolo.
  • ViewToPresenterProtocol: Ver llamadas, el presentador escucha.
  • InteractorToPresenterProtocol: Llamadas interactivas, el presentador escucha.
  • PresentorToInteractorProtocol: Presentador llama, Interactor escucha.
  • PresenterToRouterProtocol: el presentador llama, el enrutador escucha.

App Flow

La vista tiene una referencia de "ViewToPresenterProtocol" para acceder al "Presentador" y se ajusta a "PresenterToViewProtocol". En su viewDidLoad () llama a la función updateView () del protocolo.

//Ver
presentador var: ViewToPresenterProtocol?
anular func viewDidLoad () {
   super.viewDidLoad ()
   presentador? .updateView ()
}

El presentador, por otro lado, se ajusta a "ViewToPresenterProtocol". Entonces, implementa la función updateView ().

//Presentador
var interactor: PresentorToInteractorProtocol ?;
func updateView () {
   interactor? .fetchLiveNews ()
}

El presentador interior updateView () le dice al interactor que busque algunos datos de noticias en vivo.

Interactor se ajusta a "PresentorToInteractorProtocol". Entonces implementa la función fetchLiveNews (). Esta función intenta hacer una llamada de red y obtener datos. Tiene una referencia de "InteractorToPresenterProtocol" para acceder al "Presentador".

// Interactor
presentador var: InteractorToPresenterProtocol?

Si la llamada de red ha obtenido los datos correctamente, llama a la siguiente función.

// Interactor
self.presenter? .liveNewsFetched (noticias: (arrayObject? [0])!)

si no

// Interactor
self.presenter? .liveNewsFetchedFailed ()

Ahora presentador también se ajusta a "InteractorToPresenterProtocol". Entonces implementa estas funciones.

//presentador
func liveNewsFetched (noticias: LiveNewsModel) {
        ver? .showNews (noticias: noticias);
}
func liveNewsFetchedFailed () {
        ver? .showError ()
}

Entonces le dice a la vista si mostrar noticias o mostrar el error.

Ahora, Ver se ajusta a "PresenterToViewProtocol". Por lo tanto, implementa showNews () y showError (). En estas dos funciones, la vista completa la vista con los datos recuperados o el error.

La capa de entidad

Arriba, en la sección de flujo de la aplicación, la capa de entidad no se discute. No se conecta directamente con el flujo de la aplicación. Pero es una parte integral para el interactor. La capa de entidad proporciona un modelo que el interactor usa para crear objetos a partir de los datos recuperados.

Enrutador

El enrutador se encarga del enmarcado de una aplicación. Cambiar la pantalla en una aplicación es algo muy básico. En VIPER, la capa de enrutador es responsable de ejecutar eso.

Hemos discutido anteriormente que en la arquitectura VIPER cada funcionalidad tiene un solo módulo y un módulo contiene esas cinco capas. Un presentador llama al enrutador para crear un nuevo módulo. Luego, el enrutador primero inicia toda la clase de capa y devuelve el módulo.

En mi proyecto de muestra no hay cambio de módulo en la aplicación. Pero el enrutamiento ocurre cuando la aplicación se inicia por primera vez. Entonces, dentro de AppDelegate 'didFinishLaunchingWithOptions ()', se llama a la función createModule () del enrutador. Devuelve un módulo. La clase UIWindow luego muestra la vista de ese módulo.

Por qué y cuándo usar VIPER

VIPER sigue una arquitectura muy limpia. Aísla cada módulo de los demás. Por lo tanto, cambiar o corregir errores es muy fácil, ya que solo tiene que actualizar un módulo específico. También por tener un enfoque modular, VIPER crea un ambiente muy bueno para las pruebas unitarias. Como cada módulo es independiente de los demás, mantiene un acoplamiento bajo muy bien. Entonces, dividir el trabajo entre los co-desarrolladores es bastante simple.

VIPER debe usarse cuando los requisitos de una aplicación están muy bien formados. Trabajar con requisitos en constante cambio puede crear confusión y códigos confusos. Por lo tanto, no debe usarse en proyectos pequeños, ya que MVP o MVC serán suficientes. Además, se debe usar VIPER si todo el desarrollador del proyecto comprende completamente el patrón.

Herramientas VIPER

Si uno quiere usar VIPER en un proyecto, lo más inteligente sería usar un generador de estructura de módulo automático. De lo contrario, crear archivos para módulos será monótono. Hay pocos generadores disponibles en línea.

  • Generamba
  • Código VIPER
  • VIPER Gen

Conclusión

Al igual que cualquier otro patrón de diseño, VIPER se explica por sí mismo. Uno necesita ensuciarse las manos para comprender la imagen completa. Mi consejo será comenzar primero con la creación de una aplicación muy básica con VIPER y, en el proceso, leer el recurso en línea. Mi repositorio de Github también podría ser una buena referencia.

Feliz codificación :)

Larga vida al sagrado Bangladesh.

Bangladesh es un mundo de metáforas, de teatro alto y bajo, de gran poesía y música. Hablas con un agricultor de arroz y encuentras un poeta. Conoces a un barrendero de las calles y encuentras un cantante notable.
Jean Houston

Referencia:

  1. https://medium.com/ios-os-x-development/ios-architecture-patterns-ecba4c38de52
  2. https://medium.com/@ankoma22/the-good-the-bad-and-the-ugly-of-viper-architecture-for-ios-apps-7272001b5347
  3. https://github.com/MindorksOpenSource/iOS-Viper-Architecture/tree/master/iOS-Viper-Architecture
  4. https://sourcemaking.com/design_patterns