2

This is a design question/discussion.

I created a solution which contains about 50 classes.

I refactored the classes and removed duplicated codes by introducing new abstract classes which contain shared information between classes so that those classes inherit from them.

E.g.

Abstract ColumnBuilder
ColumnBuilderForDepartmentReport : ColumnBuilder
ColumnBuilderForStoreReport : ColumnBuilder

No now my design contains lots of classes and duplicated codes have been removed which is a positive thing.

Is this a good design?

I've heard we should be preferring Composition over Inheritance.

How would it apply to these kind of scenarios where you want to use inheritance to remove duplicated code? Should I refactor the code to use Composition? How?

Thanks

The Light
  • 26,341
  • 62
  • 176
  • 258
  • a lot of question have been asked on this subject: http://stackoverflow.com/questions/49002/prefer-composition-over-inheritance , http://stackoverflow.com/questions/453738/inheritance-or-composition-rely-on-is-a-and-has-a .... – Heisenbug Jun 24 '11 at 11:28

3 Answers3

2

You need both as the situation requires. Composition is preferred for creating classes, but inheritance makes sense when you need an 'is-a' relationship.

In your case, this means inheritance for the unique ColumnBuilder types, which can then be used in other classes by composition (for 'has-a' relationships).

For example, a Report class that has a ColumnBuilder, which allows you to assign either of your unique classes (and any future ColumnBuilder inheritors) thanks to the composition of an inheritable class type.

kiswa
  • 14,737
  • 1
  • 21
  • 29
1

You missed out using Interfaces with Composition - this gives you the flexibility of Composition, but retains the polymorphism of inheritance.

E.g. you could define an interface: IColumnBuilder, and have all 3 classes implement this interface.

As to whether your code is designed well - cannot tell from the information provided. Lots of classes is not a bad thing - how long is a piece of string?

My rule of thumb:

1) Use inheritance when your subclass "is-a" superclass - in the example you cite they're all column builders so inheritance would be my choice. This makes it far easier to add new column builder types.

2) Use composition where all you're trying to achieve is code reuse.

3) If you're trying to get polymorphism, but rule 1 doesn't apply (no "is-a" relationship), then use composition with interfaces.

BonyT
  • 10,750
  • 5
  • 31
  • 52
  • yes, I also have used interfaces; just didn't mention it here. I think interfaces would make the "Has a relationship" (composition) possible. – The Light Jun 24 '11 at 11:44
  • Interfaces allow polymorphism. i.e. They allow you to group collections of related objects and treat them in the same way. However, because you can implement multiple interfaces in a single object, you do not have the restriction imposed by the "is-a" requirement. This means you can use interfaces AND composition - one doesn't facilitate the other, they are separate techniques that can be combined. – BonyT Jun 24 '11 at 13:53
1

I've heard we should be preferring Composition over Inheritance.

Generally good advice. But it doesn't mean you should replace them all.

If your subclasses need all of what's in the superclasses and each subclass adds small bits of function, you might be fine to stay with inheritance.

How would it apply to these kind of scenarios where you want to use inheritance to remove duplicated code? Should I refactor the code to use Composition? How?

You can also use composition to remove duplicated code.

The refactoring you're looking for is Replace Inheritance with Delegation. Googling this phrase may find you a few references with more detail than a sample diagram, but you really ought to get the book Refactoring.

Don Roby
  • 40,677
  • 6
  • 91
  • 113