协调员:复审

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

返回协调员

因此,距离我写上一篇关于协调员的文章已经几个月了。 在此期间,发生了很多事情! 我发布了一个名为PodCatch的新应用程序(我使用协调器概念构建了该应用程序-仍在进行中):

chriswebb09 / podcatcher
podcatcher –播客应用 github.com

我参加了尝试的活动! 纽约市Swift会议:

在此过程中,我有机会更详细地探讨了这个概念,并找出了对我有用的功能。

背上盘旋

我觉得现在是时候回过头来,完成我关于协调员的系列讨论的好时机。 在我走得太远之前,我想先拥有一件事。 我认为我的第一篇文章不是对该主题的出色介绍。 它缺乏重点,因为我试图将太多概念引入范围更窄的事物中。 除了这篇文章之外,本系列文章很可能是第三部分,因为这篇文章本身并不完整,我对我最初写的内容不满意。 我知道现在回过头来是我在CoreLocation上写的系列以及我希望退出的示例项目中的一个不切实际的话题(下周暂定)。 我现在写这本书是因为我想在尝试有关该主题的对话时记下来! 上周在纽约召开的Swift大会仍然让我记忆犹新。 ¯\ _()_ /¯

应用程序控制器/协调器

因此,让我们对第一部分进行一些回顾,如果您已经阅读了该文章,那么这似乎有点多余。 视图控制器的问题之一是,随着应用程序开发的进行,它们可能变得庞大而笨拙。 这是因为它们的目的可以得到广泛的解释。 如果您的大多数应用程序都在视图中工作并且视图控制器“控制”视图,那么将许多应用程序逻辑放在其中似乎是完全合理的。 显然,这种方法存在严重的缺陷。 如果您已经阅读了Soroush Khanlou关于协调员的博客文章,那么这是多余的,如果您还没有,我只是简单地谈谈一些背景信息。

不幸的是,以视图控制器为中心的应用程序开发方法不可扩展。 协调器是将您的代码隔离为易于替换的小块的好方法,并且是解决控制器不适的解决方案的另一部分。

— Khanlou:协调员

协调器模式是一种企业软件设计模式,已适应iOS世界:

您可以通过将所有流逻辑放在应用程序控制器中来删除重复项。 然后,输入控制器向应用程序控制器请求适当的命令,以根据模型和要根据应用程序上下文使用的正确视图来执行该命令。

—马丁·福勒

我喜欢他们在顶部发布的tl; dr,它对协调员要完成的工作的定义很简洁:

处理屏幕导航和应用程序流程的集中点。

出于这篇文章的目的,我想尽可能地强调应用程序的流程和导航。

观察结果

我尝试了一些开发人员! 在纽约召开的Swift大会上,他们对协调员的使用以及与我交谈过的每个人都对他们的职责和限制有不同的解释。 我与之交谈的一些开发人员已经定义了功能,这些功能要求将任何东西标记为诸如start方法之类的协调器。 其他人则使用协调器协议,而无需任何方法来将控制其应用程序体系结构的类绑定在一起。

从我与Soroush的对话中收集到的信息,解释的范围是设计使然的。

那么什么是协调员? 协调器是使一个或多个视图控制器周围的对象。 将所有驱动逻辑从视图控制器中移出,并将这些内容向上移动一层,将会使您的生活变得更加美好。 —汗楼

除了这个定义的广泛含义外,真正由开发人员决定如何以及何时使用它们。

我遇到的一些问题

协调人/委托混合人

综上所述,使用协调器构建应用程序时,我注意到了一些事情。 由于协调员对其职责没有严格的限制,因此您很容易被他们带走。 我在项目中注意到的最大问题之一是,它们可以成为视图/视图控制器委托混合对象的协调者。 这并不一定是一件坏事,但是到了极点,我们最终可以通过使用协调器最终到达我们试图避免的位置:Massive-Coordinator-Controllers。 您不必在使用传统的iOS委派和协调器之间进行选择。 实际上,在准则很少的情况下,找到两者的位置有助于为模式提供自然的结构。

服务

服务往往是广泛的保护伞。 实际上,我可能在许多应用程序中都过于广泛地使用了该类别。 如果您考虑与现实世界相关的问题,则服务会消耗某种货币并作为回报执行某些操作。 在iOS中,服务可以像网络客户端一样严格,也可以像对模型/ UI起作用和转换的任何事物一样广泛。 弄清楚您想如何对应用程序进行分层以及每个功能的降级位置可以在开发过程中为您的体系结构提供自然的结构完整性。 我从最近几个月撤走的一件事是,在开始使用某项服务时,决定您对服务的分类要严格或广泛会有帮助。

如果我要重写示例项目,则可能不会包含UI服务。

协调员

我经历了一些迭代,例如此博客文章的示例代码。 我的第一次尝试看起来像这样:

这还不错,但是在项目结束时,我发现自己将其写出来,只是为了确保我在主要协调器中使用了start方法:

  func start() { 
childCoordinators [0] .start ()
}

对我来说,这是一个线索,说明我对整体协调器协议的了解不够广泛,对专用协调器子类型的行为的了解不够具体。

我最终确定的是:

协调子类型

主要协调员

构建PodCatch时,我遇到的有趣的事情之一是需要为逻辑流的类型划分不同的协调器。 尽管最终删除了它,但在我的第一个PodCatch版本中,我有一个FireBase后端的登录/注册屏幕,该屏幕在逻辑上与Podcast播放器隔离了。 职责是如此不同,以至于将两个区域分开似乎是合乎逻辑的。 随之而来的问题是,如果这些区域分开,我们是否需要控制它们之间的流动? 就我而言,我毫不含糊地答应了。

一统统统

在这里我可以看到我自己读这篇文章并说:“好吧,这个家伙被带走了。”你可能是对的! 我要问的是,你在这方面听到了我的声音。 还记得几段后的引用吗?

Soroush:“ 那么协调员是什么? 协调器是使一个或多个视图控制器周围的对象。 将所有驱动逻辑从视图控制器中移出,并将这些内容向上移动一层,将使您的生活更加美好。”

事情是这样:我看不出只有视图控制器才应该这样做的原因。 是什么使我们无法进一步扩展该想法,因为我们需要分层协调以使其更加出色! 如果我们的应用程序中有明确的部分,内部协调流程是分开的,那么是否可以进一步进一步抽象协调,是否理所当然?

我们的协调员的协调员\ _(ツ)_ /¯

忍受我多一点。 让我们为顶级协调员构建协调员协议:

之后,我们可以创建符合我们的AppCoordinator协议的MainCoordinator类,如下所示:

之后,我们使用协议一致性来处理应用程序不同区域之间的流程:

这种设计的有趣之处在于,它可以在我们应用程序的不同区域提供灵活性。 每个部分不一定需要具有一个总体流程。 在标签栏中,我们可以为每个标签使用几个不同的协调器流程。

另外,交换,添加或删除流程的能力使体系结构可以在各种条件下工作,例如拥有设置配置文件流程,直到用户设置其配置文件,然后将其替换为视图配置文件流程。 可以针对不同的首选项等进一步推断出来。

控制器协调员

在构建PodCatch时吸取的经验教训的旁注

如果从头开始构建PodCatch,我将做的另一件事是创建控制器协调器子类型的方式。 我特别后悔创建了一个单独的选项卡和导航协调器子类型。 回想起来,它增加了额外的复杂性,使我无法按照自己的意愿创建有组织的架构。

导航协调员:

TabCoordinator:

未回答的问题:标签栏控制器协调器?

最大的问题是弄清楚如何将协调器流集成到标签栏控制器之类的东西中。 标签栏本身是否应具有自己的协调器? 那是矫kill过正吗? 可能,我仍在努力寻求最佳方法。

回到正轨

这些都是有趣的困境,但是跟随所有线索,将这个职位拉到了太多的方向,最终使水陷入泥潭。 让我们重新关注手头的示例。 对于这个示例项目,在我的第一个实例中,我将其作为协调子类型。

那可能就足够了。 我想演示应用程序区域之间的分离,因此我添加了一个控制器协调器委托(例如,快十倍)来帮助在起始视图和颜色视图之间进行转换。 我最终选择的是:

对我来说,即使对于应用程序体系结构的基础层来说,这也开始变得过于复杂。 它仍然有效,并且如果您能找到实现同一想法的更简单方法,那就去吧。 就目前而言,我还是可以的,我希望我能尝试更多的方法。

ColorController协调员

在本示例中,实现我的ControllerCoordinator的第一个方法是处理我的视图控制器子类ColorViewController的协调器:

该实现立即引起我注意的是changeColor方法中发生的UI更改。 我认为解决此问题的更好方法是将styleService注入视图,并让视图处理UI更改/更新。 因此,这里肯定会发生一两个重构。 最终,我们正在努力分离我们的关注点。 对我来说,协调员不应该只是另一个抛出不是视图控制器的代码的地方。

重要要点

在会议期间,我想到了一些有关协调员的事情:

孩子们永远不要告诉父母该做什么 :一个困扰我的教训是Raizlab的Brian提到:孩子控制者永远不要告诉父母控制者该做什么。 意味着我们不应该在子视图控制器中调用self.navigation控制器。 协调员为我们解决了这个问题,因为从理论上讲,应用程序数据的逻辑抽象从我们的视图控制器流出并进入我们的协调器,因此我们从父/子视图控制器手中进行决策。 这是那些可以很好地转化为人际关系的编程概念之一(显然有例外)。

协调器可以通过不同的方式实现:

除了将逻辑流程推出视图控制器之外,没有“单向”或正确的方法来实现。 毛泽东可能不是在iOS博客文章中引用的最佳人选,但这有点像“百花齐放”的概念。 看到从其简单性发展而来的各种排列非常有趣。

资料来源:

EAA的P:应用程序控制器
某些应用程序包含有关在不同点使用的屏幕的大量逻辑,这可能涉及… martinfowler.com 汗楼| 协调员
将流量提取到协调器中的好处很多。 视图控制器现在可以专注于他们的目标…… khanlou.com

如果您有兴趣,那里有一些非常不错的博客文章,人们在演示他们对该概念的理解:

导航协调员
协调员是iOS的一种设计模式,在过去的几个月中,我一直很喜欢它。 您应该阅读Soroush… irace.me 斯凯·弗里曼| 迅捷—协调员
过去一周,我遇到了Soroush Khanlou的有趣演讲,介绍了使用协调器的想法… skyefreeman.io iOS协调器模式
在过去的18个月中,我一直在从事职业生涯中迄今为止最大的iOS应用程序之一。 我们把它调了一点…… will.townsend.io 我是西姆
我花了一个星期暂停功能开发并重写每个视图控制器。 而不是直接访问… www.iamsim.me