swa*_*ohn 19 language-agnostic conditional
拿一些像这样的代码
if (person.IsMale()) {
doGuyStuff();
} else {
doGirlStuff();
}
Run Code Online (Sandbox Code Playgroud)
是否应该写入以明确检查是否person.isFemale(),然后添加一个抛出异常的新else?也许你正在检查枚举中的值,或类似的东西.你认为没有人会在枚举中添加新的元素,但谁知道呢?"永远不会发生"听起来像着名的遗言.
我想你已经回答了自己的问题.如果您知道自己永远不会看到其他值:
bool isSet = ...
if (isSet)
{
return foo;
}
return bar;
Run Code Online (Sandbox Code Playgroud)
......然后不要打扰.但是,如果有可能存在两个以上的可能值,请掩盖自己.你(或维护程序员两年后)将不胜感激.
我找到'永远不会发生'的声音听起来不错,直到几个月后,当一位同事添加了代码,破坏了您的原始代码后,它才会咬你.所以,对我自己来说,即使看起来不可能,我也会确保自己的实力是否稳固.
如果你仔细阅读一些正式的方法书,他们建议你做这种事情.
定义后置条件
isMale && doGuyStuff || isFemale && doGirlStuff.
Run Code Online (Sandbox Code Playgroud)导出一些导致此后置条件的候选语句
if isMale: doGuyStuff
Run Code Online (Sandbox Code Playgroud)
这证明可以导致一些后置条件
if isFemale: doGirlStuff
Run Code Online (Sandbox Code Playgroud)
这可以证明导致一些后置条件
请注意,顺序无关紧要.实际上,如果删除任何排序假设,它会更简单.
最终结果如下:
if isMale: doGuyStuff
elif isFemale: doGirlStuff
Run Code Online (Sandbox Code Playgroud)
请注意,没有正确使用else条款.你永远不会 - 在正式的推导中 - 得出一个else条款.你总是会有积极的陈述条件: a && b || c && d各种各样的东西.很少会这样a && b || !a && c,但即便如此,你通常也会明确!a表态.
在形式上,"不可能的其他"条款应限于做类似以下的事情.
if isMale: doGuyStuff
elif isFemale: doGirlStuff
else:
raise HorrifyingSituationError
Run Code Online (Sandbox Code Playgroud)
你是否应该提出HorrifyingSituation错误,这意味着你做错了数学并且不正确地从条件中导出了语句.或者你首先不正确地定义了后置条件.
无论哪种方式,该计划都是以深刻和绝对的方式设计错误的.一般来说,这并不奇怪.第一次尝试测试时,它通常会失败.除非(经常发生),否则您选择反映后置条件原始定义中的错误的测试数据.即便如此,一旦遇到此异常,您可以轻松追踪并永久修复它.
如果它不能在生产中发生(但可能在开发过程中发生),我使用assert:
如果它不应该在生产中发生,但它可能会发生,我要么返回错误要么抛出异常。
顺便说一句,这是我在某处学到的一个巧妙的 C++ 小技巧;由于如果断言不正确,许多 ASSERT 宏将在消息框中显示它们的表达式,因此您可以对永远不应该执行的分支使用以下形式:
if (person.IsMale())
{
AdmitEntranceToManCave();
}
else
{
ASSERT(!"A female has gotten past our defenses. EVERYBODY PANIC!");
}
Run Code Online (Sandbox Code Playgroud)
字符串文字计算为(非 NULL)地址,逻辑上为 TRUE。因此,使用逻辑 NOT 运算符使其成为 FALSE。