Oct 17, 2009

How to prevent your OO program growing a GIANT INHERITANCE TREE

Object-Oriented programming is a paradigm for software engineers to seperate a computer program into discrete and reusable units, which are called "objects". One of its technique to resue the existing source codes is through "inheritance". That is, we find a common operation among objects, then we create a "parent class" to represent this operation.

"Inheitance" is an important technique to reuse source codes. However, we find it harmful in some cases.  One of download tools in our team faces suce a problem.
The functionality of the tool is to download binary images into the flash memory of a mobile phone. Since there are a wide range of mobile phones to support, the tool contains a lot of objects. Each objects represent a download process of a specific type of mobile phones. The problem is that the download processes are just slightly different with each other. One of the reasons why they are just slightly different is due to workarounds of hardware bugs. The "slightly different" codes then result in a tall and giant inheritance tree. Inheritance, generally, is a good technique. Nevertheless, when a object has too many ancestors, the operation of the object becomes obscure. The real implementation of a virtual function may be resided in any of the ancestors. It's hard to tell which one really takes effect from the source codes.

One of my colleagues wants to resolve this problem by refactoring the existing inheritance tree into a shorter one. He designs a common downloading procedure for all kinds of mobile phones. The procedure contains many but fixed steps, and each mobile can have its own step implementation if the its step is slighlty different than other mobiles phones. I am sure that he is going to succeed to reduce the height of the tree, but I doubt that he can prevent the tree from growing higher again.

The reason why he is going to succeed is primary because all of the workarounds of previous phones are known, so he can devise a download procedure general enough to cover all of the workarounds. On the other hand, the workarounds of future phones are impossible to known. When a workaround happens, it might break the existing download procedure and require to refactor the existing codes or increase the height of the tree. He said to me that the new download procedure is so general that it's impossible to break.

I think otherwise.

In the software world, it's better to have less assumptions on your source code. The less you assume, the less you will rewrite when the assumption fails. From my point of view, it's not necessary to assume that there is a one general download process which can cover all kinds of mobiles phones. Why not just assume that the download processes of mobile phones are all different. The reason why we want to find common procedures in our codes is because we want to reuse our codes. We don't want to copy and paste the same code in every place. If we do so, the code will be very hard to maintain since we need to change the same codes in many different places.

For the download tool, it's not the case. The download tool is basically a one-time programing. We write the code for a specific mobile phone. If it works, the coding is done. There are no more maintainence effort on the code. We just need a working code to download the binary images. That's all. For most of the time, it's very dangerous to refactor the source code of the download tool, because it might break the existing code and make the download tool fail on older mobiles. To prevent such problem, we need to perform a lot of regression tests. So it's even better if we don't maintain the code and leave the working code unchanged. If we want the inheritance tree shorter, we need to refactor our existing codes, which might break them. Alternatively, if we avoid inheritance and treat each download process as a seperate script, assume different mobile phones have different download process, we can get a clear program architecture. The program will be easier to read, because the download script shows all operations and workarounds it performs. It also avoid changing the existing codes and therefore it does not require the tedious process to test all old mobile phones.

Sound great. Now, please prove I am wrong


Owen said...
This comment has been removed by the author.