想象一下,我有一个带有错误的函数:
伪代码:
void Foo(LPVOID o)
{
//implementation details omitted
}
Run Code Online (Sandbox Code Playgroud)
问题是用户通过了null:
Object bar = null;
...
Foo(bar);
Run Code Online (Sandbox Code Playgroud)
然后,该功能可能会因访问冲突而崩溃; 但它也可能正常工作.错误是函数应该检查传递的无效情况null,但它从来没有.这从来都不是问题,因为开发人员被信任知道他们在做什么.
如果我现在将功能更改为:
伪代码:
void Foo(LPVOID o)
{
if (o == null) throw new EArgumentNullException("o");
//implementation details omitted
}
Run Code Online (Sandbox Code Playgroud)
那些幸福地使用这个功能的人,碰巧但没有得到访问权限,现在突然间会开始看到一个EArgumentNullException.
我是否继续让人们不正确地使用该功能,并创建该功能的新版本?或者我是否修复了该函数以包含它原本应该包含的内容?
所以现在是道德困境.您是否曾为新的代码添加新的健全性检查,安全检查和断言?或者你把旧功能称为废弃,并有一个新功能?
考虑一个常见的错误,微软必须为开发人员修复它:
MessageBox(GetDesktopWindow, ...);
Run Code Online (Sandbox Code Playgroud)
您永远不会想要在桌面上制作窗口模型.你将锁定系统.您是否继续让开发人员锁定用户的计算机?或者您将功能更改为:
MessageBox(HWND hWndParent, ...)
{
if (hWndParent == GetDesktopWindow)
throw new Exception("hWndParent cannot be the desktop window. Use NULL instead.");
...
}
Run Code Online (Sandbox Code Playgroud)
实际上,Microsoft将Window Manager更改为自动修复错误参数:
MessageBox(HWND hWndParent, ...)
{
if (hWndParent == GetDesktopWindow)
hWndParent = 0;
...
}
Run Code Online (Sandbox Code Playgroud)
在我的编写示例中,没有办法修补函数 - 如果我没有给出一个对象,我不能做我需要做的事情.
您是否可以通过添加参数验证来破坏现有代码?您是否让现有代码继续出错,结果不正确?
问题在于,您不仅修复了错误,而且还通过引入错误情况来更改方法的语义签名。
从软件工程的角度来看,我建议您尝试尽可能地指定方法(例如使用前置条件和后置条件),但是一旦方法出现,规范更改就不可能了(或者至少您会检查该方法的所有出现)并且新方法会更好。