对您接受的东西持开放态度吗?


45

[免责声明:这个问题是主观的,但我希望得到事实和/或反思的支持]

我认为每个人都知道“ 稳健性原则”,通常用Postel定律来总结:

保守发送的内容;在接受的内容上保持自由。

我同意,对于设计广泛的通信协议,这可能是有道理的(目的是允许轻松扩展),但是我一直认为,将其应用于HTML / CSS完全是失败的,每个浏览器都执行自己的无声调整检测/行为,几乎不可能在多个浏览器中获得一致的渲染。

我确实注意到,除非另有说明,否则TCP协议的RFC认为“ Silent Failure”是可以接受的……至少可以说这是一种有趣的行为。

在整个软件行业中,还有其他一些应用此原理的示例,这些示例经常出现,因为它们已经咬住了开发人员,从我的头顶开始:

  • JavaScript分号插入
  • C(静默)内置转换(如果不被截断的话,还算不错……)

并且有一些工具可以帮助实现“智能”行为:

但是,我发现这种方法虽然在与非技术用户打交道或在错误恢复过程中帮助用户时可能会有所帮助,但在应用于库/类接口的设计时仍存在一些缺点:

  • 该算法是否猜测“正确”在一定程度上是主观的,因此可能违反最小惊讶原则
  • 它使实施更加困难,从而增加了引入错误的机会(违反YAGNI吗?)
  • 它使行为更易于更改,因为对“猜测”例程的任何修改都可能破坏旧程序,几乎从一开始就排除了重构的可能性!

这就是导致我提出以下问题的原因:

在设计接口(库,类,消息)时,您是否倾向于健壮性原则?

我本人往往很严格,在我的界面上使用了广泛的输入验证,我想知道自己是否太严格了。


我想知道HTML和一般数据之间有什么区别?健壮性原则是关于沟通的。一个写-一个读。为什么网络通信与视觉或API不同?我有一个API示例,其中我们接受的自由原则简化了程序员的生活,减少了代码量,因此提高了性能+消除了错误。请看stackoverflow.com/questions/18576849
2013年

@Val:实际上,您的示例不匹配。“在接受的内容上保持自由”不仅是基础/派生的问题,它还不止于此,还接受(并解释)稍有错误的输入。
Matthieu M.

如何显示某些情况不显示该情况?
2013年

Answers:


34

我要说的是健壮性,因为它不会引起歧义

例如:解析逗号分隔的列表时,逗号前后是否有空格都不会改变语义。

解析字符串guid时,它应该接受任意数量的常用格式(带或不带破折号,带或不带大括号的括号)。

大多数编程语言在使用空格时都很健壮。特别是在不影响代码含义的所有地方。即使在与空格相关的Python中,当您位于列表或字典声明中时,它仍然很灵活。

我绝对同意,如果可以以多种方式解释某种事物,或者如果不是100%清楚其含义,那么太多的鲁棒性最终可能会很痛苦,但是鲁棒性有很大的余地,而且不会模棱两可。


1
我同意,值得的是坚固耐用。
Matthieu M.

2
甚至用逗号分隔的列表也会引起问题,例如:chrome和firefox的javascript引擎似乎接受{"key": "value",}为有效,而IE则不接受。在改进JSlint的构建过程之前,我经常偶然发现这个特定问题。
keppla 2011年

2
@keppla是实现而不是设计的问题。我不确定javascript规范是否合法,IE是否未遵循,还是FF和Chrome添加的“不错的功能”,但是在Python中它被指定为有效并如此实现。如果将其指定为有效且不起作用,则表示实现错误。如果未指定,那么就不应该真正依赖它(尽管从实用性上讲,如果它不能在主要的浏览器中运行,那么如果您不控制用户,那么它也可能不属于规范范围内)
Davy8'7

7
@ Davy8:尾部逗号似乎是非法的(stackoverflow.com/questions/5139205/…)。我不想依靠这一点,我的观点是,当足够多的人接受输入时,它就变成了事实上的标准(因为一个人没有注意到这是一个错误),这导致我们在HTML中遇到了一些错误:变得如此司空见惯,以至于您不能再将它们视作不好的输入了。
keppla 2011年

1
@keppla,在moz和Chrome中应该会失败。作为一个主要的JS开发人员,它让我很生气,因为它没有(至少在Moz中曾经如此)。它使调试更加困难,而不是简单。IE正在做它应该做的事情。失败@错误代码。HTML是一回事。我们不需要脚本语言的废话。这是鲁棒原理的可怕应用示例,浏览器供应商擅长于此。
Erik Reppen

15

当然不。防御性编程之类的技术会掩盖错误,从而使错误出现的可能性和随机性更高,从而使检测更加困难,从而更难以隔离错误。

被严重低估的“ 编写Solid Code”在反复强调使bug难以引入或隐藏方面的需求和技术方面发挥了巨大作用。通过应用其原则,例如“消除随机行为。强制错误是可复制的”。并且,“始终寻找并消除界面中的缺陷。” 开发人员将通过消除造成大量错误的模棱两可和不受控制的副作用,来极大地提高其软件的质量。


9

过度应用鲁棒性会导致您猜测用户想要什么,直到您弄错了它,这才是正确的。它还需要完全误导的信念,即客户不会滥用您的信任并创建随机的胡言乱语,而这恰好起作用,但是您将无法在版本2中提供支持。

过度使用正确性会导致您剥夺客户犯小错误的权利,直到他们抱怨自己的东西在竞争对手的产品上能正常工作,并告诉您使用5,000页标准的单词时,您可以做什么,这是正确的“ DRAFT”仍拖在蜡笔的封面上,至少有3位专家声称这是根本缺陷,还有200多位诚实的专家说,他们没有完全理解。

我个人的解决方案一直是弃用。您支持他们,但告诉他们他们做错了,并且(如果可能)告诉他们正确的最简单途径。这样,当您将错误功能关闭10年后,您至少会在纸上指出“我们已警告您可能会发生这种情况”。


+1表示弃用,这确实是一个重要概念,但令我惊讶的是,到目前为止它一直被忽略。
Matthieu M.

9

不幸的是,所谓的“健壮性原则”不会导致健壮性。以HTML为例。如果浏览器从一开始就严格地解析HTML,而不是试图猜测格式错误的内容的含义,则可以避免很多麻烦,眼泪,时间和精力的浪费。

浏览器应该只显示了一条错误消息,而不是试图在幕后进行修复。那将迫使所有的笨拙者解决他们的混乱。


引用自己(必须变老):“但是我一直认为将其应用到HTML / CSS完全是失败的”
Matthieu M.11 /

3
没错,但是同样的容错性也有助于使网络如此流行。
2011年

浏览器供应商对此失败。有了doctype,我们就可以在这方面做出自己的选择,但是到最后,只要声明了任何doctype,所有事情几乎都会以相同的方式表现出来。现在,他们认为关于如何处理故障的一套极为复杂的严格规则是解决方案?我认为他们没有发现问题。
Erik Reppen'4

您要说的是,与“健壮”相反的快速失败效率更高。
2013年

@MaR:是吗?非常有争议的功能很可能很重要。
Deduplicator

6

我将接口分为几组(如果愿意,可以添加更多):

  1. 那些在您控制之下的应该严格(通常是班级)
  2. 库API,这也应该严格,但是建议进行额外的验证
  3. 必须处理各种滥用行为的公共接口(通常是协议,用户输入等)。在这里,输入的健壮性确实会有所回报,您不能指望每个人都会解决他们的问题。并请用户记住,如果应用程序无法正常工作,那将是您的错,而不是发送了一些格式错误的废话的一方。

输出必须始终严格。


5

我认为HTML和万维网已经对鲁棒性原理进行了大规模的实际测试,并显示它是一个巨大的失败。它直接导致竞争激烈的HTML几乎是标准的混乱局面,这使Web开发人员(及其用户)的生活痛苦不堪,并且在每个新的Internet Explorer版本中都变得更糟。

自1950年代以来,我们就知道如何正确验证代码。通过严格的解析器运行它,如果语法上不正确,则抛出错误并中止。不要通过,不要收取200美元,并且出于对二进制的一切热爱,如果他犯了一个错误,请不要让某些计算机程序尝试读取编码器的思想!

HTML和JavaScript向我们展示了忽略这些原理时会发生什么。最好的做法是从错误中吸取教训,而不是重蹈覆辙。


4
@ChaosPandion:我认为问题不在于Internet Explorer本身,而在于先前版本已接受的所有非标准网页,现在每个人都必须使用...并且尝试或多或少地成功地适应。
Matthieu M.

5
我实际上认为IE团队在所有浏览器开发人员中处于最糟糕的位置。乔尔很好地总结了我的想法
Dean Harding

3
它可能使开发人员和设计人员的生活痛苦不堪,但随后我们将陷入一个非常缓慢且不断发展的静态标准中-我怀疑网络是否像现在这样。真正的赢家是浏览网络的人,而归根结底,他们才是最重要的人。
FinnNk 2010年

4
同样,尽管“健壮性”原则可能会使Web开发人员度过一生,但很难将“万维网”(现在是地球上几乎每个主要机构的组成部分)称为大规模失败
deworde 2011年

3
“自1950年代以来,我们就知道如何正确地验证代码。通过严格的解析器运行它,如果语法上不正确,则抛出错误并中止。” 将此应用到现实世界中:如果我在页面最右边的剪切位置下方拧了一个图标,那么放弃整个页面是将某人转移到其他地方的一种非常好的方法,因为他们甚至都不会注意到的问题。是的,您可以说我不应该犯错。但这只是以我尚未与您更强大的竞争对手为伍,并且不再接听您的电话。
deworde 2011年

3

与梅森的例子相反,我对会话启动协议的经验是,尽管不同的堆栈会以不同的方式解释相关的RFC(并且我怀疑这种情况会在所写的每个标准中发生),但在接受方面(适度)自由意味着您实际上可以在两个设备之间拨打电话。由于这些设备是普通的物理设备,而不是台式机上的软件,因此您只需要放宽接受范围,否则您的电话无法拨打其他品牌的电话。那不会使您的手机看起来不错!

但是,如果您正在编写库,则可能不会有多方以互不兼容的方式解释通用标准的问题。在这种情况下,我想对您接受的内容进行严格的规定,因为这样可以消除歧义。

术语表也有一个关于“猜测”用户意图的恐怖故事


一个非常有趣的故事:)我意识到,当您尝试与现有系统进行交互时,您可能需要更多的回旋余地,因为如果这样做不起作用,您就会受到指责。
Matthieu M.

实际上,如果您的电话不能与其他大多数电话一起使用,则说明您的电话不合格
SamB

1
@SamB:更换
deworde 2011年

3

没错,该规则适用于协议,而不适用于编程。如果您在编程时输入错误,则在编译(或运行,如果您是其中的一种动态类型)时会收到错误消息。让计算机为您猜测没有任何收获。与普通人不同,我们是工程师,能够准确地说出我的意思。;)

因此,在设计API时,我会说不要遵循鲁棒性原则。如果开发人员犯了一个错误,他们应该立即发现它。当然,如果您的API使用来自外部来源的数据(例如文件),则应该宽容。您图书馆的用户应该了解自己的错误,但不能发现其他人的错误。

顺便说一句,我猜想TCP协议中允许“静默故障”,因为否则,如果人们向您抛出格式错误的数据包,您将被错误消息轰炸。那就是简单的DoS保护。


1
“如果您在编程时输入错误,则在编译时会出现错误。”我向您提供数百万个编译器警告。标准编译器会吐出,同时仍会产生完美的可执行任务。
deworde

1

IMO,健壮性是设计权衡的一个方面,而不是“优先”原则。正如许多人所指出的那样,没有什么比冒充四小时尝试找出您的JS出问题的地方发臭的了,只是发现真正的问题是只有一个浏览器对XHTML Strict做了正确的处理。当所提供的HTML的某些部分完全崩溃时,它使页面破裂。

另一方面,谁想查找包含20个参数的方法的文档,并坚持认为它们与要跳过的参数的空值或空值占位符的顺序完全相同?处理该方法的同样糟糕的健壮方法是检查每个arg并尝试根据相对位置和类型猜测哪个是针对什么的,然后静默失败或尝试对无意义的arg进行“修改”。

或者,您可以通过传递对象文字/字典/键值对列表来增强流程的灵活性,并在处理到每个arg时处理它们的存在。对于非常小的perf权衡,这是一个蛋糕,并且也可以食用。

以智能和接口一致的方式重载args是使事情变得可靠的明智方法。将冗余烘焙到系统中也是如此,在该系统中,假定在各种新兴的技术领域中,每个人都拥有并运行的庞大复杂网络中,通常无法通过各种潜在的传输方式来传输数据包。

但是,容忍绝对失败(尤其是在您控制的系统内)绝不是一个好的折衷。例如,我不得不喘口气,以避免在另一个有关将JS放在页面顶部或底部的问题中引起质疑。一些人坚持认为最好将JS放在顶部,因为如果页面无法完全加载,您仍然可能具有某些功能。半工作页面比完整的页面更糟糕。充其量,它们会导致更多的访问您网站的访问者正确地假设您在找到自己之前无能为力,而不是将失败的页面仅通过自身的有效性检查后自动跳到错误页面,然后自动发送电子邮件到错误页面可以对此有所作为的人。

当您只可以提供技术含量较低的页面时,尝试在1999浏览器上提供2010功能是设计折衷方案的另一个示例。我见过的机会和浪费的金钱浪费在开发人员花在漏洞四处的解决方法上的时间,例如,为了使悬停在!@#$ ing渐变背景之上的元素变成圆角,这完全让我震惊。为了什么 提供对经过验证的技术恐惧者表现不佳的高科技页面,同时限制您在高端浏览器上的选择。

为了使其成为正确的选择,无论是短期还是长期的IMO,以健壮的方式处理输入的选择应始终使问题双方的生活更加轻松。


4
“对于带有20个参数的方法”>无需进一步查看,在5/6之后,该方法是错误的。尽管感谢您的回答:)
Matthieu M.

1

永远不要默默地失败。除此之外,尝试猜测API /库的用户想要什么,听起来并不是一个坏主意。不过,我不会遵循。有严格的要求,可能会暴露调用代码中的错误和/或对您的API /库的误解。

此外,正如已经指出的,这取决于实际猜测用户期望的难度。如果很简单,则有两种情况:

  1. 您的库的设计应有所不同(重命名某些功能或将其分成两部分),以便用户可以期待您实际提供的内容。
  2. 如果您认为您的库设计正确,意味着命名清晰明了,那么您可以尝试推断用户的意图。

无论哪种情况不是100%明显和确定性,都应将一个输入转换为另一输入,而由于许多已经提到的原因(在重构时破坏兼容性,至少让用户感到惊讶),您不应该进行转换。

与最终用户打交道时,非常欢迎尝试修复他们的输入/猜测。希望他输入无效的信息;这种情况是完全没有例外的。但是,另一个开发人员并不是一个简单的非技术用户。他具有理解错误的专业知识,并且该错误可能具有重要意义/对他有益。因此,我同意您设计严格的API,而-当然-严格伴随着清晰和简单。

我建议您阅读类似的我的问题

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.