Inside a project, reuse of code is simple, and natural. Outside of a project, it's too dark to read?
You notice some duplication, wham-wham-wham, you refactor it into a happy state. Integrate, and you're done.
However, reusing code across several projects brings a whole new set of problems. A very, very formidable set of new problems. Hence, AlistairCockburn
votes to rename "inter-project reuse" to a less naive name: "PolyBloodyHardReuse
Here are some common problems that come with attempting reuse across plural projects:
- Configuration Management - How and when, if ever, do you migrate changes in the reused class among the various applications using it?
- Class Extension - What do you do when the reused class needs a new capability? You can extend the class (easy). The other option is to inherit the class, but without the correct virtual declarations and without exposing encapsulated data (C++ specific references), it is often impossible to add the desired functionality without still having to go back and modify the base class.
- Close, But No Cigar - Related to the above, what do you do when the class you want to reuse almost does what you want? If you are doing white box (source code) reuse, no problem. If you are doing black box (binary) reuse, you may find yourself most of the way through a development cycle and realize you have to recreate the class from scratch or burn lots of effort in reverse engineering the class and coding work arounds.
- Not-for-long Reuse - Hardware capabilities change. Protocols change. *Egads*: requirements change. Reused code might not weather this change as nimbly as code that you have complete control over. Does BitRot apply to reused code? At least one Wikizen thinks so.
- Premature Publishing - Change rates for a given module tend to be wildly troublesome at first. If you try to reuse code across projects at the beginning of its life, you'll likely experience PolyVeryExtremelyBloodyHardOwieOwieDoctorItHurtsWhenIDoThisReuse.
- Nominal Reuse - Here's a class that everyone can use. It achieves its poly bloody universal reuse ability from the fact that it doesn't do anything interesting. But y'all can use it, and we're about to write a departmental policy that says you have to.
Okay, so it's bloody hard. When is it worth the difficulty?
- When change rates are low - Eventually, classes settle down. If you apply the OneResponsibilityRule, you'll find that your class learns how to handle its One Responsibility before long. Once this happens, it might be worth it to "publish" it. Look at the relative stability of standard library modules that come with your language's implementation (especially languages with ample libraries: Perl, Java, Ruby, etc.). Few would argue that Perl's LWP module, for example, hurts more than it helps.
- When many programs need to use the same logic - If a bunch of programs talk to each other, you have to figure out some way to make sure they all speak the same language. PolyBloodyHardReuse it is (much better than just duplicating the logic everywhere -- believe me.)
- When the configuration management issues are easy to work around - I haven't seen this in real life. However, I don't have much experience with fancy-schmancy technologies. Has anyone used something like EJB, OODBMS's, etc., and found the configuration management issues eased?
- When you're obeying your NotInventedHereSyndrome - "Because it was NotInventedHere" isn't a good reason for failing to reuse an existing solution. It is possible that someone else went through all the PolyBloodyDifficulty to package something that will suit your needs. You can work through some of the above-mentioned problems (such as Close, but no cigar) by wrapping the new solution in a layer of your own.
HardReuse I get. BloodyHardReuse I bloody well get. PolyBloodyHardReuse makes my parrot jacknife into the freshly rolled jet black macadam. Can someone please explain why my bird died?
It's pining for the fjords.
Poly == many. So: PolyBloodyHardReuse
would mean that there's many different reasons why it's B
loodyHard to Reuse.
It rhymes, give or take a couple syllables, with Polymorphism, a topic familiar to OO designers as "hard".
The phrase was coined by someone learning OO. He was commenting that "reuse" is a diabolically difficult topic, but the word "reuse" is so short that people think it should be easy. Comparing to topics like "polymorphism" and "dynamic binding", be said that it needed a much longer word, like "poly-bloody-hard-reuse". The phrase stuck, for the reasons that the others said (well, possibly not the "pining for the fjords" one). --AlistairCockburn
There is only one letter difference between reuse and refuse. -- AnonymousSkeptic
When the configuration management issues are easy to work around
This doesn't just mean because of tools. Take my development situation: we're building up libraries of reusable things by making things when we need them, and extending them when we need to. We have multiple projects, but we only work on one project at a time. So shared class S gets its start when we need to write it for project A. Later, when we're working on project B, we extend class S to do some new stuff. Configuration management is easy, since project A should just keep using the same version of S that it did when we left it, and project B should use the current version of S.
Then we go back to project A. We refactor the code in A to use the latest version of S at an opportune time -- typically, when we need one of the new features. Now the configuration is: A and B both use the latest S. If we extend S some more, then B just keeps using the version we left it with.
This would fall apart if, for example, we had one team working on project A and another team simultaneously working on project B, both of whom were extending S in different ways (or maybe just if those ways are incompatible). Then we'd have to treat things as one big project, in terms of code ownership and churn. But we don't have that problem, so multiple-project reuse isn't very painful for us.
To turn things around: working on only one project at a time can make multiple-project reuse easier.
The extreme correlation of this, of course, is that if you have shared code between multiple projects, developed in parallel, then you really pay attention to ContinuousIntegration
. -- RobertWatkins
I concur with this observation. Intra-app (or intra-project) reuse is far easier to obtain than inter-app reuse for some reason. --top
I suggest renaming this to IntraReuseEasier?
or the like. The current name sounds like sexual violence against tropical birds.
It's supposed to sound unpleasant - that's the point. And since when was Norway tropical?
See also ReuseReleaseEquivalencePrinciple