内容提要
实现监管规则的代码存在独特风险:错误不会报错,而是返回看似合理却严重失准的数字。以印度GST利息计算为例,存在三大陷阱:参数含义混淆(应按实缴现金而非总税额计息)、法定数值硬编码为常量、校验逻辑留在UI层。对应三个习惯:在注释中注明规则出处、将法定值设为带默认值的可选项、把输入守卫移入函数内部。核心是参数命名要杜绝歧义。
延伸解读
监管代码的独特风险:静默错误
与普通软件不同,实现监管规则的代码出错时往往不会抛出异常或产生堆栈跟踪,而是返回一个看似合理但严重失准的数字。例如,印度GST利息计算中,若错误地以总税额而非实缴现金为基数,利息可能高出六倍,但代码不会报错,测试也可能因同样的误解而通过。这种静默错误更难被发现,因为输出在形状和数量级上都显得正常,却可能误导决策。
参数命名:最廉价的防错文档
在监管代码中,参数命名至关重要。一个模糊的名称如“amount”可能让调用者传入错误的数量,而“cashTaxPaid”则明确要求实缴现金,迫使调用者检查输入是否正确。文章强调,如果参数可能与其他相似量混淆,命名应使混淆不可能发生。清晰的命名本身就是一种文档,能有效防止因误解规则而导致的错误。
法定值应作为可选项而非硬编码常量
监管规则中的数值(如税率、上限)可能随时变更,硬编码为常量会导致代码迅速过时,且无法适应特殊群体(如政府雇员)。更好的做法是将这些值设计为带默认值的可选项,零值处理常见情况,调用者可在法律变更时自行覆盖,无需等待库的发布周期。这既保持了易用性,又提供了灵活性。
输入验证必须内置于函数内部
当从应用提取库时,原本由UI层执行的输入验证(如表单限制)会丢失,导致库可能接收荒谬输入并引发严重问题(如内存耗尽)。文章建议将守卫逻辑移入函数内部,设置一个几乎不可能意外触发的上限(如100年贷款期限),这样既能防止崩溃,又不会成为用户抱怨的限制。任何UI验证都是库所缺失的验证,必须假设调用者没有UI。
Q&A
实现监管规则的代码有什么独特的风险?
错误不会报错,而是返回看似合理却严重失准的数字。
在印度GST利息计算中,常见的参数含义混淆是什么?
利息应按实际缴纳的现金税额计算,而非总税额。
为什么法定数值不应该硬编码为常量?
因为法定数值可能随时变更,硬编码会导致代码过时且无法及时更新。
如何正确处理法定数值?
将法定值设为带默认值的可选项,允许调用者覆盖。
为什么校验逻辑应该放在函数内部而不是UI层?
因为UI层的校验在逻辑提取为库后可能丢失,导致调用者传入无效输入时崩溃。
在编写实现监管规则的代码时,有哪三个习惯?
1. 在注释中注明规则出处;2. 将法定值设为带默认值的可选项;3. 把输入守卫移入函数内部。