Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Refactoring long if - else if - else with common objects

I'm looking for a way to refactor a log if/else if/else statement that also has a bit of nesting. The blocks also use quite a few common objects. My aim is to break the code apart to manageable units extracted to different classes and make it pluggable in case I need to cover a new condition.

Here's some dummy code to illustrate:

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 ...)
    }

I read a bunch of articles/SO posts of various patterns/practices that may apply, but the code's dependencies complicate it a bit for me to apply the concepts. It doesn't help that I've been looking at the code somewhat too closely for a while now so it's hard to break out from micro-managing to a birds eye view.

like image 353
romeozor Avatar asked Feb 03 '14 21:02

romeozor


People also ask

How do you refactor multiple if statements?

So, how do you refactor multiple nested if statements? The easiest possible way is to use guard clauses. A guard clause is an if statement that checks for a condition and favors early exit from the current method. If the condition is satisfied, the if block returns from the method.

How would you refactor your code to remove if conditions?

The process to refactor this hot piece of mess, is as following: Extract each branch into separate strategy classes with a common interface. Dynamically find all classes implementing the common interface. Decide which strategy to execute based on input.


1 Answers

You could break the large scope blocks into separate functions.

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

There is also interitance, where you would create candy classes and encapsulate behavior:

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

Then your code would be:

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

Of course you will need to standardize parameters and such, but you get the idea.

Read the book Clean Code, it has a lot of great ideas on how to refactor. http://www.amazon.com/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882

like image 60
Patrick Huber Avatar answered Sep 27 '22 23:09

Patrick Huber