[译] 单一职责原则在 iOS 中的应用

栏目: 后端 · 发布时间: 6年前

内容简介:本文翻译自 “Cleaner Architecture on iOS”, 作者 Tomas Hakel这篇文章不打算讲一些新的或有创新性的东西,而是来讨论一个广为人知的东西:

本文翻译自 “Cleaner Architecture on iOS”, 作者 Tomas Hakel

这篇文章不打算讲一些新的或有创新性的东西,而是来讨论一个广为人知的东西: 单一责任原则(SRP) 。更具体的说,我想讨论的是如何在  Clean Architecture 中来正确地使用它。我们应该经常提醒自己,在做决策时考虑一下 SRP,以此帮助我们设计出更好的软件。

[译] 单一职责原则在 iOS 中的应用

SRP 是什么?

先来看看 WIKI 上的定义:

The single responsibility principle is a computer programming principle that states that every module or class should have responsibility over a single part of the functionality provided by the software, and that responsibility should be entirely encapsulated by the class. All its services should be narrowly aligned with that responsibility.

单一责任原则是一种计算机编程原则,规定每个模块或类只对软件提供的功能的一部分负责,并且该职责应完全由类封装。其所有服务应与该职责严格一致。

一个类应该只有一个改变的因素。遵循这个原则,可以获得诸多好处:使修改变得更容易、减少耦合、提高可测试性、加快开发速度等等。SRP 也是 Clean Architecture 的基本思想(适用于 MVC、MVVM、响应式等等)。

为什么不使用 MVC?

最直接的答案是: Massive View Controller 。尽管这只是个玩笑话,不过实际情况确实如此。这也引出了另一个问题:为什么 MVC 是 iOS 上的默认架构,即便它会导致诸如 Massive View Controller 这样的问题?答案是,它不是首要问题。如果 Controller 很庞大,这并不是架构的错,而是 程序员 没有正确地使用它。你可以使用 MVC 编写出结构非常清晰的程序,同时可以通过以下方法轻松处理 Massive View Controller 问题:

  • 一个场景使用多个控制器;

  • 将任务委托给 worker/service 类;

一句话:使用 SRP。那么,如果 MVC 不是问题,那为什么要使用其它框架呢?原因是正如在 iOS 上的应用一样,MVC 存在一些问题,这使它会界定职责时比较模糊,留给程序员做的决定太多。比如:控制器的责任是什么?如果你不小心一点,那它所承担的就很多。那我们应该把一些需要的工作放在哪里呢?在 model 层?我们又如何去构建?MVC 并没有明确的告诉我们如何去做。这就意味着我们有很大机率引入错误。

如果我们不想考虑这些问题,就可以使用 Clean Architecture。Clean Architecture 明确划分了类的职责: Presenter 负责桥接 UI 层和业务逻辑层; Interactor 处理我们的用例;路由帮我们跳转到新页面。权责清晰,这样我们的代码就会更干净整洁。

那么,使用 Clean Architecture,可以解决 MVC 的问题么?在我们的代码中应用了 SRP 了么?不一定。这个架构非常有用,但并没有解决所有问题。我们仍然需要思考、做出选择,并努力让代码变得更加清晰。

MIP 问题

在 Apple 平台上,Clean Architecture 已经非常流行。我们有很多种选择,如 VIPER 和  Clean Swift 。在这里让我们来看一些 Clean Swift 的实际例子。

我见过一些有大型的复杂 Interactor 的工程,这些工程并不遵循 SRP。我称之为 Massive Interactor Problem(MIP) 。MIP 可能并不像 Massive View Controller 问题那么糟糕,因为 Interactor 并不关心 UI,但它依然试图去做太多的事情。问题在于,尽管我们认为自己正在使用 Clean Architecture,但并没有恰当地去划分职责。为了从根本上避免 MVC / MIP 问题,我们需要更多地使用 SRP。

Interactor 包含了应用程序的业务逻辑,但每个 View Controller 只有一个 Interactor。在小场景中,这没有问题,但正如在一个场景中只使用一个 View Controller 一样,在大的场景中,Interactor 同样面临着失控的局面。我的观点是,在复杂的场景中,Interactor不应该真正去处理任何事情:没有算法,没有数据库操作或数据解析,没有任何需要嵌套的 if 或循环语句。这些任务应该由 Worker 类来处理。Interactor 的职责是将任务交给各种 Worker ,并把结果传递给 Presenter。Clean Swift 的示例代码中,Worker 只包含一小段代码,由于比较简短,所以没有体现出它的重要性。示例这么做是没错的,毕竟 Worker 的职责是处理特定的业务逻辑。不过,我觉得需要特别强调一下 Worker 的重要性。

在 Clean Architecture 中,一个 Interactor 应该表示一个单独的用例。这意味着一个类应该只有一个关注点。在 Clean Swift 中,一个场景只有一个 Interactor,而一个场景通常会包含多个用例,所以 Interactor 会有很多职责。在问题比较简单时,我们可以选择忽略这一点,但随着 Interactor 的增长,它会变得越来越不受控制。另一种选择是将这些职责代理给 Worker 类。在这种情况下,Interactor 将创建多个 Worker。当 UI 发起一个请求时,Interactor 将简单地将请求发送给 Worker 处理,并将结果传回给 Presenter。这听起来很简单,但却大大改善了 MIP 问题。由于一个 Worker 只处理用例,它看上去更像一个 Interactor,不是么?

VIPER 是什么?

我听很多人说 VIPER 很复杂:需要花很长的时间去配置,有太多很小的类。但 VIPER 很好的实践了 SRP。如果你更关注 SRP,并将 SRP 应用于你的 MVC 工程,最后也可能会产出类似的框架(类似的事情就发生在我身上)。

Clean Swift 和 VIPER 非常相似,毕竟都是基于 Clean Architecture。主要的区别在于 VIP cycle,以及每个场景的 Interactor 的数量。但如果我们在 Clean Swift 中严格遵循 SRP,将 Clean Swift Interactor 的职责划分清楚,并为每个用例创建一个 Worker 类,基本上就是 VIPER 了(如果我们忽略一些细节,就可以将 Clean Swift 的  Worker 与 VIPER 的  Interactor 对应起来,而 Clean Swift 的  Presenter-Interactor 可以对应 VIPER 的  Presenter )。事实上,由于有 VIP cycle,Clean Swift 显得更复杂。VIPER 并不像人们所说的那么复杂。所以不要担心它所提供的东西。即使在下一个项目中你不用使用 VIPER,但去理解它,以及它的运作方式,也是大有益处的。而使用它,可以让自己和他人的工作更加轻松。

More on SRP

这里有一些建议:

  • 不要混淆抽象层。在上层业务逻辑中执行底层操作是违反 SRP 原则的。毕竟我们在处理组织或器官时,不希望去考虑细胞的复杂性,反之亦然;

  • 明确类的职责,并将其写在类上方的注释中。描述应简明扼要,同时包含所有职责。不过要留心 “manager” 这样的词。manager 用来做什么?如果不注意的话,这样的类很容易包含多个职责。当修改类时,请确保它的职责不变,否则就重构它;

  • SRP 可应用于多个级别,从通用架构到单个方法。如果一个方法做了多件事,就将这些操作分解几个新方法中,让每个方法执行特定的任务,然后在原方法中调用。记住,一个方法应该只在一个抽象层中;

  • 大段的代码意味着破坏了 SRP。如果你发现在 IDE 中滚动了很长时间,那么代码可能出问题了。SRP 是一个比行数更好的度量标准,所以不要找一个魔数来规定一个文件中代码的行数,而是列出职责。如果不止一个,就进行拆分。较短的类和方法也更容易维护,所以尽量保持合理的代码长度;

  • 务实,而不是完全遵循规范和指南,了解为什么这样设计以及想要达到的目标。然后做出明知的选择。

总之,不要写出 Massive Controllers。明确职责,确保在一个地方没有太多的职责(理想情况下,2个就是太多了)。在为类添加代码时,需要考虑类的职责,而不是简单的添加。从长远来看,遵循 SRP 最有可能节省时间 - 所以不要找借口。

如果还感觉一头雾水,可以参考以下资源。

资源

[1] https://en.wikipedia.org/wiki/Single_responsibility_principle

[2] https://8thlight.com/blog/uncle-bob/2012/08/13/the-clean-architecture.html
[3] https://clean-swift.com/clean-swift-ios-architecture
[4] https://objc.io/issues/13-architecture/viper

9 月活动

又到我们一月一次的活动日了,这次我们的内容是抽奖送 @叶孤城 __ 大大的  CodeAddict 兑换码, 开奖日期为下周一下午 6 点

[译] 单一职责原则在 iOS 中的应用

CodeAddict 是一个非常漂亮的 GitHub 客户端,可以帮助我们挖掘 github ,找到我们感兴趣的 repo。CodeAddict 有许多有趣的功能:

  1. 展示您的 github 活动;

  2. 搜索您喜欢的 repo 或用户;

  3. star 和 unstar 一个 repo;

  4. 关注或取消关注某些人;

  5. 漂亮的 UI;

  6. 分析您的 github repo 数据并将其显示为图表

没有抽到兑换码的小伙伴,可以直接购买哦,一定物有所值。

[译] 单一职责原则在 iOS 中的应用


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

在线

在线

王坚 / 中信出版集团股份有限公司 / 2016-9-1 / CNY 58.00

互联网成为基础设施,数据成为生产资料,计算成为公共服务。 移动互联网带来的真正影响,是人们的大部分时间都消耗在在线社会上了。 50多万年前的关键词是光明与黑暗,50多年前的关键词是数字和模拟,而今天的关键词是在线与离线。 移动互联网是比传统互联网在线程度更深的互联网。手机操作系统一旦做到了在线就会带来绝佳的用户体验。苹果手机不仅淘汰了传统手机,而且带来了一个新的时代。 对于......一起来看看 《在线》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具