用Ifs重构帮助

时间:2009-08-14 15:16:51

标签: refactoring .net-2.0

我一直在研究这段代码,出于某种原因,所有的if都让我疯狂了,还有一堆重复的代码。 有没有更好的方法来做到这一点?

public Program(string[] args)
    {
        try
        {
            WriteToLogFile("Starting ImportTask");
            if (args.Length == 0)
            {
                Import(DateTime.Now,DateTime.Now);
                MarkRecordsAsDeleted();
            }
            else if (args.Length == 1)
            {
                DateTime dateToImport;
                bool isValidDate = DateTime.TryParse(args[0], out dateToImport);
                if (isValidDate)
                {
                    Import(dateToImport,dateToImport);
                    MarkRecordsAsDeleted();
                }
                else
                    WriteToLogFile(String.Format("The Import date specified was invalid. - {0}", args[0]));
            }
            else if (args.Length == 2)
            {
                DateTime importStartDate;
                bool isValidStartDate = DateTime.TryParse(args[0], out importStartDate);
                DateTime importEndDate;
                bool isValidEndDate = DateTime.TryParse(args[0], out importEndDate);
                if (isValidStartDate && isValidEndDate)
                {
                    if (importStartDate > importEndDate)
                    {
                        WriteToLogFile(String.Format("Invalid date range provided. Start date = {0} End date {1}",importStartDate,importEndDate));
                        return;
                    }
                    Import(importStartDate, importEndDate);
                    MarkRecordsAsDeleted();
                }
                else
                    WriteToLogFile(String.Format("The Import date specified was invalid. - {0}", args[0]));
            }
            else
            {
                WriteToLogFile("Invalid Command Line Parameters Specified");
            }

        }
        catch (Exception ex)
        {
            WriteToLogFile("Error in Import Process = " + ex.StackTrace);
        }
    }

4 个答案:

答案 0 :(得分:5)

你在这里得到的是一个双参数函数,期望可以解析为日期的字符串。如果缺少第二个参数,则使用第一个参数;如果缺少第一个,则使用DateTime.Now。

所以,写一个两个参数的函数,它需要两个日期。叫它。有点像:

switch(args.length) {
    case 0: myFunc(DateTime.Now, DateTime.Now); break;
    case 1: myFunc(toDate(args[0]), toDate(args[0])); break;
    case 2: myFunc(toDate(args[0]), toDate(args[1])); break;
}

顺便说一下,你的功能似乎并没有提到args [1];那可能是一个错误。

答案 1 :(得分:4)

看看strategy pattern。它需要一些重要的重新分解和相当多的新类,但它应该解决你想要解决的问题。

暂时忽略这些花哨的名字,这个想法其实很简单。

您有一个抽象或接口类,它定义了一个要调用的方法。然后,您有几个派生类,您可以将if的内容移动到。

作为一个简单示例,我们可以执行以下操作:

 interface Ifoo
 {
     void myAction();
 }

 class MyCustomActionBar : Ifoo
  {
      public void myAction()
      {
          //.... details ... - Contents of single if statement.
      }
  }

 class MyCustomActionTar : Ifoo
  {
      public void myAction()
      {
          //.... details ... - Contents of next but single if statement.
      }
  }

一旦你设置了所有课程,你就可以改变你的if,如下所示。

public Program(string[] args)
{
   Ifoo _myFoo;
    try
    {
        WriteToLogFile("Starting ImportTask");
        if (args.Length == 0)
        {
            _myFoo = new MyCustomActionBar();
        }
        else if (args.Length == 1)
        {
            _myFoo = new MyCustomActionTar ();
        }
        //... etc....
        }
        else
        {
              _myFoo = new MyErrorAction(); //Definition not illustrated above
        }
        _myFoo.myAction();   //Getting your actual return values and stuff would be design details that I'm leaving out.

    }
    catch (Exception ex)
    {
         //...
    }
}

请原谅示例中的错误或拼写错误,我很快就做到了。这只是为了说明简单地介绍维基百科文章的一般想法,以提供一个快速的快照的想法..细节将更多涉及。

答案 2 :(得分:4)

这是第一遍:

public Program(string[] args)
{
    try
    {
        WriteToLogFile("Starting ImportTask");
        DateTime startTime;
        DateTime endTime;
        GetDateRange(args, out startTime, out endTime);

        Import(startTime, endTime);
        MarkRecordsAsDeleted();
    }
    catch (Exception ex)
    {
        WriteToLogFile("Error in Import Process = " + ex);
        throw;
    }
}

    private static void GetDateRange(string[] args, out DateTime startTime, out DateTime endTime)
    {
        switch (args.Length)
        {
            case 0:
                startTime = DateTime.Now;
                endTime = DateTime.Now;
                break;
            case 1:
                {
                    DateTime dateToImport;
                    var isValidDate = DateTime.TryParse(args[0], out dateToImport);
                    if (!isValidDate)
                    {
                        throw new Exception(
                            String.Format(
                                "The Import date specified was invalid. - {0}",
                                args[0]));
                    }

                    startTime = dateToImport;
                    endTime = dateToImport;
                }
                break;
            case 2:
                {
                    DateTime importStartDate;
                    bool isValidStartDate = DateTime.TryParse(args[0], out importStartDate);
                    DateTime importEndDate;
                    bool isValidEndDate = DateTime.TryParse(args[1], out importEndDate);
                    if (!isValidStartDate || !isValidEndDate)
                    {
                        throw new Exception(
                            String.Format(
                                "The Import dates specified was invalid. - {0}, {1}",
                                args[0], args[1]));
                    }

                    if (importStartDate > importEndDate)
                    {
                        throw new Exception(
                            String.Format(
                                "Invalid date range provided. Start date = {0} End date {1}",
                                importStartDate, importEndDate));
                    }

                    startTime = importStartDate;
                    endTime = importEndDate;
                }
                break;
            default:
                throw new Exception("Invalid Command Line Parameters Specified");
        }
    }

答案 3 :(得分:0)

这是我的两分钱。请注意,DateTime解析失败默认返回DateTime.Now,这很可能不是你想要的。如果是这样,只需按您的要求处理。从您的源代码中,您可以记录它并完成而不会抛出错误。根据您处理问题的方式,您可能希望在(startDate> endDate)时执行相同的操作。

以下是未经测试的代码...

public Program(string[] args)
{
    WriteToLogFile("Starting ImportTask");

    DateTime startDate = DateTime.Now;
    DateTime endDate = DateTime.Now;

    if (args.Length > 0)                    
        if (!DateTime.TryParse(args[0], out startDate)
            WriteToLogFile(string.format("Warning: StartDate argument, {0}, is invalid; value has reverted to current Date/Time.", args[0]) );

    if (args.Length > 1)
        if (!DateTime.TryParse(args[1], out endDate)
            WriteToLogFile(string.format("Warning: EndDate argument, {0}, is invalid; value has reverted to current Date/Time.", args[]) );

    if (startDate > endDate)
    {       
        WriteToLogFile(String.Format("Invalid date range provided. Start date = {0} End date {1}",importStartDate,importEndDate));
        return;
    }

    Import(startDate, endDate);
    MarkRecordsAsDeleted();
}