Belt and Braces 编程是好的实践还是只是引入了不必要的复杂性?

发布于 2024-07-16 20:20:24 字数 1025 浏览 4 评论 0原文

我想知道是否使用 腰带和背带(吊带) 方法进行编程 - 以及特别是数据验证 - 是否是好的做法。 这是从下面的例子中得出的。

我正在创建一个表单,并向所有字段添加了侦听器,这意味着仅当表单中的所有字段都具有有效值时,才会启用 OK 按钮。 然后我编写了单击“确定”按钮时运行的代码。

我悲观的一面认为腰带和支架永远不会伤害任何人,并且再次验证表单不会有什么坏处,以防我的表单逻辑中存在错误。

但后来我不知道如果验证失败该输入什么。 如果我做这样的事情:

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

那么我必须创建代码来显示一条永远不应该显示的错误消息。 任何将来维护此代码的人都会担心,并可能会被这个理论上不必要的对话所困惑。 我最不想看到的就是有人想知道为什么这个特定的对话框永远不会显示。

天平另一端的一个选择是:

if (! form.isValid()) {
  throw new RuntimeException("This should never happen!");
}

坦率地说,即使输入这个,我也觉得很脏,但也许有一个我错过的使用它的充分理由。

所以最后我得到了:

assert form.isValid();

然而,这样做的缺点是它不是真正的腰带和背带,因为背带在运行时不存在,所以如果代码中有错误,我的表单的裤子仍然会掉下来原来如此。

所以也许我根本不应该接受额外的验证,但我仍然有一部分认为这不会造成伤害。

我很想听听您在类似情况下会做什么。

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

I was wondering whether using a Belt and Braces (Suspenders) approach to programming - and to data validation in particular - was good practice or not. This came about from the following example.

I was creating a form and I added Listeners to all the fields which should mean that the OK button is only enabled if all the fields in the form have valid values. I was then writing the code which was run when the OK button is clicked.

The pessimistic side of me decided that Belt and Braces never hurt anyone and it couldn't hurt to validate the form again in case there's a bug in my form logic.

But then I didn't know what to put in if the validation fails. If I do something like this:

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

then I have to create code to display an error message which should never be shown. Anyone maintaining this code in future is then going to worry about and possibly be confused by this in theory needless dialog. The last thing I want is someone wondering why this particular dialog is never displayed.

An option at the other end of the scale is:

if (! form.isValid()) {
  throw new RuntimeException("This should never happen!");
}

Frankly, I feel dirty even typing that but perhaps there's a good reason to use it which I have missed.

So finally I ended up with:

assert form.isValid();

However, the downside of that is that it's not really belt and braces since the braces aren't there at run-time so if there is a bug in the code my form's trousers are still going to fall down as it were.

So maybe I shouldn't have the extra validation at all, but there's still a part of me which thinks it couldn't hurt.

I'd be interested to hear what you do in similar situations.

(Edit: the question is asking what is the best way to ensure the form returns valid data. Assume that the output of the form is validated again before it ends up in the database and so on.)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

哑剧 2024-07-23 20:20:24

我不做太多 UI 工作,但最近我发现自己在做一些非常类似的事情。
我留下了腰带(在每个控件发生变化时验证它)和大括号(在 OK_Click 上检查再次有效)。

我将两者都保留在其中,因为如果将来的某些更改错过了控件的验证,则单击“确定”按钮时将会捕获该更改。

在我看来,对“确定”的检查是真正的验证,而每个控件的验证只是增强用户体验的糖。

话虽如此,我并没有考虑太多,而且我也不经常做 UI 工作。

I don't do much UI work, but recently I found myself doing something very similar.
I left in both the belt (validate each control as it changes) and the braces (check is valid again on OK_Click).

I left both in on the basis that if some future change missed validation on the control, it would be caught when the OK button is clicked.

In my head the check on OK is the real validation, and the per control validation is sugar that just enhances the users experience.

That said I haven't thought about it too much, and I don't often do UI work.

淡淡の花香 2024-07-23 20:20:24

根据我的经验,“以防万一”代码有时是懒惰编程的症状。 即,我找到了一个基本上有效的解决方案,我不确定它是否总是有效,所以我将添加一些双重检查代码“以防万一”。 如果你不打算向月球发射火箭飞船,这种事情相对无害,但仍然可能是非常糟糕的做法。

对于我的(非火箭式)业务应用程序,我总是放入错误日志和友好消息,并尝试从头到尾思考问题,以便用户尽可能少地看到友好消息。 如果出现问题,我能够更好地修复它,因为我的代码不会因各种不必要的检查而变得混乱。

From my experience, "just in case" code is sometimes a symptom of lazy programming. I.e., I've found a solution that basically works, I'm not sure it will always work, so I'll throw in some double-checking code "just in case." If you're not sending rocket ships to the moon, this type of thing is relatively harmless, but can be very bad practice nonetheless.

For my (non-rocket-ship) business applications, I always put in error logging and a friendly message, and try to think the problem all the way through so that the users see the friendly message as infrequently as possible. If there is a problem, I'm better able to fix it because my code isn't cluttered up with all kinds of unnecessarily checks.

策马西风 2024-07-23 20:20:24

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

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

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

My coworkers generally do double-validate inputs, "just in case." I think it would depend largely on the people you work with or who will have to maintain your code. If you always double-validate, they will quickly catch on as to what you're doing. If you only sometimes double-validate, they will likely be confused. Perhaps you should consult with coworkers as to their habits? If you work alone or in a very small group, it would probably be okay to double-validate your inputs.

If I were to take over your code, I think the important thing is probably following a convention, either always or never put validation in both places. At least that way I wouldn't get confused.

Edit: As far as web programming goes, javascript is generally used to validate before inputs are sent to the server. Obviously, this isn't enough as users can turn off javascript and circumvent that validation, so server-side validation is necessary in that case. In any case where a user could maliciously or accidentally circumvent the first line of validation, it's imperative to also double-check on the back-end. I imagine this is less of a problem in Java, C#, etc.

陌伤ぢ 2024-07-23 20:20:24

我还想说,双重验证不会伤害任何人,只会增加安全性。

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

I would also say that double validation never hurt anyone, and can only increase security.

I'd also like to bring up a point about your business logic. I assume this is a Winforms application, but the principle applies to the web as well. The UI should not be enforcing business logic. It's fine to put validation there, but it also needs to be in the business logic.

找回味觉 2024-07-23 20:20:24

无论您决定做什么,只要确保记录意外状态并以某种方式使程序失败以防止数据损坏即可。 就我个人而言,我认为对于我不希望出现错误的情况来说,这是必需的并且足够的。

Whatever else you decide to do, just make sure you log the unexpected state and make the program fail somehow to prevent data corruption. Personally I think that is required and sufficient for a case where I'm not expecting an error.

如梦初醒的夏天 2024-07-23 20:20:24

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

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

我建议的一件事是,在 UI 中加倍验证逻辑可能有点矫枉过正,但您应该能够处理底层产生的错误。 在这种情况下,错误可能是由验证引起的。

In web (no pun intended) programming one would always take this approach because you can't depend on the client-side validation actually running; a crafty user can construct a form post or URL that simulates your client and sends data back to the server.

In a standalone app, it is less clear. I would suggest that it depends on where the validation is occurring. For example, if your validation runs in your business logic, not in your UI, then your validation ought to run every time. Using separation of concerns, the business logic shouldn't depend on the UI to do validation. After all, the business logic may be called from a typical GUI, a web app, or even an API.

One thing that I would suggest is that doubling up the validation logic in the UI, is probably overkill -- but you ought to be able to handle errors arising from the underlying layers. In this case, the errors might arise from validation.

梦境 2024-07-23 20:20:24

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

  1. 让用户做他们想做的事,然后检查他们的结果就OK了。 这对于专家用户来说非常有用,允许他们快速、增量地输入内容,但会让新手和不常使用的用户感到茫然。
  2. 在进入或离开时验证每个控件。 这可能很好,特别是对于复杂的形式(当然我们不应该设计,永远,真的,但是......!); 但做得不好会阻止人们按照自己的顺序逐步填写表格。 如果我这样做,我更喜欢视觉指示,表明出现了问题。
  3. 使得不可能输入任何错误的东西。 这可以(几乎)通过例如数字滑块、受限标量的组合框、防止错误输入的自动验证编辑框来实现。

然而,即使在情况 3 中,在某些情况下您也必须检查值的组合是否有效。 我曾经处理过一些情况,其中某些控件子集中的值相互依赖(由方程控制)。 在这些情况下,为用户提供即时反馈并不总是可行或值得付出努力,因此始终可以创建一个案例来验证“OK”。

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

I'd recommend looking at this from a purely usability perspective. How are your users supposed to work while filling in forms? Most of the time, doing validation on both the control and the form level is what I'd recommend. Of course, there are many user interaction styles you can use:

  1. Let the users do what they please, and then check on their results on OK. This can be excellent for expert users, allowing them to input things quickly and incrementally, but leaves newbies and infrequent users rather at a loss.
  2. Validate each control as it's entered or on leaving. This can be good, especially for complex forms (which of course we shouldn't design, ever, really, but...!); but done poorly can prevent people from filling in forms incrementally in their own order. I prefer a visual indication that something's amiss if I do this.
  3. Make it impossible to enter anything wrong. This can (almost) be achieved through e.g. sliders for numbers, combo boxes for restricted scalars, auto-validated edit boxes which prevent bad entries.

However, even in case 3, there are some cases where you have to check whether combinations of values are valid. I've worked with some cases where the values in some subsets of controls are dependent on each other (governed by an equation). It's not always feasible or worth the effort to provide the user with immediate feedback in these cases, so a case can always be made for validating on OK.

I'd agree with Binary Worrier that the OK check is the main one. If you're sure it should never fail, be sure to log a warning if it triggers, and sniff such events through your support channels if possible, but don't make the end user pay for programming errors.

鹊巢 2024-07-23 20:20:24

我将给出一个非常不受欢迎的答案。

我的答案是:这取决于

在人们开始愤怒地从椅子上站起来并在拿铁咖啡中添加额外的泡沫以发泄愤怒之前,请听我说完。

我修改了一个使用共享文件的ERP包。 别笑,这是日常工作。 无论如何,该系统在设计上有一个缺陷 - 它会在输入时验证数据,然后一旦写出记录,就会由于一次性验证而始终假设它是正确的。

这听起来像一个合理的方法,直到您遇到丢失数据字段、崩溃的会话、您看不到的 RAM 损坏的机器、未检测到的 LAN 连接不稳定的机器,以及编程语言本身偶尔出现一个(或两个)错误。 记录写了一半,字段可能会丢失数据,索引偶尔会无缘无故地崩溃……这样的例子不胜枚举。

现在,提供软件的供应商在很大程度上与皮带和吊带竞争,因为,嘿,时间就是金钱,而他们的业务是销售他们的产品(软件)。 每 15 分钟编写额外的健全性检查的时间就有 15 分钟可以用来产生收入。 但他们不会在凌晨 3 点接到呼叫来修复崩溃的会话或释放令人讨厌的死锁。 是的。

因此,我将断言的粗略等价物添加到我编写的过程、函数和方法中。 我对传递的数据类型进行完整性检查(它使所有变量变体),我尝试在可能的情况下交叉引用数据,并在代码中寻找“疯狂”的其他迹象。 当例程发现类似于暮光区的东西时,它会给出一个诊断对话框(用户通常会截屏并发送给我),然后尝试优雅地失败; 如果不能正常失败,用户通常会看到保存进度并注销的说明。

这是腰带和吊带吗? 是的。我喜欢这样做吗? 不。它是否多次挽救了我的理智、睡眠时间和培根?

是的。 哦,是的...

所以,如果您有一个“敌对”的编程环境,您不能总是信任输入代码的数据,这是合理的嵌入各种健全性检查......全程穿着腰带和吊带。

否则,就不需要了。

I'm going to give an incredibly unpopular answer.

My answer is: it depends.

Before people start rising up from their chairs in indignation and add extra froth to their latte' from venting their rage, hear me out.
an angry programmer punching a screen

I modify an ERP package that uses shared files. Don't laugh, it's the day job. Anyways, the system has a single flaw in the design - it validates the data upon input, and then always assumes it is correct due to that one-time validation, once it writes records out.

This sounds like a reasonable approach until you run into missing data fields, crashed sessions, machines with bad RAM that you can't see, machines with spotty LAN connections that go undetected, and occasionally a bug (or two) in the programming language itself. Records are half-written, fields may go missing data, indexes occasionally just implode for no reason...the list goes on.

Now, the vendor that provides the software very much runs against belt-and-suspenders because, hey, time is money, and they're in business to sell their product (software). Every 15 minutes of time writing additional sanity checks is 15 minutes that could be spent generating revenue. But they don't get paged at 3am to fix crashed sessions or release nasty deadlocks. I do.

So I add the rough equivilent of asserts into the procedures, functions, and methods that I write. I do sanity checks on the data types passed (it makes all variables variants), I attempt to cross-reference data when possible, and I look for other signs of "insanity" in the code. When a routine finds something that resembles the twilight zone, it gives a diagnostic dialog (which the user typically screen-shots and forwards to me) and then attempts to gracefully fail; if it can't gracefully fail, the user usually sees instructions to save what progress they have and log out.

Is this belt-and-suspenders? Yes. Do I like having to do this? No. Has it saved my sanity, sleep time, and bacon on many many occasions?

Yes. Oh, yes...

So, if you have a "hostile" programming environment where you can't always trust the data that's being fed to your code, it's reasonable to embed all kinds of sanity checks...go full belt-and-suspenders, all the way.

Otherwise, it's not needed.

十秒萌定你 2024-07-23 20:20:24

我认为腰带和背带不是一个好的做法。

如果需要极高的可靠性,例如宇宙飞船软件的情况,那么保证它的方法是提供并行运行的多个不同的实现,所有这些实现都提供相同的输入,并且都期望提供相同的输出。 显然,那不是腰带和背带,而是别的东西。

如果极端的可靠性不是问题,那么腰带和背带实际上只会以您自己发现的方式使事情变得复杂。

您最终得到的断言是最好的做法,因为断言旨在捕获错误并记录代码,而这正是当前情况下发生的情况:如果表单在您的点无效断言,那么您的表单中的其他地方就有错误,并且该断言本质上记录了这样一个事实:此时在您的代码中您期望表单的有效性已经得到处理。 此外,应该在应用程序的测试阶段消除发生此错误的可能性,因此它永远不会在生产中发生,这再次符合断言的目的和预期用途。

如果您确实喜欢皮带和大括号范例,那么您仍然可以将断言视为皮带和大括号方案的一部分,但要在正确的上下文中:测试。 这个断言在测试期间是带和大括号的,因为它保证您在代码中的其他地方完成了所有正确的测试。

I think that belt and braces is not a good practice.

If extreme reliability is required, as the case is for example with spaceship software, then the way to guarantee it is by providing multiple different implementations that run in parallel, are all provided the same input, and are all expected to provide the same output. Clearly, that's not belt and braces, it is something else.

If extreme reliability is not an issue, then belt and braces really only complicates things precisely in the ways that you discovered by yourself.

The assertion that you ended up with is the best thing to do, because assertions are meant to catch bugs and to document the code, and that's precisely what is happening in the situation at hand: if the form is not valid at the point of your assertion, then you have a bug elsewhere in your form, and the assertion is essentially documenting the fact that at this point in your code you expect that the validity of the form has already been taken care of. Also, the possibility of this bug happening should be eliminated during the testing phase of your application, so it should never happen in production, which is again in par with the purpose and intended use of assertions.

If you really like the belt and braces paradigm, then you can still consider the assertion as part of a belt and braces scheme, but in the right context: testing. This assertion is belt and braces during testing, because it guarantees that you have done all the right tests elsewhere in your code.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文