写点什么

iOS 中 MVC、MVP、MVVM、VIPER 等技术框架的选型与实践

用户头像
行者
关注
发布于: 2021 年 02 月 07 日

前言


  • 架构和设计模式是我们工作和面试中都比较重要的一个环节,

  • iOS开发中,当你开始做项目,或者梳理完需求后,你要做的并不是马上写下你的第一行代码,而是需先设计好整个项目的技术框架

  • 今天,我将全面介绍开发中主流的技术框架MVCMVP 、 MVVM模式以及非主流的VIPER模式,并实例讲解MVP模式,希望大家可以有点收获。


1. 选型技术框架给项目带来的好处


  • 可扩展性

架构良好的项目具有良好的扩展能力。 比如一年后如果有新的需求,需要添加新功能,好的架构设计会让会让开发更容易,可扩展性更强。

  • 可维护性

功能开发完成后,如果有需求更改的请求,好的架构可以随时响应。 架构良好的应用程序更易于维护。

  • 可靠性

应用程序应该能够正确执行预期的功能,并且可以容忍用户犯错误或以意外方式使用软件。 通常即使遇到一些异常情况或者边界条件,系统也应继续正常运行。

  • 其他好处

  • 模块化功能

使得程序模块化,即:内部的高聚合模块之间的低耦合

  • 提高开发效率

开发人员只需专注于某一点(视图显示、业务逻辑 / 数据处理)

  • 提高测试效率

方便后续的测试 & 定位问题



切记:不要为了设计而设计,也不要过度设计,否则反而会提高开发成本和开发量


2. 如何进行技术框架的选型


架构模式上,每种模式都各有优点,也各有局限性。越高级的模式复杂性越高,实现起来也越难,学习成本越高。最近火热的微服务架构,比起 MVC,复杂度不知增加了多少倍。


在实际项目中思考架构时,也不会想着要用哪种模式,我只思考现阶段,以现有的人力资源和时间资源,如何才能更快更好地完成需求,适当考虑下如何为后期扩展或重构做准备。


技术选型,决策关键不在于每种技术方案的优劣如何,而在于你团队的水平、资源的多寡,要根据实际情况选择最适合你们当前阶段的架构方案。当团队拓展了,资源也充足了,肯定也是需要再重构的,到时再思考其他更合适更优秀的方案。



2. iOS 开发的主流技术框架


  • 主要有MVCMVPMVVM 3 种主流的模式以及VIPER偏小众的模式

  • 下面,我将详细 & 具体的介绍上述几种技术框架


2.1 MVC


下图显示了 Model View Controller 三者之间的关系。


Model模型是数据所在的地方。 诸如持久性,模型对象,解析器,管理器和网络代码之类的东西都在这里。

View视图层是应用程序的外观。 它的类通常不包含任何特定于域的逻辑,因此通常可以重用。 例如,UILabel 是一个在屏幕上显示文本的视图,它是可重用和可扩展的。

Controller通过委派模式在 View 和模型之间进行中介。 在理想情况下,控制器实体将不知道其处理的具体视图,它将通过协议与抽象进行通信。 一个经典的示例是 UITableView 通 UITableViewDataSource 协议与其数据源进行通信的方式。


MVC 存在的问题:


  • 分层设计弱,控制器几乎在这里处理所有事情,它处理业务逻辑和表示逻辑,包括更新 UI,动画等。

  • 由于业务逻辑,表示逻辑和 UIKit 成员在控制器中混合在一起,因此难以进行单元测试。 可测试的类不应依赖任何 UIKit 成员无法轻易扩大规模。

  • 难以维护,当项目成长时,控制器将变得混乱和沉重。


2.2 MVP

MVP 模式是从“Model-View-Controller”模式派生的,但存在一些差异。 MVP 模式具有一个称为 Presenter 的新层,这是 MVP 的主键。


  • 这里的 View 与 Model-View-Controller 模式中的 View 相同,除了 View 不应直接与 Model 交互,View 只能与 Presenter 交互。

  • Model 也与 Model-View-Controller 模式中的模型相同,但是 Model 也不能直接与 View 交互,它应该仅与 Presenter 交互

  • Presenter 是 Model-View-Presenter 模式引入的新层,如图所示,Presenter 是一个中间层,用于处理 View 和 Model 之间的通信。 它解决了许多 MVC 问题,例如可测试性,可维护性,可伸缩性。


优点


  • 降低耦合

  • 模块职责划分明显

  • 利于测试驱动开发

  • 代码复用

  • 隐藏数据

  • 代码灵活性


缺点


视图的渲染放在 Presenter 中,所以视图和 Presenter 的交互会过于频繁。如果 Presenter 过多地渲染视图,往往会使得它与特定的视图的联系过于紧密。


Presenter 层的职责:


  • 一般而言,它应该处理表示逻辑。 它负责显示什么内容以及何时基于。

  • 通常,Presenter 也可以处理业务逻辑,但是在具有巨大业务逻辑的应用程序中,您应该为业务添加业务层。 另外,架构模式不是圣经,您可以根据自己的应用程序及其业务进行自定义。

  • Presenter充当 View 和 Model 之间的中间层,因此它可以处理从控制器接收的输入并对它们进行一些操作,如重新格式化数据,验证输入或过滤数据等。 此外,当模型更改时,演示者还应更新 Controller 以便更新 View。


2.3 MVVM


MVVM(Model-View ViewModel)架构模式与 iOS 中实现的 MVC 类似,但提供了更好的 UI 和表示逻辑分离。 这种解耦导致 iOS 中的视图控制器类更清晰,灵活且易于阅读 MVVM 模式源自与 MVP 相同的 Model-View-Controller 模式,它也具有与 MVP 相同的组件和关系,但是 Presenter 层被 ViewModel 层取代,并且 View 与 ViewModel 之间的通过数据绑定实现通信。

下图显示了 Model View ViewModel 三者之间的关系。



Model View 与 MVP 模式相同,现在让我们重点关注ViewModel


什么是ViewModel?它的职责是什么?ViewModel 是 MVVM 体系结构模式的核心,并提供了业务/表示逻辑与 View / ViewController 之间的连接。视图(UI)通过将输入数据(由模型定义)传递给 ViewModel 来响应用户输入。反过来,ViewModel 评估输入数据,并根据业务逻辑工作流以适当的 UI 呈现进行响应。


除了以下两点,ViewModel 的职责与 MVP 中的 Presenter 相同:


  • 通过数据绑定范例将 ViewModel 与 View 紧密结合,使用最广泛的是Reactive Programming,有很多框架可以实现Reactive Programming,例如RxSwiftReactiveCocoaBond

  • ViewModel 应该随时表示 View 的当前状态,这意味着 ViewModel 是一个从字面上表示 View 的模型(例如,如果我们的登录屏幕包含两个用于用户名和密码的 UITextfields。那么,ViewModel 应该具有两个 String 属性,分别代表用户名 Textfield 和密码 TextField),当您使用任何响应式框架或任何数据绑定方法来实现它时,这非常容易。


优点


  • 双向绑定时,当 Model 变化时,View-Model 会自动更新,View 也会自动变化。

  • View 的功能进一步的强化,具有控制的部分功能。

  • 控制器的功能大部分移动到 View 上处理,大大的对控制器进行了瘦身。


缺点


  • 数据绑定使得 Bug 很难被调试。

  • 数据双向绑定不利于代码重用。

  • 大的模块,model 很大,不利于内存的释放。


2.4 VIPER



VIPER 是我们最后一个要介绍的框架,这个框架比较有趣的是它不属于任何一种 MV(X) 框架。


到目前为止,你可能觉得我们把职责划分成三层,这个颗粒度已经很不错了吧。现在 VIPER 从另一个角度对职责进行了划分,这次划分了 五层


  • Interactor(交互器) - 包括数据(Entities)或者网络相关的业务逻辑。比如创建新的 entities 或者从服务器上获取数据;要实现这些功能,你可能会用到一些服务和管理(Services and Managers):这些可能会被误以为成是外部依赖东西,但是它们就是 VIPER 的 Interactor 模块。

  • Presenter(展示器) - 包括 UI(but UIKit independent)相关的业务逻辑,可以调用 Interactor 中的方法。

  • Entities(实体) - 纯粹的数据对象。不包括数据访问层,因为这是 Interactor 的职责。

  • Router(路由) - 负责 VIPER 模块之间的转场


实际上 VIPER 模块可以只是一个页面(screen),也可以是你应用里整个的用户使用流程(the whole user story)- 比如说「验证」这个功能,它可以只是一个页面,也可以是连续相关的一组页面。你的每个「乐高积木」想要有多大,都是你自己来决定的。


如果我们把 VIPERMV(X) 系列做一个对比的话,我们会发现它们在职责划分上面有下面的一些区别:


  • Model(数据交互)的逻辑被转移到了 Interactor 里面,Entities 只是一个什么都不用做的数据结构体。

  • Controller/Presenter/ViewModel 的职责里面,只有 UI 的展示功能被转移到了 Presenter 里面。Presenter 不具备直接更改数据的能力。

  • VIPER 是第一个把导航的职责单独划分出来的架构模式,负责导航的就是 Router 层。


如何正确的使用导航(doing routing)对于 iOS 应用开发来说是一个挑战,MV(X) 系列的架构完全就没有意识到(所以也不用处理)这个问题。


3. MVP 和 MVVM 的比较


首先让我们同意,它们两者几乎相同,并且它们之间的差异并不大,有人认为,MVVMMVP的响应式版本。


MVP 和 MVVM 之间的主要区别总结如下


  • Presenter具有其视图的引用,即使该引用作为协议通过也仍然是演示者的依赖关系之一。将引用作为协议类型传递并不意味着 Presenter 没有对 View 的引用。协议方法仅用于测试和重用目的,而 ViewModel 没有对其视图的任何引用,这使 ViewModel 易于测试和重用。

  • Presenter处理表示逻辑和业务逻辑(如果我们没有业务层),而视图模型执行相同的操作,但是视图模型精确地保存当前视图状态。

  • MVVM 应该使用响应式框架(RxSwift,ReactiveCocoa,Bond 等)以响应式方式编写,而 MVP 不需要数据绑定。


4. 如何选择合适的架构


如果非要选择的话,我的建议是根据个人或团队的理解和能力,选择适合自身的架构模式。具体建议如下:


  1. 对于简单的、改动不大的项目,那就不要用设计模式或者架构方法,只需要将每个模块封装好,方便调用即可。

  2. 对于偏向展示型的 App,绝大多数业务逻辑都在后端,App 主要功能就是展示数据,交互等,建议使用 MVVM。

  3. 对于工具类或者需要写很多业务逻辑 App,使用 MVP 或者 MVVM 都可。

  4. 如果想通过一个项目去学习架构和设计模式,建议用 MVC 然后在此基础上慢慢挖掘改进。最后你可能发现,改进的最终结果可能就变成了 MVP,MVVM。


最后,架构设计的目的是提升代码的可读性、可维护性,而不是过度提升代码复杂性,更不是随意引入某某框架。Google 官方也说了,万能架构是不存在的。如果是已经非常稳定的项目,则没有必要重新架构。只不过作为开发人员,还是要保持对新技术的敏感性。


发布于: 2021 年 02 月 07 日阅读数: 61
用户头像

行者

关注

还未添加个人签名 2020.05.13 加入

还未添加个人简介

评论

发布
暂无评论
iOS中MVC、MVP、MVVM、VIPER等技术框架的选型与实践