¿Qué es la arquitectura MVVM? Para mi gusto, es el futuro de las arquitecturas de desarrollo de aplicaciones. Llevo ya tiempo usando esta arquitectura y me parece muy cómoda, que es su principal ventaja sobre VIPER. También respeta los principios SOLID, es fácilmente testable y una de sus muchas ventajas es que se usa tanto en iOS como en Android ya que VIPER no llegó a gustarle a los desarrolladores Android por su complejidad.
Model
Este elemento es común en todas las arquitecturas de desarrollo. Se trata de una clase o struct que define las propiedades de un objeto. La definición de modelo es que debe ser una estructura de código sencilla, sin funcionalidad. Unicamente propiedades. Y en caso de tener que añadir algún tipo de funcionalidad la separaremos por extensiones dentro del mismo archivo o en archivos separados. Esta estructura debe ser tan sencilla que no debe dar problema al extender el protocolo Codable.
import Foundation struct Person : Codable { var name : String var age : Int var height : Double }
View Model
La principal tarea del view model es ejecutar toda la lógica de una pantalla. También tiene la función de llamar a servicios REST y de extraer datos de la base de datos. Aunque como recomendación, es mejor separar estas consultas en clases distintas para centralizar funcionalidades. El view model tiene contacto directo con el modelo y se comunica con la vista mediante un protocolo. También tiene contacto con el router para hacer cambios de pantallas.
import Foundation class PersonViewModel { weak var view:PersonViewControllerProtocol! var router: PersonRouter! var person:Person! func loadView() { self.person = Person(name: "Alvaro", age: 22, height: 1.79) self.view.didLoadView() } func showNextScreen() { self.router.showPersonsList() } }
VIEW
La vista es sencilla, ya que no debe tener lógica. Solo tiene las funciones de modificar los elementos de la vista según ordene el view model y de pasar las interacciones de la vista al view model para que este las procese y actúe en consecuencia. En mi caso me gusta que la vista conozca directamente al view model y evitar un protocolo intermedio. Aunque es buena práctica usar protocolos para las comunicaciones. El problema es que se vuelve pesado el desarrollo y puede llegar a resultar incómodo y realmente no cambia tanto el resultado ya que el único acceso que tiene la vista al view model y a usar sus variables y funciones públicas.
import UIKit class PersonViewController : UIViewController { var viewModel:PersonViewModel! @IBOutlet weak var name: UILabel! @IBOutlet weak var age: UILabel! @IBOutlet weak var height: UILabel! override func viewDidLoad() { super.viewDidLoad() self.name.textColor = UIColor.red self.age.textColor = UIColor.orange self.height.textColor = UIColor.blue self.viewModel.loadView() } @IBAction func personButtonAction() { self.viewModel.showNextScreen() } } //MARK: - ViewModel communication protocol PersonViewControllerProtocol : class { func didLoadView() } extension PersonViewController : PersonViewControllerProtocol { func didLoadView() { self.name.text = self.viewModel.person.name self.age.text = "\(self.viewModel.person.age) años" self.height.text = "\(self.viewModel.person.height) metros" } }
ROUTER
El router también es un elemento común en arquitecturas y se encarga básicamente de la transición entre pantallas, de formar y relacionar a los elementos de la arquitectura y de proporcionar a cada elemento los datos necesarios para formar la pantalla.
import Foundation class PersonRouter { weak var viewController : PersonViewController! static func getViewController() -> PersonViewController { let viewController = PersonViewController() let router = PersonRouter() let viewModel = PersonViewModel() viewController.viewModel = viewModel viewModel.router = router viewModel.view = viewController router.viewController = viewController return viewController } func showPersonsList() { let vc = PersonListRouter.getViewController() self.viewController.present(vc, animated: true, completion: nil) } }
XCODE Y MVVM
Como ya sabemos XCode proporciona muchas herramientas para automatizar tareas, en este caso la creación de las clases. Podemos automatizar la creación usando templates. Si usamos por ejemplo MVVM con RxSwift podemos crear clases de las que heredar ciertas funcionalidades y crear un módulo usando cocoa pods.
Así que no hay excusas para usar arquitecturas limpias. Quizás tiene un poco de trabajo al principio pero luego se agradece.
Por: Álvaro Royo
iOS Senior Developer | Instructor de “Superpoderes iOS” en el Bootcamp Desarrollo Mobile de KeepCoding
Si tienes algo que deseas compartir o quieres formar parte de KeepCoding, escríbenos a [email protected]