检查先决条件应该由谁负责?

Whose resposibility should it be to check preconditions?

在函数是关键角色的过程语言中,契约设计范式基本上表示在接受参数的函数和调用者之间存在协议。

协议内容类似于 "if the caller ensures that the preconditions of the function are met, then the function will behave in an expected manner and/or return expected values."

如果我们严格按照这种方式编写代码,那么只有调用者负责确保函数的正确输入。但是以防御性编程的名义,包含内部保护措施以防调用者做一些愚蠢的事情似乎是明智的。

谈到软件架构和设计时,最好的方法是什么?

这是来电者的责任。例如,如果传递一个空指针,strlen 的实现会做什么?它唯一能做的就是中止程序——这在 C 语言中是一个可行的选项,如果是极端的话。在 C++ 中,它可能会抛出异常(但如果它遵循 C++ 标准则不会),但处理该异常将非常困难难的。因此,允许程序将 运行 保持在已知状态的唯一明智的解决方案是不使用空指针作为参数调用 strlen,从而将检查这个的责任放在调用上代码。

正如 Neil 所说,检查是调用者的责任。你说,

it seems wise to include internal safeguards in case the caller does something stupid.

为了描述为什么这不是理想的方法,我将扩展 Neil 的示例,该示例使用检查传递给 strlen 的空指针,想象两种情况:

  1. 调用 strlen 的函数预先检查输入。
  2. strlen 在对参数进行操作之前在内部检查其参数。

如果您只调用一次 strlen,这两种方法的效率没有区别。但是,想象一下,您不是对 strlen 进行一次调用,而是连续多次调用 strlenstrstr 和其他字符串函数。在场景 1 中,无论您对字符串库中的函数进行 1、2、10 或 100 次调用,您只需检查一次错误输入。在场景 2 中,每次调用都被迫检查输入,从而使过程变得更慢。