Language agnostic 抛出新异常与将消息写回用户(避免异常)

Language agnostic 抛出新异常与将消息写回用户(避免异常),language-agnostic,exception-handling,Language Agnostic,Exception Handling,我看到很多编写的代码中,如果参数的形式不正确,就会抛出异常。基本上是“扔新的…” 这有什么好处?通过检查参数可以避免异常(例如,如果为null,则将消息写回网页/winform)。为什么在异常昂贵时不使用这种方法 感谢您引发异常: 让其他程序员明白这种情况是例外的 允许软件调用所涉及的方法来清楚地处理问题 向工具和编译器显示情况异常,以便它们可以帮助程序员 允许将信息传递给异常对象本身中的处理例程 打印字符串-嗯-真的没有 就异常的“费用”而言,只有在异常情况下才会抛出异常,即很少抛出异常,

我看到很多编写的代码中,如果参数的形式不正确,就会抛出异常。基本上是“扔新的…”

这有什么好处?通过检查参数可以避免异常(例如,如果为null,则将消息写回网页/winform)。为什么在异常昂贵时不使用这种方法

感谢您引发异常:

  • 让其他程序员明白这种情况是例外的
  • 允许软件调用所涉及的方法来清楚地处理问题
  • 向工具和编译器显示情况异常,以便它们可以帮助程序员
  • 允许将信息传递给异常对象本身中的处理例程
打印字符串-嗯-真的没有


就异常的“费用”而言,只有在异常情况下才会抛出异常,即很少抛出异常,并且作为处理错误的一部分——我个人没有遇到异常的“费用”是一个问题的情况。关于这一点的更多讨论请参见。

例如,如果您正在编写一个库,供您不知道或还不存在的代码使用,那么如何处理该错误取决于调用的代码


所以抛出异常是很自然的事情。允许您将如何处理该错误场景的决定权留给调用者/消费者。

一般来说,从语言角度讲,假设异常代价高昂是不正确的。这取决于许多因素

通常,异常是一种表示错误条件的通用方法,它独立于任何形式的表示。发送带有错误消息的页面会使错误报告与表示、UI紧密结合。就灵活和可扩展的设计而言,这通常不是一个好主意

这个问题是一般性的,语言是不可知的,因此答案并不深入细节

顺便说一句,根据编程语言、错误处理设计和其他因素的数量,方法可能会有所不同。但是,了解各种选项是个好主意:

    在C++中,在Boost项目中,说:
不要太担心什么 消息很高兴有个口信 程序员有机会 弄明白了,但你不太可能 能够撰写相关的 用户可理解的错误消息位于 引发异常的点(…)

  • Krzysztof Cwalina建议为.NET提供一组非常有用的工具,但实际上它们与语言无关

考虑到上述指导原则,经过一段时间的考虑后,还不清楚此类错误网页应该显示什么、信息的级别、非常技术性或更为用户友好。使用异常,可以在系统的各个级别上提供更大的灵活性,因为当您需要处理(即显示错误)时,它会捕获其中一条规则,否则将忽略它

如果代码将编译到库中并在多个应用程序中重用,则最好抛出异常。在这种情况下,调用库的客户端应该适当地处理异常,并报告一条用户友好的消息

我抛出异常而不是向标准输出写入错误消息有两个主要原因

  • 调试更容易-我知道程序是否因为错误而退出。另外,由于Java中的异常可以子类化,所以我确切地知道发生了什么类型的错误

  • 如果您编写了一个API,然后决定使用GUI前端,那么您可能希望将这些异常显示在消息对话框中,而不是将它们写入标准输出


  • 这里有几点值得一提:

    • 首先,您认为异常昂贵的假设通常是不真实的-异常是。。。异常它们不应该经常出现,对程序性能产生任何有意义的影响。如果您看到了足够多的异常,认为性能是一个问题,那么您将面临更大的挑战

    • 其次,一个编写良好的类、函数或模块程序应该能够在某种程度上优雅地检测和处理无效输入。它有助于代码的维护人员和调试人员尽可能在引入问题时找到问题所在。如果不检查参数,它们通常会导致代码中的失败,而这与实际错误相差甚远。调试此类问题可能非常痛苦

    • 第三,假设所有代码都知道执行它的上下文。方法可能深入到框架或库中,不知道它是否在web应用程序、控制台应用程序、NT服务等中运行。此外,在整个代码体中显示有关无效参数的信息是一种糟糕的做法,这种做法应该集中并控制责任,否则UI很容易成为一堆错误,夹杂在实际的表示内容中

    • 最后,异常允许程序有时处理问题并从中恢复,而不是将问题暴露给用户。不要在出现错误时立即直接显示错误,从而削弱此功能。当然,最常见的无效参数是编程缺陷的症状(而不是环境或配置问题),因此在大多数情况下它们无法处理。但是,话说回来,有时候它们是可以处理的


    在大多数环境中,编写异常测试比编写到控制台的内容更容易:

    it "should reject a negative initial balance" do
      Account.new(-1).should raise_error(ArgumentError, "Invalid balance: -1")
    end
    
    这就是所谓的合同设计

    契约式设计的基本思想是,对象之间有契约,如果调用方不履行契约,则rece