【问题标题】:Do exceptions break encapsulation?异常会破坏封装吗?
【发布时间】:2011-11-09 14:34:49
【问题描述】:

首先,当您不想担心实现的细节时,会创建一个类或库,但随后您需要了解该类的内部工作原理以正确处理它可能抛出的异常。

这不是打破了封装和信息隐藏的原则吗?还是我完全错了?

当然我可以有一个通用的 try/catch 块来拦截所有异常,但这绝对是一种不好的做法。

那么在不知道可能抛出的每个异常的详细信息的情况下,我怎样才能提出好的异常处理策略呢?

【问题讨论】:

    标签: exception-handling encapsulation


    【解决方案1】:

    一个设计良好的类或库会将它抛出的异常记录为接口的一部分,甚至可以定义它自己的异常类层次结构。例如,如果磁盘已满,一个 foo 子类类可能会抛出一个“foo 持久性异常”,而如果网络中断,另一个子类会抛出一个“foo 持久性异常”。作为调用者,您将捕获 foo 持久性异常,因为您担心数据未持久化。不应期望您专门针对磁盘已满、网络故障、磁盘不存在、磁盘写入错误、子空间收发器干扰等编写代码。

    您可能对其中的许多都无能为力。

    【讨论】:

      【解决方案2】:

      类库不必抛出与其代码相同的异常。对于无法在内部处理的预期异常,它可能应该映射到 API 使用者不容易理解“原始”异常的备用异常类型。 API 使用者应该能够将预期的异常视为 API 的输出,就像使用 API 的任何其他产品一样。另一方面,对于 API 开发人员和消费者来说,意外的异常完全是另一回事......

      【讨论】:

        【解决方案3】:

        不是这样的;它适用于使用最终产品的最终用户或“不需要知道内部实现”的类,但您肯定会知道它,因此可以相应地处理错误机制。

        顺便说一句,这就是任何 API 都带有良好文档的原因......以便其他开发人员至少了解它的内部工作原理。

        希望这能澄清这个想法。

        【讨论】:

          【解决方案4】:

          首先,当您不希望创建一个类或库时 担心实现的细节,但是你需要 知道类的内部工作以正确处理异常 它可能会抛出。

          这不是打破了封装和信息的原则吗 躲起来?还是我完全错了?

          当 calee 由于某些运行时错误而无法履行其承诺并且无法从该状态恢复时,应引发异常。必须在接口/文档中指定可能引发的异常。我不明白这如何破坏封装。另一方面,使用返回码并不能强制调用者处理异常错误,即使显式忽略它也是如此。

          当然,我可以有一个通用的 try/catch 块来拦截所有异常, 但这绝对是一种不好的做法。

          如果您使用的界面的设计者没有明确指定可以抛出哪些异常以及由谁/what_function 抛出

          那么我怎样才能想出好的异常处理策略 了解可能引发的每个异常的详细信息?

          “详细信息”实际上是异常规范,这就是您需要了解的全部内容。同样,它应该是文档/界面的一部分。

          无论如何,异常应该很少发生,这可能就是为什么有人将它们命名为异常。如果它发生得太频繁,那么有人不会再将它们命名为异常,而是“通常”之类的东西,正常的、无异常的“代码”将成为异常:)

          如果您过多地使用 try/catch 废话,那么该代码有问题。

          【讨论】:

          • 如果上层有可能想要捕获它们并继续,异常不应在应用层之间冒泡而不被捕获并包装在自定义异常中。例如,如果允许在 IDictionary.Add 执行期间的某个时间发生的 ArgumentException 渗透到调用者,则调用者将不知道调用是否被拒绝(不更改数据结构),因为密钥已经存在,或者它是否部分执行并更改或损坏了字典。
          猜你喜欢
          • 1970-01-01
          • 2011-05-10
          • 2013-04-16
          • 2012-11-28
          • 2013-05-14
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-04-27
          相关资源
          最近更新 更多