Swift中的领域驱动设计:如何停止与架构斗争

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

为什么DDD不是“另一种模式”

\n\n

您是否曾经因为“业务逻辑分散在所有控制器中”而从头重写项目?或者,您的UserManager是否膨胀到2000行,没有人真正理解它在做什么?听起来熟悉吗?

\n\n

在Swift开发的世界里,我们已经习惯了MVC、VIPER或MVVM。但所有这些模式都解决同一个问题:如何将UI与逻辑分离。然而,它们几乎没告诉我们如何组织业务逻辑本身。这时,领域驱动设计(DDD)登场了——这是一种将应用程序的领域置于核心,而非框架的方法。

\n\n

在本文中,我们将通过实际示例探讨如何在Swift中应用领域驱动设计。您将看到,DDD并非抽象理论,而是一个强大的工具,能使代码可读、可测试且易于应对变化。

\n\n

用简单的话说什么是DDD

\n\n

想象一下,您正在编写一个电商应用。MVC会告诉您:“创建一个Product模型、一个ProductViewController控制器和视图。”而DDD会问:“在您的业务中,‘商品’是什么?它可以没有价格吗?当它被添加到购物车时会发生什么?”

\n\n

领域驱动设计是一种软件建模方式,使代码尽可能精确地反映业务的语言和规则。您不再使用“技术性”实体(如DataManager),而是使用领域对象:Order、Customer、Invoice。

\n\n

DDD的基本构建块

\n\n

为了避免在术语中迷失,请记住三个主要概念:

\n\n
    \n
  • Entity(实体)——具有身份的对象。两个字段相同的对象是不同的实体(就像两个同名不同人)。
  • \n
  • Value Object(值对象)——仅由其属性定义的对象。如果两个对象的所有字段都匹配,它们就是同一个对象(如日期或金额)。
  • \n
  • Aggregate(聚合)——一组被视为一个整体的相关对象。聚合有一个根(root entity),通过它可以访问所有内部对象。
  • \n
\n\n

听起来很枯燥?让我们用Swift来实现。

\n\n

用Swift编写领域模型

\n\n

假设我们正在构建一个任务管理应用(TODO列表)。我们从最简单的开始——任务状态的Value Object。

\n\n
// Value Object: 任务状态\nstruct TaskStatus: Equatable {\n    let rawValue: String\n    \n    static let todo = TaskStatus(rawValue: "todo")\n    static let inProgress = TaskStatus(rawValue: "inProgress")\n    static let done = TaskStatus(rawValue: "done")\n    \n    // 业务规则:只能转换到下一个状态\n    func canTransition(to newStatus: TaskStatus) -> Bool {\n        switch (self, newStatus) {\n        case (.todo, .inProgress), (.inProgress, .done):\n            return true\n        default:\n            return false\n        }\n    }\n}
\n\n

请注意:我们没有使用枚举,因为在真实业务中,状态可能来自服务器或存储在数据库中。TaskStatus是一个不可变对象,它自身知道自己的规则。

\n\n

现在,我们创建一个Entity——任务本身:

\n\n
// Entity: 任务\nfinal class Task {\n    let id: UUID\n    var title: String\n    var description: String\n    private(set) var status: TaskStatus\n    let createdAt: Date\n    \n    init(id: UUID = UUID(), title: String, description: String, status: TaskStatus = .todo) {\n        self.id = id\n        self.title = title\n        self.description = description\n        self.status = status\n                

博客

书籍推荐