Belt and Braces编程是好的做法还是仅仅引入了不必要的复杂性?

时间:2009-04-20 11:57:53

标签: assertions

我想知道是否使用Belt and Braces (Suspenders)方法编程 - 特别是数据验证 - 是否是好的做法。这来自以下示例。

我正在创建一个表单,并且我将监听器添加到所有字段,这意味着只有在表单中的所有字段都具有有效值时才会启用OK按钮。然后我编写了单击OK按钮时运行的代码。

我悲观的一面决定腰带和大括号从不伤害任何人,如果我的形式逻辑中存在错误,再次验证表格也不会有什么坏处。

但是如果验证失败,我不知道该放什么。如果我做这样的事情:

if (! form.isValid()) {
  displayErrorMessage();
}

然后我必须创建代码来显示永远不会显示的错误消息。任何在将来维护此代码的人都会担心并且可能会在理论上对此进行不必要的对话。我想要的最后一件事是有人想知道为什么永远不会显示这个特定的对话框。

比例另一端的选项是:

if (! form.isValid()) {
  throw new RuntimeException("This should never happen!");
}
坦率地说,即使输入它也觉得很脏,但也许有一个很好的理由使用它我错过了。

所以最后我最终得到了:

assert form.isValid();

然而,其缺点是它并不是真正的腰带和支架,因为在运行时支架不存在,所以如果代码中有错误,我的表格的裤子仍然会掉下来。

所以也许我根本不应该进行额外的验证,但仍然有一部分人认为它不会受到伤害。

我很想知道你在类似情况下做了什么。

编辑:问题是询问确保表单返回有效数据的最佳方法是什么。假设表单的输出在数据库结束之前再次进行验证,依此类推。)

9 个答案:

答案 0 :(得分:5)

我没有做很多UI工作,但最近我发现自己做了非常相似的事情。 我离开了两个腰带(在每个控件改变时验证它们)和大括号(在OK_Click上检查再次有效)。

我之所以离开,是因为如果将来某些更改错过了控件的验证,则会在单击“确定”按钮时捕获它。

在我的脑海中,对OK的检查是真正的验证,并且每个控件验证都是糖,只会增强用户体验。

那说我没有考虑太多,我不经常做UI工作。

答案 1 :(得分:5)

根据我的经验,“以防万一”代码有时是懒惰编程的症状。即,我找到了一个基本上有效的解决方案,我不确定它是否会一直有效,所以我会抛出一些双重检查代码“以防万一。”如果你没有向月球发射火箭飞船,这种类型的东西相对无害,但仍然是非常糟糕的练习。

对于我的(非火箭飞船)业务应用程序,我总是输入错误日志和友好消息,并尝试一直考虑问题,以便用户尽可能不经常看到友好消息。如果出现问题,我可以更好地修复它,因为我的代码不会因各种不必要的检查而混乱。

答案 2 :(得分:1)

我的同事通常会对输入进行双重验证,“以防万一。”我认为这在很大程度上取决于您与之合作的人员或者必须维护代码的人员。如果你总是双重验证,他们会很快发现你正在做什么。如果您有时只进行双重验证,他们可能会感到困惑。也许你应该和同事一起讨论他们的习惯?如果您单独工作或在一个非常小的团队中工作,那么双重验证您的输入可能是可以的。

如果我要接管你的代码,我认为重要的是可能遵循一个约定,要么总是要么永远不要在两个地方都进行验证。至少那样我不会感到困惑。

编辑:就网络编程而言,javascript通常用于在输入发送到服务器之前进行验证。显然,这还不够,因为用户可以关闭javascript并绕过验证,因此在这种情况下需要服务器端验证。在任何情况下,如果用户可能恶意或意外地绕过第一行验证,则必须仔细检查后端。我想这在Java,C#等中不是问题。

答案 3 :(得分:1)

我还会说双重验证从不伤害任何人,只能提高安全性。

我还想提出一个关于业务逻辑的观点。我假设这是一个Winforms应用程序,但该原则也适用于Web。 UI不应该强制执行业务逻辑。将验证放在那里很好,但它也需要在业务逻辑中。

答案 4 :(得分:1)

无论您决定做什么,只需确保记录意外状态,并使程序失败以某种方式防止数据损坏。我个人认为这对于我不期待错误的情况是必要且充分的。

答案 5 :(得分:1)

在web(没有双关语)编程中,人们总会采用这种方法,因为你不能依赖于实际运行的客户端验证;一个狡猾的用户可以构建一个模拟客户端的表单帖子或URL,并将数据发送回服务器。

在独立应用中,它不太清楚。我建议它取决于验证发生的位置。例如,如果您的验证在您的业务逻辑中运行,而不是在您的UI中运行,那么您的验证应该每次运行。使用关注点分离,业务逻辑不应依赖于UI来进行验证。毕竟,可以从典型的GUI,Web应用程序甚至API调用业务逻辑。

我建议的一件事是在UI中加倍验证逻辑可能有点过分 - 但你应该能够处理由底层产生的错误。在这种情况下,错误可能来自验证。

答案 6 :(得分:1)

我建议从纯粹的可用性角度来看待这个问题。填写表格时,您的用户应该如何工作?大多数时候,我会建议在控件和表单层面进行验证。当然,您可以使用许多用户交互样式:

  1. 让用户做他们喜欢的事情,然后确定他们的结果。这对于专家用户来说非常好,允许他们快速和渐进地输入内容,但让新手和不经常的用户感到茫然。
  2. 在输入或离开时验证每个控件。这可能是好的,特别是对于复杂的形式(当然我们不应该设计,永远,真的,但......!);但做得不好可以防止人们按照自己的顺序逐步填写表格。如果我这样做的话,我更喜欢视觉表明某些事情不对。
  3. 无法输入任何错误。这可以(几乎)通过例如数字滑块,限制标量的组合框,自动验证的编辑框,可防止错误输入。
  4. 但是,即使在案例3中,在某些情况下您还必须检查值的组合是否有效。我曾经处理过某些控件子集中的值彼此依赖的情况(由等式控制)。在这些情况下向用户提供即时反馈并不总是可行或值得努力,因此总是可以在OK上进行验证。

    我同意Binary Worrier认为OK检查是主要检查。如果您确定它永远不会失败,请确保在触发时记录警告,并在可能的情况下通过支持渠道嗅探此类事件,但不要让最终用户为编程错误付费。

答案 7 :(得分:1)

我会给出一个令人难以置信的不受欢迎的答案。

我的回答是:取决于

人们开始愤怒地从椅子上站起来,并为他们的拿铁咖啡添加额外的泡沫。发泄愤怒,听我说。 an angry programmer punching a screen

我修改了使用共享文件的ERP包。不要笑,这是白天的工作。无论如何,系统在设计中有一个缺陷 - 它在输入时验证数据,然后总是假设它是正确的,因为一次性验证,一旦它写出记录。

这听起来像一个合理的方法,直到你遇到丢失的数据字段,崩溃的会话,你看不到的RAM不良的机器,没有检测到的有点局域网连接的机器,偶尔还有一个bug(或两个)在编程语言本身。记录是半写的,字段可能会丢失数据,索引偶尔会无缘无故地崩溃......列表继续。

现在,提供该软件的供应商非常依赖腰带和吊带,因为嘿,时间就是金钱,他们在商业中销售他们的产品(软件)。每15分钟写一次额外的健全检查是15分钟,可以用来产生收入。 但他们不会在凌晨3点被分页以修复崩溃的会话或发布令人讨厌的死锁。我做。

因此,我将粗略的等效断言添加到我编写的过程,函数和方法中。我对传递的数据类型进行了完整性检查(它使所有变量变量),我尝试在可能的情况下交叉引用数据,并寻找其他的"疯狂"在代码中。当一个例程找到类似于黄昏区域的东西时,它会给出一个诊断对话框(用户通常会屏幕截图并转发给我),然后尝试优雅地失败;如果它无法正常失败,用户通常会看到保存所取得的进展并注销的说明。

这是腰带和吊带裤吗? 是的。我喜欢这样做吗? 不。它在很多场合都能保存我的理智,睡眠时间和培根吗?

<强> 是。哦,是的......

所以,如果你有一个敌对的&#34;编程环境你总是可以信任被提供给你代码的数据,嵌入各种理智检查是合理的...和吊带,一路。

否则,不需要它。

答案 8 :(得分:0)

我认为腰带和牙套不是一个好习惯。

如果需要极端可靠性,例如太空船软件的情况,那么保证它的方法是提供多个不同的并行运行的实现,都提供相同的输入,并且都希望提供相同的输出。显然,这不是腰带和括号,而是其他东西。

如果极端可靠性不是问题,那么腰带和牙套确实只会使你自己发现的方式完全复杂化。

你最终得到的断言是最好的做法,因为断言是为了捕获错误并记录代码,而这恰恰是在手头的情况下发生的事情:如果表单是在您的断言时无效,那么您的表单中的其他地方就有一个错误,并且该断言基本上记录了这样一个事实,即在您的代码中您希望表单的有效性已经得到了解决。此外,应该在应用程序的测试阶段消除发生此错误的可能性,因此它不应该在生产中发生,这与断言的目的和预期用途相同。

如果你真的喜欢腰带和大括号范例,那么你仍然可以将断言视为腰带和括号方案的一部分,但在正确的背景下:测试。这个断言在测试过程中是带和括号,因为它保证你在代码的其他地方完成了所有正确的测试。