.NET 设计:冒泡异常以更好地重构实体消费者,这是一种好的做法吗?
.NET Design: Bubbling up exceptions to better refactor entity consumers, is it a good practice?
不确定这是讨论这个问题的最佳场所,因为它有点宽泛,所以我将尝试稍微缩小范围。
我的背景
前几天,我向我最近加入的团队的经理询问了一些关于一些设计决策的问题。我正在为一家企业投资银行开发一个交易应用程序,其中有很多遗留代码(就像任何其他经过 5 年多变化而幸存下来的软件应用程序一样)。
简而言之,不抛出任何异常似乎是这里的常见做法,不真正检查传递给方法或构造函数的参数。虽然我同意在某些情况下参数检查毫无价值,但当某些类型或值范围无法使用您的方法时抛出异常可能会有所帮助。
人们在这里使用 TDD,我对此很满意,但我认为这种做法并不能阻止一切。但是吞下异常并让其他灾难悄悄发生绝非更好,测试在许多方面有助于防止此类问题的发生,但并非总是如此。
这总是一个上下文问题,但在我过去的一份工作中,异常帮助我的团队提高了代码质量,通过冒泡我们遇到的所有问题,主要是指出异常值传递给一些实体,啊遗留代码......再次)并进行适当的重构。
问题/场景
假设我有一个 B 类型使用的 A 类型,一般来说,在 B 滥用 A 的情况下(例如值超出范围等),当 B 面对 A 抛出异常时,真的是这样吗?不好的做法?它应该帮助 B 以正确的方式处理 A(例如,将正确的参数传递给构造函数等)。当您查看 .NET 框架时,当您滥用 类 时会出现很多异常,然后会引发异常并让您知道它不应该与这个或那个一起使用。
同样,异常应该是异常的,但如果我们以一个非常简单的实体或方法解析 IP 地址为例,.NET Framework 会温和地让您知道传递的字符串不适合:
var address = IPAddress.Parse(@"It makes sense =]");
// An unhandled exception of type 'System.FormatException' occurred in System.dll
// Additional information: An invalid IP address was specified.
问题
当然,总是有很多上下文需要考虑,并不是那么黑白分明,但您认为设计 API 以告知开发人员 类 无法使用此值是一种好方法吗? ? (除了文档,如果有的话)而不是例如 returning null 当它不能工作时,什么是最合法的?你怎么知道你是否必须抛出异常或简单地 return false / null 来表示它不能工作?
只要在预期的工作流程中没有遵循某些内容,就应该抛出异常。例如,如果使用不正确的参数调用方法(如您的代码片段中),如果外部资源(例如文件)不可用,或者应用程序处于不允许调用该方法的状态。
异常允许其他开发人员决定异常冒泡到什么程度才能被妥善处理。此外,异常会提供有关出错的信息。
简单地 returning null 引入了一个问题,即所有 return 值在使用之前必须检查是否为空。否则,您可能会在导致整个应用程序崩溃的地方出现空引用异常。因此,returning null 只应比抛出异常更例外地使用。
不确定这是讨论这个问题的最佳场所,因为它有点宽泛,所以我将尝试稍微缩小范围。
我的背景
前几天,我向我最近加入的团队的经理询问了一些关于一些设计决策的问题。我正在为一家企业投资银行开发一个交易应用程序,其中有很多遗留代码(就像任何其他经过 5 年多变化而幸存下来的软件应用程序一样)。
简而言之,不抛出任何异常似乎是这里的常见做法,不真正检查传递给方法或构造函数的参数。虽然我同意在某些情况下参数检查毫无价值,但当某些类型或值范围无法使用您的方法时抛出异常可能会有所帮助。
人们在这里使用 TDD,我对此很满意,但我认为这种做法并不能阻止一切。但是吞下异常并让其他灾难悄悄发生绝非更好,测试在许多方面有助于防止此类问题的发生,但并非总是如此。
这总是一个上下文问题,但在我过去的一份工作中,异常帮助我的团队提高了代码质量,通过冒泡我们遇到的所有问题,主要是指出异常值传递给一些实体,啊遗留代码......再次)并进行适当的重构。
问题/场景
假设我有一个 B 类型使用的 A 类型,一般来说,在 B 滥用 A 的情况下(例如值超出范围等),当 B 面对 A 抛出异常时,真的是这样吗?不好的做法?它应该帮助 B 以正确的方式处理 A(例如,将正确的参数传递给构造函数等)。当您查看 .NET 框架时,当您滥用 类 时会出现很多异常,然后会引发异常并让您知道它不应该与这个或那个一起使用。
同样,异常应该是异常的,但如果我们以一个非常简单的实体或方法解析 IP 地址为例,.NET Framework 会温和地让您知道传递的字符串不适合:
var address = IPAddress.Parse(@"It makes sense =]");
// An unhandled exception of type 'System.FormatException' occurred in System.dll
// Additional information: An invalid IP address was specified.
问题
当然,总是有很多上下文需要考虑,并不是那么黑白分明,但您认为设计 API 以告知开发人员 类 无法使用此值是一种好方法吗? ? (除了文档,如果有的话)而不是例如 returning null 当它不能工作时,什么是最合法的?你怎么知道你是否必须抛出异常或简单地 return false / null 来表示它不能工作?
只要在预期的工作流程中没有遵循某些内容,就应该抛出异常。例如,如果使用不正确的参数调用方法(如您的代码片段中),如果外部资源(例如文件)不可用,或者应用程序处于不允许调用该方法的状态。
异常允许其他开发人员决定异常冒泡到什么程度才能被妥善处理。此外,异常会提供有关出错的信息。
简单地 returning null 引入了一个问题,即所有 return 值在使用之前必须检查是否为空。否则,您可能会在导致整个应用程序崩溃的地方出现空引用异常。因此,returning null 只应比抛出异常更例外地使用。