在 try-catch 语句中解释错误处理的正确位置是什么?似乎您可以在 try 块或 catch 块的开头放置解释性注释。

// Possible comment location 1
try
{   
    // real code
}
// Possible comment location 2
catch
{
    // Possible comment location 3

    // Error handling code

}
有帮助吗?

解决方案

我通常会做以下事情。如果只处理一个例外,我通常不会打扰,因为它应该是自我记录的。

try
{   
    real code // throws SomeException
    real code // throws SomeOtherException
}
catch(SomeException se)
{
    // explain your error handling choice if it's not obvious
}
catch(SomeOtherException soe)
{
    // explain your error handling choice if it's not obvious
}

其他提示

“评论是谎言”。处理这些变量名称和一般逻辑,以便您可以避免它。如果你真的需要撒谎,可以在catch区内进行。

我觉得这根本不重要。

我认为通过评论记住的重要事项是解决为什么代码是这样的,而不是代码正在做什么,首先是。这并不是说你不应该在简明的评论中解释复杂的逻辑,但为什么这么重要。

如何设置代码以便不需要额外的注释?

try
{ 
   performDifficultAct( parameter );
}
catch (ArgumentOutOfRangeException couldNotFindArgument)
{
   // handle exception
}
catch (Exception otherUnknownException )
{
   // handle exception
}

无需记录您是否可以使用变量和方法命名来显示正在发生的事情。无需记录是否必须记录或引发异常 - 源代码中的记录消息无论如何都应该是不言自明的。唯一一次你需要在你的代码中需要额外的文档时,代码正在做什么是完全不明显的,或者你需要添加一个容易错过的问题或模糊的步骤,需要解释任何人代码将来。

编辑:为了澄清一点,这里有更多关于我如何使用那些“捕获”的信息。声明,为维护程序员和用户/支持/ QA /使用该软件的任何其他人提供有用的信息。还说明了我绝对想在代码中添加额外注释的情况:

public void PerformSomeActionOrOther(string parameter)
{
  try
  { 
     // For some reason an eleven character string causes a bluescreen from Kernel32
     if (parameter.Length==11) parameter+=" ";

     performDifficultAct( parameter );
  }
  catch (ArgumentOutOfRangeException couldNotFindArgument)
  {
     this.Log.WriteLn("Argument out of range exception in ArbitraryClass.PerformSomeActionOrOther");
     this.Log.WriteLn(String.Format("Probable cause is that {0} is not in the array", parameter));
     this.Log.WriteLn(String.Format("Exception: {0}", couldNotFindArgument.Message));
  }
  catch (Exception otherUnknownException )
  {
     this.Log.WriteLn("Unexpected exception in ArbitraryClass.PerformSomeActionOrOther");
     this.Log.WriteLn(String.Format("Exception: {0}", otherUnknownException.Message));
     throw( otherUnknownException );
  }
}

绝对不要对它的顶部进行评论,因为除了“在这里启动异常处理块”之外,你能说些什么呢?关于捕获声明的评论更好,但总的来说,你还会说些什么? “处理NullPointerException”?

我会去评论IFF你需要说你正在做一些令人兴奋的事情,比如链接到应用程序域异常。

我认为一个写得很好的try / catch应该简明扼要。我同意@Jason的说法为什么更为重要,但同样重要的是要尽可能简洁地将代码保持在内部。

如果您使用了特定的异常,它也会有所帮助。例如,如果您使用Java,请尝试捕获NullPointerException而不是通用Exception。这可以解释为什么try catch存在以及你正在做什么来解决它。

只要您保持一致,位置无关紧要。我个人的偏好如下:

//comment 1: code does XYZ, can cause exceptions A, B, C
try {
    //do something
}
//comment 2: exception A occurs when foo != bar
catch (ExceptionA a) {
    //do something
}
//comment 3: exception B occurs when bar is null
catch (ExceptionB b) {
    //do something
}
//comment 4: exception B occurs when foo is null
catch (ExceptionC c) {
    //do something
}

我知道这不是您要寻找的答案,但请不要发表评论。如果您的代码不够清晰,无法在没有注释的情况下独立存在,那么您应该重构它,直到它变得清晰为止。 杰弗里·巴勒姆o刚刚写了一个 博客文章 这句话说得最好。

通常,评论倾向于记录以下任一内容:

  • 代码太紧凑。事情看起来像这样: ++i?--g:h-i;
  • 需要总结的长代码块
  • 代码要么是一次性的,要么没有明确的存在理由

请参阅下面的简化示例,了解对异常块进行一些简单注释的示例,以及无需注释的版本。

bool retries = 0;
while (retries < MAX_RETRIES)
{
    try
    {
        ... database access code
        break;
    }
    // If under max retries, log and increment, otherwise rethrow
    catch (SqlException e)
    {
        logger.LogWarning(e);
        if (++retries >= MAX_RETRIES)
        {
            throw new MaxRetriesException(MAX_RETRIES, e);
        }
    }
    // Can't retry.  Log error and rethrow.
    catch (ApplicationException e)
    {
        logger.LogError(e);
        throw;
    }
}

虽然上述注释促进了可重用性,但您本质上必须同时维护代码和注释。可以(并且最好)对其进行重构,以便在没有注释的情况下更清晰。

bool retries = 0;
while (canRetry(retries))
{
    try
    {
        ... database access code
        break;
    }
    catch (SqlException e)
    {
        logger.LogWarning(e);
        retries = incrementRetriesOrThrowIfMaxReached(retries, e);
    }
    catch (ApplicationException e)
    {
        logger.LogError(e);
        throw;
    }
}

...

private void incrementRetriesOrThrowIfMaxReached(int retries, Exception e)
{
    if (++retries >= MAX_RETRIES)
        throw new MaxRetriesException(MAX_RETRIES, e);

    return retries;
}

private bool canRetry(int retries)
{
    return retries < MAX_RETRIES;
}

后一个示例可能看起来需要更多代码才能获得非常微妙的好处,但其收益怎么强调都不为过。代码同样易于理解,但您的好处是不需要一组单独的元数据(注释)来解释代码。代码本身就解释了。如果您的 catch 代码块太长并且需要注释来总结,请考虑将其重构为单独的方法以提高可读性。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top