Catalog 边界
Catalog 的职责是解析用户输入,而不是定义单位身份。这个边界决定了 LunarUnits 如何处理符号、别名和自定义单位。
问题
实际应用中,用户输入通常来自字符串:m/s^2、N、Hz、kg。这些符号需要解析,但符号本身不应该成为核心单位模型的全局状态。
如果把 Catalog 做成全局 mutable registry,会带来几个问题:
- 不同模块注册同一个符号时,行为依赖加载顺序。
- 测试之间可能互相污染。
- 同一段解析代码在不同上下文下得到不同结果。
- 核心 unit identity 被用户界面符号影响。
选择
LunarUnits 把 Catalog 设计成不可变查找值。Parser 接收一个 Catalog,并基于它解析单位表达式。扩展 Catalog 会返回新值,而不是修改全局表。
这样,解析上下文由调用方显式传入。CLI、Web UI、测试和领域应用都可以拥有自己的符号表。
避免的错误
这个边界避免了“看不见的全局注册”导致的行为漂移。解析失败也可以被应用层清楚处理,而不是在 core 层制造隐式依赖。
代价
代价是调用 parser 时必须携带 catalog。相比全局默认表,这多了一点样板代码;但换来的是可测试、可复现、可组合的解析行为。
边界
Catalog 不参与单位的数学身份判断。单位是否兼容由 dimension 和 unit scale 决定;Catalog 只负责把用户写下的符号映射到单位。
使用建议
通用应用可以从 @preset.all() 开始,因为它覆盖内置单位包。领域应用可以在此基础上添加局部别名,例如 force、flow 或业务系统中的标准缩写。也可以按输入范围只组合部分领域的 Catalog。
重复绑定同一个符号时,后写入的绑定生效。这个能力适合局部上下文里的别名或覆盖;公共 CLI、教程和共享配置应尽量避免让常见符号产生歧义。