简体   繁体   English

抢先验证还是异常处理?

[英]Preemptive Validation or Exception handling?

I am trying to decide between 2 patterns regarding data validation: 我试图在两种有关数据验证的模式之间做出选择:

  1. I try to follow the nominal workflow and catch exceptions thrown by my models and services: unique/foreign constraint violation, empty fields, invalid arguments, etc... (!! I catch only exceptions that I know I should) 尝试遵循正常的工作流程,并捕获由我的模型和服务抛出的异常 :唯一/外部约束冲突,空字段,无效参数等...(!!我仅捕获我知道应该的异常)

    • pros: Very few code to write in my Controllers and Services: I just have to handle exceptions and transcribe them to a user-understandable message. 优点:在我的控制器和服务中编写的代码很少 :我只需要处理异常并将其转录为用户可理解的消息。 Code very simple and readable . 代码非常简单易读

    • cons: I need to write specific exceptions , which can be a lot of different exceptions sometimes. 缺点:我需要编写特定的异常 ,有时可能会有很多不同的异常。 I also need to catch and parse generic PDO/Doctrine exceptions for database exceptions (constraint violations, etc...) to translate them into exceptions that are meaningfull (eg: DuplicateEntryException ). 我还需要捕获和解析数据库异常(违反约束等)的通用PDO / Doctrine异常,以将其转换为有意义的异常(例如: DuplicateEntryException )。 I also can't bypass some validation : let's say an object of my model is marked as locked: trying to delete it will raise an exception. 我也无法绕过某些验证 :假设我的模型对象被标记为锁定:尝试删除它会引发异常。 However I may want to force its deletion (with a confirmation popup for example). 但是,我可能想强制将其删除(例如,出现确认弹出窗口)。 I won't be able to bypass the exception here. 我将无法绕过此异常。

  2. I test and pre-validate everything explicitly with code and DB queries. 我使用代码和数据库查询显式测试和预先验证所有内容 For example, i'll test that something is not null and is an integer before setting it as an attribute in my model. 例如,在将其设置为模型中的属性之前,我将测试东西是否不为null以及是否为整数。 Or I'll make a DB query to check that I am not going to create a duplicate entry. 或者,我将进行数据库查询以检查是否不会创建重复条目。

    • pros: no need to write specific exceptions , because I prevalidate everything so I shouldn't be doing a lot of try/catch anyway. 优点: 无需编写特定的异常 ,因为我会预先验证所有内容,因此无论如何我都不应该进行大量的try / catch。 Also I can bypass some validation if I want to. 我也可以绕过一些验证

    • cons: Lots of tests and validation to write in the controllers, services and models. 缺点: 需要在控制器,服务和模型中进行大量测试和验证 I will be performing more queries (the validation part). 我将执行更多查询 (验证部分)。 The DB already does the validation for foreign keys, unique constraints, not null columns... I shouldn't ignore that and recode it myself. 数据库已经对外键,唯一约束,而不是空列进行了验证 ……我不应该忽略它并自己重新编码。 Also this leads to very boring code ! 这也导致非常无聊的代码

I would rather use one pattern or the other, not a mix, in order to keep things as simple as possible. 我宁愿使用一种模式或另一种模式,而不是混合使用,以使事情尽可能简单。

The first solution seems to me like the best, but I'm afraid it might be some kind of anti-pattern ? 在我看来,第一个解决方案似乎是最好的,但恐怕可能是某种反模式 or maybe behind its theoretical simplicity it is hiding situations very hard to handle? 还是在其理论简单性的背后隐藏了很难处理的情况?

I would suggest that data validation should happen at the perimeter of an application. 我建议数据验证应在应用程序的外围进行。 That is to say, that any data coming in should be checked to make sure it meets your expectations. 也就是说,应检查任何传入的数据以确保其符合您的期望。 Once allowed into the application, it's no longer validated, but it is always escaped according to context (DB, email, etc.) This allows you to keep all of the validation together and avoids the potential duplication of validation work (it's easy to come up with examples where data could validated twice by two models that both use it.) Joe Armstrong promotes this approach in his book on Erlang, and the software he's written for telcom stations runs for years without restarting, so it does seem to work well :) 一旦允许进入应用程序,它将不再进行验证,但始终会根据上下文(数据库,电子邮件等)进行转义。这使您可以将所有验证保持在一起,并避免了验证工作的潜在重复(很容易实现)举个例子,数据可以使用两个模型对两次数据进行两次验证。)Joe Armstrong在其关于Erlang的书中推广了这种方法,并且他为telcom电台编写的软件可以运行多年而无需重新启动,因此它看起来确实运作良好: )

Additionally, model expectations don't always perfectly line up with the expectations established by a particular interface (maybe the form is only showing a subset of the potential options, or maybe the interface had a dropdown of US states and the model stores states from many different countries, etc.) Sometimes complex interfaces can integrate several different model objects in a manner that enhances the user experience. 此外,模型期望值并不总是与特定界面建立的期望值完全一致(也许表单仅显示了潜在选项的子集,或者该界面包含美国各州的下拉列表,并且模型存储了许多州的状态有时,复杂的界面可以以增强用户体验的方式集成多个不同的模型对象。 While nice for the user, the interaction of these models using the exception approach can be very difficult to handle because some of the inputs may be hybrid inputs that neither model alone can validate. 虽然对用户很好,但是使用异常方法进行的这些模型的交互可能很难处理,因为某些输入可能是混合输入,而任何一个模型都无法单独验证。 You always want to ensure validation matches the expectations of the UI first and foremost, and the second approach allows you to do this in even the most complex interfaces. 您始终希望确保验证首先和最符合UI的期望,而第二种方法甚至可以使您在最复杂的界面中进行验证。

Also, exception handling is relatively expensive in terms of cycles. 而且,就周期而言,异常处理相对昂贵。 Validation issues can be quite frequent, and I'd try and avoid such an expensive operation for handling issues than have the potential of being quite frequent. 验证问题可能会非常频繁,因此,我会尽量避免使用昂贵的操作来处理问题,而不是可能会非常频繁。

Last, some validation isn't really necessary for the model, but it's there to prevent attacks. 最后,该模型实际上并不需要进行某些验证,但是可以防止攻击。 While you can add this to the model, the added functionality can quickly muddy the model code. 虽然您可以将其添加到模型中,但是所添加的功能可以迅速使模型代码变得混乱。

So, of these two approaches, I would suggest the second approach because: 因此,在这两种方法中,我建议第二种方法,因为:

  1. You can craft a clear perimeter to your app. 您可以为应用程序设计清晰的边界。
  2. All of the validation is in one place and can be shared. 所有验证都在一个地方,并且可以共享。
  3. There's no duplication of validation if two or more models make use of the same input. 如果两个或多个模型使用相同的输入,则验证没有重复。
  4. The models can focus on what they're good at: mapping knowledge of abstract entities to application state. 这些模型可以专注于他们擅长的领域:将抽象实体的知识映射到应用程序状态。
  5. Even the most complex UI's can be appropriately validated. 即使是最复杂的UI,也可以适当地进行验证。
  6. Preemption likely will be more efficient. 抢占可能会更有效。
  7. Security-focused validation tasks that don't really belong in any model can be cleanly added to the app. 真正不属于任何模型的,针对安全性的验证任务可以完全添加到应用程序中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM