SwiftUI e arquiteturas: MVP

Compartilhe

Compartilhar no facebook
Compartilhar no google
Compartilhar no twitter
Compartilhar no linkedin

Olá!!! Esse é meu segundo artigo sobre como integrar SwiftUI às arquiteturas mais comuns. No artigo anterior, eu falei como integrar SwiftUI com MVC e agora vou falar sobre MVP.

Se você leu meu último artigo, fico feliz em falar com você de novo. Se não, fico feliz em falar com você agora, e sugiro que leia o artigo de MVC.

Eu vou continuar de onde parei e fazer algumas comparações, mas ainda será possível entender esse artigo separadamente.

Então, vamos começar.

  •       •      

MVP

A arquitetura MVP consiste em três componentes:

  •   Model: Serviços, provedores de dados, gerenciadores, e entidades que representam os dados da aplicação. Os elementos dessa camada são responsáveis por coisas como requisição de rede, persistência, parser de informações e assim por diante.
  •       View: Responsável por renderizar a tela, receber ações do usuário e informar o presenter sobre elas.
  •       Presenter: Recebe ações a partir da view, faz as requisições necessárias para a camada de modelo para lidar com as ações apropriadamente, e formata os dados para serem apresentados na view.

Se você não está familiarizado com MVP, possivelmente está dizendo:

Espera um minuto, isso é só MVC substituindo ViewController por Presenter. Isso está certo?

E, bem, realmente parece isso, mas tem algumas diferenças. No MVP com UIKit, o UIViewController é considerado como parte da view e a responsabilidade do Controller do MVC passa para o presenter.

image1

 

Mas por quê? Como isso muda as coisas?

Lembre-se que UIViewControllers também lidam com o ciclo de vida da view, com métodos como viewDidLoad, viewWillAppear e viewDidAppear. Consequentemente, eles se tornam muito difíceis de testar, porque esses comportamentos não são fáceis de mockar.

A ideia com MVP é mover a lógica para fora do ViewController, e colocá-la no presenter, assim podemos testá-la sem nos preocuparmos com o ciclo de vida da view.

Na verdade, o presenter é totalmente independente da view e não deve nem saber se está sendo utilizado UIKit, SwiftUI ou qualquer outra coisa. O que também torna mais fácil alterar o framework de UI utilizado, como faremos nesse tutorial.

  •       •      

MVP com UIKit

Primeiro, eu vou mostrar uma aplicação com MVP e UIKit, e depois vou mudar ela para SwiftUI. O app de exemplo basicamente apresenta uma lista de usuários e tem a opção de ordená-los por nome ou idade.

Primeiro, precisamos definir um serviço para carregar os dados e os modelos usados pela view. No caso, User e UserViewModel. O primeiro é o modelo retornado pelo backend e deve ser utilizado apenas por componentes com lógica de negócios (camada de model e presenter).

E o segundo é criado pelo presenter a partir do primeiro para ser usado especificamente pela view para renderizar as informações. Essa é uma boa prática porque torna a view independente das respostas do servidor.

SwiftUI e arquiteturas: MVP

image3

Em seguida, nós criamos o presenter, exibimos seus métodos através do UserPresenterProtocol, e delegamos alguns métodos de renderização para a view, usando o protocolo UserPresenterDelegate. Dessa forma, o presenter depende da interface, em vez de depender da implementação concreta da view (princípio da inversão de dependências), tornando mais fácil substituir a view e criar componentes mocks que implementam esses protocolos, para testar o presenter.

image4

Note também que o presenter lida com como os objetos são apresentados, ordenando eles, criando o campo nome, e transformando a data de nascimento em uma string com a idade do usuário. E ele não possui nenhum elemento do UIKit, IBOutlets ou IBActions.

E, finalmente, nós fazemos o UsersViewController implementar o protocol PresenterDelegate.

image5

Mas agora, a pergunta principal:

  •       •      

Como usar isso com SwiftUI?

 Bom, nós seguiremos uma abordagem muito similar a que foi utilizada no tutorial de MVC. Iremos substituir o UIViewController por uma Store, e fazer a Store implementar o PresenterDelegate:

image6

 Então, nós criamos a view usando SwiftUI e a fazemos ter uma referência para a store e para o presenter. Desse jeito, ela pode renderizar o estado de acordo com a informação da store, e chamar o presenter para lidar com ações do usuário e carregar dados.

image7

Basicamente, a view envia eventos para a store, que envia para o presenter, que então lida com elas da mesma forma que faria no MVC. Depois, chama a store utilizando os métodos do delegate para atualizar seu estado.

 Uma vez que a store atualiza sua propriedade local que controla o estado, a mudança é publicada utilizando o framework Combine, informando a view para se recarregar, pois ela tem a store como um observed object (objeto observado).

Capture

Note também que no exemplo foi utilizada a mesma prática do artigo anterior, decompondo a view em várias views menores.

 

Então temos uma view para cada estado: LoadingView, ErrorView, EmptyStateView e UsersDisplayView. E uma outra view (UsersView) para controlar o estado a ser apresentado e se comunicar com o presenter.

Note também como cada componente é pequeno e tem uma responsabilidade bem clara, e como foi fácil substituir o UIKit por SwiftUI quando utilizamos MVP. O presenter e o model não tiveram nenhuma alteração.

. No próximo artigo eu vou falar sobre VIPER e Clean Swift, que são arquiteturas mais complexas e frequentemente utilizadas. Fique ligado(a)!

Charântola

Charântola

iOS developer. Interested in code architecture, algorithms, new technologies, movies and series.

Deixe um comentário

Categorias

Posts relacionados

Siga-nos

Baixe nosso e-book!

%d blogueiros gostam disto: