Monday, June 20, 2011

Resharper series – Replacing constructors with creation methods

Replacing your constructors with creational methods or static factories helps to reduce cumbersome code with multiple overloaded constructors in the class and clients having confusion which one to invoke and how. The overloaded constructors in your code creates confusion in the mind of a fellow programmer when he wants to create a new instance of the object, the main problem with these constructors are that they cannot be renamed to give a meaningful name. One of the easiest ways to address this problem is to use creation methods or static factories.
Creation methods have better readability and by having meaningful names so that the consumer gets a clear idea of each method and when to use them. Let's see how we can use refactoring to remove overloaded constructors in the code and replace them with creation methods.
  • As a first step of refactoring find the client code that calls the constructor to create an instance of the type.

[TestMethod]
public void AllDucksCanSwimTest()
{
    var pool = new Pool(_ducks);
    Assert.IsTrue(pool.CanAllDucksSwim());
}

  • In the above test method I have a constructor for instantiating the Pool object, which we can refactor to create a new creation method.

  • Use the Extract method refactoring to create a new static method to get the Pool instance

  • Now use the Move to another Type refactoring to move the method to the Pool class.



public class Pool
{
    private readonly IList<Duck> _ducks;

    public Pool(IList<Duck> ducks)
    {
        _ducks = ducks;
    }

    public static Pool GetPool(List<Duck> ducks)
    {
        return new Pool(ducks);
    }

    public bool CanAllDucksSwim()
    {
        foreach (var duck in _ducks)
        {
            duck.Swim();
        }
        return true;
    }

    public bool CanAllDucksQuack()
    {
        foreach (var duck in _ducks)
        {
            duck.Quack();
        }
        return true;
    }
}

public class Pool
{
    private readonly IList<Duck> _ducks;

    Pool(IList<Duck> ducks)
    {
        _ducks = ducks;
    }

    public static Pool GetPool(List<Duck> ducks)
    {
        return new Pool(ducks);
    }

    public bool CanAllDucksSwim()
    {
        foreach (var duck in _ducks)
        {
            duck.Swim();
        }
        return true;
    }

    public bool CanAllDucksQuack()
    {
        foreach (var duck in _ducks)
        {
            duck.Quack();
        }
        return true;
    }
}

  • Compile the code and make sure that it builds successfully.

2 comments:

Anonymous said...

Don't you think that creating xx different methods to create object is worse than multiple constructors with summary description? In my opinion it is easier and more natural to check overloaded constructors than to look for some other method (i didnt write your code, i dont know which functions should i use to create object in particular situatuin, so i have to check them all...)

Prajeesh said...

Hi,
During development, if we have multiple overloaded constructors on a class it is hard to decide
which constructor to call while initializing the object.

Replacing the constructors with intention-revealing creation Methods can avoid this confusion.