在 try-catch 语句中解释错误处理的正确位置是什么?似乎您可以在 try 块或 catch 块的开头添加解释性注释。
// Possible comment location 1
try
{
// real code
}
// Possible comment location 2
catch
{
// Possible comment location 3
// Error handling code
}
在 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
}
如果您可以使用变量和方法命名来显示正在发生的事情,则无需记录。如果您必须记录或引发异常,则无需记录 - 源代码中的记录消息无论如何都应该是不言自明的。唯一需要在代码中添加额外文档的情况是,当代码在做什么完全不明显时,或者您必须添加一个容易错过的陷阱或模棱两可的步骤,这将需要任何查看将来的代码。
编辑:为了澄清一点,这里有更多关于我如何使用这些“catch”语句来为维护程序员和用户/支持/质量保证/使用该软件的任何其他人提供有用的信息。还说明了我绝对想在代码中添加额外注释的情况:
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 );
}
}
绝对不要评论它的顶部,因为除了“在此处启动异常处理块”之外,您还能说什么有用的?对 catch 语句的评论更好,但总的来说,你要说什么?“处理 NullPointerException”?
如果你需要说你正在做一些令人兴奋的事情,我会去发表评论,比如链接到应用程序域异常。
我认为写得好的 try/catch 应该简洁而具体。我同意@Jason 的观点,即为什么更重要,但同样重要的是,让 catch 中的代码尽可能简洁。
如果您使用特定的异常来捕获它也会有所帮助。例如,如果您使用 Java,请尝试捕获 NullPointerException 而不是通用异常。这应该解释为什么存在 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
}
我知道这不是您要寻找的答案,但根本不要发表评论。如果你的代码不够清晰,无法在没有注释的情况下独立存在,那么你应该重构它直到它清晰为止。Jeffrey Palerm刚刚写了一篇博文,说明了这一点。
通常,评论倾向于记录:
++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 代码块太长并且需要注释来总结,请考虑将其重构为单独的方法以提高可读性。