層級 | 主要職責 | 是否依賴 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 項目依舊保持靈活與可維護。