HandsAppMVP: arquitetura iOS para terceirização de desenvolvimento de estúdio

imagem

Um bom código começa com a arquitetura e os aplicativos para iOS não são exceção. Existem muitos padrões padrão, mas o objetivo deste artigo não é falar sobre eles, mas sobre a experiência de adaptar um deles e desenvolver o seu. Chamamos essa adaptação de HandsAppMVP.

imagem

No desenvolvimento do iOS, a arquitetura determina principalmente a organização de classes e dependências para um ViewController específico. No entanto, o componente central pode ser não apenas ele, mas simplesmente o UIView. A escolha depende da tarefa específica.

Comparação de arquitetura


Existem vários modelos de arquitetura padrão para iOS: MVC, MVP, MVVM, VIPER (os links para a descrição de cada um podem ser encontrados no final do artigo).

Escolhendo uma arquitetura para desenvolvimento, identificamos os principais parâmetros aos quais ela deve corresponder: velocidade de desenvolvimento, flexibilidade e um baixo limite de entrada. Em seguida, começamos a comparar três arquiteturas conhecidas com esses parâmetros em mente (o modelo de comunidade MVC para iOS foi enterrado por muito tempo devido à não conformidade grave com responsabilidade única).

Para uma equipe de terceirização, a velocidade de desenvolvimento é especialmente importante. O VIPER é a arquitetura mais complexa e "lenta"; o desenvolvimento é mais rápido usando MVP ou MVVM puro, pois eles têm menos componentes.

Flexibilidade significa a adição ou remoção indolor de funcionalidades no aplicativo. Esse parâmetro se correlaciona fortemente com a velocidade de desenvolvimento em todas as etapas da vida útil do aplicativo, exceto a inicial. A flexibilidade também está intimamente relacionada à simplicidade dos testes - testes automáticos dão ao desenvolvedor a confiança de que ele não quebrará nada e ajuda a evitar bugs. O MVP clássico é mal coberto por testes, especialmente se você não usar as interfaces de classe discutidas abaixo. O MVVM do ponto de vista de teste também tem desempenho ruim, porque o teste do código reativo leva muito mais tempo. O VIPER é ótimo para escrever testes, porque respeita o princípio da responsabilidade exclusiva, tanto quanto possível, e as aulas dependem de abstrações.

E o último parâmetro que consideramos é o limite de entrada. Ele mostra a rapidez com que novos desenvolvedores (em primeiro lugar, os jones) penetram na arquitetura. Aqui, o MVVM usando bibliotecas reativas de terceiros (RxSwift, PromiseKit etc.) ocupa um último lugar honroso por razões óbvias. O VIPER também é uma arquitetura bastante complexa devido ao grande número de componentes. O MVP tem o limite de entrada mais baixo.

Depois de ponderar os prós e os contras, chegamos à conclusão de que precisamos de algo tão simples quanto o MVP e tão flexível quanto o VIPER. Então nasceu a idéia de criar sua própria arquitetura baseada neles - HandsAppMVP.

Expandir MVP


Os principais componentes de nossa arquitetura são Model, View, Presenter. Eles desempenham as mesmas funções que no MVP clássico de acordo com o esquema conhecido:

imagem
[Esquema do MVP clássico]

Aqui e abaixo, cada componente de interação (quadrado azul) nos diagramas é uma classe cuja vida útil coincide com a vida útil da Visualização. Uma seta sólida indica a propriedade de outro objeto, um link forte e uma seta pontilhada indica um link fraco. Com referências fracas, evitamos dependências circulares e vazamentos de memória.

Interfaces


Primeiro, adicionamos as interfaces ViewInput e ViewOutput a esse esquema clássico. Levamos em consideração o quinto princípio do SOLID - o princípio da inversão de dependência. É mais provável que não seja uma adição, mas um refinamento para o MVP. A dependência de abstrações ajuda a se livrar da estrita conexão dos componentes e permite que você escreva testes normalmente. O esquema que leva em consideração as interfaces é semelhante a este:

imagem
[Adicionando interfaces ViewInput e ViewOutput] Um

pequeno retângulo é uma interface.

Um desenvolvedor atento perguntará: onde estão as interfaces do Model? Agora nos voltamos para eles.

Trabalhar com dados


O modelo de dados em arquiteturas móveis é um conceito coletivo. Um exemplo padrão: um aplicativo bate na rede para interagir com o servidor, salva os dados no CoreData para trabalho offline, grava algumas informações simples nos UserDefaults e armazena o JWT no Keychain. Todos esses dados que estão sendo interagidos compõem o modelo.

A classe que é responsável por interagir com o contêiner de dados de um tipo específico, chamamos de serviço de dados. Para cada contêiner (banco de dados remoto, banco de dados local, UserDefaults etc.), uma classe de serviço é adicionada ao HandsAppMVP que interage com o apresentador. Agora você também pode adicionar interfaces de entrada / saída para cada serviço de dados:

imagem
[Adicionando serviços para trabalhar com dados]

Nem toda classe de serviço precisa estar conectada ao apresentador usando uma interface, como, por exemplo, ao usar Moya. Moya é uma biblioteca de rede de código aberto. O Moya fornece uma classe de serviço pronta (MoyaProvider) e, ao escrever testes, não precisamos criar um objeto simulado que substitua o ApiProvider. O Moya fornece um modo de teste especial; quando ativado, o MoyaProvider não bate na rede, mas retorna os dados do teste (mais detalhes podem ser encontrados aqui). Nesse caso, o apresentador não se refere à abstração do MoyaProvider, mas à implementação. E obtemos feedback desse serviço usando fechamentos. Um exemplo de implementação pode ser encontrado no projeto de demonstração.

Este exemplo é mais uma exceção do que uma regra e mostra que a adesão ao SOLID nem sempre é a melhor solução.

Navegação


Consideramos a navegação no aplicativo como uma responsabilidade separada. HandsAppMVP usa uma classe especial para ele - roteador. O roteador contém um link fraco para a tela, com o qual pode mostrar uma nova tela ou fechar a atual. O roteador também interage com o apresentador usando a interface RouterInput:

imagem
[Adicionando um componente para navegação (roteador)]

Montagem de componentes


A última adição ao MVP clássico que usamos é o Assembly, uma classe de coletor. É usado para inicializar o View e outros componentes do HandsAppMVP, bem como implementar dependências. Assembly contém o único método público - `assemble () -> UIViewController`, cujo resultado é o UIViewController desejado (ou UIView) com o gráfico de dependência necessário.

Não mostraremos o Assembly no diagrama da arquitetura, pois ele não está conectado aos componentes do MVP e seu ciclo de vida termina imediatamente após a criação.

Geração de código


Para economizar tempo, automatizamos o processo de criação de classes HandsAppMVP usando Generamba. Os modelos usados ​​para Generamba podem ser encontrados em nosso repositório. Um exemplo de configuração para o Generamba está no projeto demo.

Como resultado da geração de uma tela específica, obtemos um conjunto de classes que corresponde ao esquema HandsAppMVP, um conjunto de testes de unidade para criar e implementar componentes e uma classe de modelo para testes do apresentador.

O que aconteceu


Se você comparar o HandsAppMVP cara-a-cara e o VIPER, notará que eles são muito semelhantes e o primeiro é distinguido apenas pela ausência do componente Interactor. Porém, ao nos livrarmos da camada entre os serviços e o presente (o interator), além de simplificar a interação com a rede usando Moya, recebemos um aumento notável na velocidade de desenvolvimento.

Aconselhamos que você preste atenção suficiente à arquitetura no estágio de design, a fim de evitar futuros erros globais, disputas com clientes e atormentar os desenvolvedores, e, em vez disso, conduzir com competência e previsibilidade o processo de desenvolvimento.

Lembre-se de que qualquer arquitetura pode não ser adequada especificamente para o seu projeto; portanto, não se apresse em se apegar cegamente a modelos prontos e a histórias de sucesso de seus aplicativos. Não tenha medo de desenvolver e aplicar suas soluções - elas podem se tornar mais valiosas e flexíveis para você do que as já prontas.

Em conclusão, recomendamos alguns bons artigos sobre a arquitetura dos aplicativos iOS que nos ajudaram a entender os meandros e fazer uma escolha:

  1. Padrões arquiteturais no iOS
  2. iOS Swift: arquitetura MVP
  3. Análise da arquitetura VIPER no exemplo de um pequeno aplicativo iOS no Swift 4
  4. Implemente MVVM no iOS com RxSwift

A documentação de código aberto do SurfStudio também foi muito útil e inspirada .

Por fim, estamos colocando um link no projeto DEMO , escrito em HandsAppMVP, que mencionamos várias vezes no artigo.

All Articles