重构if if - else if - else with common objects

时间:2014-02-03 21:03:21

标签: c# design-patterns

我正在寻找一种重构日志的方法,如果/ else if / else语句也有一些嵌套。这些块也使用了很多常见的对象。我的目标是将代码分解为提取到不同类的可管理单元,并使其可插拔以防我需要覆盖新条件。

这里有一些虚拟代码来说明:

List<ValidationResult> validationResults = new ...;
Inspector inspector = commonInspector;
bool additionalOp = commonFlag;
HashSet<Thing> thingsToCheck = theThings;
foreach (var thing in thingsToCheck)
{
    if (IsCandy(thing) && thing.IsWrapped && thing.IsHard)
    {
        var inspected = inspector.Inspect(thing.Value);
        if (inspected != thing.Value)
        {
            validationResults.Add(new ...);
            if (additionalOp)
            {
                thing.Taste();
            }
        }
    }
    else if (IsChocolate(thing))
    {
        var sweet = (Sweet)thing;
        List<BadCalories> badCalories;
        while (var calorie in sweet.Calories)
        {
            if (calorie.IsGood)
                continue;
            badCalories.Add(calorie);
        }

        foreach (var badCal in badCalories)
        {
            var inspected = inspector.Inspect(badCal.Value);
            if (inspected != badCal.Value)
            {
                validationResults.Add(new ...);
                if (additionalOp)
                {
                    badCal.Taste();
                }
            }
        }
    }
    else
    {
        if(thing ...)
        else if (thing ...)
    }

我阅读了一些文章/可能适用的各种模式/实践的帖子,但代码的依赖关系使我对应用概念有点复杂。一段时间以来我一直在密切关注代码并没有帮助,所以很难从微观管理中突破到鸟类视角。

4 个答案:

答案 0 :(得分:6)

您可以将大范围块分解为单独的函数。

if(IsHardWrappedCandy(thing))
  ValidateHardWrappedCandy(thing);
else if (IsChocolateCandy(thing))
  ValidateChocolateCandy(thing);

还有interitance,您可以在其中创建糖果类并封装行为:

public abstract class CandyBase
{
    public abstract void Validate();
}
public class HardWrappedCandy : CandyBase
{
  public override void Validate()
  {
     // TODO: Validation logic
  }
}

然后你的代码将是:

foreach(var candy in candies)
   candy.Validate();

当然你需要标准化参数等,但你明白了。

阅读“清洁代码”一书,它有很多关于如何重构的好主意。 http://www.amazon.com/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882

答案 1 :(得分:0)

您应该为所有“事物”创建一个界面,声明必须执行的各种检查。

然后你的“东西”必须实现所说的界面,这样你就可以调用支票而不用担心实际的实现类型是什么。

//Interface
public interface ICheck
{
    bool Check1();
}

//Class
public Chocolate : ICheck
{
   public bool Check1()
   {
      //logic goes here
   }
}

干杯

答案 2 :(得分:0)

您似乎正在尝试将常见信息从thing传递到inspector。为此,您需要以下方法:

  1. 检索要检查的对象
  2. 检查他们
  3. 所以我们定义两个接口:

    可用于检查物体的物品。

    interface IInspectable
    {
        string Value { get; }
        void Taste();
        // And any other methods that need to be called while inspecting
    }
    

    和另一个可用于检索必须检查的thing中的所有对象。

    interface IThing
    {
        IEnumerable<IInspectable> GetStuffForInspection();
    }
    
    从那里开始,我们可以实现我们的类

    class Candy : IThing, IInspectable
    {
        public IEnumerable<IInspectable> GetStuffForInspection()
        {
            if (IsWrapped && IsHard)
                yield return this;
        }
    
        public String Value { ... }
        public void Taste() { ... }
    }
    
    class Chocolate : Sweet, IThing
    {
        public IEnumerable<IInspectable> GetStuffForInspection()
        {
            Calories.Where(c => !c.IsGood);
        }
    }
    
    class Calorie : IInspectable
    {
        public String Value { ... }
        public void Taste() { ... }
    }
    

    允许您删除所有if语句

    foreach (var thing in thingsToCheck)
    {
        foreach (var inspectable in thing.GetStuffForInspection())
        {
            var inspected = inspector.Inspect(inspectable.Value);
            if (inspected != inspectable.Value)
            {
                validationResults.Add(new ...);
                if (additionalOp)
                {
                    inspectable.Taste();
                }
            }
        }
    }
    

答案 3 :(得分:0)

这是战略模式的用途。

http://www.oodesign.com/strategy-pattern.html

您可以这样做:

List<ValidationResult> validationResults = new ...;
Inspector inspector = commonInspector;
bool additionalOp = commonFlag;
HashSet<IThing> thingsToCheck = theThings;
foreach (IThing thing in thingsToCheck)
{
    thing.Validate(inspector);
}

...

public interface IThing
{
    void Validate(Inspector inspector, ...);
}

public abstract CandyBase : IThing
{
    public abstract void Validate(Inspector inspector);
}

public HardWrappedCandy : CandyBase
{
    public override void Validate(Inspector inspector)
    {
         // HardWrappedCandy validation logic here
         var inspected = inspector.Inspect(this);
         ...
    }
}

public Chocolate : IThing
{
    public void Validate(Inspector inspector)
    {
        // Chocolate validation logic here...
    }
}

public SomethingElseInTheFuture: IThing
{
    public void Validate(Inspector inspector)
    {
        // SomethingElseInTheFuture validation logic here...
    }
}