层级 | 主要职责 | 是否依赖 iOS / UIKit? |
---|---|---|
Presentation (UI) | 视图、控制器、ViewModel,将用户操作转成「意图」,把结果渲染到屏幕 | 是 |
Domain | 业务规则 与 用例 (Use Case),维护系统在概念上的真实世界模型 | 否(纯 Swift,完全无框架依赖) |
Data / Infrastructure | 网络、数据库、文件、Keychain、BLE…任何“把数据拿进来/写出去”的具体实现 | 是 |
一句话:Domain 层 = 纯业务核心,既不关心 UI,也不关心数据从哪里来,只关注「业务要做成什么样」。
为什么以前几乎感受不到它?
- MVC / MVVM 在小型项目里把业务代码直接写进
Controller
/ViewModel
,Domain 与 UI 混在一起时就很难察觉它的存在。 - 项目规模一旦变大,UI 逻辑(动画、路由)与业务规则(计费、权限)纠缠,就会让测试、复用、多人协作变痛苦;这时才需要显式抽出 Domain。
Domain 层包含什么?
组件 | 说明 | Swift 示例 |
---|---|---|
Entity / Value Object | 业务对象及其不变式 | swift struct Order { let id: UUID let items: [OrderItem] func total() -> Decimal { … } } |
Use Case / Interactor | 对应〝用户故事〞的业务流程;组合多实体完成一次操作 | swift protocol PlaceOrderUseCase { func execute(request: PlaceOrderRequest) throws -> Order } |
Repository 接口 | Domain 面向的数据抽象,用协议表达,无实现细节 | swift protocol OrderRepository { func save(_ order: Order) throws func by(id: UUID) -> Order? } |
Domain Service(可选) | 涉及多个实体但不属于任何一个实体的方法 | PaymentService , DiscountCalculator |
关键词:纯 Swift + 不依赖三方库 —— 这样才能在单元测试里无需启动 App、无需网络就验证业务规则。
与 iOS 常见架构的对应关系
架构 | Domain 所在位置 |
---|---|
VIPER | “Interactor” 就是 Domain 用例;“Entity”=Domain 实体 |
Clean Swift / VIP | “Interactor” + “Entity” |
Clean Architecture | 内层「Domain」圆环 |
MVVM-C | 额外抽出一个 UseCase / Service 层即可形成 Domain |
简单示例:聊天未读数
需求:展示未读消息数量,并在后台推送来时更新
- Entity:
Conversation
,UnreadCounter
- UseCase:
GetUnreadCountUseCase
- Repository 协议:
UnreadRepository
- Infrastructure 实现:
UnreadApiDataSource
,UnreadCoreDataDataSource
- UI:
Bloc/Cubit
或ViewModel
,只调用GetUnreadCountUseCase
现在改用本地 Realm 缓存?只换 Infrastructure 层实现,Domain 与 UI 毫无改动。
如何在现有 iOS 项目引入 Domain 层?
-
收集业务规则
- 订单金额计算、优惠叠加、登录态判断等经常被多处调用、变化概率低的逻辑。
-
抽出纯 Swift 类型
- 把
UIKit
,FoundationNetworking
,CoreData
依赖砍掉,只留下值类型 / 协议。
- 把
-
定义用例协议
PlaceOrder
,SendMessage
,MarkAsRead
… UI 通过协议调用,用 DI (如 Swinject) 注入。
-
重构 UI
- Controller 里不再处理业务计算,仅收集输入,调用 UseCase,拿结果渲染。
-
编写单元测试
- 用内存 FakeRepository 替换实际网络/数据库,快速验证边界条件。
小结
- Domain 层 = 你 App 的“核心大脑”。
- 它独立于任何框架,因此可移植、可测试、可长期演进。
- 把 Domain 抽清楚后,UI 和数据层都变成可替换的「插件」,让大型 iOS 项目依旧保持灵活与可维护。