Top Trumps in God Objects
If we were playing the children’s game Top Trumps with Java
interface definitions I think that I’d win every time. That’s because
I’ve just found an interface, which is part of a prestigious company’s
public API with with 167 methods. Trump that! Imagine, if the interface
definition contains 167 methods, how big is the implementation class? In
the words of a texting teenager “OMG”.
You’ll probably know that objects that are as out of control as this are usually called God Objects or Monster Objects and there’s an anti-pattern of the same name which explains it all. If you look on at various definitions of the God Object Anti-Pattern, they usually say a god object is an object that “knows too much or does too much”1, words which seem to crop up all too often if you dig around the internet. In modern programming speak this generally means that a god object:
- is a HUGE violation of the single responsibility principle
- generally breaks all the laws of demeter
- is tightly coupled to just about every other part of the application
These types of objects are not that uncommon (though I haven’t seen too many until recently and none as bad as this one) and it makes you wonder, how does such a mess arise? It’s surely easier to do a good job than to make a complete mess. So, I tried to come up with some of the excuses that the professional company in question might give for creating a God Object of such magnitude:
- Lack of time, tight deadlines. This doesn’t really stand up as an excuse. From experience, I find that it’s quicker to do a proper job, with Unit tests, than it is to hack in some extra functionality.
- The programmer adding in a new change “couldn’t be bothered” to refactor and do a proper job, such as changing the whole thing was too much effort and he/she had better things to do like catching up with friends on Facebook. Hm-mm probably...
- The developer didn’t want to break anything (too scared). This does stack up if you’re asked to add additional functionality to an existing god object that doesn’t have any unit tests. There’s always that feeling of fear and apprehension that you may break something. The only way out of this is to write tests, which is dull and tedious. See my point above: “couldn’t be bothered”
- Programmer ineptitude. Enough said.
The question is: how do you go about fixing such a mess and the standard answer is to apply the single responsibility principle, creating groups of methods that are responsible for individual bits of functionality. These should then be removed from the god object one at a time and implemented as objects in their own right.
But, and in this case there’s a BIG BUT, what if you can’t refactor? The interface has above has nothing to do with me, it’s not my code2 and I don’t have access to its source code. The answer is to apply the same idea, splitting the monster class’s methods up in to functional groups, but then writing a set of Adaptors (aka Delegate and Wrapper) classes one for each functional area.
The rough UML diagram above demonstrates the solution to my particular problem, though it should be remembered that with 167 methods there will be lots of adaptor classes, each with proper documentation and unit tests... all of which leaves me with that nagging feeling of “can I be bothered”, after all, Facebook is calling...
2I’d be hugely ashamed if it was...