gpt4 book ai didi

c# - 关于我们在具有多个客户端的分布式应用程序中进行验证的方法的思考

转载 作者:行者123 更新时间:2023-11-30 12:30:41 25 4
gpt4 key购买 nike

我是来这里听听您对到目前为止我们采用的验证方法的想法。我们仍处于开发过程的初期,因此我们仍然可以对其进行更改。验证对于此应用程序和我们的客户非常重要,因此我们需要找到最佳方法。让我描述一下到目前为止我们所做的...

我们正在构建此应用程序,该应用程序将由不同的客户端使用。我们不控制所有客户,因此对所有层的验证都有严格的要求。我们确实控制了一些客户端应用程序,其中一个是约100个用户使用的WPF应用程序。在此应用程序中,工作流程如下:

|                     Client                   |                                 Backend Service                             |
ViewModel -> ClientRepository -> ServiceClient -> Service (WCF) -> ApplicationService -> DomainModel -> Repository -> Database

我们认为以下是进行验证的候选对象。
  • 客户端:ViewModel验证,用于支持具有必需字段,长度等的UI。
  • 后端:服务请求DTO验证,因为我们不能依靠客户端始终提供100%的有效值。
  • 后端:域模型实体验证。我们不希望我们的实体永远处于无效状态,因此执行操作时每个实体将包含不同的检查。
  • 后端:数据库验证,例如失败的约束(FK,唯一性,长度等)

  • 客户端的ViewModel验证非常明显,对于我们自己的客户端而言,应在到达服务之前在其中纠正尽可能多的错误。虽然不能说其他应用程序消耗了我们的服务,但是应该假定最坏的情况。

    服务请求DTO应该首先针对第三方应用程序和我们自己的客户中的错误进行验证。确保请求正确,可以防止稍后在处理请求时弹出错误,从而确保更有效的服务。就像ViewModel验证一样,这取决于不同属性的必填字段,长度和格式(例如电子邮件)。

    域模型中的实体应该自己确保它们始终具有完全有效的属性/属性,我们以 Customer实体为例来实现这一点。
    public class Customer : Entity
    {
    private Customer() : base() { }

    public Customer(Guid id, string givenName, string surname)
    : this(id, givenName, null, surname) { }

    public Customer(Guid id, string givenName, string middleName, string surname)
    : base(id)
    {
    if (string.IsNullOrWhiteSpace(givenName))
    throw new ArgumentException(GenericErrors.StringNullOrEmpty, "givenName");
    if (string.IsNullOrWhiteSpace(surname))
    throw new ArgumentException(GenericErrors.StringNullOrEmpty, "surname");

    GivenName = givenName.Trim();
    Surname = surname.Trim();

    if (!string.IsNullOrWhiteSpace(middleName))
    MiddleName = middleName.Trim();
    }
    }

    现在,尽管这可以确保属性有效,但 CustomerValidator类将对Customer类进行整体验证,以确保其处于有效状态,并且不仅具有有效的属性。 CustomerValidator使用FluentValidation框架实现。在将客户对象提交到数据库之前,在应用程序服务中调用它。

    到目前为止,您如何看待我们的方法?

    我有点担心的是,到处都有异常的使用。例如。上面示例中的 ArgumentException,但在对象的当前状态不允许调用某些方法的情况下,也可以使用 InvalidOperationException

    希望这些异常将很少被抛出,因为服务请求DTO已经过验证,因此我认为这可能还可以吗?例如,当验证服务请求DTO时,除非在验证中出现错误,否则永远不要引发参数异常。因此,您可以说域模型中的这些参数检查充当了额外的安全层。另一方面,如果客户端调用一个服务方法,则该 InvalidOperationException可以引发,该服务方法在Customer对象上调用一个在当前状态下不可用的方法(因此它应该失败)。

    你有什么感想?如果一切正常,当出现故障时,如何通过WCF适当通知用户?它是 ArgumentExceptionInvalidOperationException还是包含错误列表的异常(使用CustomerValidator类验证客户对象后,ApplicationService会抛出该异常)。我是否应该以某种方式捕获所有这些异常并将其转换为WCF抛出的一些常规故障异常,以便客户端可以对此作出 react 并通知用户发生了什么?

    我很想听听您对我们的方法的想法。我们正在开始构建这个相当大的应用程序,我们真的想找到一种执行验证的好方法。在我们的应用程序中,有一些非常关键的部分,其中数据的正确性非常重要,因此验证非常重要!

    最佳答案

    我个人的观点是,域一致性应由域处理。因此,无需使用CustomerValidator

    至于异常(exception),您应该考虑到ArgumentNullException分开,它们应该是普遍存在的语言的术语(有关更深入的说明,请参见http://epic.tesio.it/2013/03/04/exceptions-are-terms-ot-the-ubiquitous-language.html)。

    顺便说一句,即使您的所有DTO之前都已通过验证,也永远不要从域中删除适当的验证。业务不变量是其自身的责任。

    至于性能:异常(exception)具有计算量,但是在我到目前为止看到的大多数DDD方案中,它们都不是问题。当命令来自人时,它们尤其不是问题。

    编辑
    验证始终是域的责任。以一个ISIN值对象为例:它由其构造函数通过引发适当的异常来确保its own invariants。在编码良好的域中,您不能保存无效对象的实例。因此,您不需要任何验证器即可累积错误。

    同样,只要且仅当工厂是获取实例的唯一方法时,工厂才能确保业务不变量。技术上的不变量,例如db列长度,应该不在范围之内,因此工厂可能是它们的理想位置。这也将具有启用异常链接的优势:SqlException对于客户端而言不是很容易表达。

    使用表现性异常,客户只需要尝试/捕获他们可以处理的异常(请记住,向用户呈现异常是处理异常的一种方式)。

    关于c# - 关于我们在具有多个客户端的分布式应用程序中进行验证的方法的思考,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15589316/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com