On of the highly debatable problems that we come across as programmers is the classical inheritance vs composition problem. It haunts us as we try to figure out how to group duplicate code across multiple classes, and today the rant shall be about that.
A language like Java uses the keyword “extends” to indicate inheritance. I love that, because it helps the code become more readable, and it becomes clear to any programmer what our class’s relationship is to its superclass.
From there, you just have to keep in mind that when you design your class hierarchies that any superclass within that hierarchy will impose itself as an “alias” to the subclass… I don’t think that was clear, so let’s see an example:
Let’s say we are designing a “View Controller” hierarchy. In
UIKit, the developers decided to go with
ViewController, then under that comes
TableViewController, … etc. Notice that
TableViewController can still be called a
ViewController, so we say that
ViewController is just an abstract alias of
Notice also how this imposes the type of hierarchy we have here. We are essentially making a controllers hierarchy based on the type of view they have. This isn’t a must, it’s just how developers of
AppKit decided to go.
That’s all nice and dandy.. The trouble starts creeping in when the developers want to extend these classes to provide their application-specific hierarchies.
So, in the problem I am having, we have a bunch of
ViewControllers that are related to the login process. The duplicate code that we want to eliminate is related to the HUD loading indicator that we show when the authentication process starts, and then removing it when the authentication is complete.
The code I came across made the obvious approach of defining a
LoginViewController superclass, and extended that class in the different login service (facebook, twitter, email). The only problem here is that some of the classes are
TableViewController while others are not! So, if they all inherit from
LoginViewController, they either all have to be
TableViewController or plain
ViewController, depending on what
LoginViewController derives from…
Now, we reach the composite approach. In the problem described above, we simply inherit from
ViewController in each of the login classes depending on the use case. This hierarchy matches what we see in
UIKit so it is the best approach. How about the duplicate HUD code?
We simply have to define a new class, call it
AuthHUDController. That class will then be instantiated in those classes in a single line of code, then some customization can be made to it per use case, giving us more flexibility.
Ideally, we would want to eliminate all duplicate code, including the instantiation of the
AuthHUDController, but doing that without ending up with a weird and implicit implementation (using AOP or similar) is very tricky, and would probably be best avoided.
There is actually another composite solution, and that is to make
LoginViewController a subclass of
ViewController, then in the classes that were deriving from
TableViewController we move the table view code to a new class, and make that a composite in the old class.
In any case, it’s both using the beauty of composition.
The problem ends up not being that difficult if we realized the above definitions and sticked to them!