Tag: Alexander Emmanuel)

将视图模型建模为函数

注意:本文假设您了解RxSwift的基础知识或对MVVM有了一般的了解。 如果您不这样做,Internet上有大量令人难以置信的资源(包括下面链接的资源)可以帮助您入门。 另一个注意事项: Point-Free的 Brandon Williams 和 Stephen Celis 最初对这个想法睁开了眼睛 。 如果您尚未签出,则应该这样做。 他们发布的内容对于Swift开发人员来说绝对是必不可少的,订阅可能是您今年做出的最有价值的投资。 介绍 关于如何将RxSwift与MVVM配对,已经写了成千上万的单词,并进行了数小时的讨论。 在Grailed,我们一直热衷于与社区进行创新,以改善我们的代码并为我们的消费者创造更好,更可靠的产品。 出于这个目标,我们一直在使用一种MVVM形式,该形式通过函数式编程和RxSwift来提供可靠性,可测试性和稳定性。 我们喜欢它的许多方面,但是遇到了大多数MVVM开发人员都会熟悉的一系列问题。 问题所在 有时可能不清楚如何组织代码。 在互联网上漂浮的数十种MVVM变体中,每个视图似乎对视图层如何与其视图模型进行交互都有不同的看法。 缺少清晰的模式可能会使MVVM中的开发感到特别和不一致,从而可能导致可维护性问题。 视图模型也可能变得非常冗长。 由于许多版本的MVVM中缺乏结构,其他人选择为视图模型编写更为明确的输入和输出合同,但传统上这是以大量的样板为代价的。 同时,其他版本也不能防止视图模型的使用者错误地使用其API。 从视图层订阅视图模型的输入众所周知是一种反模式,但这是我在多个生产代码库中看到的。 理想情况下,编译器将阻止我们完全犯此错误。 由于Swift的类和结构初始化规则,视图模型也可能变得难以设置。 例如,当您必须将输出Observable设置为类或结构的属性时,这些输出取决于输入Subject 。 有时您会遇到这样的情况:在完成所有属性的初始化之前,您不能引用self ,但是由于需要引用self ,因此无法初始化属性。 忘记绑定视图模型的输入或输出也很容易,而且编译器在做错事情时也不会帮助我们找出问题。 编译器是我们的朋友,如果它可以帮助我们,那就太好了,这样我们就不会犯这种愚蠢的错误。 一种解决方案 现在,我们已经解决了RxSwift带来的MVVM的一些痛点,让我们以一个流行的MVVM风格编写一个简单的代码示例,并研究如何改进它。 所有笔触的开发人员都知道,编写纯函数可以解锁可测试性和可理解性的级别,否则,即使不是不可能,也很难实现。 问题在于我们编写的许多类型的代码无法完全适合纯函数,因此我们努力为尽可能多的模型建模纯函数。 这种见解驱使许多MVVM开发人员创建他们的视图模型,以具有一组明确的输入和输出,以便我们可以更类似于功能地对待它们。 输入是函数调用或Subject ,输出是回调,可变变量或Observable ,并且视图的业务逻辑在视图模型内部建模为输入到输出的转换,主要是在视图模型的初始化程序中。 Kickstarter开源应用可能是第一个,也是最知名的迭代。 尽管它是用ReactiveSwift编写的,但它们的想法几乎是相同的。 这个开源的应用程序使许多开发人员(包括我自己)对我们如何使用MVVM实现应用程序的可测试性和稳定性打开了眼睛。 让我们以经典的RxSwift为例,使用用户名和密码字段以及登录按钮的简单登录表单。 我们只希望在用户名和密码均填写后才启用该按钮,并且当用户单击该按钮时,我们希望显示一些有关其成功登录的消息(我们将在此处对其进行硬编码,在以后的文章中将详细介绍如何处理网络)。 这是一个示例,说明如果遵循Kickstarter应用程序中列出的模式,该如何编写。 如此小的屏幕在这里有很多事情要做,所以花一点时间来消化它。 我非常喜欢这种风格的几件事: 视图模型创建了一个非常明确的契约,关于它的功能以及应如何使用它 很少有错误使用视图模型API的方法 视图模型没有副作用 从外部查看此视图​​模型并了​​解如何对其进行测试非常容易 […]