This week I want to discuss another bullet from my code review checklist.
Consider delegation over inheritance. I have had some pretty heated debates on this topic in the past and I will even take it a step further and say the rule should state that we should favor delegation over inheritance. Let’s consider the following classic (and intuitive) person/student/teacher example. A class diagram might look something like this
Person is our base class; Teacher and student derive from person. We can say that a student Is A person and that a Teacher Is A person.
The up-side of this design is it is simple, intuitive, and it will perform well. The down side of this approach is that there is a tight coupling between the derived classes and the base class, we are breaking encapsulation by making the functionality of the derived class dependent on the functionality in the base class, and we may even break encapsulation on our Person class by using protected or public access modifiers where we normally wouldn’t do so.
The problem with breaking encapsulation is that making a change to one class (our base class) can cause unintended changes in other consuming classes (our derived classes). I can’t begin to tell you how many times I have seen a seemingly small change to a base class break huge pieces of an application.
Now let’s consider using delegation rather than inheritance. We will change our class diagram to look like the following:
We can say a teacher Has A person and similarly student Has A person.
The down-side of this design is that we have to write more code to create and manage the person class and thus the code will not perform as well (though in most cases I suspect the performance hit is negligible). We also cannot use polymorphism - we cannot treat a student as a person and we cannot treat a teacher as a person. The up-side of this design is that we can decrease coupling by defining a person interface and using the interface as the return type for our Person property rather than the concrete Person class, and our design is more robust. When we use delegation we can have a single instance of a person act as both a student and a teacher. Try that in C# using the inheritance design!