【问题标题】:Is rethrowing exceptions good practice?重新抛出异常是好的做法吗?
【发布时间】:2015-04-06 07:23:53
【问题描述】:

您认为捕获异常并重新抛出它是一种好习惯吗?

基本上我有一段代码,其中颜色是使用其构造函数和 3 个参数创建的。并且颜色构造函数可能会抛出异常。

    public PointExtend(double x, double y, int r, int g, int b)
        : base(x, y)
    {
        try
        {
            var color = new Color(r, g, b);
            Color = color;                
        }
        catch (InvalidColorValueException)
        {
            throw;
        }
    }

Resharper 说,catch-throw 子句是多余的,我同意,考虑到我没有对 Exception 做任何事情,而是再次抛出它,如果我没有,它无论如何都会泄漏到 UI,但这段代码不是用于一个更容易阅读的程序员,所以如果他创建 PointExtend 他就会知道代码可能会抛出什么?

【问题讨论】:

  • 我认为这是毫无意义的,除非您抛出自定义异常
  • catch/throw 是多余的。这相当于根本没有抓到。这不是更简洁的代码,这是一个意外的惊喜和令人头疼的尝试,试图理解作者的意思以及代码中是否缺少某些东西
  • 良好实践是什么意思?你想达到什么目的?
  • @PanagiotisKanavos Petar 提到了 Comments,npinti 提到了上面的 ///summary 函数,我完全忘记了。我认为他们的想法实际上是有效的,并且会从现在开始选择我自己的方式,而不是重新抛出异常。
  • @ErnodeWeerd 我试图让程序员更容易阅读代码。程序员看到,这个 PointExtend 构造函数可能会抛出异常,所以如果他想在其他地方使用 PointExtend 构造函数,他将不得不捕获可能抛出的 InvalidColorValueException。但我现在发现这样做不是最好的主意,使用 cmets 或 ///summary 更受欢迎。

标签: c# exception


【解决方案1】:

除非您正在执行任何特定的日志记录或异常包装,否则您可以将其移除。

如果您希望程序员知道可能的异常,请记录它:

/// <summary>
/// Creates a new instance of <code>PointExtend</code>
/// </summary>
/// <param name="x">...</param>
/// <param name="y">...</param>
/// <param name="r">...</param>
/// <param name="g">...</param>
/// <param name="b">...</param>
/// <exception cref="InvalidColorValueException">Should the provided rgb values be out of range</exception>
public PointExtend(double x, double y, int r, int g, int b)
        : base(x, y)
    {            
            var color = new Color(r, g, b);
            Color = color;                            
    }

这将允许使用您的 API 的其他程序员知道构造函数的作用以及任何潜在的陷阱。不是每个人都可以访问您的代码。

编辑:根据@Philip Stuyck 的评论,虽然我同意,但我也认为我们并不生活在一个理想的世界中。您推荐的问题是:

  • 如果要求您提供 DLL 的混淆版本会怎样?当公司出售他们的 DLL 时,通常会发生这种情况。您无法真正查看代码,方法名称只能到此为止。
  • 大多数项目往往不仅仅是少数几个类,而且每次都通过代码来弄清楚发生了什么可能会非常耗时,并且可能会使人们停止使用您的产品。在我看来,开源项目是this 的一个明显例子。
  • 最后,更重要的是,在我看来,您可以在 summary 部分中说明代码的作用(至少在 .NET 的情况下)。评论和文档应阐明为什么选择了给定的方法。

【讨论】:

  • 这其实很简洁,我完全忘记了C#提供的///summary能力,谢谢。
  • @OndřejŠimon:在理想的世界中,代码应该被记录下来,因为你永远不知道其他人将在谁/从哪里工作。
  • 这些都是我在学校的项目,但我想你应该学会在你的小项目上很好地编程,这样在处理大项目时,其他程序员阅读你的代码不会有问题。
  • @OndřejŠimon:较大的项目通常是较小项目的集合。此外,最好在开始时学习好的做法,因为一旦掌握了这些坏习惯,就很难改变它们。
  • 在理想世界中,代码不需要文档或注释。只有写得不好的代码才需要注释。
【解决方案2】:

你真的从那些试图说服你应该记录你的代码的人那里得到了糟糕的建议。

只有写得不好的代码才需要 cmets,而不是花精力写注释,好的注释,把精力花在你的代码上,这样它就根本不需要注释。

这是否意味着所有评论都是邪恶的。不,当然不是。在某些情况下仍然需要注释,因为编程语言并不总是最适合很好地描述正在发生的事情。但即便如此,也必须小心,因为评论将开始有自己的生命。

http://apdevblog.com/comments-in-code/

是一篇引用 Robert C. Martin 的 Clean Code 的博客

那本书有一整章是关于 cmets 的,那些认为你需要评论的人最好阅读那本书。

在您的特定情况下,如果您真的觉得当您捕获异常然后重新抛出异常时代码更好,请务必将其保留。 我个人会把它排除在外。但对我来说,这只是一个风格问题。与您的同事达成协议,并在您的团队中保持一致。

我在这里的回答可能会引起很大的争论,你们都可以就这个问题发表自己的看法。 (Robert Martin 也说过同样的话 ;-))但事实是,在许多情况下,注释只会使代码混乱并降低可读性。注释被忘记更新,因此不再与真实代码内联,...

记录所有内容的另一种方法是编写好的单元测试。通过阅读单元测试的代码,如果它们写得好,您将了解代码应该如何使用。也就是说,如果您正在编写一个供其他人使用的 api。

编写良好且分层良好的代码不需要针对系统中的每个类进行处理。如果您必须这样做才能理解代码,那么结论还是一样的。这是糟糕的代码。

方法名、变量名、类名走得很远。看了干净代码这本书,我的代码风格有了很大的改变。

我写软件已经 20 年了,我看过,写了很多评论。在许多情况下,仍然不清楚他们在该评论中的真正含义,或者该评论明显是错误的。

【讨论】:

  • 感谢您在此回复中投入的时间,菲利普。所以你实际上认为我应该删除 try catch 子句,然后另一个程序员,如果有人在我的代码上工作,应该自己想办法,Color 构造函数实际上可能会抛出异常,这意味着他必须打开 Color 类以及,而不是直接在 PointExtend 类中看到它?我也不是 cmets 的粉丝,我尝试编写易于理解的代码,但到目前为止,我们主要使用 C++ 编写算法,并且直到最近才被引入整个异常概念。
  • 这就是我在团队会议上的立场,以消除 try catch。但如果团队做出不同的决定,我会跟进团队的决定。在设计方面,SW 并不总是黑白分明。
【解决方案3】:

如果您想让程序员知道一些事情,请使用 cmets。 捕获和抛出异常是一种开销并且是无用的(除非您在重新抛出之前对其进行了处理,即记录它),因此程序员实际上会感到困惑,认为存在错误并且不了解最初的意图是什么。

【讨论】:

  • npinti 提到了 ///summary,我想从现在开始我会使用它。不过还是谢谢你的回复。我很感激,Petar。
  • 需要注释的代码是坏代码。重写代码,以便它自己记录。
  • @PhilipStuyck 我应该如何重写代码的这个特定部分,一个创建对象可能抛出异常的部分?在这种情况下,我认为一些文档是必要的。
  • 您保持原样,或者按照 resharper 的建议删除不需要的代码。但是您不要添加注释,因为注释可能会脱离上下文,并且会脱离其余代码的上下文。
【解决方案4】:

如你所说,上面代码中的 throw 毫无意义,所有运行时都会做的只是重新抛出相同的异常。你可以去掉try catch,它的作用是一样的。

如果你对异常本身做了某些事情,那就是捕获它的原因,否则让它冒泡并给用户一个有意义的消息,把它记录在一个错误日志中,你和用户不只是得到一个无意义的异常弹出:)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-11-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-19
    相关资源
    最近更新 更多