
在一篇深度文章中,TripAdvisor iOS 首席工程师 Ben Sarrazin 讲述了他们向可组合架构(TCA)迁移的旅程。这一迁移的目的是取代他们现有 iOS 应用中的模型-视图-视图模型-协调器(MVVM-C)架构。
Sarrazin 解释说,离开 MVVM-C 的决定是由几个因素驱动的,这些因素都与应用复杂性的增长和团队的扩大有关。其中一个痛点是导航:
也许我们 MVVM-C 实现中最痛苦的一个方面是导航结构——或者更准确地说,是缺乏导航结构。我们的协调器可以启动其他任意一个协调器,结果发展成一个导航的可能性几乎无法被文档描述或推理的网络。
例如,当一个匿名用户访问网站并尝试执行需要认证的操作时,这种复杂性变得显而易见。即使在这样一个常见的场景中,MVVM-C 导航也会涉及众多协调器、视图模型和事件映射器,使得代码库难以理解和修改。
另一个挑战来自于协调器对 UIViewControllers 的依赖,这增加了复杂性,并要求使用 Combine 作为 SwiftUI 和 UIKit 之间的通信层。
调试基于 Combine 的事件链是非常困难的,特别是当它们跨越多个协调器并由多个发布者和操作符层组成时。
相比之下,TCA 承诺了几个优势,如与 SwiftUI 的无缝集成、强大的测试能力以及改进的可组合性。TripAdvisor 团队还看重 TCA 的发展和成熟度,及其高质量的文档和支持。
为了完成迁移,TripAdvisor iOS 团队采用了自下而上的方法。他们首先找出没有子级的视图模型,并将它们替换为 TCA 存储,然后逐步向上推广到父视图模型。
对导航元素也采用了类似的“叶到根”策略,但这里有一个转折。实际上,由于 TCA 需要集中的、基于状态的导航,协调器并没有一对一地替换。相反,父协调器承担了其子级的导航责任。最后这让导航有了单一真实来源:作为一个 TCA reducer 实现的全局路由器。
这种导航整合代表了我们迁移中最变革性的方面。我们目前有数十个具有重叠责任和复杂交互的协调器,最终我们将拥有一个干净、基于状态的导航系统,它更强大,也更容易理解。
这一迁移需要完全的心态转变,Sarrazin 解释说。它还带来了一些挑战。一个关键的洞察是,在 TCA 中复制现有的功能层次结构并不总是最佳方法。相反,团队学会了考虑在父组件和子组件之间发送动作的影响,这可能导致过度的双向通信。他们发现,更好的模式是在可能的情况下将共享行为集中到父组件中。
另一个挑战是在很短的时间内发出了太多动作,在滚动列表时就会出现这样的问题。为了解决这个问题,团队发现抑制高频输入,并尽量减少发送到存储的动作数量是很有效的,这样可以尽量在 reducer 中进行简单的状态更新。
TCA 在测试领域也带来许多好处,帮助减少测试的脆弱性。
我们发现,使用 TCA 的 TestStore 编写的测试为应用程序行为提供了更强的保证。通过测试让我们对功能按预期工作有很高的信心,这并不总是适用于我们之前的测试方法,特别是出现对 Combine 和调度器的重度依赖时。
此外,团队发现 TCA 测试通常可以成为一种设计反馈:当测试变得难以阅读或编写时,这通常是底层代码可以改进的迹象。
总的来说,根据 Sarrazin 的说法,迁移被证明是非常有效的。他的文章提供了许多宝贵的见解,超出了本文可以覆盖的范围。如果你对完整细节感兴趣,不要错过原文。
原文链接:How Tripadvisor Migrated to The Composable Architecture for Their SwiftUI App
评论