2. Ent领域边界概念:领域边界、实体与值对象在报表中的角色
在报表系统中,错误往往不是孤立的代码缺陷,而是领域边界(Domain Boundary)被突破、实体(Entity)与值对象(Value Object)职责混淆所引发的系统性故障。理解这三者的本质,是构建健壮报表错误处理体系的第一道防线。
2.1 什么是领域边界
领域边界是软件系统中不同业务子域之间的逻辑分界线。在报表架构中,它划定了“数据采集域”、“计算聚合域”、“展示渲染域”各自的责任范围与通信协议。越过边界的数据必须经过显式转换与校验,否则就会引入不可追踪的错误。
核心原则:领域边界是错误隔离的天然屏障。边界内的错误应被内部消化,边界外的错误必须通过契约接口暴露。
报表系统中的典型领域边界
| 边界名称 | 输入 | 输出 | 错误风险 |
|---|---|---|---|
| 数据源边界 | 原始数据库行、API响应 | 规范化数据记录 | 字段缺失、类型不匹配、空值 |
| 计算边界 | 规范化数据记录 | 聚合指标、统计结果 | 除零、精度溢出、维度缺失 |
| 展示边界 | 聚合结果 | 图表配置、表格数据 | 格式化异常、国际化缺失 |
2.2 实体(Entity)在报表中的角色
实体是具有唯一标识且生命周期可追踪的对象。在报表系统中,实体代表那些“你是谁比你的值更重要”的业务概念。实体的状态可以变化,但其身份保持不变。
报表中的典型实体
- 报表模板(ReportTemplate):拥有唯一ID,包含布局、数据源绑定、权限配置,可被多次修改和版本化。
- 报表实例(ReportInstance):每次执行生成的快照,拥有独立ID,记录生成时间、参数、状态(成功/失败)。
- 用户(User):报表的订阅者或操作者,身份贯穿整个报表生命周期。
- 数据源连接(DataSourceConnection):数据库或API的配置实体,包含连接字符串、认证信息。
实战提示:实体的错误处理应围绕“身份一致性”展开。例如,当报表实例状态变为“失败”时,必须保留原始请求ID和错误上下文,以便后续重试或审计。
2.3 值对象(Value Object)在报表中的角色
值对象通过属性值来定义自身,没有独立标识。两个值对象如果所有属性相同,则视为相等。在报表中,值对象用于封装那些“是什么比是谁更重要”的数据片段。
报表中的典型值对象
| 值对象 | 属性 | 不可变性要求 | 常见错误 |
|---|---|---|---|
| 金额(Money) | 数值、币种 | 创建后不可修改 | 币种混用、精度丢失 |
| 日期范围(DateRange) | 开始日期、结束日期 | 开始 ≤ 结束 | 反向范围、时区错乱 |
| 百分比(Percentage) | 分子、分母、小数位数 | 分母不为零 | 除零、超过100%未校验 |
| 地址(Address) | 国家、城市、街道、邮编 | 格式标准化 | 字段缺失、编码错误 |
2.4 实体 vs 值对象:错误处理视角的对比
| 维度 | 实体(Entity) | 值对象(Value Object) |
|---|---|---|
| 错误追踪方式 | 通过ID追踪错误历史 | 通过值校验即时失败 |
| 错误恢复策略 | 状态回滚 + 重试 | 重新创建合法值 |
| 并发冲突风险 | 高(需乐观锁/悲观锁) | 低(不可变,无状态) |
| 持久化方式 | 独立表,有主键 | 嵌入实体表或序列化 |
| 错误传播范围 | 影响整个实体生命周期 | 仅影响当前计算上下文 |
2.5 领域边界实战:错误传播与隔离
在报表系统中,一个典型的错误传播路径如下:
- 值对象校验失败:例如
Percentage(150, 100)超出范围,值对象立即抛出InvalidPercentageError。 - 实体捕获并记录:
ReportInstance实体捕获该错误,将自身状态置为FAILED,并记录错误码和原始值。 - 领域边界拦截:计算边界拦截到实体状态变化,不将原始值对象异常直接暴露给展示层,而是返回标准化的
ReportResult对象。 - 展示层渲染错误提示:展示边界根据
ReportResult中的错误码,渲染用户友好的提示信息。
常见反模式:将值对象的原始异常(如
ArithmeticException)直接抛出到展示层。这会导致领域边界失效,用户看到技术栈信息,且错误无法被实体层统一管理。
2.6 小结:边界、实体、值对象的协同原则
- 边界即契约:每个领域边界定义清晰的输入/输出协议,错误必须按协议转换。
- 实体负责生命周期:实体的错误处理包含重试、回滚、状态机转换。
- 值对象负责即时校验:值对象在创建时完成所有校验,失败则不允许存在。
- 错误向上转型:底层值对象的校验错误,应被上层实体包装为领域错误,再被边界拦截为标准化响应。