帮助重构这个混乱嵌套的方法

时间:2009-01-09 14:38:01

标签: refactoring nested-if

好的,我想要一些意见,我可以解决这个方法的混乱!

它与许多嵌套的'if'语句有关。

但是我意识到我必须确切地知道方法失败的地方,目前在每个相应的'else'子句中我记录错误(失败的'if'条件')。

注意:忽略事物背后的任何逻辑,请关注样式和结构,因为我已经创建了所有的函数名称等。

这是骨架结构:

   public void MyMethod()
{

   try
   {
    bool tryAgain = false;

    string filename = DownloadFile();

    if( IsFileFormatOk(filename) )
    {

        blah = GetBlah(filename);

        if(blah.ID > 0)
        {

            if(ImportFile(filename)
            {

                string username = GetUserFromFile(filename);

                if(isValidUser(username))
                {

                    // few more levels to go
                    //
                    //
                    //

                }
                else
                {
                    LogError(filename, ...); // specific to this if statement
                    tryAgain = true;
                }


            }
            else
            {

                LogError(filename, ...); // specific to this if statement
                tryAgain = true;
            }

        }
        else
        {
            LogError(filename, ...); // specific to this if statement
            tryAgain = true;
        }

    }
    else
    {
        LogError(filename, ...); // specific to this if statement
        tryAgain = true;
    }

   }
   catch
   {
   }
   finally
   {
    if(tryAgain)
    {
        // blah
    }
   }


}

7 个答案:

答案 0 :(得分:5)

我会努力改变你的逻辑,这样你就可以尽快从方法中返回,而不是嵌套更多的逻辑。例如:

//  GOOD
if (!file.exists())
    return;
// Rest of the code

// BAD
if (file.exists()){
    // Code goes here
}
return;

这可能有助于删除一些嵌套并使事情变得不那么复杂。

答案 1 :(得分:3)

我猜有很多逻辑等待在其他地方提取,但无论如何这是另一种平铺嵌套的方法:

try
{
  if( !IsFileFormatOk(filename) )
    throw new MySpecificException(...); // pass specific log params

  blah = GetBlah(filename);

  if(blah.ID <= 0)
    throw new MySpecificException(...); // pass specific log params

  if(!ImportFile(filename)
    throw new MySpecificException(...); // pass specific log params

  string username = GetUserFromFile(filename);

  // ...
}
catch (MySecificException e)
{
  LogError(filename, e.LogParams)
  // blah
}

答案 2 :(得分:1)

您可以先将toplevel if(true branch)放在一个单独的方法中。并继续直到满意为止。

所以一般来说你改变了:

if (condition) {
  // Block1
} else {
  // Block2
}

if (condition) {
  Block(...);
} else {
  Block2(...);
}

请注意需要传递给新方法的局部变量。

答案 3 :(得分:0)

编辑:现在我知道有这么多级别,我们需要采取另一种方法。我不知道“再试一次”中的内容,但你需要改变逻辑,以便测试失败案例,而不是成功案例。如果它失败了,记录并返回(或以某种方式再做一次尝试)。否则,你可以继续走if if。

if(EndOfWorld)
{
    WriteLastLogEntryEver();
    return; //run away
}

//we're safe (for now)
ChargeOnAhead();

在我知道嵌套的级别之前,我建议如下。

public void MyMethod()
{

   try
   {
    bool tryAgain = false;

    string filename = DownloadFile();

    if( IsFileFormatOk(filename) )
    {

        tryAgain = DoBlah(filename, ...);
    }
    else
    {
        LogError(filename, ...); // specific to this if statement
        tryAgain = true;
    }

   }
   catch
   {
   }
   finally
   {
    if(tryAgain)
    {
        // blah
    }
   }


}

private bool DoImport(string filename, blah)
{

    if(ImportFile(filename))
    {

            // and so forth!
            return false;
    }

    LogError(filename, ...); // specific to this if statement
    return true;
}

private bool DoBlah(string filename)
{
        blah = GetBlah(filename);

        if(blah.ID > 0)
        {

            return DoImport(filename, ...);

        }

        LogError(filename, ...); // specific to this if statement
        return true;

}

我确信你可以再重构一次,并将// and so forth拉入新方法。这取决于你要来回传递多少东西。如果你传递的太多,请考虑成为参数或类字段是否更有意义。


答案 4 :(得分:0)

如果出现错误,您应该尝试让所有正在调用的方法抛出异常。抛出的异常应包含您要记录的任何错误消息。创建一个LogError()方法,该方法接受任何异常并记录嵌入的消息。像这样(伪代码):

MyMethod()
{
  try
  {
    string filename = DownloadFile()
    blah = GetBlah(filename)
    ImportFile(filename)
    ...
  }
  catch DownloadFileException, GetBlahException, ImportFileException e
  {
    LogError(e)
  }
}

当然,您必须创建所有这些例外,但这非常简单。在大多数语言中,您只需子类化顶级异常对象。

答案 5 :(得分:0)

这是jjnguy的建议,已实施:

public void MyMethod() {
    try
    {
        bool tryAgain = false;
        string filename = DownloadFile();

        if( !IsFileFormatOk(filename) )
        {
            LogError(filename, ...); // specific to this if statement
            tryAgain = true;
            return;
        }

        blah = GetBlah(filename);
        if(blah.ID <= 0)
        {
            LogError(filename, ...); // specific to this if statement
            tryAgain = true;
            return;
        }

        if(!ImportFile(filename))
        {
            LogError(filename, ...); // specific to this if statement
            tryAgain = true;
            return;
        }

        string username = GetUserFromFile(filename);

        if(!isValidUser(username))
        {
            LogError(filename, ...); // specific to this if statement
            tryAgain = true;
            return
        }

        // few more levels to go
        //

    finally
    {
        if(tryAgain)
        {
            // blah
        }
   }
}

答案 6 :(得分:0)

对于这类问题,http://refactormycode.com/非常有用。

虽然SO人员真的致力于重构一些代码。 ;)