当前位置: 首页 > 知识库问答 >
问题:

客户端检查后置/方法检查前置条件?

慕意致
2023-03-14

公共方法的先决条件和后决条件构成了该方法与其客户之间的合同。

1.根据,调用者不应该验证后置和被调用的方法不应该验证先决条件:

让我们回顾一下平方根函数sqrt的前提和后置,如程序49.2所示。调用sqrt的函数负责向函数传递一个非负数。如果传递了一个负数,平方根函数应该什么都不做来处理它。另一方面,如果一个非负数被传递给sqrt,sqrt有责任传递一个满足后置的结果。因此,调用sqrt的人不应该做任何事情来检查或纠正结果。

如果操作的前置条件失败,则责怪调用者如果操作的后置条件失败,则责怪被调用的操作

但正如另一篇文章中包含的代码所示,调用的方法确实验证了前提条件:

/// <summary>Gets the user for the given ID.</summary>
public User GetUserWithIdOf(int id,
        UserRepository userRepository) {
  // Pre-conditions
  if (userRepository == null)
      throw new ArgumentNullException(
          "userRepository");
  if (id <= 0)
      throw new ArgumentOutOfRangeException(
          "id must be > 0");

  User foundUser = userRepository.GetById(id);

  // Post-conditions
  if (foundUser == null)
      throw new KeyNotFoundException("No user with " +
          "an ID of " + id.ToString() +
          " could be located.");

  return foundUser;
}

a) 既然满足方法的先决条件是客户机的责任,那么被调用的方法是否也应该检查先决条件是否满足?

b) 由于被调用的方法负责传递满足后条件的结果,调用方是否应该检查后条件?

2.第一篇文章中提到的好处之一是“前置条件和后置条件可以用来在OOP中划分类之间的责任”,我理解为也在说验证前置条件不是被调用方法的责任,也不是调用者的责任验证后置。

但是,坚持这样的理念难道不会让我们的代码更加脆弱吗?因为它盲目地相信另一方(另一方是调用方或方法)会兑现它的promise?

3.如果调用方/被叫方不盲目信任对方,那么我们不是失去了后置条件和前置条件提供的很多好处吗,因为现在被叫方必须承担检查前置条件的责任,调用方必须承担验证后置条件的责任?

谢谢

编辑

3.

如果调用方/被叫方不盲目信任对方,那么我们不是失去了后置条件和前置条件提供的很多好处吗,因为现在被叫方必须承担检查前置条件的责任,调用方必须承担验证后置条件的责任?

调用方不需要验证post条件,因为它们应该由被调用的方法来确保。被调用的方法不需要验证前提条件,因为没有其他方法来强制契约。

a)您是否假设后置只应声明/保证返回值为指定类型或null(如果返回值为nullable)?除了返回值的类型之外,不能后置条件也声明其他东西(不能通过类型系统验证),比如返回值是否在指定范围内(例如:不能后置也声明类型int的返回值将在10-20的范围内)?在这种情况下,客户端不需要检查后置吗?

b) 那么,我们可以说第一篇文章声称被调用的方法不应该检查前提条件是错误的吗?

2.编辑

不,后置条件可以是任何东西,而不仅仅是空检查。无论哪种方式,客户端都可以假设后置条件已经被验证,这样,例如,如果合同声明已经确保,您就不需要验证int范围。

a) 您之前说过,被调用的方法需要检查前提条件,以减少代码的易受攻击性,但我们是否也可以推断调用方需要验证后条件(例如,验证返回的int值是否在后条件promise的范围内),以减少调用方代码的易受攻击性?

b) 若客户端可以盲目信任后置条件所做的声明(当后置条件做出返回值在某个范围内这样的声明时,我会说这是一种盲目信任),为什么调用方法不能同时信任调用方将满足调用方法的先决条件?

共有1个答案

商飞尘
2023-03-14

a) 既然满足方法的先决条件是客户机的责任,那么被调用的方法是否也应该检查先决条件是否满足?

是的,客户机有责任确保满足前提条件,但是被调用的方法必须验证这一点,因此示例中会进行空检查。

b) 由于被调用的方法负责传递满足后条件的结果,调用方是否应该检查后条件?

调用方应该能够依赖于被调用方法的约定。在您提供的示例中,方法GetUserWithIdOf确保满足post条件,否则会引发异常。存储库本身没有post条件,即它将始终返回用户,因为可能找不到用户。

2.第一篇文章中提到的好处之一是“可以使用前置条件和后置条件在OOP中划分类之间的责任”,我的理解是,被调用方法不负责验证前置条件,调用方也不负责验证后置条件。

被调用方法仍然负责验证前置条件,因为它们通常不能由类型系统验证。像Eiffel这样的语言提供了更大程度的静态合同验证,在这种情况下,可以利用该语言强制执行先决条件。就像在Java/C中一样,您可以强制方法参数为给定类型,Eiffel将这种类型的验证扩展到更复杂的契约声明。

但是坚持这样的哲学难道不会让我们的代码更加脆弱吗,因为它盲目地相信另一方(另一方要么是调用方,要么是方法)会兑现它的promise?

是的,这就是为什么必须核实先决条件。

3.如果调用方/被叫方不盲目信任对方,那么我们不是失去了后置条件和前置条件提供的很多好处吗,因为现在被叫方必须承担检查前置条件的责任,调用方必须承担验证后置条件的责任?

调用方不需要验证post条件,因为它们应该由被调用的方法来确保。被调用的方法不需要验证前提条件,因为没有其他方法来强制契约。

更新

a) 不,post条件可以是任何内容,而不仅仅是空检查。无论哪种方式,客户机都可以假设post条件已被验证,例如,如果合同声明已确保,则不需要验证int范围。

b) 我想是的。引述:

如果传递了一个负数,平方根函数应该不做任何处理。

if表示被调用的方法已经进行了某种验证。什么都不做是无声的失败,这可能是一种反模式。

随后的引述:

如果操作的前置条件失败,则责怪调用者如果操作的后置条件失败,则责怪被调用的操作

将失败的前置条件归咎于调用方的唯一方法是首先确定前置条件已失败。因为被调用的方法“拥有”这个前提条件,所以它应该是标记失败的最后一站。

更新2

a、 b)调用方可以信任post条件的原因是,post条件可以通过被调用的方法来保证。被调用的方法是声明和拥有合同的方法。被调用的方法不能信任调用方的原因是没有人保证满足前提条件。被调用的方法不知道它可能拥有的所有调用方,因此它必须自己进行验证。

 类似资料:
  • 突击测验,炙手可热!你已经知道 Puppet 的配置设置保存在 puppet.conf 文件里, 在该文件里没有提及的任何参数都会使用其默认值。 你怎样才能显示所有的配置参数的值呢(不管它是否在 puppet.conf 文件里有明确设置)? 你可以使用 Puppet 的 --genconfig 开关。 操作步骤 运行如下命令: # puppet --genconfig 工作原理 这将输出每个配置参

  • 本文介绍了 DM 提供的前置检查功能,此功能用于在数据迁移任务启动时提前检测出上游 MySQL 实例配置中可能存在的一些错误。 使用命令 check-task 命令用于对上游 MySQL 实例配置是否满足 DM 要求进行前置检查。 检查内容 上下游数据库用户必须具备相应读写权限。当数据迁移任务启动时,DM 会自动检查下列权限和配置: 数据库版本 5.5 < MySQL 版本 < 8.0 Maria

  • js 语法检查主要用到的 loader 和插件有:eslint-loader eslint eslint-config-airbnb-base eslint-plugin-import 这里主要采用的是airbnb编码规范(参见:https://github.com/BingKui/javascript-zh) 一、安装loader 和插件 #安装 loader 和插件eslint-loader

  • 问题内容: 我正试图顺应HTML5浪潮,但面临一个小问题。在HTML5之前,我们曾使用Flash检查文件大小,但现在的趋势是避免在Web应用程序中使用Flash。有什么方法可以使用HTML5在客户端检查文件大小? 问题答案: 这可行。将其放置在事件侦听器中,以了解输入是否发生更改。

  • 本文向大家介绍Python检查ping终端的方法,包括了Python检查ping终端的方法的使用技巧和注意事项,需要的朋友参考一下 菜鸟一枚,写着试了试,虽说有点杂乱,但还是能用,我是在linux下运行的 大致说下过程: 1、把需要ping的网段中所有ip存到数组中(我是放到数组中了,其实直接for循环,一个个的也行) 2、遍历数组,逐个ping 3、根据ping返回的字符串,判断是否ping通

  • 因此,我们正在使用全局MTL部署istio 1.0.2,目前进展顺利。对于健康检查,我们为服务添加了单独的端口,并根据文档进行了配置: https://istio.io/docs/tasks/traffic-management/app-health-check/#mutual-tls-is-enabled 我们的应用程序端口现在位于 8080 上,运行状况检查端口位于 8081 上。完成此操作后