书评:App Architecture:Swift中的iOS应用程序模式

自大约11年前的2008年3月iOS推出以来,核心的iOS MVC架构并未发生实质性变化。 多年来,随着应用程序变得越来越复杂,MVC和UIKit的局限和缺点促使开发人员开发和使用替代体系结构。

App体系结构:Swift中的iOS应用模式研究了在iOS上构建软件的不同体系结构方法。 尽管所有体系结构都稍有不同,但本书描述了关注点分离,不变性,单向数据流和可测试性的通用主题,这些主题是这些体系结构的基础概念,所有开发人员在构建高质量软件时都应努力争取。 虽然这本书与概念本身无关,但概念是从本书中摘取的最重要的内容。 体系结构来来去去,但是概念是常青的。

与以往一样,在处理建筑时,请遵循建筑的黄金法则: 保持简单,愚蠢

记住:建筑只是达到目的的一种手段。 专注于最后。 关注客户,用户。

关于建筑

标准很棒,每个人都应该有自己的标准。 克里斯·科恩(Chris Koehnen)

建筑—繁重的术语

术语“架构”有点像是四个字母的单词。 在考虑软件设计,体系结构或Rx之类的库以某种方式思考时,软件开发人员会变得非常热情和/或防御。 他们使人两极分化。 使它们成为可能的体系结构和工具可以成为许多人的信仰。 在研究体系结构之前,重要的是我们要全神贯注,不要陷入陷阱! 客户不会对所使用的模式或架构的“清洁度”有所了解。

然后是建筑的近亲-“模式”。 模式本身通常是有用的设计。 像体系结构一样,如果将模式的关注点放到了极致,则冒着从为客户的角度设计软件到为设计的目的设计软件的风险。 一切都与软件在内部的实用程度,软件的“纯”程度等有关。同样,不要忽视客户

专注于概念

在这样的背景下,我想说的是,本文将着重于本书中描述的每种特定体系结构的优点。 实际上,这本书的作者并没有主张任何一种架构都优先于另一种架构。 明智之举。 没有*正确*的架构。

不要挂在一个特定的体系结构上。 没有“正确的”架构。 但是好的架构通常遵循通用的概念和模式。 这些概念跨越了整个架构。 了解这些基础知识,您将轻松理解任何体系结构。

这些概念,而不是它们的单个特定实现,对您而言,最重要的是要摆脱本文。

我们将重点关注的基本概念包括:

* 关注点分离。
*不变性。
*单向数据流。
*与UIKit和MVC的交互。

建筑很重要。 代码前设计!

专家提示:体系结构很重要。 高质量的软件并非偶然发生。 设计中考虑了思想。 真正的黑客会仔细考虑他们的设计,将其视为一种艺术形式。

想要跳进去,手指到键盘,启动代码是很常见的。 但是帮自己一个忙。 停下来想一想。 首先设计系统。 了解您需要的数据,系统各层以及通信模式。 开始编写代码很容易。 很难考虑应该如何设计系统。 但是随着时间的流逝,您将不得不回答一些棘手的问题。 早点做。 经常做。 哦,请记住: KISS

乍一看似乎并非如此, 但请记住,构建应用程序生命周期的只有一小部分 。 重构,维护和新功能是出色的体系结构成本的回报。

iOS应用程式架构状态

iOS已经存在了10年了,MVC架构并没有实质性的改变。 UIView,UIViewController和模型对象的范围差不多。 iOS开箱即用给我们什么?

  • 视图:UIView等。
  • 控制器:UIViewController及其派生类。
  • 型号:核心数据,PONSO(普通的旧NSObject)
  • 沟通:代表团,NSNotification,KVO。

大C

视图和模型层对于理解和实现来说很简单。 但是,当应用程序变得复杂时会发生什么呢? 这种逻辑何去何从? 它不在“ M”中。 不是“ V”。 实际上,整个应用程序都需要写在某个地方。 剩下的唯一地方是控制器层。

在iOS开发人员中长期存在的笑话是MVC代表“ Massive View Controller”。 VC可以轻松推入1000行代码,尤其是对于涉及的视图。

VC太大时会发生什么?

  • 状态变得极其难以推理。
  • 单元测试同样庞大,需要大量的样板和基础设施来进行设置。
  • 重构比较困难。

整本书以及互联网上绝大多数iOS架构讨论都描述了简化控制器层的方法。 如何将逻辑分离为离散的组件和通信模式,但如何与UIKit配合使用。

开源救援

在Google推出适用于Android的架构组件的同时,苹果公司将iOS架构模式留给了开发者社区来构建。

Android体系结构组件为Android开发人员引入了一组模式和工具。 拥有一套“官方”架构会增加成为标准的机会。 如果他们能够赶上(不保证会成功),那么它确实可以帮助Android社区解决平台碎片化问题,改善整个Internet上的文档,并使社区和应用程序代码库无处不在。

苹果尚未在UIKit之上提供任何架构工具或指南。 开发人员社区介入其中,提供了其他软件平台上常见的iOS友好体系结构示例。 MVVM,MVP,VIPER等版本均已为iOS创建。

所有这些第三方体系结构都来自不同的社区-学术界,功能编程,网络等。示例包括:

  • Web — Elm,React,Flux
  • iOS-毒蛇
  • 功能/接收
  • MVP,MVVM

建筑特征

让我们看一下评估和/或设计应用程序时要考虑的三个最重要的特征。

  • 关注点分离
  • 单向数据流(各层之间的通信)
  • 不变性

关注点分离

“ Massive View Controllers”的主要问题是,当它们处于整体状态时,您不容易对其进行推理或测试代码。

分离出应用程序的逻辑层和组件(关注点)。

您是否有发出网络请求的视图控制器? 那句柄视图过渡? 那做复杂的逻辑或计算吗? 所有都是分离的候选人。 将该逻辑从视图控制器中移到专用组件中。

在构造各层时,请遵循“干净架构原则”并由内而外进行构建。 您软件的最内层应该*不*知道上层。

单向数据流(UDF)

单向数据流是一个奇特的术语,用于描述数据如何流经系统。 简而言之-数据始终沿一个方向流动。 UI动作流向模型,模型动作流向UI。

单向数据流(UDF)
— — — — — — — — — — — — — — — — — —

查看->查看操作->交互逻辑->模型操作->模型

查看<-查看更改<-表示逻辑<-模型更改

通过高级示例很容易理解。

假设用户点击了一个UIButton。 ViewController IBAction触发。 视图控制器并没有在视图控制器中执行所有逻辑,而是仅将消息发送到较低层,该较低层可能执行该逻辑-可能是验证,格式化或计算。 该层又将消息发送到下一层,即模型层。

如果模型层发生更改,它将通知其委托人或侦听器它具有新数据。 侦听器接收事件,为UI准备新数据,并通知视图层(也许是View Controller)可以显示新数据。 视图层将更新UIView。

为什么单向数据流如此重要? *它使您可以清楚地说明您的代码*。 在海量视图控制器问题中,VC处理了应用程序的所有逻辑。 通过在系统各层之间定义清晰的接口,并以相同的方向“要求”所有数据流,可以轻松了解状态的处理位置并解决问题。

单向数据流在Web上很常见。 React / Redux是围绕UDF构建的。 很高兴看到iOS社区采用了UDF。

不变性

尽可能在模型和数据结构中保持不变。 不变的数据结构有助于防止大量与状态相关的问题。 不变性简化了跨线程的状态管理(通常不需要锁定不可变资源),防止意外的状态操纵,并通过不允许图层“欺骗”和操纵现有数据结构来帮助强制单向数据流。

始终喜欢数据结构的不变性。 如果您习惯使用可变数据结构,则需要纪律和思想去思考不可变性,但是一旦养成了使用不可变数据结构的习惯,您就会更有理由对自己的状态进行推理应用。

而且,随着围绕Rx的模式和工具以及函数式编程变得越来越主流,不变性成为一种要求。 功能性编程语言和工具希望您的数据结构是不变的。

范例程式码

整个文章都是很棒的理论,但是在您看到代码之前,理论可能很难真正理解或付诸实践。

该书的作者在书中描述的所有体系结构中创建了一个简单的示例iOS应用程序。 您可以在此处找到代码。

同样,阅读此代码时要考虑的最重要的事情是理解上述概念的表示方式。 这些概念是您在编写*您的*应用程序时想一想的想法。 问你自己:

  • 我应该在应用程序的哪一层创建? (关注点分离)
  • 各层如何通信? Rx? 代表们? (单向数据流)
  • 谁负责更改模型的状态? (不可变性)

值得您花时间阅读本书示例。 他们写的很好,而objc.io的作者是iOS领域最好的思想领袖。

最后的想法

这本书使我看到了iOS空间中对体系结构的需求 。 这对我来说是真正的礼物。 我已经临时实现了许多这样的模式,但实际上并没有在很大程度上正式考虑架构。 本书强调了真正的“需要”,以便在开始之前认真考虑如何设计系统。

我以为这本书可能要短得多。 模式非常相似,这本书相当重复。

VIPER是本书中未涵盖的常见iOS模式。 我觉得专门针对iOS体系结构的书应该考虑一下。

我希望看到更多有关Rx和反应式编程的背景。 我认为Rx会极大地改变系统的设计方式。 更多有关Rx的背景将对人们有所帮助。

最终思想

作为软件工程师,我们是工匠。 即使10年后,iOS仍为我们提供很少的原语来构造代码,而由我们自行设计和构建应用程序。

尽管有许多架构,但是关注点分离,单向数据流和不变性的基本概念超越了架构。 了解这些内容,您将可以编写干净,可维护和可测试的软件。

参考书目

  • 清洁建筑原理
  • [使用VIPER·objc.io构建iOS应用
  • 与关注点分开的大型VC。
    *`I`:交互器。 商业逻辑。
    *`E`:实体。 模型。
    *`P`:演示者。 驱动UI。
    *`V`:视图
    *`R`:路由器—用于UI控制流(segues等)
  • 榆木建筑·榆木入门
  • Redux·JS应用程序的可预测状态容器
  • Android体系结构组件| Android开发人员