There are a lot of common design mistakes engineers make. Premature optimization is one cited by most texts. That said (and C++ Coding Standards gets it right), writing code in a vacuum, ignorant of obvious injection of performance-killing code, is little better.
I’ve discovered a new pet peeve over time, and that’s the desire to make a general solution out of everything. My philosophy in this matter is simple: The best time to make a solution general is when you need to write it the second time. Some engineers have the ability to perceive when something they are writing is going to be used again and again, and they know to make it general. Many more think they know when to make something general, and do so judiciously.
What happens? A few things, and they aren’t good. First thing: people spend a tremendous amount of time implementing generic solutions. Generic solutions require a lot of thought, a lot of planning. If people want their generic code to be used in a generic fashion (that is by themselves and by other people), it has to be well documented. Lots of examples. It needs to be field-tested and tuned. It should probably go through more careful review. It takes so much longer to write a general and generic solution.
Why is this a problem? Thing number two: The same generic solution is implemented by many people. Worse yet, sometimes people implement a similar generic solution themselves. Without extensive evangelism and management of what sort of generic infrastructure abounds, the wheel will keep being re-invented. If your engineers are re-inventing the wheel all the time, but the wheels they are inventing are “generic” then something is seriously fucked up. This sort of crap happens all the time. Honest.
One of the interesting talks I went to while at Blizzcon was the jobs panel. I have never really been interested in the game industry, and don’t particularly like LA, but it was interesting to hear the engineers talk a bit. The two interesting take-aways were that Blizzard is a huge fan of mini-languages, and that Blizzard rewrites its games, from scratch, every single time. They don’t re-use old code, they don’t make generic solutions. They write from scratch, every time.
You’ve heard it before: Object oriented programming is a fad, and the grand vision of reusable code and generic bits of functionality organized into libraries that all get along together is a myth.
Thing number three: Generic solutions create overhead. Learning curves for other people. More complex wrapper and interface code has to be written. Longer compile times. Potential for runtime impact. Generic code can’t solve all the facets of a specific problem, requiring either a compromise of the requirements, or enhancements to the supposed generic solution.
Writing good generic code is important. A strong software engineering organization knows how to build up and leverage generic infrastructure. It knows ways to make a generic solution as fast and clean as the bespoke option. For this to be possible requires strong leadership, management, and propagation of knowledge. But a great software engineering organization also has a culture of not always electing to go down that path. Sometimes it’s important to focus on getting the job at hand done, and save the perfect architecture for a rainy day. It’s not always a bad thing to step back and say “that’s good enough for now.” Or to say “this might be something we want to refactor in the future.”