2

我对 VIPER 架构中协议的好处有点困惑。我了解 DI(依赖注入)是通过协议实现的,并有助于避免对象之间的直接依赖关系——我同意。

但是我正在从使用的角度来看一个真正的好处,一个例子可能是 - 特别是协议如何帮助在单元测试中受益(测试交互器部分)。

我们不能通过方法回调的 using 块来实现相同的目标吗?希望有人可以通过一些示例从使用角度帮助我理解

干杯

4

2 回答 2

4

使用回调,例如从 Interactor 到 Presenter,会使测试 Presenter 变得更加困难。

在为 Presenter 如何处理输入(从 Interactor 发送)编写测试时,您的测试必须在 Presenter 上调用某些方法,这会导致 Presenter 对 Interactor 进行调用,这会导致 Interactor 将数据发送到 Presenter .

通过让 Presenter 实现由 Interactor 定义的协议,您的测试可以直接在 Presenter 上调用适当的输入方法。

至于声明协议,我以模拟角色而不是对象的方式练习 TDD(http://www.jmock.org/oopsla2004.pdf)。这些协议通过关注对象做什么(它的角色)而不是它如何做来帮助提供更好的抽象。

协议本身对单元测试没有什么价值。您的单元测试将为被测系统的依赖项提供测试替身(http://martinfowler.com/bliki/TestDouble.html)。即使您将依赖项公开为具体类,您仍然可以为您的测试创建测试替身。

在 Objective-C 中,您可以使用模拟库,例如 OCMock ( http://ocmock.org ) 或 OCMockito ( https://github.com/jonreid/OCMockito ) 来创建存根、间谍或模拟具体类。

在 Swift 中,您可以通过子类化每个用作依赖项的具体类来创建测试替身。

简而言之,协议不是用来简化单元测试的,而是在更高的抽象层次上描述应用程序的功能。

下面是一个例子,说明抽象协议在事后是如何有益的:

我创建了一个协议来表示用户可以在屏幕上执行的操作,例如ProfileUserActions,具有changeName和等操作changeAddress。Presenter 实现ProfileUserActions了 ,并且 View 接受了 aProfileUserActions作为依赖项。当用户点击屏幕上的按钮时,视图将向其userActions对象发送适当的消息。

当我想添加分析时,我能够创建一个新的、独立的ProfileAnalytics类,该类也实现了ProfileUserActions. 我在 View 和 Presenter 之间插入了分析对象,这允许应用程序捕获分析,而无需修改 View 或 Presenter。

于 2016-12-18T05:47:40.830 回答
0

通过使用协议,您可以更轻松地更换 VIPER 结构中的实现。例如,您可能有一个交互器正在处理一个正在写入文件系统的类。您不想在单元测试中测试文件系统,因此,如果您将文件系统写入操作放在协议后面的交互器中,则可以将文件系统写入操作替换为内存实现。

至于交互器本身的协议,我认为对您的选择更加务实一点是值得的。如果为测试构建交互器很容易,并且作为测试的一部分不会引起任何副作用,那么可能不需要该协议。另一方面,如果您必须创建许多其他依赖项,那么让交互器符合协议可能是值得的,这样您就可以更轻松地伪造从交互器获得的输出。

于 2016-12-17T12:54:13.927 回答