-
Notifications
You must be signed in to change notification settings - Fork 0
Arquitetura do Projeto
Aqui eu vou documentar minha análise e a decisão sobre qual arquitetura de software usar no meu projeto, o GameSource.
Para fazer a escolha certa, primeiro eu precisei entender a característica mais importante do SwiftUI: ele é um framework declarativo.
Na prática, isso significa que, em vez de dar ordens passo a passo para a tela mudar, eu simplesmente descrevo o que a tela deve mostrar em cada situação específica. A UI é uma função direta do estado (UI = f(State)).
Por exemplo:
-
Se a variável
isLoadingfortrue, então a tela mostra um indicador de carregamento. -
Se a variável
errorMessagetiver um texto, então a tela mostra essa mensagem de erro. - Se a minha lista de jogos estiver preenchida, então a tela mostra os jogos.
A consequência direta disso é que o SwiftUI recria partes da tela (a View) a cada mudança de estado. A View não é um objeto fixo, mas sim uma struct leve, um "desenho" temporário do estado atual. Por isso, busquei uma arquitetura onde o "estado" e a "lógica" fiquem em um lugar separado e mais estável, fora da View.
Minha primeira investigação foi sobre o padrão MVC, que divide o app em três partes:
- Model: Onde ficam os dados brutos e regras de negócio.
- View: A tela que o usuário vê, responsável por exibir os dados e capturar interações.
- Controller: O intermediário que conecta o Model e a View.
Embora seja um padrão conhecido, eu concluí que o MVC apresenta riscos para o GameSource:
- Risco de "Controller Gigante": O maior problema que identifiquei é a tendência do Controller de acumular responsabilidades em excesso, um problema conhecido como "Massive View Controller". No meu caso, um único Controller para a biblioteca teria que gerenciar as chamadas para as APIs da Steam e da RAWG.io, cuidar do cache e conter toda a lógica de filtros. Isso o tornaria um componente de difícil manutenção.
- Dificuldade de Testes: Como a lógica estaria fortemente acoplada à UI, seria muito difícil realizar testes de unidade. Para validar a lógica de filtro, por exemplo, eu dependeria de testes de UI (XCUITest), que são mais lentos e frágeis, de acordo com minha pesquisa.
Em seguida, eu analisei o padrão MVVM, que foi projetado para resolver os problemas do MVC, especialmente em frameworks reativos. Ele introduz uma nova peça:
- Model e View: Mantêm as mesmas responsabilidades de antes.
- ViewModel: Este é o novo intermediário. Ele prepara os dados do Model para a View, mas o mais importante é que o ViewModel não tem conhecimento direto da View. Ele apenas expõe o estado e a lógica, e a View reage a essas mudanças.
Na minha análise, os benefícios do MVVM para este projeto são:
-
Alta Testabilidade: Esta é a maior vantagem que encontrei. Como o ViewModel é uma classe comum, independente da UI, eu posso testá-lo de forma isolada. Minha abordagem de teste seria instanciar o
GameLibraryViewModelem um ambiente de teste, simular (mock) as respostas das APIs e verificar se ele lida com todos os cenários. Isso me permite garantir uma qualidade de código muito maior. -
Organização e Escalabilidade: O MVVM é mais organizado e modular. A lógica complexa de buscar dados de várias APIs para a tela de detalhes ficará contida no
GameDetailViewModel, sem afetar o resto do aplicativo. Se eu decidir adicionar uma nova API no futuro, saberei exatamente onde mexer. -
Alinhamento Nativo com SwiftUI: Eu percebi que o MVVM parece ter sido feito para o SwiftUI. As ferramentas do framework, como
ObservableObject,@Publishede@StateObject, são perfeitas para implementar o MVVM de forma limpa e eficiente.
| Critério | Model-View-Controller (MVC) em SwiftUI | Model-View-ViewModel (MVVM) em SwiftUI | Por que isso é importante para a minha decisão? |
|---|---|---|---|
| Testabilidade | A lógica acoplada à UI dificulta testes isolados e confiáveis. | O ViewModel é projetado para ser testado de forma independente da UI. | A complexidade das integrações de API no meu projeto exige testes para garantir a qualidade, e o MVVM me oferece as ferramentas para isso. |
| Manutenção e Escalabilidade | Alto risco de criar "Controllers gigantes", dificultando a evolução do projeto. | Por ser modular, facilita adicionar novas funcionalidades e dar manutenção de forma isolada. | O MVVM me permite crescer o projeto com mais facilidade, permitindo adicionar novas funcionalidades sem quebrar o que já existe. |
| Acoplamento | O Controller está fortemente ligado ao Model e à View. | O ViewModel não tem conhecimento da View, o que me permite reutilizar o código. | Com baixo acoplamento, eu posso, por exemplo, criar uma versão do app para macOS no futuro, reaproveitando toda a lógica dos meus ViewModels. |
| Compatibilidade com o SwiftUI | O modelo de controle do MVC entra em conflito com a natureza reativa do SwiftUI. | Funciona perfeitamente com o SwiftUI, como por exemplo com a utilização de ObservableObject. |
Adotar a arquitetura que melhor se alinha com o framework resulta em um desenvolvimento mais eficiente e um aplicativo mais estável. |
Após a análise comparativa detalhada, eu decidi adotar a arquitetura Model-View-ViewModel (MVVM) para o desenvolvimento do projeto GameSource.
Essa escolha é fundamentada na natureza declarativa do SwiftUI e nos riscos que o padrão MVC apresentaria ao projeto, principalmente a baixa testabilidade e a provável criação de "Controllers Gigantes".
O MVVM se destacou como a escolha superior por três motivos principais:
- Alta Testabilidade: A capacidade de testar a lógica do ViewModel de forma isolada é crucial para garantir a qualidade e a robustez do aplicativo.
- Organização e Escalabilidade: A separação clara de responsabilidades vai facilitar a manutenção e a adição de novas funcionalidades no futuro, sem que o código se torne confuso.
- Alinhamento com SwiftUI: O padrão utiliza as ferramentas do SwiftUI de forma nativa e eficiente, o que resulta em um desenvolvimento mais limpo e um aplicativo mais estável.
A adoção do MVVM estabelece uma base técnica sólida e escalável, me dando a confiança necessária para construir um aplicativo de alta qualidade.
- MVC vs MVVM on iOS: Key Differences With Examples - Netguru: https://www.netguru.com/blog/mvc-vs-mvvm-on-ios-differences-with-examples
- MVVM in SwiftUI for a Better Architecture - Matteo Manferdini: https://matteomanferdini.com/swiftui-mvvm/
- Mastering MVC in SwiftUI: The Classic, No-Nonsense Approach - Medium: https://medium.com/@jaredcassoutt/mastering-mvc-in-swiftui-the-classic-no-nonsense-approach-36e54b0b816e
- @StateObject vs. @ObservedObject: The differences explained - SwiftLee: https://www.avanderlee.com/swiftui/stateobject-observedobject-differences/
- Writing testable code when using SwiftUI - Swift by Sundell: https://www.swiftbysundell.com/articles/writing-testable-code-when-using-swiftui/
- SwiftUI Architectures: Model-View, Redux & MVVM - QuickBird Studios: https://quickbirdstudios.com/blog/swiftui-architecture-redux-mvvm/