调研 The Composable Architecture (TCA) 框架


1. 框架概述

The Composable Architecture (TCA) 是一个由 Point-Free(Brandon Williams 和 Stephen Celis)开发的开源 Swift 库,专注于以一致、可理解的方式构建 Apple 平台应用(支持 iOS、macOS、iPadOS、visionOS、tvOS 和 watchOS)。它与 SwiftUI、UIKit 等 UI 框架兼容,受到 Elm 架构和 Redux 的启发,但通过 Swift 的类型系统和现代特性(如宏、async/await)进行了深度优化。TCA 的核心目标是提供模块化、可测试、符合人体工程学的应用架构,解决以下问题:

  • 状态管理:用值类型(如 struct)管理状态,确保跨视图共享和即时更新。
  • 模块组合:将复杂功能拆分为小型、隔离的模块,便于组合和复用。
  • 副作用处理:通过 Effect 类型管理异步操作(如网络请求),确保可测试性。
  • 测试:支持单元测试、集成测试和端到端测试,覆盖复杂场景。
  • 人体工程学:用最少的概念(State、Action、Reducer、Store、Effect)构建简洁 API。

TCA 的设计理念在 Point-Free 的视频系列中逐步完善,文档提到通过多集视频(https://www.pointfree.co/collections/composable-architecture)从头讲解架构,适合深入学习。


2. 核心组件与实现

TCA 的核心围绕五个类型/概念展开,文档提供了清晰的代码示例(见 <DOCUMENT>),以下进一步总结并补充分析:

  1. State(状态)
  • @ObservableState 宏标记的结构体,描述功能所需数据。例如:
    swift @ObservableState struct FeatureState: Equatable { var count = 0 var numberFact: String? }
  • 使用值类型(struct)避免可变状态的复杂性,Equatable 确保状态比较高效。
  • @ObservableState 利用 Swift Observation 框架(Swift 5.9+),自动生成观察逻辑,适合 SwiftUI 视图更新。
  1. Action(动作)
  • 枚举所有可能的交互或事件,如用户操作、通知或 API 响应。例如:
    swift enum FeatureAction { case decrementButtonTapped case incrementButtonTapped case numberFactButtonTapped case numberFactResponse(String) }
  • 动作是单向数据流的入口,触发 Reducer 执行状态变更。
  1. Reducer(减速器)
  • @Reducer 宏定义,描述如何根据 Action 更新 State 并返回 Effect。例如: @Reducer struct Feature { @ObservableState struct State: Equatable { /* ... */ } enum Action { /* ... */ } @Dependency(\.numberFact) var numberFact var body: some Reducer&lt;State, Action&gt; { Reduce { state, action in switch action { case .decrementButtonTapped: state.count -= 1 return .none case .incrementButtonTapped: state.count += 1 return .none case .numberFactButtonTapped: return .run { [count = state.count] send in let fact = try await numberFact.fetch(count) await send(.numberFactResponse(fact)) } case let .numberFactResponse(fact): state.numberFact = fact return .none } } } }
  • Reducer 是 TCA 的核心逻辑单元,确保状态变化确定性,Effect 管理副作用。
  1. Store(存储)
  • 运行时引擎,持有 State,接收 Action,执行 Reducer,驱动 UI 更新。例如:
    swift let store = Store(initialState: Feature.State()) { Feature() }
  • 在 SwiftUI 中,StoreOf<Feature> 与视图绑定,自动观察状态变化。
  1. Effect(效果)
  • 表示副作用(如网络请求、定时器),通过 .run.none 返回。例如:
    swift return .run { [count = state.count] send in let fact = try await numberFact.fetch(count) await send(.numberFactResponse(fact)) }
  • 支持 Combine 和 async/await,易于取消和测试。

依赖管理

  • TCA 通过 @Dependency 宏和 DependencyValues 提供依赖注入。例如,NumberFactClient 封装 API 调用:
  struct NumberFactClient: DependencyKey {
      var fetch: (Int) async throws -> String
      static let liveValue = Self { number in
          let (data, _) = try await URLSession.shared.data(from: URL(string: "http://numbersapi.com/\(number)")!)
          return String(decoding: data, as: UTF8.self)
      }
  }
  • 测试中可轻松 mock 依赖:
  let store = TestStore(initialState: Feature.State()) {
      Feature()
  } withDependencies: {
      $0.numberFact.fetch = { "\($0) is a good number" }
  }

3. 最近更新(基于 GitHub Releases 和社区讨论)

根据 GitHub 仓库(截至 2025 年 3 月 31 日,版本 1.20.2)及相关讨论,以下是 TCA 的最新动态:

  • Swift 5.9+ 宏支持:引入 @Reducer@ObservableState 宏,简化 Reducer 协议和状态观察,减少 boilerplate。例如,1.7.0 版本(2024 年)添加了 Observation 支持(#2593),软弃用旧 API,优化 SwiftUI 集成。
  • 并发改进
  • 修复 Store 中 Combine subject 的数据竞争问题(#3447, #3475),提升线程安全。
  • 隔离根 Store 的取消操作(#3660),优化 Effect 性能。
  • 测试增强
  • 修复 TestStore 的问题,如忽略新属性包装器(#3666)。
  • 改进动态 Ascertain autocomplete(#3463),提升测试体验。
  • 导航工具:计划在 1.0 版本前完善导航支持,适配 SwiftUI 3.0+ 的栈导航(#1477)。
  • 模块化示例:社区贡献了模块化应用的样例项目(#3173),展示如何在多目标(iOS/macOS)中共享模块,解决 Xcode SPM 缓存问题。
  • Swift 6 支持:支持 Swift 6 语言模式和严格并发检查(#3173),确保未来兼容性。

这些更新表明 TCA 持续优化性能、并发和开发者体验,尤其在 Swift 生态的最新特性(如宏、Observation)上保持领先。


4. 优缺点分析

优点

  • 模块化:支持功能拆分和组合,适合大型项目。例如,isowords 游戏(https://github.com/pointfreeco/isowords)展示了复杂应用的模块化实现。
  • 测试性TestStore 支持 exhaustive 测试,覆盖状态变化和 Effect。例如:
  @Test
  func testFeature() async {
      let store = TestStore(initialState: Feature.State()) {
          Feature()
      } withDependencies: {
          $0.numberFact.fetch = { "\($0) is a good number" }
      }
      await store.send(.incrementButtonTapped) { $0.count = 1 }
      await store.send(.numberFactButtonTapped)
      await store.receive(\.numberFactResponse) { $0.numberFact = "1 is a good number" }
  }
  • 副作用管理:Effect 使异步操作可控、可测试,优于传统的闭包回调。
  • 跨平台:支持所有 Apple 平台,兼容 SwiftUI 和 UIKit。
  • 社区活跃:191 位贡献者、1270 个 PR、1200+ GitHub 讨论,社区支持强大(如 TCACoordinators、TCAComposer 等扩展库)。

缺点

  • 学习曲线:概念(如 Reducer、Effect)对新手稍复杂,需熟悉单向数据流。社区反馈早期 TCA 使用复杂,但最新更新(宏、教程)已降低门槛。
  • Boilerplate:尽管宏减少了样板代码,某些场景仍需较多代码(如私有 Action 封装需额外 struct)。社区建议未来用宏进一步简化。
  • 性能:值类型和观察机制高效,但大型 State 需小心管理内存(Swift 编译器优化已缓解此问题)。
  • 依赖管理:需手动注册依赖(如 NumberFactClient),可能在复杂项目中增加维护成本。

5. 实际应用场景

TCA 适用于需要强壮架构的复杂应用,尤其在以下场景:

  • 大型项目:如 isowords(字谜游戏),展示了 TCA 在导航、状态共享和副作用中的能力。
  • 跨平台开发:支持多平台模块共享(#3173),适合 iOS/macOS 混合项目。
  • 高测试覆盖:如 Primer 和 Zines 应用,利用 TCA 的测试工具实现低成本、高覆盖测试。
  • 实时应用:通过 Effect 和 Observation,支持实时状态更新,适合动态 UI(如 SwiftUI 视图)。

社区案例:

  • Life Progress 应用(https://github.com/Bartozo/Life-Progress-iOS):使用 TCA 的最新 Reducer 协议,展示了现代化特性。
  • Tic-Tac-Toe 示例:展示模块化设计和 SPM 集成。

6. 安装与使用

安装

  1. Xcode → File → Add Package Dependencies…
  2. 输入 URL:https://github.com/pointfreeco/swift-composable-architecture
  3. 选择目标:
  • 单目标:直接添加 ComposableArchitecture。
  • 多目标:创建共享框架,依赖 TCA(如 Tic-Tac-Toe 示例)。

最低要求

  • Swift 5.10+
  • iOS 15+、macOS 12+ 等

文档与学习资源

  • 官方文档:https://pointfreeco.github.io/swift-composable-architecture/
  • 交互式教程:Meet the Composable Architecture(DocC 格式)。
  • 示例目录:包含计数器、语音备忘录、待办列表等。
  • Point-Free 视频:深入讲解 TCA 的设计与实现(https://www.pointfree.co/collections/composable-architecture)。

7. 社区与生态

  • 活跃社区:1.5k forks、13.4k stars,116 个 release,57,000+ Slack 消息。
  • 讨论平台
  • GitHub Discussions(https://github.com/pointfreeco/swift-composable-architecture/discussions)
  • Swift 论坛(https://forums.swift.org/c/related-projects/swift-composable-architecture)
  • Point-Free Slack 社区
  • 扩展库
  • Composable Architecture Extras:增强功能。
  • TCAComposer:生成样板代码的宏框架。
  • TCACoordinators:支持 Coordinator 模式。
  • 贡献:欢迎 PR 提交新库或翻译(如 README 的多语言版本)。

8. 与其他架构的对比

TCA 基于 Elm 和 Redux,但更适配 Swift:

  • 比 Elm:更灵活的 Effect 系统,集成 Swift 的类型安全和并发特性。
  • 比 Redux:更严格的副作用管理(强制用 Effect),减少运行时错误。
  • 比 MVVM:更强的测试性和模块化,适合复杂应用,但可能比轻量 MVVM 多 boilerplate。

9. 结论与推荐

TCA 是一个功能强大、现代化的 Swift 架构,适合需要高可维护性、可测试性和模块化的项目。最新更新(1.20.2)通过宏和并发优化显著降低了使用门槛,尤其适合 SwiftUI 项目。社区活跃,资源丰富(如 isowords、DocC 教程),是 Apple 开发者构建复杂应用的理想选择。缺点(如学习曲线)正通过宏和文档改进逐步缓解。

推荐场景

  • 大型、长期维护的 iOS/macOS 应用。
  • 需要高测试覆盖率的团队项目。
  • 跨平台、模块化开发的复杂场景。

建议

  • 从官方示例(Examples 目录)开始,尝试简单计数器。
  • 学习宏(如 @Reducer)以减少 boilerplate。
  • 参与社区讨论,获取最新模式(如导航、依赖管理)。

发表评论

人生梦想 - 关注前沿的计算机技术 acejoy.com 🐾 步子哥の博客 🐾 背多分论坛 🐾 知差(chai)网 🐾 DeepracticeX 社区 🐾 老薛主机 🐾 智柴论坛 🐾