
原创作者:Piyush Sharma
原文链接:https://medium.com/@piyush.dez/ios-architectures-5a19cd56edc2
一个好架构的特质:
- 每个对象应该有清晰的角色
- 能够轻松地跟踪数据流
- 不应该依赖于特定的框架
- 灵活,因为它简单,而不是因为我们使用了太多的抽象
- 关注分离
- 可测试的
- 明确界限,一个对象应该只对一件事负责
为什么我们需要一个好架构?
如果你正在debug一个有不同实现的巨大的类,你将会发现你自己很难在这个类找到导致bug的原因,并且修复它。你会遇到的大部分常见的问题:
- 你的数据直接在
UIViewController
中存储 - 你的
UIViews
做了太多的事情 -
Model
是个简单的哑模型 - 你的单元测试其实没有覆盖到什么
所以应对这种复杂情况最简单的方法就是按照 单一功能原则 在多个实体之间划分责任。
受欢迎的架构模式:MVC,MVP,MVVM,VIPER,VIP
首先,我们把整个项目划分为3个实体:
- Model —— Model 就是用来数据存储。持久化代码,模型对象,解析器,帮助程序、扩展、常量和网络代码都在其中。
-
网络代码(Network code):你可能会使用一个单例类用于整个app的网络通信,包括网络请求,响应,还有错误处理。
-
持久化代码(Persistence code):你使用这个部分代码当需要持久化数据到数据库,Core Data,或者保存数据到设备。
-
解析代码(Parsing code):你应该会在Model层中包含解析网络响应的对象。例如,在Swift model对象中,你能用 JSON encoding/decoding 来进行解析处理。这样的话,一切都是自我包含,解析的时候,网络层不必知道所有的Model细节。业务逻辑和解析逻辑都包含在Model里面。
-
管理者和抽象类(Managers and abstraction classes):每个人都使用它们,需要它们,但没人知道它们叫什么或者它们属于哪里。它通常有典型的 “manager” 对象,用于连接其他的类。
-
Views —— view 层是我们app的表层。它的类如果没有包含任何特定领域逻辑的话通常都是可以复用的。比如,
UILabel
是一个可以在屏幕上展示文本的view,并且它是可复用和扩展的。 -
Controller/Presenter/ViewModel —— 把 controller 层当作app的大脑,或者引擎;它决定了下一步会发生什么。controller通过委托模式在视图和模型之间进行调解。controller实体是不知道正在处理的view的具体实现。相反,它将通过协议和抽象层进行通信。一个经典的例子就是
UITableView
和它的数据源是通过UITableViewDataSource
协议进行通信的。
MVC

Controller是View和Model之间的调度者,所以View和Model并不知道对方的存在。

Cocoa MVC 鼓励我们写“复杂”的 View Controller,因为它们与View的生命周期息息相关,很难说它们是分离的。

View Controller 最终成为一个委托和所有东西的数据源,通常负责调度和取消网络请求。
MVVM
View 和 ViewController 进行互动,ViewController 又和 ViewModel 互动,然后 ViewModel 会和其他的 helpers,managers 存在关联。

VIPER
这个架构强制以结构式的方式编写代码,并将ViewController 的职责划分到更小的对象上。

-
Interactor —— 包含与数据(实体)或网络相关的业务逻辑,如创建实体的新实例或从服务器获取实体。出于这些目的,你将使用一些服务和管理器,它们不是VIPER模块的一部分,而是外部依赖项。交互器中完成的工作应该独立于任何UI。
-
Presenter —— Presenter主要由驱动UI的逻辑组成。它知道何时呈现用户界面。它从用户交互中收集输入,以便更新UI并向 Interactor 发送请求。演示者还从 Interactor 接收结果,并将结果转换为有效地显示在视图中的形式。它将处理数据并决定向用户显示什么。
-
View —— 它等待Presenter给它内容显示; 它从不要求 Presenter 提供数据。Presenter 不知道UILabel, UIButton等的存在,它只知道它所维护的内容以及它应该在什么时候显示。由 View 决定如何显示内容。
-
Entities —— Entities 是由 Interactor 操作的模型对象。Interactor 从不将Entities传递给显示层(如Presenter)。
-
Router —— 负责VIPER模块之间的segue。View Controller不应该知道下一个View Controller是什么,以及如何设置它。由于Presenter包含对用户输入作出响应的逻辑,所以是Presenter知道何时导航到另一个屏幕,以及导航到哪个屏幕。它们共同描述了从一个屏幕到下一个屏幕的路线。
由 Interactor 进行网络操作,但它不会直接处理网络代码。它会询问一个依赖类,比如network manager 或者 API client。Interactor 可能必须合并来自多个源的数据,以提供满足用例所需的信息。然后由Presenter 获取 Interactor 返回的数据并将其格式化以供演示。
-
数据存储负责向 Interactor 提供实体。当 Interactor 应用其业务逻辑时,它将需要从数据存储中检索实体,操作实体,然后将更新后的实体放回数据存储中。数据存储管理实体的持久性。Entities 不知道数据存储,因此Entities不知道如何持久化它们自己。Interactor 也不应该知道如何持久化实体。
-
有时,Interactor 可能希望使用一种称为数据管理器(data manager)的对象类型来促进其与数据存储的交互。数据管理器处理更多特定于存储的操作类型,如创建获取请求、构建查询等。这使得 Interactor 可以更多地关注应用程序逻辑,而不必了解如何收集或持久化实体。
简洁的Swift架构(VIP)
view controller, interactor 和 presenter 是 VIP 架构中三个主要的部分。

一个典型的场景是,如果用户点击应用程序用户界面中的一个按钮。view controller构造一个请求对象并将其发送给interactor。interactor接受请求对象并执行一些工作。然后将结果放入响应对象中,并将其发送给presenter。presenter获取响应对象并格式化结果。然后将格式化的结果放入View Model对象中,并将其发送回view controller。最后,view controller将结果显示给用户。

VIP 很好地划分了组件的职责。view controller 通过发送请求直接与 interactor 交互。interactor调用worker的方法,worker执行一些工作,并通过向presenter发送带有数据模型的响应来返回interactor响应的这些请求。presenter格式化要显示的数据,创建一个View Model,并通知view controller它应该基于View Model更新它的视图。view controller通过调用Router上的方法来决定何时导航到不同的场景。Router执行下一个视图控制器的设置,并处理连接、传递数据和委托设置。
网友评论