If语句:在相同条件下处理分层的最佳方法

本文关键字:分层 处理 最佳 方法 条件下 语句 If | 更新日期: 2023-09-27 18:29:15

我对编程还很陌生,但我一直在努力确保学习良好的设计实践。我的问题是关于如何处理这种if-statement的情况,因为它似乎违反了Don't Repeat Yourself

我有一个带有构造函数的类,其中包含一个连接到数据库的方法。如果连接代码块中存在错误,该方法将写入string。然后,我有一个处理方法来分析数据库的元数据,如果发现任何错误,也会写入错误。如果连接方法中已经存在错误,我不希望运行元数据分析,但这是最好的方法吗?:

public bool Process()
{
    if (ErrorLog == null)
    {
        //Metadata analysis code that may write errors
        if (ErrorLog == null)
            return true;
        else
            PublishErrorLog();
        return false;
    } 
    else
        PublishErrorLog();
    return false;
}

If语句:在相同条件下处理分层的最佳方法

您的最终函数可以看起来像这样简单:

public bool Process()
{
    if (hasError())
        return false;
    //Metadata analysis code that may write errors
    //Note that error log may change here
    return !hasError(); //updated by juharr
}

解释:

如果带有//metadata analysis的行实际上可以更改ErrorLog的状态,那么您提供的代码可能不是完全相同的条件。

简化步骤1:单If-Else循环

然而,看到你的嵌套循环,我宁愿通过做这样的来让代码变得更容易处理和阅读

public bool Process()
{
    if (ErrorLog != null){
        PublishErrorLog();
        return false;
    }
        //Metadata analysis code that may write errors
       //Note that error log may change here
    if (ErrorLog != null){
        PublishErrorLog();
        return false;
    }
    return true;
}

基本上,您不需要制作嵌套的if-else,而是制作可以首先返回的简单语句。如果它满意,你就返回,否则你就继续。

这样,您的代码就变成了单个条件循环——没有嵌套循环。

简化步骤2:错误日志+具有错误组合功能

你还可以进一步改进上面的代码,假设你的错误记录模式是一样的,你可以创建这样的函数

bool hasError(){
    if (ErrorLog != null){
        PublishErrorLog();
        return true;
    }
    return false; //no error, can continue
}

最终代码

那么Process函数将看起来像

public bool Process()
{
    if (hasError())
        return false;
    //Metadata analysis code that may write errors
    //Note that error log may change here
    return !hasError(); //updated by juharr
}

非常简洁。你也可以在其他地方重复这种模式。

其他答案都是有效的。但对我来说,这似乎是使用Exceptions的完美案例。任何时候,只要您向ErrorLog写入,也会抛出异常。然后,您可以在顶部正好有一个块来处理错误。

public bool Process()
{
    if (ErrorLog != null)
        //At this point, the PublishErrorLog should have already been called.
        return false;
    try
    {
        // Do Metadata analysis that may throw errors
    }
    catch (ErrorLogException e)
    {
        PublishErrorLog()
        return false;
    }
    return true;
}

这样做的优点是,元数据分析可以根据需要进行复杂和嵌套。它只需要抛出异常。

编辑:

正如Aron所指出的,这完全可以在没有ErrorLog作为类成员的情况下完成。日志信息可以存储在异常本身中。捕获块可能看起来像:

catch (ErrorLogException e)
{
    var logMessage = e.logMessage;
    PublishErrorLog(logMessage);
    return false;
}

您似乎在使用ErrorLog属性来表示连接的有效性。如果ErrorLog是一个字符串,正如我从你的问题中了解到的那样,我会有一种特定的方法来判断连接是否有效,并且不依赖于日志的无效性。

例如

public bool Process()
{
    if (HasValidConnection)
    {
        //Metadata analysis code that may write errors
    }
    if (ErrorLog == null)
    {
        // no errors establishing the connection neither processing metadata
        return true;
    }
    else
        PublishErrorLog();
    return false;
}