Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-core/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 关于我们在具有多个客户端的分布式应用程序中进行验证的方法的思考_C#_Wcf_Validation_Domain Driven Design - Fatal编程技术网

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

C# 关于我们在具有多个客户端的分布式应用程序中进行验证的方法的思考,c#,wcf,validation,domain-driven-design,C#,Wcf,Validation,Domain Driven Design,我来这里是想听听你们对我们迄今为止所采取的验证方法的看法。我们还在开发过程的早期,所以我们仍然可以改变它。验证对于这个应用程序和我们的客户来说非常重要,所以我们需要找到最佳的方法。让我描述一下我们到目前为止所做的工作 我们正在构建这个应用程序,它将被不同的客户端使用。我们并不控制所有的客户端,因此对所有层的验证都有严格的要求。我们确实控制一些客户端应用程序,其中一个是约100个用户使用的WPF应用程序。在此应用程序中,工作流如下所示: | Client

我来这里是想听听你们对我们迄今为止所采取的验证方法的看法。我们还在开发过程的早期,所以我们仍然可以改变它。验证对于这个应用程序和我们的客户来说非常重要,所以我们需要找到最佳的方法。让我描述一下我们到目前为止所做的工作

我们正在构建这个应用程序,它将被不同的客户端使用。我们并不控制所有的客户端,因此对所有层的验证都有严格的要求。我们确实控制一些客户端应用程序,其中一个是约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

你觉得怎么样?如果一切正常,当出现故障时,我如何通过WCF适当地通知用户?无论是
ArgumentException
InvalidOperationException
,还是包含错误列表的异常(由ApplicationService在使用CustomerValidator类验证客户对象后引发)。我是否应该以某种方式捕获所有这些异常,并将它们转换为WCF引发的一般故障异常,从而客户机可以对其作出反应并通知用户发生了什么


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

我个人的观点是,域一致性应该由域来处理。因此不需要
CustomerValidator

至于异常,你应该考虑,<代码> AguMutnulLeExabue>代码>,它们应该是泛在语言的术语(更深层次的解释)。 顺便说一句,即使您的所有DTO都已经过验证,您也不应该从域中删除正确的验证。业务不变量是它自己的责任

至于性能:异常有计算开销,但在我目前看到的大多数DDD场景中,它们都不是问题。特别是当命令来自人类时,它们不是问题

编辑
验证始终是域的责任。以
ISIN
value对象为例:由其构造函数通过抛出适当的异常来确保。在编码良好的域中,不能持有无效对象的实例。因此,您不需要任何验证器来累积错误

同样,当且仅当工厂是获取实例的唯一方法时,工厂才能确保业务不变量。技术不变量,如db列长度,应该不在该领域内,因此工厂可能是他们的好位置。这还具有启用异常链接的优势:SqlExceptions对于客户端来说没有太多表现力

对于表现性异常,客户只需尝试/捕获他们可以处理的异常(记住,呈现异常