Tuesday, June 28, 2011

Resharper series - Extracting factory classes

You may have come across code that creates a new instance of an object and setting it to a default state before working on it. Sometimes however the creation requirements of this object may grow and clouds the original code that was used to create the object. This is where a Factory class comes into play. For e.g. have a look into the below given test cases and classes.

[TestMethod]
public void ZoomLensesCanHaveMacroModeAlso()
{
    const string lensDescription = "Canon EF-S 55-250mm f/4.0-5.6 IS Telephoto Zoom Lens";
    var zoomLens = new ZoomLens(lensDescription);

    zoomLens.SetCloseupConversion(true);
    Assert.IsTrue(zoomLens.HasMacroMode());
}

[TestMethod]
public void WideAngleLensesHaveUltraWideView()
{
    const string lensDesription = "Canon EF 35mm f/2 Wide Angle Lens";
    var wideAngleLens = new WideAngleLens(lensDesription);

    wideAngleLens.SetUltraWideView(true);
    Assert.IsTrue(wideAngleLens.HasUltraWideView());
}

The classes used in the sample are as given below.
public class ZoomLens
{
    private readonly string _lensDescription;
    private bool _closeUpConversionEnabled;

    public ZoomLens(string lensDescription)
    {
        _lensDescription = lensDescription;
        _closeUpConversionEnabled = false;
    }

    public void SetCloseupConversion(bool closeUpConversion)
    {
        _closeUpConversionEnabled = closeUpConversion;
    }

    public bool HasMacroMode()
    {
        return _closeUpConversionEnabled;
    }
}

public class WideAngleLens
{
    private readonly string _lensDesription;
    private bool _enableUltraWideView;

    public WideAngleLens(string lensDesription)
    {
        _lensDesription = lensDesription;
        _enableUltraWideView = false;
    }

    public void SetUltraWideView(bool enableUltraWideView)
    {
        _enableUltraWideView = enableUltraWideView;
    }

    public bool HasUltraWideView()
    {
        return _enableUltraWideView;
    }
}

As you can see from the classes used in the sample, I can implement a class hierarchy by creating a superclass or an interface for the camera lenses and move the common methods to that type and make the subclasses implement/ inherit the superclass. This provides the situation for usage of a Factory method that makes it easy for programmers to extend the functionality of the framework by introducing polymorphic creations of objects.
First we need to extract all common methods and properties of these classes to a common base class. I have used the Extract Superclass refactoring to create a superclass for the classes in this sample.



After extracting the superclass, we need to create the constructor for the base class with the common properties.
public class CameraLens
{
    protected string _lensDesription;

    public CameraLens(string lensDescription)
    {
        _lensDesription = lensDescription;
    }
}

Refactor the base class to use this constructor during object creation.
public WideAngleLens(string lensDesription) : base(lensDesription)
{
    _enableUltraWideView = false;
}

Use the Pull members refactoring to move the methods as abstract to the parent class.



Repeat the steps for other inheriting classes also. Compile and run the test cases.
Next use the Extract Method refactoring to move the creation logic to creation methods in the test cases.

After applying the refactoring pattern the code looks like
public void ZoomLensesCanHaveMacroModeAlso()
{
    const string lensDescription = "Canon EF-S 55-250mm f/4.0-5.6 IS Telephoto Zoom Lens";
    CameraLens zoomLens = CreateCameraLens(lensDescription);

    zoomLens.SetCloseupConversion(true);
    Assert.IsTrue(zoomLens.HasMacroMode());
}

private static CameraLens CreateCameraLens(string lensDescription)
{
    return new ZoomLens(lensDescription);
}

Use the Move to another type refactoring pattern and specify the name of the new class in the type as given below

Make the Create method non- static and use the Extract Interface refactoring as given below.
Now you can use this interface as a dependency for your client classes that needs to create the Camera lenses or change the test cases as given below
private ICameraLensFactory _zoomCameraLensFactory;

[TestInitialize]
public void Initialize()
{
    _zoomCameraLensFactory = new ZoomCameraLensFactory();
}

[TestMethod]
public void ZoomLensesCanHaveMacroModeAlso()
{
    const string lensDescription = "Canon EF-S 55-250mm f/4.0-5.6 IS Telephoto Zoom Lens";
    var zoomLens = _zoomCameraLensFactory.CreateCameraLens(lensDescription);

    zoomLens.SetCloseupConversion(true);
    Assert.IsTrue(zoomLens.HasMacroMode());
}


Wednesday, June 22, 2011

Resharper series - Replacing state altering conditionals with state pattern

If your code has some complex state altering conditional logic, you can refactor that code to use a State pattern implementation by replacing the type code with subclasses. For e.g the Order class given below has the OrderState implemented as a string. The state of the class is changed on some conditional logic.
public class Order
{
    private const string NEW = "New";
    private const string SUBMITTED = "Submitted";
    private const string APPROVED = "Approved";
    private const string INPROGRESS = "InProcess";
    private const string COMPLETED = "Completed";

    private string _orderState;

    public Order()
    {
        _orderState = NEW;
    }

    public string GetState()
    {
        return _orderState;
    }

    public void Submitted()
    {
        if(_orderState.Equals(NEW)) _orderState = SUBMITTED;
    }

    public void Approved()
    {
        if(_orderState.Equals(SUBMITTED)) _orderState = APPROVED;
    }

    public void Processing()
    {
        if(_orderState.Equals(APPROVED)) _orderState = INPROGRESS;
    }

    public void Completed()
    {
        if(_orderState.Equals(INPROGRESS)) _orderState = COMPLETED;
    }
}

We can refactor this to State pattern to have States implemented as classes.
First step of refactoring involves changing OrderState to a type-safe entity by making it a class rather than having it as string instances. We use the Encapsulate fields refactoring pattern to encapsulate the _orderState variable.




After encapsulating fields for _orderState the code now looks as.
public void Submitted()
{
    if(GetOrderState.Equals(NEW)) SetOrderState = SUBMITTED;
}

public void Approved()
{
    if(GetOrderState.Equals(SUBMITTED)) SetOrderState = APPROVED;
}

public void Processing()
{
    if(GetOrderState.Equals(APPROVED)) SetOrderState = INPROGRESS;
}

public void Completed()
{
    if(GetOrderState.Equals(INPROGRESS)) SetOrderState = COMPLETED;
}

Next we create new classes for the OrderState hierarchy and use that instead of the strings an use the Extract superclass pattern to create a superclass OrderState for these classes.





public class NewOrder : OrderState
{
}

Next we need to change the _orderStatus type to OrderState in the Order class from string. First we apply the Extract method pattern to the const string values as given below




After extract method is applied, we need to change the signature of these methods to use the OrderState instead of string. The Change Signature refactoring can be used to do this.





After applying these refactoring the code looks like
private static readonly OrderState NEW = GetNewStatus();

private static OrderState GetNewStatus()
{
    return new NewOrder();
}

Do the same for other states also            
The final version of our Order class now looks like.
public class Order
{
    private static readonly OrderState NEW = GetNewStatus();

    private static OrderState GetNewStatus()
    {
        return new NewOrder();
    }

    private static readonly OrderState SUBMITTED = GetSubmittedStatus();

    private static OrderState GetSubmittedStatus()
    {
        return new SubmittedOrder();
    }

    private static readonly OrderState APPROVED = GetApprovedState();

    private static OrderState GetApprovedState()
    {
        return new ApprovedOrder();
    }

    private static readonly OrderState INPROGRESS = GetInProgressState();

    private static OrderState GetInProgressState()
    {
        return new InProgressOrder();
    }

    private static readonly OrderState COMPLETED = GetCompletedState();

    private static OrderState GetCompletedState()
    {
        return new CompletedOrder();
    }

    private OrderState _orderState;

    public Order()
    {
        SetOrderState = NEW;
    }

    public OrderState GetOrderState
    {
        get { return _orderState; }
    }

    public OrderState SetOrderState
    {
        set { _orderState = value; }
    }

    public OrderState GetState()
    {
        return GetOrderState;
    }

    public void Submitted()
    {
        if(GetOrderState.Equals(NEW)) SetOrderState = SUBMITTED;
    }

    public void Approved()
    {
        if(GetOrderState.Equals(SUBMITTED)) SetOrderState = APPROVED;
    }

    public void Processing()
    {
        if(GetOrderState.Equals(APPROVED)) SetOrderState = INPROGRESS;
    }

    public void Completed()
    {
        if(GetOrderState.Equals(INPROGRESS)) SetOrderState = COMPLETED;
    }
}


Tuesday, June 21, 2011

Resharper series - Replacing conditional logic with strategies


When you have a method with lots of conditional logic (i.e., if statements), you're asking for trouble. Conditional logic is notoriously difficult to manage, and may cause you to create an entire state machine inside a single method. In such a situation, it is better to move each algorithm variation to new classes or to subclasses of the host class. The ideal solution would be to replace these conditional statements with a strategy implementation and delegate the execution to the concrete strategy implementations.
For e.g consider the test code and Calculator implementation given below. The execute methods runs a different algorithm based on the operator chosen.
[TestMethod()]
public void ExecuteMethodShouldCalculateTheSumIfOperationSelectedIsAddition()
{
    var calculator = new Calculator();
    calculator.SetOperation(Operator.Add);
    var result = calculator.Execute(3, 5);
    Assert.IsTrue(result == 8);
}

[TestMethod]
public void ExecuteMethodShouldCalculateTheDifferenceIfOperationSelectedIsSubtraction()
{
    var calculator = new Calculator();
    calculator.SetOperation(Operator.Subtract);
    var result = calculator.Execute(3, 5);
    Assert.IsTrue(result == -2);
}

[TestMethod]
public void ExecuteMethodShouldCalculateTheMultipledResultIfOperationSelectedIsMultiplication()
{
    var calculator = new Calculator();
    calculator.SetOperation(Operator.Multiply);
    var result = calculator.Execute(3, 5);
    Assert.IsTrue(result == 15);
}

[TestMethod]
public void ExecuteMethodShouldCalculateTheDivisionResultIfOperationSelectedIsDivision()
{
    var calculator = new Calculator();
    calculator.SetOperation(Operator.Divide);
    var result = calculator.Execute(15, 5);
    Assert.IsTrue(result == 3);
}

public class Calculator
{
    private Operator _operator;

    public void SetOperation(Operator operation)
    {
        this._operator = operation;
    }

    public int Execute(int firstArgument, int secondArgument)
    {
        if(_operator == Operator.Add)
            return firstArgument + secondArgument;
        if (_operator == Operator.Subtract)
            return firstArgument - secondArgument;
        if(_operator == Operator.Multiply)
            return firstArgument * secondArgument;
        if (_operator == Operator.Divide)
        {
            if (secondArgument != 0)
                return firstArgument / secondArgument;
            else
                throw new ArgumentException("Divider cannot be zero");
        }
        return 0;
    }
}

public enum Operator
{
    Add,
    Subtract,
    Multiply,
    Divide
}
  • As a first step to refactoring this code, we use the Extract Method to extract the logic to separate methods as given below.


  • Once you have completed all the extractions the code now looks like.

public int Execute(int firstArgument, int secondArgument)
{
    if(_operator == Operator.Add)
        return PerformAdd(firstArgument, secondArgument);
    if (_operator == Operator.Subtract)
        return PerformSubtraction(firstArgument, secondArgument);
    if(_operator == Operator.Multiply)
        return PerformMultiplication(firstArgument, secondArgument);
    if (_operator == Operator.Divide)
        return PerformDivision(firstArgument, secondArgument);
    return 0;
}

private int PerformDivision(int firstArgument, int secondArgument)
{
    if (secondArgument != 0)
        return firstArgument / secondArgument;
    else
        throw new ArgumentException("Divider cannot be zero");
}

private int PerformMultiplication(int firstArgument, int secondArgument)
{
    return firstArgument * secondArgument;
}

private int PerformSubtraction(int firstArgument, int secondArgument)
{
    return firstArgument - secondArgument;
}

private int PerformAdd(int firstArgument, int secondArgument)
{
    return firstArgument + secondArgument;
}

  • Next we use the ‘Move to another type’ refactoring to move these methods to separate classes, which we’ll make as concrete strategy implementations later.



  • After this refactoring your code looks like

public class Calculator
{
    private Operator _operator;

    public void SetOperation(Operator operation)
    {
        this._operator = operation;
    }

    public int Execute(int firstArgument, int secondArgument)
    {
        if(_operator == Operator.Add)
            return AdditionStrategy.PerformAdd(firstArgument, secondArgument);
        if (_operator == Operator.Subtract)
            return SubtractionStrategy.PerformSubtraction(firstArgument, secondArgument);
        if(_operator == Operator.Multiply)
            return MultiplicationStrategy.PerformMultiplication(firstArgument, secondArgument);
        if (_operator == Operator.Divide)
            return DivisionStrategy.PerformDivision(firstArgument, secondArgument);
        return 0;
    }
}

  • Use the ‘Rename’ refactoring to change the name of PerformAdd, PerformSubtraction.. methods to Execute.

  • After renaming we’ll use the ‘Extract Superclass’ refactoring to create a superclass for these Strategies.


  • Now create an abstract method Execute with the same signature as in the base classes in the newly created superclass.
  • Use the resharper intellisense to make the superclass abstract.

  • Now move to the subclasses and make the execute method override, using the resharper menu.

  • Finally create a new Factory implementation to create concrete instances for these strategies based on the parameter passed and use this in the Calculator class as given below.

public int Execute(int firstArgument, int secondArgument)
{
    var operationStrategyFactory = new OperationStrategyFactory(_operator);
    var operationStrategy = operationStrategyFactory.Create();
    return operationStrategy.Execute(firstArgument, secondArgument);
}