Premature generalisation

When making some new software, a programmer may want the software to be easily adaptable, so that maintaining it and adding new features to it becomes easy. Sometimes, this is tried through premature generalization, which is a bad thing.

Premature or speculative generalization is taking into account all kind of features which are not currently asked for.

Dave Smith:

This is really going to be a clean framework. I'll make an abstract class out of this part so that folks can subclass it later, and I'll put in a bunch of well-commented overridable hooks in the concrete subclasses so that folks can use them as templates, and just in case somebody ever needs to build special debug subclasses, I'll put in extra stubs over there (somebody will thank me for 'em one of these days). Yeah, this is really going to be neat.

Ryan Farley:

Sometimes referred to as “over-abstraction”. Your requirements might be to code X, but you think it would be really cool to also account for the possibility of YZ so you abstract, or overly generalize your code to include for the future possible need for XYZ. You brag to your fellow programmers or to your client about how not only you can do X, but also if you ever need to do Y or Z then that is already built in. “How cool is that?!”. Well, it might be cool, but chances are that Y and Z will never be needed.

You get it when people say, “Oh, I think we need the ability to this kind of thing someday” and thus want all sorts of hooks and special cases to handle things that aren’t required. The result often is harder to understand and maintain.

There you have one of the problems with premature generalisation: the code becomes harder to read and maintain because it has things for features you are not going to need.

Eric Gunnerson:

The problem is that there are at least three distinct layers in the layout manager. I write a line of code that says:
toolbarTable.SetColMargin(0, 10);
and when I step into it, I don't step into the appropriate TableFrame. I step into a wrapper class, which forwards the call onto another class, which forward onto another class, which finally does something.

Of course there will be features that get added later on. The problem is, you can not foresee which features they will be. If you take into account all kinds of features that may be added later on, somebody will think of a feature that you had not taken into account. The generalised structure of your code does not help with this feature, so you did it all for nothing.

Johan Karlsson:

After a couple of weeks it was decided that we was going to use another low level protocol for the communication. It turned out that my general design was useless, since I did not anticipate all the aspect of the problem. First of all I realized that I do not have the powers, like Nostradamus, to see into the future. I also came to the conclusion that you have to know the domain, before making any generalization. You have to do your first implementation in that domain, before you should make any general design. When you continue to evolve your product, you can figure out what parts of the code that is reasonable to generalize.

Dave Smith:

Over time, I've learned that trying to get an abstraction right the first time is like premature optimization--until you can make decisions based on real usage patterns, your early guesses are liable to be off.