使用协调器构建应用程序:第一部分

驯服无节制的应用程序架构

链接到示例GitHub项目

注意:示例项目在撰写本文时尚未完成,目前只是草稿。

在过去的几个月中,我一直关注的开发领域之一就是构建模块化代码。 我在一月份回信了我尝试重构TaskHero时遇到的挫折感。 当时我说这不是我最后的决定,这是我要花时间反思的问题。 在此期间,我尝试了几种成功实现应用程序模块化的方法。 我发现构建模块化应用程序代码的更成功的方法之一是使用Coordinator设计模式和委托。

这篇文章是关于使用协调器构建应用程序以及使用它的优点/缺点的两部分系列文章的第一篇。 第一部分主要涉及概念和为什么要使用它的原因,第二部分将进一步介绍实现。 我已经建立了一个示例项目,但它还没有最终的形式,更多的是本文撰写时的草稿。 如果您有兴趣查看该示例,欢迎您。 我在顶部发布了指向它的链接。

信用到期

如果您还没有阅读Soroush Khanlou的博客,我强烈建议您开始阅读。 这是一个很好的资源,它帮助改变了我处理应用程序体系结构的方式。 这篇文章的灵感来自他的几篇文章。 我特别建议阅读他有关使用协调器的系列文章。

MVC可能意味着超过一件事

Model-View-Controller及其衍生产品是最常用的应用程序体系结构之一。

苹果定义:

模型-视图-控制器(MVC)设计模式为应用程序中的对象分配以下三个角色之一:模型,视图或控制器。 该模式不仅定义了对象在应用程序中扮演的角色,还定义了对象之间的通信方式。 三种类型的对象中的每一种都通过抽象边界与其他对象分开,并跨这些边界与其他类型的对象进行通信。 在应用程序中,某些MVC类型的对象的集合有时称为“ 层” ,例如模型层。

模型视图控制器

如果您生活在Apple编程世界中,那么您会很快了解到Apple一直在使用MVC架构。 实际上,MVC嵌入了UIKit的核心。 虽然MVC是一种非常有用的设计模式,但是如果处理不当,则会存在一些缺陷。 这些陷阱并不是一开始就很明显的,特别是如果您不熟悉编程的话。

MassiveViewController

ViewController的基本问题之一是,随着应用程序开发的进行,它们会迅速变得庞大而笨拙。 这可能会导致多个问题。 首先,从实际的角度来看,要使用包含许多应用程序功能的不同部分的大型类可能会很困难。

由于可以广泛地解释ViewControllers的用途,因此很容易将似乎不适合其他地方的代码放入其中。 这可能导致MVC综合征-Massive-View-Controller。 ViewController的问题可能像Singletons一样,因为它们的用途是可以解释的,因此任何东西都可能属于它们。

抢救ViewModels?

大多数人试图克服MVC综合征时首先看的地方之一就是ViewModels 。 那么为何不? 这是一种向应用程序添加另一层抽象的方法,这正是我们想要的,对吗? 好的,这绝对是朝正确方向迈出的一步。

ViewModel是视图显示逻辑的抽象。 抽象之所以好,是因为它们使应用程序的不同区域分离。 抽象化应用程序功能的不同方面是我们如何整理代码的方式。

答案的一部分-不是解决方案

虽然ViewModels不是解决我们难题的灵丹妙药,但是它们也会出现问题。 首先,要隐藏在ViewModel的ViewController中填充的所有代码将变得非常容易,从而创建一个全新的综合症:Massive-View-Models。 发生这种情况时,我们的ViewController看起来很漂亮,但脏的秘密隐藏在ViewModel中。 使用ViewModels可以解决的只是一部分难题,它们的实用程序不应该被打折,而不能打折。 隐藏混乱不是我们要在这里努力的方向,我们想要的是模块化。

注意:如果您想深入了解ViewModels,建议您阅读 本文

模块化

脆性

当我们的代码脆弱时,微小的更改可能会在整个应用程序中引起问题。 当我们将应用程序功能的不同区域绑定在一起时,我们的代码将变得脆弱。 我们的代码越纠缠和纠缠,我们的代码就越脆弱。 从逻辑上讲,这是完全合理的。 重叠的相互依赖性意味着更改整个系统中应用程序级联的一个区域。

大视图控制器的最大问题之一是它们纠缠了您的流程逻辑,视图逻辑和业务逻辑。 —协调员

在软件开发中,模块化与易碎性相反。 模块化代码意味着功能的不同领域在很大程度上是独立存在的,或者仅松散地依赖于其他类。

促进封装和模块化

编写模块化代码有几个好处。 一方面,由于功能松散耦合,因此重构过程变得更加容易。 您会发现,您可以对一个方面进行重大更改,而不必完全更改代码。 通过允许我们轻松地隔离或组合地测试代码的不同方面,模块化还使为我们的代码编写测试变得更加简单和有效。

代表们!

在OOP中,根据实现的不同,继承既可以是天赋,也可以是祸根。 如果正确使用继承,则可以增强应用程序模块化并提升DRY代码。 如果使用不当,您最终可能会得到一个充满小丑车类的粉笔应用程序。 小丑汽车类是充斥着不必要的属性的类,这些类的方法在继承链的每个级别上都被添加。 这就是委派可以进入的地方。我们可以根据需要使用委派来构造类,而不是随身携带旧行李。

“委派就像通过对象组合手动完成继承。” —最佳实践软件工程

通过使用委托,我们可以使用协议一致性来使我们的代码更具可重用性和模块化性。

协调员

协调员可以帮助您恢复秩序并驯服不守规矩的应用程序体系结构。 当我们使用协调器时,尽管不是完全,我们还是开始远离MVC。 协调器取代了ViewController,成为我们应用程序逻辑流程的最高仲裁者。 实际上,协调器是该逻辑流程的抽象。 我们通过自由使用委托来完成此抽象。

我发现当我使用协调器模式时,我自然更倾向于使我的代码更具模块化。 老实说,我不确定这是由于模式产生的心态造成的,还是模块性是协调员抵抗力最小的途径。 无论如何,我发现我一直在努力解决的几个问题都没有设法解决。

抽象的抽象抽象的

我遇到的第一个问题是对多种协调器类型的需求。 不同的控制器需要不同类型的协调器。 考虑到UINavigationControllers和UITabBarControllers之间的差异,您无法像控制UIViewController一样控制UINavigationController的流程。 这需要一种最终的抽象,一种抽象来统治它们!

一统统统

不同类型的协调员

为了处理我们控制器中的差异,我们创建了符合基本协调器协议的各种协调器。

导航协调员

TabBarControllerCoordinator

包起来

我认为这是一个休息的好地方。 我知道很多都是理论,但请放心! 下一篇文章,我们将更深入地研究代码…

最佳实践软件工程–委托
上图显示了如何在Java中为实际类实现多继承行为。 当然……最佳实践软件工程.ifs.tuwien.ac.at 模块化编程–维基百科
模块接口表示该模块提供和需要的元素。 在… en.wikipedia.org中定义的元素 模型视图控制器
关于Cocoa编程的核心概念,模式和机制的简短文章的集合。 developer.apple.com 委托模式–维基百科
在委托中,一个对象通过委托给第二个对象(委托)来处理请求。 委托人是一个帮助者…… en.wikipedia.org