修复常见的库函数,还是放弃呢?

Ian*_*oyd 5 language-agnostic

想象一下,我有一个带有错误的函数:

伪代码:

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)

在我的编写示例中,没有办法修补函数 - 如果我没有给出一个对象,我不能做我需要做的事情.

您是否可以通过添加参数验证来破坏现有代码?您是否让现有代码继续出错,结果不正确?

Chr*_*bek 2

问题在于,您不仅修复了错误,而且还通过引入错误情况来更改方法的语义签名。

从软件工程的角度来看,我建议您尝试尽可能地指定方法(例如使用前置条件和后置条件),但是一旦方法出现,规范更改就不可能了(或者至少您会检查该方法的所有出现)并且新方法会更好。