gpt4 book ai didi

c# - 如何从未经检查的异常中恢复?

转载 作者:搜寻专家 更新时间:2023-11-01 01:01:23 25 4
gpt4 key购买 nike

如果您想以相同的方式处理每个失败,例如通过记录它并跳到下一个请求,向用户显示消息并处理下一个事件等,未经检查的异常是可以的。如果这是我的用例,我所要做的就是在我的系统中捕获一些高级别的一般异常类型,并以相同的方式处理所有事情。

但我想从特定问题中恢复过来,我不确定用未经检查的异常处理它的最佳方法。这是一个具体的例子。

假设我有一个 Web 应用程序,使用 Struts2 和 Hibernate 构建。如果在我的“操作”中出现异常,我会将其记录下来,并向用户致以诚挚的歉意。但是我的 Web 应用程序的功能之一是创建新的用户帐户,这需要一个唯一的用户名。如果用户选择了一个已经存在的名称,Hibernate 会在我的系统内部抛出一个 org.hibernate.exception.ConstraintViolationException(一个未经检查的异常)。我真的很想通过要求用户选择另一个用户名来从这个特定问题中恢复过来,而不是给他们同样的“我们记录了你的问题,但现在你已经被清理了”消息。

这里有几点需要考虑:

  1. 很多人同时创建帐户。我不想将整个用户表锁定在“SELECT”以查看名称是否存在和“INSERT”(如果不存在)之间。在关系数据库的情况下,可能有一些技巧可以解决这个问题,但我真正感兴趣的是一般情况,由于基本的竞争条件,预检查异常将不起作用。同样的事情也适用于在文件系统中查找文件等。
  2. 考虑到我的 CTO 因阅读“Inc.”中的技术专栏而导致的偷渡式管理倾向,我需要围绕持久性机制建立一个间接层,这样我就可以抛弃 Hibernate 并使用 Kodo 或其他任何东西,而无需更改任何内容除了最底层的持久化代码。事实上,在我的系统中有几个这样的抽象层。尽管有未经检查的异常,我如何防止它们泄漏?
  3. 检查异常的一个明显弱点是必须在堆栈上的每个调用中“处理”它们——通过声明调用方法抛出它们,或者通过捕获它们并处理它们。处理它们通常意味着将它们包装在另一个类型适合抽象级别的已检查异常中。因此,例如,在检查异常领域,我的 UserRegistry 的基于文件系统的实现可能会捕获 IOException,而数据库实现会捕获 SQLException,但两者都会抛出隐藏底层实现的 UserNotFoundException。我如何利用未经检查的异常,在不泄露实现细节的情况下减轻每一层包装的负担?

最佳答案

IMO,包装异常(检查或其他)有几个值得付出代价的好处:

1) 它鼓励您考虑所编写代码的故障模式。基本上,您必须考虑您调用的代码可能抛出的异常,然后您将考虑为调用您的代码抛出的异常。

2) 它使您有机会向异常链中添加额外的调试信息。例如,如果你有一个方法在重复的用户名上抛出异常,你可以用一个包含有关失败情况的附加信息(例如,提供重复用户名的请求的 IP)的异常来包装该异常对较低级别的代码不可用。异常的 cookie 踪迹可以帮助您调试复杂的问题(对我来说肯定有)。

3) 它使您可以独立于较低级别的代码实现。如果您正在包装异常并且需要将 Hibernate 换成其他 ORM,您只需更改 Hibernate 处理代码。所有其他代码层仍将成功使用包装的异常,并以相同的方式解释它们,即使底层环境已经改变。请注意,即使 Hibernate 以某种方式发生变化(例如:它们在新版本中切换异常),这也适用;它不仅仅是用于批发技术更换。

4) 它鼓励您使用不同类别的异常来表示不同的情况。例如,当用户尝试重用用户名时,您可能会遇到 DuplicateUsernameException,而当您由于数据库连接断开而无法检查重复的用户名时,可能会遇到 DatabaseFailureException。反过来,这可以让您以灵活而强大的方式回答您的问题(“我该如何恢复?”)。如果您收到 DuplicateUsernameException,您可能会决定向用户建议一个不同的用户名。如果您收到 DatabaseFailureException,您可以让它冒泡到它向用户显示“停机维护”页面并向您发送通知电子邮件的程度。一旦您有了自定义异常,您就有了可自定义的响应——这是一件好事。

关于c# - 如何从未经检查的异常中恢复?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33497/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com