Is it a good rule of thumb to always write code for the intent of re-using it somewhere down the road? Or, depending on the size of the component you are writing, is it better practice to design it for re-use when it makes sense with regards to time spent on it. What is a good rule of thumb for spending extra time on analysis and design on project components that have "some probability" of being needed later down the road for other things that may or may need this part.

For example, if I have the need for project X to do things A, and B. A definitely needs to be written for re-use because it just makes sense to do so. B is very project specific at the moment, and I can hack it all together in a couple days to finish the project on time and give everyone kudos for being a great team, etc. Or if we say, lets spend a whole friggin' 2 weeks figuring out what project Y/Z might need this thing for and spend a load of extra time on on part B because someday we might need to use it on project Y/Z (where the savings will be realized).

I'd imagine a perfect world situation would be a nicely crafted combination of project specific vs. re-use architected components given the project. However some code shops might feel it would be a great idea to write everything for the intention of using it at some point down the road.

This is an entirely different question from the question that it is supposedly a duplicate of. If this is not evident by the wording of the question itself, then it should at least be evident by the fact that the best answer here is at odds with the best answer there.
–
Mike NakisJan 17 at 8:21

1

@MikeNakis - Then edit this question and make the differences more clear. As it stands, your comment appears to be little more than shameless self-promotion.
–
GlenH7Jan 17 at 15:26

7 Answers
7

In my experience, trying to always make everything reusable may lead to over-engineering. However, a certain non-excessive amount of effort to make things reusable is always worth trying to put into things, (when things are amenable to reusability,) because a reusable component is a general purpose component, which means that its interface is abstracted, which means that it is easier to understand it on its own, and figure out how it works and why it works, and what it does and how it does it, when you look at it on its own, or when you look at it 6 months down the road and you don't even remember ever having written it. And these benefits are of course in addition to the fact that it is reusable.

So, to cut a long story short, I believe that the rule of thumb should be: make it reusable if doing so will make its interface and / or its implementation easier to understand.

What is a good rule of thumb for spending extra time on analysis and design on project components that have "some probability" of being needed later down the road for other things that may or may need this part.

For cases like above my preferences are based on an estimate derived at one of my past projects: re-usable code takes 3-4x times more efforts to write (YMMV).

Another thing I noticed is that it's quite hard to properly design code for re-use when all you've got is just one usage example. In other words, when I design "for just in case", without having an example for that, it often turns out that I have to redesign it later when need for real re-use arises.

Given above I tend to avoid designing for re-use until I have a real case for that. In that sense I rather strongly follow YAGNI. On the other hand, when there is at least one case of re-use I try to re/design for that instead of duplicating code - even when my plain calculation of efforts is still in favor of duplication (2x efforts vs 3-4x) - guess this preference have something to do with considerations of further maintenance.

For example, if I have the need for project X to do things A, and B. A definitely needs to be written for re-use because it just makes sense to do so. B is very project specific at the moment, and I can hack it all together in a couple days to finish the project on time and give everyone kudos for being a great team, etc. Or if we say, lets spend a whole friggin' 2 weeks figuring out what project Y/Z might need this thing for and spend a load of extra time on on part B because someday we might need to use it on project Y/Z (where the savings will be realized).

In case like above I'd personally go for quick hacking for B.

The only thing that makes me uncomfortable would be if there are no traces left for this decision (like what is the problem, what options were considered, what was the decision and why). But this is really easy to handle - I do it routinely at decisions like that: just register it in your issue tracker, describe things and let it be there until time allows to take care of that. Or until there's time to prepare that
other project Y/Z - when you can include friggin' 2 weeks in the estimate.

The best practice is to write neat and understandable code irrespective of re-use purposes. A good written code can always find it's place in the future. You don't need to specifically write code in a manner which suits re-usage. All you need to do is follow good design principals and a bit of self-documenting code. This will make your code reusable itself.

As you already pointed out, it does come down to balance. In scientific/economics terms, you would evaluate the two sides of your decision, reusable code vs. app-specific hack and sum up the costs and benefits of each side and also take into account any probability values (e.g. the chance the code will actually be needed anywhere else). In reality, we do these calculations subconsciously (using common sense, experience, gut feeling...) almost every day.

Technically, our designs should always be modular and reusable as much as possible, but there are plenty of instance where a "hack" as you put it, will take half a day to write vs. generic component a week. In that case, I would take a stance of the YAGNI principle.

On the other hand, if a) you know there's 80-90% chance the code will be needed again, and it makes sense and b) it doesn't take significantly more time to make it reusable, then I say go ahead and design for reusability... and then for everything else there's the middle gray area :)

Also, in the past I've had success taking the middle ground between your two approaches. I had projects where certain functionality could have been made reusable since day 1, but doing so would have incurred additional costs. So instead, I kept all the code local. In future work when the need for similar functionality arose, I went back to projects where this work was done originally, and at that time paid the extra cost of wrapping those classes into a reusable module. Doing this gives you few advantages: 1) you don't pay extra cost until you need it and 2) later on when you do make a reusable component, you can leverage your knowledge of how well original code worked out in app-specific case and modify its design as needed before introducing it to "the world".

In some cases, original projects were never modified to use the new v2.0 reusable modules because original code already worked and with no active development it made no sense to modify that code. In other cases, once reusable components were tuned and improved, we went back and replaced custom implementations, but only after custom implementations actually required work to be done. So one lesson from all this: even if you "hack" or write custom code, take an hour or two to come up with a clean interface. In the future if you have to modify this code, that interface will make it that much more simpler to remove custom code and replace it with library calls.

YAGNI only works in the context of code that is constantly, relentlessly refactored. Otherwise it leads to major pain.
–
sq33GDec 27 '11 at 11:41

2

@sq33G But equally trying to second guess what comes next will bog you down horribly - which is where elements of the agile philosophy come from. I've taken substantially to focusing on solving the problem at hand and worrying about "what if" when it happens - but, as suggested, there are coding styles and practices that will make dealing with change less painful
–
MurphDec 27 '11 at 15:45

If it turns out you DO need to re-use it, refactor it as needed. If you have good unit tests in place, the refactoring is fairly low-risk. Besides, in my experience, code that is testable is pretty close to being re-usable anyway. You might need to add in an extension point or two, but if your code is clean to begin with, it shouldn't be a huge deal.

I don't have a rule of thumb in terms of time/effort/cost, but the line I like to use is "reusable code isn't part of a project, it is a project." This is because truly reusable code needs to have its own very well defined set of requirements that take into account everything that's going to be using it and may be using it in the future.

Of course, you can take any given component that's being written as part of a project and make it reusable. But the difference between something that's "reusable" (in quotes) and something that truly does have the potential to be reused is whether or not it can meet the needs of multiple real consumers in all aspects - flexibility, deployment considerations, performance, behavior, configurability, etc. The level of design required to get all that essentially makes a piece of reusable code a project unto itself.