解决的方法是快速失败。
我们没有代码,也没有很多根据代码测试或不测试分支前缀的前缀示例。我们所拥有的是:
- 089-100 =>测试分支
- 10B,10C =>测试分支
- <088 =>可能是真实分支
- > 100 =>可能是真实分支
该代码允许数字和字符串的事实有点奇怪。当然,可以将10B和10C视为十六进制数,但是如果将前缀全部视为十六进制数,则10B和10C不在测试范围之内,将被视为实分支。
这可能意味着前缀存储为字符串,但在某些情况下被视为数字。这是我能想到的最简单的代码,它复制了这种行为(使用C#进行说明):
bool IsTest(string strPrefix) {
int iPrefix;
if(int.TryParse(strPrefix, out iPrefix))
return iPrefix >= 89 && iPrefix <= 100;
return true; //here is the problem
}
用英语来说,如果字符串是一个数字,并且介于89到100之间,则它是一个测试。如果不是数字,那就是测试。否则,这不是测试。
如果代码遵循此模式,则在部署代码时没有任何单元测试可以捕获此错误。以下是一些单元测试示例:
assert.isFalse(IsTest("088"))
assert.isTrue(IsTest("089"))
assert.isTrue(IsTest("095"))
assert.isTrue(IsTest("100"))
assert.isFalse(IsTest("101"))
assert.isTrue(IsTest("10B")) // <--- business rule change
单元测试表明“ 10B”应被视为测试分支。上面的@ gnasher729用户说,业务规则已更改,这就是上面的最后一个声明所显示的内容。在某个时候断言应该已经切换到isFalse
,但是那没有发生。单元测试在开发和构建时运行,但此后再也没有。
这是什么教训? 该代码需要某种方式来表示已收到意外输入。这是编写此代码的另一种方法,该代码强调该代码期望前缀为数字:
// Alternative A
bool TryGetIsTest(string strPrefix, out bool isTest) {
int iPrefix;
if(int.TryParse(strPrefix, out iPrefix)) {
isTest = iPrefix >= 89 && iPrefix <= 100;
return true;
}
isTest = true; //this is just some value that won't be read
return false;
}
对于不了解C#的用户,返回值指示代码是否能够解析给定字符串中的前缀。如果返回值为true,则调用代码可以使用isTest out变量检查分支前缀是否为测试前缀。如果返回值为false,则调用代码应报告预期的给定前缀,并且isTest out变量无意义,应将其忽略。
如果您可以接受例外处理,则可以改用以下方法:
// Alternative B
bool IsTest(string strPrefix) {
int iPrefix = int.Parse(strPrefix);
return iPrefix >= 89 && iPrefix <= 100;
}
这种选择更为简单。在这种情况下,调用代码需要捕获异常。无论哪种情况,代码都应该以某种方式向调用者报告它不希望将strPrefix转换为整数。这样,代码很快就会失败,银行可以迅速找到问题,而不会令SEC感到尴尬。