Inheritance easily grows out of control

Interface inheritance is good.

Inheritance
Parts of your behavior are inherited from your parents. That is  “interface” inheritance. The interface of your parents defines the part of your behavior. Just like yours defines the parts of the behavior of your children.

Update

Just stumbled upon this excellent and succinct short text on how not to use inheritance. In C++ in particular, and I am adding: in general.

The purpose of inheritance in C++ is to express interface compliance (subtyping), not to get code reuse.

That text is also about differences v.s. the Objective-C, but it is priceless if and when you spot the growth of the weed of C++ inheritance.

Original post

I always have bright ideas in the morning. This morning I thought of ATL. And its usage of templates and inheritance. I figured it is a typical inheritance for the implementation cases. Which is bad.

Inheritance of interfaces is an implementation of the ‘behavior extension’ concept. Which is good. Interface inheritance is used to re-use the behavior of the base interface. Just the behavior. The interface is completely decoupled from the class which implements it. Very good indeed. And surprisingly absent from some key OO designs and implementations in widespread use today.

W3C DOM objects are a typical example of bad inheritance. In DOM every object has properties and methods of an invisible root DOM object. So we have dozens or more, methods and properties, on each and every DOM object. Regardless of its required behavior. Same on each and every DOM object. This is in many cases, much, much more than we need on a particular object. Example :

DOM element “XML” is represented with a DOM object which has all the visual properties and methods as (for example) DIV element has. And they are mostly totally unusable and are seriously getting in the way, especially when you are new to the DOM scripting/programming, and its zillions of objects, methods, events, and properties. A sure recipe for making many mistakes and introducing bugs.

Another example of evil inheritance is MFC. A naive, single rooted, and elaborate hierarchy of classes (not interfaces), which makes for an sea of very heavy classes with hundreds of methods and those crazy “Hungarian notation” named variables. While working in your favorite IDE they are ALL there even if you do not need them and do not have a clue what are they all for. Again, a sure sign you are bound to make bugs. If you use MFC, that is.

Information Hiding

That is the KEY problem with a class inheritance: information overflow. A total opposite of the first law of OO: Information must be hidden as much as possible. So-called ‘information hiding’. A foundation cornerstone of OO. Sadly broken by the likes of MFC, DOM ….. and somewhat by ATL.

Yes, I like ATL because it uses C++ to the full and shows (same as ISO C++ std lib) very clearly, why C++ is very elegant and complete. Of course, if you know how to make it be that way.

Sadly, the ATL team, I suppose under the dark and large shadow of MFC, adopted the class inheritance approach, too. Although much better variety than MFC. But (sadly) ATL classes, at the end of the day, inherit from template instances which are nothing else but classes, again. Only the code looks more snazzy.

ATL implementation inheritance pattern is this (deliberately simplistic but still canonical code) :

Ok, some of you might have recognized this as a so-called “Curiously Recurring Template Pattern”. But this is basically the “inheritance for implementation” idiom. Looks pretty snazzy, does it not?

Well, the first problem (with any kind of inheritance) shows particularly in modern IDE’s. Imagine now that Base has many methods. You want to use only one. But, in the IDE, all the others are immediately and readily available and very close. Too close for comfort. Your IDE and its VS editor IntelliSense will show ALL of them. Many of them. But you need only one. Found it yet? And this is just for a single class inherited.

To make matter worse, in MFC and ATL you inherit several classes. And each one has many methods and properties. And they are all available to you at the same time. Providing all the methods visible from all o them all the time; through the IntelliSense feature. A lot of them. And still, you want only one. All of this is directly opposite of the key postulate of the OO: information hiding. Much better and dare I say proper way is this:

This concept is called Delegation. We delegate the job to the instance of the  Log_Service. Delegation gives total encapsulation of App2 and its implementation. A template instance Log_Service<App2> is now totally hidden. Information hiding is achieved: Users of App2 do not know what doesLog_Service<App2> do internally. They just use it. They are even unaware of its existence. This also means that replacing Log_Service<App2> with e.g. Rest_Log_Service<App2>  is completely painless. Provided they both have the same interface. This does not break existing App2 usage in any way. Clients of App2 are completely isolated from this change.

Of course, both Log_Service<App2> and Rest_Log_Service<App2> have both to conform to the same, clean and simple and narrow interface.  Just like every other class should. Narrow interface? Ok, this is another key concept. I shall stop here, this is all that I thought off, this morning …

DBJ