Refactoring hierarchy construction

In this article I’d like do talk about refactoring of construction of hierarchy and high cohesion pattern.

Imagine you’ve got a big enough hierarchy of objects in your system. On the top of this hierarchy there is an abstract base class or skeletal implementation of some interface(s).

While system evolves the more and more concrete implementations are getting involved.

Each implementation extends functionality of base class and requires additional data for its creation and/or initialization.

Lets see the picture:

Hierarchy overview

Hierarchy overview

As you can see we’ve got IBase interface on the top of the hierarchy. This interface announces foo() method.

AbstractBase class introduces 2 protected fields and provides skeletal implementation for IBase interface.

ConcreteClassN where N is 1,2…5 are concrete implementations of IBase interface through AbstractBase class.

As you can see each concrete implementation introduces new functionality and requires additional data fields as well. Here is the defenition of AbstractBase:

public abstract class AbstractBase implements IBase {

    protected AbstractBase(Object field1, Object field2) {

	this.field1 = field1;
	this.field2 = field2;

	if (!validateFields())
	    throw new IllegalArgumentException(
		    "Invalid fields passed to constructor");
    }

    @Override
    public void foo2() {
	// dowork
    }

    protected boolean validateFields() {

	// ...
	// do validation of field1 and field2

	return true;
    }

    protected Object field1;
    protected Object field2;
}

Now we can sublass AbstractBase and implement foo(). If needed we can override validateFields() in concrete implementations in order to validate additional data fields:

public class ConcreteClass2 extends AbstractBase {

    protected ConcreteClass2(Object field1, Object field2, Object field5,
	    Object field6) {
	super(field1, field2);

	this.field5 = field5;
	this.field6 = field6;

	if (!validateFields())
	    throw new IllegalArgumentException(
		    "Failed to validate fields including field3 and field4");
    }

    @Override
    public void foo() {
	// ...
	// provide concrete implementation of foo() here
    }

    @Override
    protected boolean validateFields() {
	boolean result = false;

	if (super.validateFields()) {
	    // ...
	    // validate field3 and field4 here
	    result = true;
	}

	return result;
    }

    protected Object field5;
    protected Object field6;
}

As you can see ConcreteClass2 class introduces two additional fields: field5 and field6. It also overrides validateFields() and provides concrete implementation of foo() method.

Finally lets take a look at ConcreteClass6 implementation:

public class ConcreteClass6 extends ConcreteClass2 {

    protected ConcreteClass6(Object field1, Object field2,
	    Object field5, Object field6, String str1, String str2) {
	super(field1, field2, field5, field6);

	this.stringField1 = str1;
	this.stringField2 = str2;
    }

    @Override
    public void foo() {
	// ...
	// implement custom foo() here
    }

    @Override
    protected boolean validateFields() {
	boolean result = false;

	if (super.validateFields()) {
	    // ...
	    // validate stringField1 and stringField2 here
	}

	return result;
    }

    String stringField1;
    String stringField2;
}

ConcreteClass6 again introduces 2 new fields stringField1 and stringField2, overrides foo() and validateFields().

I hope you’ve got the first point – constructors in our hierarchy are the nightmare:

    protected AbstractBase(Object field1, Object field2) {

and

    protected ConcreteClass2(Object field1, Object field2, Object field5,
	    Object field6) {

and

    protected ConcreteClass6(Object field1, Object field2,
	    Object field5, Object field6, String str1, String str2) {

and so on…

I’m also pleased that you’ve pointed out to the solution. Yes, we should use introduce parameter object pattern here.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: