Class hierarchies are bad and other useful tips
What? You are saying that class hierarchies aren’t bad? Well, sometimes, you are right, they are not. Most of the time, however, they are. This is because developers using OOP tend to think in hierarchies, i.e. to find ways to fit all of the code they need to write into one or more set of classes. This means that they do not think in terms of the code they are writing right now, instead they try to anticipate what they will need, often with less-than-remarkable results. That is not to say that you will always be in a position where it’s unclear what will be happening next. Sometimes, you know you will be using different classes in a hierarchy even though that doesn’t exist yet. Let’s make a couple of examples so that you have a better idea about what I am saying.
Suppose you are requested to receive input from a hardware device through RS232: it is as clear as the sky that in the future you may need to have other devices, too, so it does make sense to build a base receiving class with a virtual, empty handler to inherit in the actual class.
Conversely, imagine you receive a request to add two dialogs to an application: unless those dialogs behave in a similar way, there is no reason to have a common ancestor. Lots of developers, however, will do just that, for no good reason: “because I have received a request for two new dialogs, they must be somehow related, so let’s make them inherit from the same ancestor”. Bollocks. Just make them separate already.
The other big problem lots of devs have with classes is that they don’t think long enough about their design, which will lead to creating monsters that are confusing to use, read and maintain.
Example: many years ago, before touch screens were cool, I was tasked with doing a kiosk application. One of its features commanded that it had to allow advertising on the four sides of the screen with rotating ads which could be of any kind. When this is the description you receive, your first instinct is to inherit a visual control which will own a list of files and will display them one by one. Sounds fair enough, right? It does, until you realise that your surface does not change, only your files do. So why inherit from a visual control and constrain the class to that? It makes no sense in the grand scheme of things. Besides, what if the surface has to change for some reason? Thus, you are better off decoupling the actual code for the list from the surface. Here, I said it: decouple. Now, I am not saying that you should have a base class here, because — unless you have already planned to change the surface — that is completely useless. But having this decoupling means that you do not have to worry about it, that if your business requirements change you won’t be caught out. It is much more testable, compact and reusable, even if it’s just a single class.
The last thing I want to talk about and where I see way too many developers falling short is their ability to look at the technical requirements as a gateway of the business ones. Every technical choice affects the business opportunities you can take or have to miss. Get it right and you’re off to the races; get it wrong and you are in trouble. At the end of the day, things such as decoupling aren’t so much related to the technical side but to the business one. You do not decouple to make your life easier (although that is a byproduct) but to grab more opportunities without going broke. The same can be said for pretty much everything else: use of interfaces, unit testing and so on.
So, do me a favour please: the next time you need to make a class, don’t do a hierarchy :)