你在哪里进行验证?

Jus*_*gey 12 architecture validation

希望你能看到我在下面的场景中描述的问题.如果不清楚,请告诉我.

你有一个分为三层的应用程序,

  • 前端UI层,可以是asp.net webform,也可以是窗口(用于编辑Person数据)
  • 中间层业务服务层,编译成dll(PersonServices)
  • 数据访问层,编译成dll(PersonRepository)

在我的前端,我想创建一个新的Person对象,根据用户在UI中输入的内容设置一些属性,如FirstName,LastName,并调用PersonServices.AddPerson,传递新创建的Person.(AddPerson不必是静态的,这只是为了简单起见,在任何情况下,AddPerson最终都会调用Repository的AddPerson,然后它将持久存储数据.)

现在,我想听听你的意见的部分是验证.在某个地方,新创建的Person需要进行验证.您可以在客户端执行此操作,这很简单,但如果我想在PersonServices.AddPerson方法中验证Person,该怎么办?这将确保我想要保存的任何人都将得到验证,并消除对完成工作的UI层的任何依赖性.或者,可以在UI和业务服务器层中验证.到目前为止听起来不错吧?

因此,为简单起见,我将更新PersonService.AddPerson方法以执行以下验证检查 - 检查FirstName和LastName是否为空 - 确保我的存储库中不存在此新Person

如果所有验证都通过并且Person被持久化,则此方法将返回True,如果验证失败或者Person未被持久化,则返回False.

但是这个AddPerson返回的布尔值对于我来说在UI层是不够的,以便为用户提供保存过程失败的明确原因.那么一个孤独的开发者呢?最后,我希望AddPerson方法能够确保其即将保存的内容是否有效,如果没有,则能够将我的UI层无效的原因告知我的UI层.

只是为了让你的果汁流动,解决这个问题的一些方法可能是:(在我看来,其中一些解决方案很糟糕,但我只是将它们放在那里,这样你就能理解我想要解决的问题)

  • 而不是AddPerson返回一个布尔值,它可以返回一个int(即0 =成功,非零等于失败,数字表示失败的原因.

  • 在AddPerson中,在验证失败时抛出自定义异常.每种类型的自定义异常都有自己的错误消息.此外,每个自定义异常都足够独特,可以捕获UI层

  • 让AddPerson返回某种自定义类,该类具有指示验证是通过还是失败的属性,如果它确实失败了,原因是什么

  • 不确定这是否可以在VB或C#中完成,但是将某种属性附加到Person及其底层属性.此"附加"属性可能包含验证信息等内容

  • 在此处插入您的想法或模式

  • 也许在这里

为长篇大论的问题道歉,但我肯定想听听你对此的看法.

谢谢!

Ale*_*lli 8

多层验证适用于多层应用程序.

UI本身可以进行最简单,最快速的检查(所有必填字段,使用适当的字符集等),以便在用户输入错误时立即提供反馈.

然而,业务逻辑应该具有最大的验证责任份额......并且如果这是"重复"的话,一旦它不是问题,即,如果业务层重新检查应该在UI中检查过的东西 - BL应该检查所有的业务规则(这对UI的正确性进行了双重检查,启用了多个不同的UI客户端,这些客户端可能并非在检查中都是完美的 - 例如智能手机上可能没有良好javascript的特殊客户端,依此类推 - 并且,有点,防范恶意攻击的客户端).

当业务逻辑将"已验证"的数据保存到数据库时,层应该执行自己的检查 - 数据库很擅长,并且再次不用担心重复 - 数据库的工作是强制执行数据完整性(您可能希望有一天能够以不同的方式向其提供数据,例如,从其他来源导入大量人员的"批量加载器",确保所有这些加载数据的方法始终遵守数据完整性规则的关键); 一些规则(如唯一性和参照完整性)最好在DB中实施,特别是出于性能原因.

当DB向业务层返回错误消息(未作为约束X被插入的数据)时,后者的工作是在业务术语中重新解释该错误并将结果提供给UI以通知用户; 当然,BL必须同样向UI提供有关业务规则违规的清晰完整信息,同样向用户显示.

因此,"自定义对象"显然是"唯一的出路"(在某些情况下,我只是将其作为JSON对象).当DB拒绝持久化时保持Person对象(以维持其"验证问题"属性)看起来不是一种简单明了的技术,所以我不会考虑那个选项; 但是如果你需要它(例如,为了让"再次告诉我有什么问题")功能,也许如果客户端在响应准备好之前就离开了,需要在以后顺利重启;或者,这些对象的列表供以后审核,&c) ,那么"自定义验证 - 失败对象" 可以附加到该列表......但这是一个"次要问题",主要是BL用这样的对象响应UI(也可以使用它)如果插入确实成功,则提供有用的非错误信息).