Fab Camp Fire

More about Fab Gear's modus operandi.

Technology Choices
Practical Applications
Practical Applications

Your professors, your elders, all the magazines you read, they all extoll the benefits of reusable code, and code that's designed with the future in mind. The benefits of well designed code are quite real, of course, but we all need to recognize that there are very real costs, as well.

Do you really want used code?
Imagine, if you will, two groups of developers that need a similar, but not quite identical, function. One might be tempted to have one group develop the function, and the second group use and extend that work. That's great, but if the function has a different priority in each of the groups, or if a conflicting requirement arises, there are going to be delays. Meanwhile, future changes to support one group may have unforeseen effects on the other.

In some cases - but obviously not all - it's quicker and easier to have both groups develop independently, and then have someone integrate the two approaches when and if appropriate. That seems like extra effort, but in many cases you'll end up with a cleaner design and tighter code, in less total time. It takes experience to recognize those situations, but the common "obvious" answer isn't always the wisest.

The Dangers of Overbuilding
All-purpose code also has a price. I often find young developers working very hard to come up with a design that does what it's meant to do, but also suits some ill-defined future tasks. The same developers who tell you they can't work without clear requirements will build complex edifices to support an imaginary future.

This is frequently time ill-spent. You don't know what the future holds. Unless you're working explicitly on a general-purpose library, the class you're working on will likely never be used for any future purpose. At all. And even if it is eventually used, it probably won't be for the purpose you've foreseen. You're smart, but you're not prescient. You can't draw a line based on a single point.

It's often difficult to know when a design is complete - when you should start coding. I've been called into a situation in which a developer had clearly worked hard on a design, but had been working at too high a level - the class diagram. Inevitably, the design focused on the diagram itself. It looked great, naturally, but the code based on that design was slow, difficult to implement, and error prone to use. In the end it had to be scrapped and rewritten. Why? Because the developer was focusing on the purity of the object oriented design, and was writing a general-purpose library when the project needed only a few simple capabilities.

Back to Basics
It is always better to create a clean, minimal design that meets your immediate needs, and layer your software intelligently such that you create a few building blocks in addition to your main product. If, in the future, someone needs to re-factor your work, they'll have an easier time of it if your work is easy to understand and avoids the complexity that leads to bugs. Meanwhile, the result of that future revision will almost always be better than you could have done originally, since it has the benefit of experience with the original design, not to mention real requirements.

Think of it from a cost perspective: you'll typically spend much more time trying to develop the perfect, future-resistant class than it would take to develop the thing reasonably, then revise it later. And you'll end up with a better design, since it will be focused on the tasks at hand, rather than a mix of real and fantasy requirements.

To me, this point about not trying to design for an unknown future is similar to the well known advice to avoid optimization until you understand the working system - or as Donald Knuth put it, "Premature optimization is the root of all evil". Obviously you should write reasonably efficient code, but avoid going to great lengths to optimize areas that haven't demonstrated the need. You'll almost always guess wrong, and end up with code that's overly complicated for no real benefit.

Now I don't want to leave the impression that I'm against everything the pundits have been pushing for years. Shared code and sound design are critical to our productivity. It's just that as you gain experience in real-world projects, you begin to realize that there are tradeoffs in software development, and that balancing all these interests is one of the key skills of a successful developer and project manager.

Back to the Front

history   contact
shim Fab Gear Interactive
Case Studies
The Process
The People