# 设计示例与反例

以下是为本规范编写的工程示例，不是书中案例。用于边界判断，不能把示例里的技术选型当作所有项目的要求。

## 示例一：领取权益，封装调用协议

需求：用户领取一项权益，不能重复发放，也不能超发。

容易泄漏细节的接口让每个调用方依次调用：

```text
findClaim → checkQuota → decrementQuota → insertClaim
```

调用方必须理解事务、并发和失败后的状态。只把这些方法移动进一个 `ClaimManager`，仍然没有减少调用者需要掌握的知识。

可考虑的抽象是：

```text
claimBenefit(userId, benefitId) → 已领取的凭证或明确的业务失败
```

在本例业务契约下，模块负责原子地处理额度与领取记录；同一用户重复领取返回已有凭证，不再次扣减。实际实现依据项目的唯一约束、事务或其他一致性机制，不能仅凭这个接口名称宣称具备并发安全性。

验证首次领取、重复领取、额度不足，以及并发条件下不超发、不重复扣减。资格判断如果依赖独立业务政策，应由明确的业务边界负责，不能偷偷嵌入通用存储组件。

## 示例二：导入配置，按知识划分

两个模块分别读取和写入配置，都知道字段别名、版本规则及转义方式。修改格式时必须同时改两边，这是知识分散的证据。

把双向转换规则放在配置编解码模块，由它统一解释外部格式；文件读取和写入可以继续由独立 I/O 能力完成。运行时使用清晰的配置模型，无需处理转义细节。

验证合法样本、非法格式和项目要求支持的版本。判断收益看格式变更涉及的位置与运行时的使用方式，不看是否减少文件数。

## 示例三：短方法是否应该删除

一个业务服务只是原样转发存储方法，需要检查它是否提供实际边界。以下情形不能仅因代码短就删除：

- 方法是明确的事务入口。
- 包装层执行权限检查或隔离第三方协议。
- 项目约定依赖该入口，或已发布接口处在明确的兼容窗口。

反过来，“以后也许会用到”本身不足以证明新增包装层的价值。优先使用现有结构，只有能说明当前职责时才增加层。

## 示例四：注释表达契约

对 `expiresAt = issuedAt + validitySeconds` 写“计算过期时间”几乎没有增加信息。

更有价值的注释可能是：

```text
有效期从首次签发时刻计算，重复领取不续期；时间采用 UTC 秒级时间戳。
```

该注释说明调用方和维护者必须知道的规则。只有实现与业务证据确实支持时才能写入；不允许为了让文档完整而发明契约。

## 示例五：抽象增量与过度设计的分界

需求是让现有导出功能支持一个新的日期筛选条件。如果查询边界清晰，只需扩展现有参数并覆盖边界用例，不必新增查询接口、导出插件注册表或通用报表引擎。

如果三个实际导出入口分别维护同一套日期范围解释规则，则可以集中这项规则，并让现有入口使用它；输出格式等无关差异仍留在各自边界。

验收同时检查用户得到正确结果、日期规则有一致语义。不要以“抽象还没完善”为由只交付空接口；也不要以“先让功能跑起来”为由继续复制已经明确重复的规则。
