C#处理异常和异常的数据错误和警告的最佳实践

时间:2019-03-06 23:11:40

标签: c# asp.net-core inversion-of-control nuget-package onion-architecture

我们正在创建一个新的.Net Core库,这是一个驻留在Clean Architecture中的应用程序服务。

新服务将通过RepositoryService层读取新的客户详细信息,并通过RestApiService层将其发布到多个系统,包括:CreditCheck系统,计费系统等。

在新的应用程序服务中,我们希望使用一致的方式来处理RestAPi服务的响应。响应数据包括:

- Return values:  entities returned by restAPI service 

 - Exceptions like an error 500, time outs.. that have bubbled up from the RestAPi. 

- Data Errors messages such as Customer already exists, bank details invalid

- Warning messages ... "Processing continues as normal, but order is flagged" 

这是最后两个困扰我们的人,因为这与与没有业务逻辑的存储库层的交互不同,因此基本上返回成功或异常。

Microsoft和SOLID实际上声明使用异常处理是必经之路,无论是异常,错误还是警告。

但是在这种情况下,尚不清楚它如何工作..

  a. We loose the option of handling and forwarding on the return values. 
     We really don't fancy storing all this in the exception message

   - Whilst not a show stopper, we fear the code will be more difficult to read than it needs to be.    

   - Exception handling is expensive,but not worried too much on this score with number of transactions. 

我们被吸引到了如何使用FluentValidation或混合版本的知识,它需要与Logging和RepositoryService一起使用,因为我们需要log和解码东西。

我们真的不希望重复RestAPi服务层方法,即分别处理HTTP异常,然后处理返回值,这些返回值基本上是带有Errors Status,Error代码和消息的扩展实体。

我们不希望上述特定于我们公司。问题似乎与处理来自我们的应用程序服务中的第3方业务逻辑层的消息有关。

所以我们的问题是,我们如何才能最好地处理应用程序服务层中附带数据的错误警告,并且仍然具有可测试和可维护的SOLID代码?

1 个答案:

答案 0 :(得分:0)

Microsoft和SOLID是正确的。

正确的方法是按照标准惯例(和c#)进行异常处理,而与其他考虑因素(例如性能)无关。

通常来说,“错误”有两种不同类型,即技术和业务逻辑。

无法连接到数据库,无法从REST服务接收500,等等...都是技术性的,由于它们可能是短暂的,因此您可以尝试从这种情况中恢复,有时没有成功,最终导致业务编排/处理失败。

业务逻辑错误(例如“客户已存在”,“银行明细无效”,“输入数据不是有效格式”)是非暂时性的,并且仅由业务规则(某些隐式,其他显式)确定,并且会停止也要停止进程,而没有恢复的可能,这仅仅是因为某些事物未处于正确/预期的状态。

我们之所以使用Exceptions(作为技术工件)是有原因的,并且可以“适当地”处理这些硬性停止。

每次抛出Exception时,应用程序都会遍历堆栈,直到第一个可以处理此类Exception的可用Exception Handler为止,然后将控件返回给您,并返回到将要发生的已知位置(遥测,重新抛出,显示对话框)给用户...)

任何试图替代这种传播(错误)的机制都必须依靠,例如劫持方法的返回值以提供状态,或强制将out参数包含在所有方法签名中,这将带来可怕的后果实施中的影响。

是的,有时您当前的设计看起来过于“扁平”,以至于您试图在这里和那里劫持返回值,创建一个高度耦合的组件,但是您永远无法知道系统复杂性将如何增长,这意味着在某个时候您将在系统上增加额外的层,很可能“替代机制”方法不合适,您将不得不以常规方式和富于想象力的方式来支持它们。

因此,尝试实施定制解决方案将产生紧密耦合的技术要求,必须全面支持该技术要求,从体系结构的角度来讲,这简直是“不好”(不好的做法)

如果您使用的任何服务都无法产生有意义的,结构合理的“错误”信息,则该服务的设计不正确,问题就转移到了客户端(以SOA术语讨论)。

唯一不会在客户端造成混乱的“最正确”解决方案是通过创建服务代理以尊重实现方法所需的规则。

我对错误处理的建议非常简单,请遵循众所周知且已经存在数十年的规则,不要自己尝试解决此问题,否则您将面临太多问题,请为每个服务,并将它们正确集成到您的代码库中(单元测试等)

关于警告,没有任何人建议使用异常来处理此问题,您的问题中的那些“警告”是与服务交互时的正常输出/业务逻辑支持的逻辑状态,因此,同样,如果服务设计得如此糟糕以至于只用包含“警告”一词的文本字符串来答复您,那么处理该状态的地方就是从服务返回的数据合同中,并且您被迫将其解析为请注意情况,然后您的服务代理应进行检查,并向客户提供有意义且结构合理的输出。