The siren song of reuse…

We've been doing some planning 'round these parts - planning that I unfortunately can't talk about - but it's led to a fair amount of discussion about architecture, both inside the team and outside the team.

Which has got me thinking about reuse.

Reuse has been one of the Holy Grails of software development for a long time, along with... Well, work with me, I'm sure there are others. True AI!. That's another.

Anyway, reuse has been discussed since time immemorial (October 13th, 1953), for some pretty sound reasons:

  • Software is hard and expensive to develop

  • We already break things apart into "components" to simplify development

  • We've all written subroutines that are used in multiple places.

It seems that if we did a little more planning, paid a little more attention, were just a little smarter, we could build our components in a more general way, and others could benefit from them.

And yet, people have been trying to do this for a long time, and have mostly failed at it. There are successes - widely-used successes - but they're fairly small in number. Surprisingly, people are still optimistic about going down the reuse path, and since they are likely to fail anyway, I therefore present some rules that can help them get there faster.

Eric's N rules for failing at reuse

Authoring reusable components:

  • It really helps to have delusions of grandeur and importance. You are going to be the ones who succeed at doing what others have failed at.

  • Pick a wide/diverse scope. You're not building a good UI framework for client applications, your framework is going to work for both client and web applications.

  • Plenty of technical challenge. That's what makes it fun and keeps you interested.

  • No immediate clients. You are building a *Component*, and when you are done, clients can use it.

In my experience, that's more than enough by itself, but it helps if you can throw in some obscure algorithms and quirky coding styles. I'm already assuming that you don't have any real tests.

Consuming other people's components:

  • You absolutely *must* sign up to work with something as it is being developed. There is simply no better way to waste vast amounts of time. Unfinished implementations block you, regressions set you back, and even if you don't get those, you at least get hours of refactoring to switch to the new version. It's best if you do this on a "milestone" basis, roughly every 6 weeks or so. That's short enough that you're randomized often, but long enough that waiting for bug fixes is really painful.

  • Commit to using the other component early and deeply. If somebody asks, "what will you do if <x> is too buggy, too late, or doesn't do what you need?", you can't have an answer.

  • Make sure that your use of the component is a variant of what the component is really being used for. In other words, the creator of the component is building the thing to do <x>, and you want to do <y>, which is kindof like <x>.

  • A quick prototype should be enough to ensure that you can do it.

  • If you can't get the authoring group to commit to producing what you want, take a snapshot of their code and work on it yourself.

  • Don't plan any schedule time or impact to deal with issues that come up.

  • If possible, buy the component you're using. Because if you paid for it, the quality will be higher, and they'll have to give you good support.

I hope these tips help you.

If you're a bit leery of reuse, then good for you. I have only a few thoughts to offer:

If you're thinking about doing something, it's always a build vs buy decision. Even the best general-purpose framework out there is just that - a general-purpose framework. It's not designed to do exactly what you want to do.

In the abstract, there are three phases of using a component in your code:

Phase 1 is great. The component is doing what you want, and it's quick and easy to do it. Let's say for sake of argument that this gets you to the 80% point in your project, and it gets you there quick.

Phase 2 is a harder. You're starting to reach the limits of the component, and it's tough to get it to do what you want. Tough enough that it's taking more time, and you're using up the time that you saved in phase 1. But you still feel like it was the right decision.

Phase 3 is much harder. It's taken you as long to get here as a custom-written solution would have taken, and making further progress is considerably slower than if you had written everything. Worse, you can see the point where you'll reach a wall where you can't do anything more, and it's close.

Different projects obviously reach different phases. Some never venture out of phase 1, and others are deep in phase 3. It's hard to tell where you'll end up, but if a given component is central to what you do, you are much more likely to end up in phase 3.  

The obvious problem is that prototyping is always done in phase 1, and the rapid progress you make there is oh-so-tempting. The whole application UI is laid out in a week of work using Avalon. I got this demo with moving pictures done in 3 days using XNA. We all want to believe that it's really going to be that easy.

Stay strong against the lure of the siren song.

Comments (4)

  1. Zeno of Elea says:

    The Dichotomy: Successful reuse is impossible since that which is moving down the reuse path must arrive at the use before it arrives at the reuse.

  2. Ben Fulton says:

    Isn’t this what denigrators would call the "Not-Invented-Here" syndrome?  😉

  3. ericgu says:


    Yes, though I think of NIH as a different syndrome. NIH is all about "we can do better" (which is sometimes a part of authoring components, though for many components there isn’t really an option to use something that already exists), but the big reuse mistakes are on the adoption side, which is pretty much the opposite of NIH.

  4. Reference Seeker says:

    October 13th, 1953 seems like such a specific date that I’m guessing you have a particular publication or event in mind.  Could I trouble you to share what that publication or event is?

Skip to main content