Have you ever wondered how exceptions start to shape and have an impact on your project? Are they useful? Do they affect performance in anyway?
在我的大学最近的一堂课上,有一个关于异常的具体讨论,以及异常如何对您的项目造成影响。 大多数对话都涉及从多个角度讨论异常如何工作,何时有用以及它们如何影响您的项目的争论。 代码的可读性,耦合性,性能和异常的整体有用性。 我想稍微探讨一下这个想法,看看当您开始使用它们时有什么含义。
以我的经验,异常处理是一个非常广泛且经过讨论的主题,对此有几种不同的见解,通常是由于每个人的亲身经历而形成的。 我已经看到程序员通过对每个单个操作或方法执行一次try / catch来做大量的防御性代码,用一个异常处理将所有内容放在一个大型try / catch中,而一无所获。
Is exception handling useful?
是的,如果您正在访问可能以关键方式失败的特定资源(例如,访问数据库,API调用,打开文件等),这在场景中非常方便。由于超时,这些情况最终会失败, 找不到资源,您未遵守数据库中的特定规则(例如外键或必填字段)或意外错误。 异常允许您从这些情况中恢复并向用户显示错误页面,找不到页面,“抱歉,请稍后再试”。 有意义的事情将使用户知道出现了问题,而不仅仅是关闭或冻结其窗口或浏览器。
当您开发供其他团队使用的库时,或者要为开源做贡献时,异常也非常有用。 通常,人们不会花时间阅读特定库的工作原理,而只是使用它。 如果他们错过了某些事情,抛出异常将是一种很好的方式来教育他们并控制他们如何与您的图书馆互动。
But sometimes, could it be a little bit too much?
另一方面,我们还有其他场景正在使用Exception,这可能有点过大,因为您可以通过其他简单的控制结构来解决该场景。
以下面的示例为例:您有一个名为Employee的类,该类具有一个接受1个参数(名称)的构造函数。 假设该名称为必填项,并且您不能创建没有名称的Employee。 因此,您决定实现一个自定义异常,即当name == null时,将此异常抛出给想要使用它的任何人,我们将其称为EmployeeException。 这意味着:
- 您应用程序的每个要创建员工的部分都需要将代码括在try catch中以捕获该特定错误应用程序的每个部分都将同时依赖Employee和EmployeeException,这将增加耦合,从而可能导致将来出现维护问题。try / catch会造成一些混乱,因为您将抛出EmployeeException。 是因为名字是空的吗? 还是我还必须设置其他变量? 还是名称需要具有特定格式? 显然,您可以将异常的名称更改为更容易理解的名称,但是如果您是在团队中工作或使用外部库,并且其他人对该异常进行了编码,则可能导致混乱。 并想象是否有几个错误可能引发该异常? 您会为它们每个创建一个自定义例外吗? 这可能会增加项目与员工之间的耦合。这可能会对性能产生影响(我将在稍后解释)
我们可以通过向Employee类添加一个静态方法来解决此问题,该方法从一组特定的参数中返回一个布尔值,该布尔值显示是否可以创建Employee,这将有助于我在上面指出的要点。 这将是异常处理,验证输入和创建验证方法的替代方法之一。
And how about the performance of my application?
对于此讨论,我认为我可以采用更实际的方法。 因此,我创建了一个简单的Java项目,该项目确实遵循我之前提到的Employee方案。 基本上,我们使用构造函数(字符串名称)创建一个Employee,并且如果name为null,则抛出异常。 我们执行相同的操作,但是在创建Employee之前添加了isValid方法进行检查。 我使用了for循环并多次运行构造函数进行了测试,因为要看到时间执行方面的差异,我需要创建1个以上的Employee。 因此,我测试了以下方案:
1-创建一个名称为null的Employee,并用try / catch包围它。
2-创建一个雇员,其中一半将引发错误,一半将通过并用try / catch包围它。
3-创建一个Employee,其中一半将引发错误,一半将通过try / catch并将其包围,并且在捕捉时,我执行ex.getStackTrace()只是为了模拟异常处理。
4-创建一个雇员,其中五分之一将引发错误并用try / catch包围它。
5-创建一个名称为“ test”的Employee,并用try / catch包围它,但是由于它是有效名称,因此不会引发任何异常
6-创建一个名称为“ test”的雇员,但是在执行isValid之前
我执行了这些总设置为100、1000、10000、100000、1000000的方案。以下是结果(以毫秒为单位):
- 对于i = 100,相差不大,执行时间为0到1毫秒对于i = 1000,方案1、2、3所花费的时间是方案4、5、6的3倍。这开始使我们想到处理异常需要更多的时间。 此外,从数字5可以看出,如果未引发异常,则添加try / catch块不会降低性能。对于i = 10000,方案1、2、3的花费是其他方案的16到23倍对于i = 100000,情形1和3的飞行时间分别为136 ms和154 ms,情形5和6的飞行时间分别为5 ms和4 ms。对于i = 1000000,引发和管理异常的方案最多可能需要1秒钟。
To sum up!
总的来说,可以说例外显然是编程语言的支柱之一。 它们使我们能够从几种关键情况中恢复,并允许我们将这些信息传达给用户。 此外,它使我们能够在catch闭包上跟踪这些错误,因此我们可以从这些错误中学习并迭代我们的项目以防止它们发生。
另一方面,我们需要考虑到异常不仅影响最终用户,而且影响开发人员。 自定义异常会导致代码维护,可读性和性能方面的问题。 恕我直言,它说的更多是个案分析,有时它们可能会很有帮助,但在其他情况下,可能会引起一些麻烦! 在将异常引入混合之前,只需确保您有所考虑即可。
from: https://dev.to//juanigalan91/is-there-a-price-to-pay-for-using-exceptions-58gl