使用异常处理库的(可能更改的)错误代码
本文关键字:错误代码 异常处理 | 更新日期: 2023-09-27 17:57:01
假设您正在使用返回错误代码的库。您希望为库编写包装器,并且希望处理代码中出现异常的错误。
如果库仍在由其他人开发中,并且错误代码可能会更改(可能有新的错误代码,可能会有已弃用的错误代码,或者某些错误代码可能会略有改变含义),您的解决方案是什么来处理这个问题?
这就是我现在所处的情况。就我而言,该库是用C++编写的,我们使用的是 C#。库的编码人员说错误代码可能会改变,我必须找到一种方法来处理它。
我们最初的解决方案是:
- 创建一个 XML 文件,其中包含不同类别(终端错误、输入错误等)中的错误代码。
- 包装器在启动时获取这些错误代码。
- 通过检查错误代码的类别引发相应的异常。
因此,假设一个方法返回错误代码 100,然后包装器检查错误代码的类别。如果是终端错误,则抛出终端错误异常,如果是用户输入错误,则抛出用户输入错误异常。
这应该有效,但我觉得这不是最佳解决方案。我想知道好的企业软件如何处理错误代码的更改。
你建议怎么做?
编辑:我已经质疑错误代码将发生变化的事实,并且库的编码人员说代码正在开发中。这是一种算法,所以即使算法的工作方式也会随着它的原始研究而改变(他正在写他的博士学位)。所以他说可能会有不同的错误,或者有些错误在未来可能无关紧要。
在这种情况下,您正在使用 XML 文件的数据驱动方法似乎是一个很好的方法。 但是,我会质疑为什么错误代码会发生变化 - 这表明没有对正在开发的库进行适当的设计。 它应该有一个定义明确的错误代码结构,而不是要求你不断改变对它们的解释。
您可能希望尝试使用一个整体的"库异常"异常类,并根据库错误的"类型"为要引发的每个不同类型的异常对其进行子类化。 至少这样,您可以捕获所有库错误,即使特定类型的异常之一从网络中溜走。 即。在试图抓住TerminalErrorException
之后,你会抓住类似LibraryException
的东西.
稍微改变一下对情况的看法,你会更容易解决这个问题:
- 您正在处理框架,我们将其称为外部框架。
- 另一方面,您正在为框架 - 内部框架。
- 您的代码(客户端应用程序)使用内部框架,假设它提供用于问题域的功能。据我了解,并且我相信,客户端应用程序不应该对外部框架有任何想法。
现在,问题归结为以下问题:内部框架的功能是否清晰地概述和最终确定? 还是也会改变?
如果它正在更改(可能是因为外部框架),那么内部框架正在开发中。这意味着,客户端应用程序需要等到内部框架准备就绪才能宣布第一个版本准备就绪(可能在外部框架完成后)。
现在错误处理:
应用程序中的错误就像合同一样。函数的调用方仅预期特定的异常情况和特定类型的错误。每个可能的错误都由每个函数预定义和记录,类似于其输入参数和返回值。
这对您意味着什么:
- 定义内部框架的最终设计(越早越好)。
- 确定内部框架的每个函数可能引发的错误类型。
- 使用客户端应用程序中的内部框架,并仅预期预期和记录的异常。不要尝试/捕获内部框架中不期望的任何内容。基本上,遵守合同。
- 如果错误代码发生更改,则不会更改内部框架中函数的概念。它仍然需要抛出它之前抛出的相同类型的错误(根据合同)。唯一需要更改的部分是如何将新代码转换为预期(收缩)错误之一。你可以用任何更好的方式解决它。
为什么最后一个假设没问题?因为我们说过内部应用程序的设计是最终的,不会改变。错误合同也是最终设计的一部分。
例:
//external.
int Say(char* message);
//internal.
///<summary>
/// can throw (CONTRACT): WrongMessageException, SessionTimeOutException
void Say(string message) {
int errorCode = External.Say(message);
//translate error code to either WrongMessageException or to SessionTimeOutException.
}
无法翻译? 当前签约的错误或外部框架出现问题:也许您应该终止该过程? 出乎意料的是出了点问题!!
//client.
...
try {
Internal.Say("Hello");
}
catch (WrongMessageException wme) {
//deal with wrong message situation.
}
catch (SessionTimeOutException stoe) {
//deal with session timeout situation.
}
如果有什么问题提出来,请告诉我。
将错误代码转换为异常:
这显然是针对每个错误代码的某种分类。类别可以是每个目标异常,异常可以按函数分类。这正是错误协定的含义:按函数对异常进行分类;并按异常对错误代码进行分类。
下面是一个伪配置。将此作为如何分类的初步想法:
category Say [can throw]: { WrongMessageException, SessionTimeOutException }
category WrongMessageException [by error code]: { 100, 101 }
category SessionTimeOutException [by error code]: { 102, 103, 104 }
当然,您不需要为这种印象编写解析器(这是人类可读的伪配置)。您可以使用 XML 或任何类型的源存储类似的句子,这将帮助您配置错误转换规则和函数协定。
参考
书籍:Jeffrey Richter - CLR via C#,第 3 版。第 20 章 - 例外和状态管理分章 - 指南和最佳实践。子章节 - 隐藏实现细节以维护"合同"。
本章将异常描述为合约,并解释如何对函数抛出的合约进行分类。这可以确认此处提供的解释的正确性和可信度。
这个呢:
您说您已经存储了错误类别(DB或XML文件)让我们逗乐我们有一些
主详细信息表,称为 ErrorCategory(Master) 和 ErrorDetail(Detail)
我将重新命令将列(属性)添加到您的错误类别表中称为 CustomExceptionType,它将是一个文本属性,包含程序集的全名和指定异常的类名(例如:CustomExceptions,CustomExceptions.TerminalError )
我们将需要一个基类 4 我们所有的自定义异常,我们称之为BaseCustomException calss
我们需要一个 ExceptionFactory 类,我们称之为CustomExceptionFactory class
我们的 ExceptionFactory 将有一个名为 CreateException 的方法,如下所示
Public BaseCustomException CreateException(EceptinCategory category, ExceptionDetail detail)
{
var customException = Activator.CreateInstance(category.CustomExceptionType) as BaseCustomException;
customException.SetDetails(detail);
return customException;
}
因此,在运行时,我们的 CustomExceptionFactory 对象将使用 CustomExceptionType 使用 Reflection 创建特定异常的实例。
我更喜欢 CustomExceptionFactory 和 BaseCustomException 在汇编中实现并且所有派生的 CustomExceptions 都在另一个程序集中实现,因此我们的主应用程序将与 CustomExceptions.Dll
无关在未来,通过更改C++工厂,我们的主要应用程序将不需要重建,我们所需要的只是更改 CustomExceptions.Dll 中的表和 impementaion 的数据。(可以使用XML或配置文件或
跳这个会有所帮助。
好的,如果你想灵活并且不依赖于代码,我认为在第一次运行应用程序时使用反射来生成自定义类将是最好的。这是粗略的解释。如果你喜欢它,我可以进一步解释。C++代码的提供程序应创建一个将保存所有错误代码的类 - 例如公共类 Errors{public static readonly IOError = 100}。当您启动应用程序时,您将检查此类是否修改,如果它被修改,您将为每个错误代码生成异常类。在上面的示例中,您将生成继承异常 .net 类的类 IoException。之后,您可以在包装器中使用它并单独捕获每个异常。另一种可能的解决方案是修改您提到的 xml - 对于每个错误代码添加异常类 - 使用错误代码 100 的示例,您将拥有 IoException 类。 之后你需要实现这个类并使用它......
旧代码并保留其名称,而不是让您的代码名称不断更改。由于您的作者似乎对设计不感兴趣,请让他在您可以检索的stderr
流上报告警告和错误。
此外,使用代码字符串对构建CSV或XML似乎很简单,算法编写者可以根据需要自由编辑。为不同类型的错误保留一定范围的代码编号(输入错误为 1000,终端错误为 2000 等),让您的包装器使用他编写的代码字符串对解释返回代码。
然后根据错误类型(由数字范围确定)引发异常。