HarmonyOS掌上记账APP开发实践第53篇:领域组件设计模式:bill_base 与 asset_base 的领域驱动设计
2026/7/21 2:53:21 网站建设 项目流程

053 — 领域组件设计模式:bill_base 与 asset_base 的领域驱动设计

简介

在传统 MVC 架构中,业务逻辑和 UI 代码往往混杂在一起,导致代码难以复用和测试。MoneyTrack 引入了领域驱动设计(DDD)思想,将核心业务逻辑抽取到领域基础包bill_baseasset_base中。这些基础包遵循"无 UI 纯逻辑"的原则,只包含 Enums(枚举)、Types(类型定义)和 Models(数据模型)三部分,不依赖任何 UI 框架。这种设计让同一套业务逻辑可以被不同 UI 组件复用,也大幅简化了单元测试——测试领域包不需要搭建 UI 环境。

核心知识点

1. DDD 领域驱动设计

DDD 将应用按业务领域拆分为独立的"限界上下文":

  • bill_base:账单位领域,包含账单类型枚举、账单状态、收支类别、账单查询参数。
  • asset_base:资产领域,包含资产类型、资产账户模型、货币类型、资产统计聚合。
  • 每个领域包自治管理自己的数据结构和业务规则,彼此之间通过 common 层的共享基类(如BaseEntity)实现低耦合的跨领域引用。

2. 领域包的三层结构

每一个领域基础包都严格遵循 Enums / Types / Models 三层架构:

asset_base

Enums/AssetType.ets
资产类型枚举

Types/AssetFilter.ets
资产筛选接口

Types/AssetReport.ets
资产报表类型

Enums/CurrencyType.ets
货币类型枚举

Models/AssetModel.ets
资产数据模型

Models/AssetCalculator.ets
资产计算器

bill_base

Enums/BillType.ets
账单类型枚举

Types/BillQueryParams.ets
查询参数接口

Types/BillSummary.ets
统计摘要类型

Enums/BillStatus.ets
账单状态枚举

Enums/CategoryType.ets
收支类别枚举

Models/BillModel.ets
账数据模型

Models/BillValidator.ets
账单校验器

Enums 层:定义领域内所有的枚举常量。例如BillType.EXPENSE表示支出、AssetType.CASH表示现金资产。

Types 层:定义 TypeScript 接口和类型别名,用于跨模块的数据传递约定。例如BillQueryParams定义了账单列表的筛选条件接口。

Models 层:定义数据模型类,包含数据验证、格式化、业务计算等纯方法,不涉及任何 UI 渲染。

3. 领域包与 UI 包的分离原则

领域包与 UI 包的分离是 DDD 在鸿蒙工程中落地的核心原则:

  • 领域包(bill_base / asset_base):纯 ArkTS 代码,零 UI 依赖,可独立编译和测试。
  • UI 包(bill_card / asset_card):包含 @Component 声明,依赖 UI 框架,引用领域包的数据类型。
  • 分离的好处:当 UI 框架升级或替换时,领域逻辑不受影响;同一套领域逻辑可以同时服务于多个 UI 组件。

4. 跨领域引用

虽然每个领域包独立自治,但在实际业务中,账单与资产存在自然的关联。跨领域引用通过 common 层的共享基类实现:

// common/lib-utils/src/main/ets/BaseEntity.etsexportabstractclassBaseEntity{id:string;createdAt:string;updatedAt:string;abstractvalidate():boolean;}// bill_base/Models/BillModel.etsimport{BaseEntity}from'@moneytrack/lib-utils';exportclassBillModelextendsBaseEntity{amount:number;categoryId:string;assetId:string;// 关联资产ID,通过 ID 引用而非直接引用 AssetModelvalidate():boolean{returnthis.amount>0&&!!this.categoryId;}}

这里的关键原则是"通过 ID 引用而非对象引用"——BillModel 持有 assetId 字段指向资产,但不直接持有 AssetModel 对象,从而避免 bill_base 对 asset_base 的强依赖。

项目代码案例

Enums/Types/Models 三层完整代码框架

Enums/BillType.ets

exportenumBillType{EXPENSE='expense',INCOME='income',TRANSFER='transfer'}

Types/BillQueryParams.ets

exportinterfaceBillQueryParams{type?:BillType;startDate?:string;endDate?:string;categoryIds?:string[];minAmount?:number;maxAmount?:number;keyword?:string;}

Models/BillValidator.ets(业务校验逻辑):

exportclassBillValidator{staticvalidateAmount(amount:number):string|null{if(amount<=0)return'金额必须大于零';if(amount>99999999.99)return'金额超出上限';if(!/^\d+(\.\d{1,2})?$/.test(String(amount)))return'金额格式错误,最多两位小数';returnnull;}staticvalidateBill(bill:BillModel):string[]{consterrors:string[]=[];constamountError=this.validateAmount(bill.amount);if(amountError)errors.push(amountError);if(!bill.categoryId)errors.push('请选择收支类别');if(!bill.assetId)errors.push('请选择关联资产');returnerrors;}}

asset_base/Models/AssetModel.ets

exportclassAssetModel{id:string;name:string;type:AssetType;balance:number;currency:string;formatBalance():string{return`¥${this.balance.toFixed(2)}`;}isOverdrawn():boolean{returnthis.balance<0;}}

领域驱动设计的核心价值在于:业务逻辑独立于 UI 框架、可复用、可测试,为后续 6 个 UI 组件包的开发提供了稳固的基础。

推荐参考文档

  • 领域驱动设计(DDD)基础
  • 组件化架构设计模式
  • ArkTS 面向对象编程指南

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询