Mark Needham

Thoughts on Software Development

Small step refactoring: Overload constructor

with 2 comments

I’ve previously written about some approaches that I’ve been taught with respect to taking small steps when refactoring code and another approach which a couple of colleagues have been using recently is the idea of overloading the constructor when refactoring objects.

On a couple of occasions we’ve been trying to completely change the way an object was designed and changing the current constructor would mean that we’d have to change all the tests against that object before checking if the new design was actually going to work or not.

Given a simple example where we want to change the following object to take in a completely different type and not use ‘field1′ or ‘field2′ anymore:

public class Foo
{
	public Foo(string field1, int field2)
	{
		// and so on
	}
}

One approach would be to change that constructor to take in the extra parameter and then gradually phase out the other parameters:

public class Foo
{
	public Foo(string field1, int field2, Bar bar)
	{
		// and so on
	}
}

An alternative is to create another constructor and leave the old one as it is before changing the tests one by one to make use of the new approach.

public class Foo
{
	public Foo(string field1, int field2)
	{
		// we gradually phase this one out
	}
 
	public(Bar bar)
	{
		// the new constructor
	}
}

Even if we want to still use ‘field1′ and ‘field2′ we can still make use of this approach and just default the extra value until we’ve migrated our tests across.

public class Foo
{
	public Foo(string field1, int field2, Bar bar)
	{
		// and so on
	}
 
	public Foo(string field1, int field2) : this(field1, field2, new Bar())
	{
	}
}

I quite like this approach as it allows us to keep the code compiling while we’re making changes to it to improve the design.

The main thing to remember with this approach is not to keep the old approach around for too long and to make sure we move our code across to use the new approach as quickly as possible otherwise it can become very confusing for other pairs which come across the code in this half way state.

Be Sociable, Share!

Written by Mark Needham

April 25th, 2010 at 10:48 pm

  • http://blogs.ugidotnet.org/luKa/ Luca Minudel

    imho this can be also an example of Latent Code Pattern. You can add a new user feature: gradually make changes to the code and put new code under tests and even in production before the new user feature is completed and accessible to the users.

    in this case the new feature could be a new parameter (bar) added to a simulation model Foo where initially instead of that parameter it was simply a constant value (with the same value of new Bar()).

    before all the required changes are completed (e.g. required changes in the DB and in the GUI) with this technique you can put in use, under test and in production the new code of the new simulation model that will behave like the old one because is using the constant new Bar() every time when called from the old code that know only about field1 and field2.

  • Pingback: Incremental Refactoring: Create factory method at Mark Needham