【问题标题】:Good practice design pattern for Exception handling异常处理的良好实践设计模式
【发布时间】:2015-06-25 20:32:48
【问题描述】:

对于底层方法的以下代码,我在每个方法中都有异常处理代码

throw new Exception("The error that happens");

有什么办法可以避免在每种方法中一次又一次地编写这段代码?

我正在尝试编写自己的代码,而不是使用任何日志框架

private void TopLevelMethod()
{
    try
    {
        SomeMethod();
    }
    catch (Exception ex)
    {
        // Log/report exception/display to user etc.
    }
}

private void SomeMethod()
{
    TestPartA();
    TestPartB();
    TestPartC();
    TestPartD();
}

private void TestPartA()
{
    // Do some testing...
    try
    {
        if (somethingBadHappens)
        {
            throw new Exception("The error that happens");
        }
    }
    catch (Exception)
    {
        // Cleanup here. If no cleanup is possible, 
        // do not catch the exception here, i.e., 
        // try...catch would not be necessary in this method.

        // Re-throw the original exception.
        throw;
    }
}

private void TestPartB()
{
    // No need for try...catch because we can't do any cleanup for this method.
    if (somethingshappens)
    {
        throw new Exception("The error that happens");
    }
}

【问题讨论】:

  • 你知道throw & throw newthrow & throw new 之间的区别吗?看看这里以及谷歌搜索stackoverflow.com/questions/2999298/…
  • 谢谢。我知道了。我正在尝试使用任何集中管理器寻找一些用于异常管理的良好设计模式。
  • 创建您自己的处理异常等的自定义类。对于应用程序来说,这在本质上就一些好的设计模式而言是相当固执的,但这只是我的看法。..
  • 只是一个意见:与其在方法中抛出异常,不如构建返回布尔值(成功或失败)并更新错误字符串或错误容器(例如 List)的函数。您将在调试模式下看到这种方法的好处,这种方法只会在意外异常时中断。
  • Graggito: 请给出示例代码示例。谢谢....

标签: c# .net design-patterns


【解决方案1】:

只有当你想做一些有意义的事情时才捕获错误,例如:

  1. 用框架异常包装异常(例如SqlException。ADO.NET 永远不会向您传递套接字级错误。它会向您传递有意义的 SQL 错误代码)
  2. 清理
  3. 实际响应(例如重试或插入默认值)

日志记录几乎是不合适的。顶级处理程序应记录。当然不是路径中的每个方法都应该记录。日志和代码太混乱了。不要那样做。

只是不要吞下错误信息,让错误冒出来。这样就没有理由在任何地方插入本地日志记录代码来记录错误。

【讨论】:

    【解决方案2】:

    如果您更喜欢使用类似代码风格的函数式编程,一种方法是使用回调错误回调。 示例:

        private void SomeMethod()
        {
            // do something
        }
         public bool Execute(Action act, Action<Exception> onErrorCallback)
            {
                var res = true;
                try
                {
                    act();
                }
                catch (Exception ex)
                {
                    res = false;
                    onErrorCallback(ex);
                }
                return res;
            }
    

    并像这样使用Execute

       var successfull = true;
       successfull &= Execute(SomeMethod, (ex) => {  /* clean up */ });
       successfull &= Execute(SomeMethod, (ex) => {  /* clean up */ });
       successfull &= Execute(SomeMethod, (ex) => {  /* clean up */ });
       successfull &= Execute(SomeMethod, (ex) => {  /* clean up */ });
       if (!successfull)
           ; // show user or something else
    

    【讨论】:

    • 你刚刚介绍了大家最讨厌 JavaScript 到 C# 的东西。用于传递结果的回调。
    • 另外,你带来了ON ERROR RESUME NEXT :)
    【解决方案3】:

    Graffito:能否提供示例代码示例。谢谢...

    您的代码已重构:

    private void TopLevelMethod()
    { 
        List<string> errors=new List<string>() ;
        if (!SomeMethod(errors)) { /* Log/report errors/display to user etc. */ }
    }
    
    private bool SomeMethod(List<string> errors)
    {
        return TestPartA(errors) && TestPartB(errors) && TestPartC(errors) && TestPartD(errors);
    }
    
    private bool TestPartA(List<string> errors)
    {
      bool result = true ;
      try 
      {
        // Do some testing...
        if (somethingBadHappens) { result=false; errors.Add("The error that happens"); }
      }
      catch (Exception ex) { errors.Add("Error in TestPartA: "+Ex.Exception.Message.ToString()) ; }
      return result ;
    }
    
    private bool TestPartB(List<string> errors)
    {
      bool result = true ;
      // Do some testing...
      if (somethingBadHappens) { result = false ; errors.Add("The error that happens"); }
      return result ;
    }
    

    【讨论】:

    • 将异常转换为返回值失去了异常带来的好处。此外,此代码 sn-p 中的所有方法都依赖并改变共享状态(列表),这是另一个缺点。我会在代码审查中失败。
    • usr 说“将异常转换为返回值失去了异常带来的好处”。对于许多异常,返回值是适当的(例如,写入文件失败)。应保留一些例外情况(例如,检测先前程序提供的异常数据)。另请注意,异常处理很慢。例如,基准测试 "b=int.tryParse(s,out i) 与 "try { i=int.Parse(s) ; } 捕捉 {}"。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-12-04
    • 2011-07-29
    • 1970-01-01
    • 1970-01-01
    • 2012-09-20
    • 2010-09-14
    • 2012-01-15
    相关资源
    最近更新 更多