【发布时间】:2014-12-15 00:48:07
【问题描述】:
我在http://www.objc.io/issue-13/viper.html(以及其他一些来源)中阅读了有关 VIPER 架构的信息,但我仍然无法弄清楚一件事,每个演示者是否应该最多与一个交互器交互?
这里有一个更长的讨论可能更好地解释我的问题:Use Case with 2 ways for the same action
【问题讨论】:
标签: ios architecture ios8
我在http://www.objc.io/issue-13/viper.html(以及其他一些来源)中阅读了有关 VIPER 架构的信息,但我仍然无法弄清楚一件事,每个演示者是否应该最多与一个交互器交互?
这里有一个更长的讨论可能更好地解释我的问题:Use Case with 2 ways for the same action
【问题讨论】:
标签: ios architecture ios8
据我所知,每个 VC 的演示者都是独一无二的。但是,当演示者需要多个交互者时,他可能会使用它们。
在我看来,interactor 是业务逻辑的一层,它们可以相互交互,presenters 可以和它们中的许多交互。
但是,将正确的逻辑放在正确的层中很重要。例如,注意不要将业务逻辑放在演示者层,因为它非常诱人,同时必须在多个交互器之间导航。请记住,仅将业务逻辑放在交互器中。
【讨论】:
理想情况下,否。一位 Presenter 应该知道只有 ONE Interactor 的存在。但是交互器本身可以有很多数据管理器。我通常至少使用两个数据管理器:一个用于 API 请求,一个用于本地数据管理。
有关 VIPER 架构的更多高级技巧和有用的良好实践,我推荐这篇文章:https://www.ckl.io/blog/best-practices-viper-architecture(包括示例项目)
【讨论】:
正如 Marcelo 指出的那样,理想情况下不会。但是我觉得为数据管理器添加“D”到 VIPER 也不理想。
VIPER 的一个大问题是演示者在接收到来自视图的输入时已经知道要“触发”哪个用例,因此它已经对业务用例有一些先验知识。在我看来,仅这一事实就对整个架构提出了质疑,因为如果演示者只是通知交互者一个与用例无关的或纯粹的 UI 事件在视图上,它就没有任何存在的意义。无论如何,VIPER 中的演示者必须有一点“业务逻辑”。
因此,由于演示者已经必须通过与交互者交谈来编排用例,因此每个业务用例有一个交互者,如果每个“模块”有多个业务用例,演示者可以连接它们。如果没有变通方法,VIPER 的边界通常很难在实践中维护,但它是一个很好的架构,可以迫使开发人员考虑关注点分离。
【讨论】:
根据CheeseCake Best Pratices,连接多个VIPER模块的唯一方法应该是使用路由器层。这样,如果您删除任何模块,唯一会在其他相关模块中出现错误的层将是路由器。此外,为了避免耦合,实体可能会被放置在专门用于此目的的单独模块中。最后,为了减少代码重复,相似的实体(例如,用户和配置文件)将被分组到相同的数据管理器中。
【讨论】:
聚会有点晚了,但我只是在谷歌上搜索了这个问题,寻找其他东西。
这实际上取决于您对 VIPER 的实施。没有一个正确的,据我所见,人们以非常不同的方式实现它,应该根据您的特定需求进行调整。
一些项目的每个视图都有紧密耦合的交互器,其中视图显示数据,演示者在视图和交互器之间传递数据(在流程中转换它),交互器处理每个视图的业务逻辑。在这种情况下,演示者将只与一个交互者交谈。
其他项目根据用例实现交互器,或者换句话说,“次要”功能。这样您就可以避免在模块之间重复业务逻辑。演示者可以在此处与多个交互者交谈。
还有一些项目为每个“大”功能实现大型交互器,或者我们应该说每个应用程序的区域。这样一来,交互者往往会很大,但也真正成为负责应用程序业务逻辑决策的“智能”层,并且他们往往可以访问做出这些决策所需的一切。
让我们在这里举个例子 - 假设您在应用程序的侧边菜单和设置中有一个注销按钮,对于注销您需要清除数据库、钥匙串、用户默认值和网络会话.一个相当常见的场景。
在第一种情况下,每个视图都有一个交互者,显然你有重复的业务逻辑。我相信这就是“原始”VIPER 的工作方式,但这可能不是最好的方法。
在第二种情况下,您可能需要一个“用户会话交互器”来处理用户的登录和注销。
在第三种情况下,您将拥有一个“用户交互器”,它不仅可以处理会话,还可以保存和管理所有用户数据。
我通常的方法是第三种选择,它的缺点是需要将交互器拆分到多个文件中。许多人使用第二个选项。对于您的项目,第一个选项也可能是最好的 - 例如,如果您的项目中的屏幕之间几乎没有重叠并且它们与功能紧密对齐。
【讨论】: