如何在Swift中应用单一责任原则

有时,当我们学习编码时,很难理解类责任的概念。 这是因为我们的第一个项目变得难以维护,原因是我们的代码中按类包含许多行,更重要的是,它承担了许多责任。

真正了解类责任的一种好方法是考虑可伸缩性。

让我们看一个如何使用它的例子。 但是,在此之前,我想先介绍一些理论并解释为什么这个概念在软件设计中很重要。

每个类在软件项目中负有单个责任的思想,并且将责任封装在一个唯一的类中的想法有一个名称:单一责任原则

这是SOLID软件设计的5条主要原则之一,他们在面向对象编程中尝试定义一个指南,以拥有更易懂,灵活和可维护的软件。

这些原则是:

  • 单一责任原则
  • 开闭原则
  • 里斯科夫替代原则
  • 接口隔离原理
  • 依赖倒置原则

这些概念的作者Robert C. Martin(他写了软件体系结构中最重要的书之一,即Clean Code)谈到“一类应该只有一个改变的理由” ,因此他将责任定义为更改。

例如,让我们考虑一个编译并打印报告的模块。 想象一下,可以出于两个原因而更改这种模块。 首先,报告的内容可能会改变。 其次,报告的格式可能会改变。 这两件事因不同的原因而改变。 一种实质性和一种化妆品。

单一责任原则说,问题的这两个方面实际上是两个单独的责任,因此应该放在单独的类或模块中。 耦合由于不同原因在不同时间发生变化的两件事,将是一个糟糕的设计。

使班级专注于单个关注点很重要的原因是,它使班级更加强大。 继续前面的示例,如果更改了报表编辑过程,则存在更大的危险,即如果打印代码属于同一类,则该打印代码将被破坏。 (示例摘自 Wikipedia

如果我们定义班级,知道他们在项目中的职责是什么,我们可以:

  • 轻松了解其在代码各部分中的功能。
  • 更快,更详细地修改现有逻辑。
  • 以较少的问题查找错误或有害行为的来源。
  • 不同类或模块中的抽象逻辑。
  • 拆分时没有重大问题的实现,因此以后可以完全替换它们。
  • 通过类或模块以更有效的方式定义单元测试,因此我们可以测试一小段代码,而无需测试更多的代码。

正如我之前说过的,您可以在类中考虑可扩展性以定义职责。 这就像思考是否可能在我们的项目中修改需求并在我们的体系结构中查看如何进行这些修改一样简单。

例如,如果我们看到要进行小的视图更改,则必须修改或修改业务逻辑,则我们没有正确定义项目中的职责。

让我们看一下Swift中的一个具体示例。

假设我有一个应用程序,它显示了商店中的商品列表。 到目前为止,我只有一个ItemsViewController负责该流的所有逻辑,数据和表示。 同样,当用户选择一个项目时,它也会打印日志。

您可以在https://github.com/fedejordan/SRPExample中查看代码

为此, ItemsViewController使用UITableView在列表中显示项目。 另外,我们使用一个名为ItemTableViewCellUITableViewCell子类来显示这些元素。

但是,假设我们要更改视图,例如,使用UICollectionView. 在这种情况下会有什么问题?

视图代码与项目数据逻辑非常耦合。 如果我们更改视图,则很有可能也会修改负责该项目的类。

真正的问题在于以下几行:

 让item = items [indexPath.row] 

为什么这里有问题?

因为我们正在使用UITableView索引来获取数组中的特定项目。 我们应该以某种方式抽象化视图使用UITableView

为了避免这种情况,我们将重构 ItemsViewController并将模型逻辑移至另一个名为ItemsInteractor类。

您可以在https://github.com/fedejordan/SRPExample的collection_view_refactor分支中查看最终结果。

我们是否在ItemsInteractor了更改? 没什么。 我们只是更改了功能的外观。

这也使我们能够以更加模块化的方式进行测试。 我们首先可以测试视图,然后是业务逻辑。 当然,为了正确进行测试,我们需要做一些更可注入的操作,例如,我们可以使用模拟类初始化模块,并且我们依赖Swift中的接口或protocols 。 基本上,这意味着,例如,不要在ItemsInteractor内创建ItemsViewController ,因为它是一个依赖项,应该从其实现中抽象出来。 但这一切都超出了文章的目的。

似乎我们没有做太多工作。 我们只是从数据模型中删除了视图逻辑。 真的值得吗? 在此示例中,也许它并不是太有用,实际上可能是我们只需要一个列表,而没有别的。

但是,当我们拥有更复杂的UI时,我们必须使同一视图适应不同的数据源,或者以不同的流程共享数据模型。 应用此概念使我们可以重用代码并以更适当的方式扩展项目。 为此,重要的是要了解我们维护的每个班级应该承担哪种责任。

我想补充一点,我认为,此概念是拥有良好代码的必要条件。 实际上,在任何编写不好的代码中,我们总会发现任何一个类承担着不止一个责任。 因此,我们看到了“单一责任原则”的重要性。

我们的Swift示例使我们能够理解为什么正确定义职责很重要。 仅仅因为我们要进行布局更改,如何将正确的模块化体系结构作为项目可扩展性的关键。

总结一下,我想得出一个结论,即始终关注我们的项目可扩展性 ,我们将能够查看我们是否正确定义了类或模块的职责。

非常感谢您阅读本文!

我希望你喜欢它。 您可以在评论部分中发送有关主题的任何消息或建议,或者直接给我发送电子邮件至fedejordan99@gmail.com