This topic was inspired by a discussion I had yesterday regarding someone’s design for an application. It reminded me how hard it is to make design choices, and how hard it is to conceive software ‘on paper’.
I always had a great dislike for SomethingManager classes. My great dislike started when I wrote a central piece of a vast Linux-based Media Center environment, which I’ll talk about in more detail later in this post.
SomethingManager classes are usually code smell. Reasons:
- They tend to grow in an erratic manner: you usually revisit Manager classes a lot, adding new functionality that ‘obviously’ belongs to them.
- They tend to grow a lot; being the writer of a 4k-lines-of-code-and-90-methods-class this is a lesson that I learnt the hard way.
- They are impossible to test; how do you test a manager, especially when it spawns applications in the most interesting parts?
- They require a lot of support; the Manager class usually requires other classes to be ‘set up in a certain way’, and because of that they tend to create other managers in related sections of your application. Like in real life, Managers only talk well to other managers and their wife (who is probably an accountant).
- While not obvious at design time, Managers tend to collect multiple roles and mingle them in an awful compost that makes you rise your fist and shout: “Teachers, leave the kids alone!”.
- Breaking down a Manager class is usually re-engineering, not refactoring. The lucky few can spot several multiple roles that this class covers, and can later break down the class into several classes; but they are truly lucky if the roles weren’t mingled in a sad and awful way, and if they have the time to re-engineer that part.
So it’s pretty safe to say that when you have a Manager class in your design you will have a problem in two years time. And I talk from experience: I rarely seen a Manager class that shouldn’t have been renamed to something else or didn’t fail miserably. And one such Titanic level disaster was my ApplicationManager.
This Media Center suite of applications was (somewhat unintuitively) made out of many applications because the threading model in the late 1990s and early 2000s was still crippled on Linux (Apache doing prefork was a lot more efficient than the threaded version, for example). The first task I ever had as a professional programmer (aka for money) was to port the threading primitives from MFC to Linux, and that was (still) a challenging task in 2001.
In late 2002 I was in charge of creating this central node of a big MediaCenter project. It was called ‘ApplicationManager’, and its job was to spawn applications when requested by another application called ‘Menu’ and to monitor when they close. It was easy, it was obvious.
It ended up with a central class that spawned 3500 lines of code, managed communication between applications (for some reason, the applications couldn’t talk to each-other, but that reason was lost in time), maintained a few popups, managed focus of the applications, started EPG scans and stopped wizards because, well, there was no other way to stop them. How did that happen?
It’s simple. Under Linux, nowadays, you can safely use threads, D-Bus, X.Org, and WebKit, and solve 99% of the issues that ApplicationManager was solving (and of another manager that crippled the media center solution). After we created the initial design where the AM maintained a stack of applications and a list of predefined applications that can be started, we decided that we can’t use CORBA for IPC (the experience we had with mico is horrendous) and we had to move to something more light-weight. In our case, we used messages from the standard POSIX offering, and they were fast enough for what we needed (D-Bus was still in conception stages when we tackled this issues).
And then there was XFree86. My goodness, such a horrid piece of horse manure – it was the #1 reason the product failed and things like DirectFB were still in infancy stages. Unfortunately we didn’t have the experience of the embedded space; things would’ve been a whole lot different if we had the experience we gained in the following years. Anyway, back to my ApplicationManager: because of the way XFree86 was built we had to maintain focus of the applications correctly. This was hard to decide inside the application (the application never knew if it had focus or not, if it was active or not); so the application manager was supposed to move the focus from one window to another. But (holy scythe) Qt spawned multiple windows inside the XFree86 system. Result? Hell.
And XFree86’s undocumented Xlib was roses compared to the horse manure that Mozilla was to embed in an application. Now that’s one awful piece of crap. Have you ever tried? Don’t. Use webkit instead.
The DMC achieved the impossible by using all these crappy components. But the core had to suffer; this ApplicationManager collected all the faults in design choices, and amplified them. When I woke up one morning with line #3000 in my editor I understood the errors of what we did. Unfortunately, by then, there was no other way.
In a similar way, a Manager class collects the faults in design choices and the set of workarounds. So here’s my plea: stay away from them. You can start with one, but rename it later to something better once you identified the role you actually want it to fulfill.
And please, don’t get me started on *Engine classes.