views:

959

answers:

18

We all write reusable classes and code.

We factor in configurability to allow us to reuse this fantastic new class again and again.

We tell our bosses that spending this extra time now will save us time and money later.

But in reality, for those of us who don't write third party libraries, and spend our time working on a application as a whole, how many times does that one class you spent extra time writing to be reused actually get reused in another project?

How many bespoke classes do you have in your library which will get used in more than one project?

+27  A: 

My common rule of thumb is:

  1. If you repeat it once, copy it.
  2. If you repeat it twice, refactor it.
leppie
I would refactor that to "If you repeat it once, refactor it." You might not be the only maintainer of one of those copies. It's a real pain when they get out of synch.
Bill the Lizard
I'd say:1. Design the code itself "right" the first time, but only from the point of view of functionality.2. If you have to use it again, and you can't do it directly through re-use, then copy with comments as mentioned above.3. If you have to do it a third time, refactor for reuse.
MadKeithV
For some reason, this reminds me of homer simpson's "Leaves of three, let it be. Leaves of four, eat some more!" But I have no idea why....
Mitch Wheat
+1 - reuse adds complexity, so extracting a small section as separate function is sometimes more code than the two copies. Complex code should be extracted on first reuse, though.
peterchen
+17  A: 
MadKeithV
+1  A: 

If you're sure you're not going to need it again, don't bother. Not even if you think it might come in handy. Refactor it when you really need it again...

However, not making it reuseable is no excuse for not making it transparent. Whenever I write code as transparently as possible, it always turns out to be 99% reusable already...

Vincent Van Den Berghe
+11  A: 

leppie wrote:

My common rule of thumb is:

  1. If you repeat it once, copy it.
  2. If you repeat it twice, refactor it

And I would add, make sure that a comment is added to both parts of the code to indicate the duplication in case there's a bug. You don't want to fix it in one part and not the other (BTDTGTT).

Rob

RobS
I think that if you need a comment to remind you of the duplication, it should have been refactored.
Svante
A: 

I agree with you insofar as there is no point in coding in a way that makes the class easy to use outside of the current application. Most if us don't do this and in business environments there is no need to. If another application needs this functionality at a later date then extracting and commonalising the code can be done as part of that second project, and management are likely to agree with this viewpoint.

However it is good practice to make your code reusable within the constraints of the current application. Refactor your code so as to avoid duplication within your current scope of work. This way you make it easier to work with at a later date. Don't so much code for reuse as for change, change is far more common.

Jack Ryan
I have had reusability ingrained into me from when I was learning to program many moons ago. It is a natural thing for me to think this way, but I am starting to think that maybe it is not always a good practice.
Xetius
A: 

My 2c is that the ethic of code-reuse needs to be a company thing, not just a project thing. This means that when you start a new project, the primary concern is "which other projects can I steal code from to get this job done as well and as quickly as possible?".

This WILL conflict with the question of "what's the best - or trendiest - language/tool for the job?"

Companies that have this approach end up with a pool of engineers that can easily switch from project to project, because language, framework and internal code base are all consistent.

The down-side is that switching to a "new" language or framework is much more politically difficult, even though it WILL need to happen at some point.

Roddy
A: 

One of the reasons why SOA has been failing, or hasn't lifted of yet, is that it's difficult to reuse a service: either it's too specific and it can't be used elsewhere, or too generic (and usually very complex) and doesn't meet the needs of different clients.

This ain't "code reuse", it's "service reuse", but there are some common concepts.

t3mujin
+3  A: 

I'm no expert in XP methodology (or any methodology), but I think the YAGNI principle could be applied here.

Only modify the code for reuse when you have to reuse it.

lamcro
+2  A: 

There is a difference between configurability and reusability- the former can be extremely useful in a lot of different situations, when the environment changes or whatever else- making things configurable in the way I understand it, is mostly a case of separating code and data- that's just good practice really.

Designing for reusability is only really useful if you're creating something you are planning to use as a library for multiple projects. As the years go by I have become increasingly aware of the YAGNI principle and these days I simply aim to write clean and robust code for the task at hand. My experience has been that if something is going to be reused it is very unlikely that you will predict exactly how it will need to be reused, so it's much better to only add the code that you need for now. That way if you need to reuse it in future you can add new stuff that does exactly what you need without having to break any existing functionality that you wrote in the past trying to anticipate how you might need it now.

You may find that after doing this a couple of times you have a library that is stable and robust and doesn't need you to change it because it actually does all the things you need- to me it's much easier to allow that to happen in that evolutionary way than to waste too much time guessing about the future.

glenatron
+1  A: 

Once you get above the level of technical utilities I have seen very little actual reuse in the real world.

If you think about it the reasons are clear. Say the widget_bodger application contained 90% of the functionality you require than you would just add the missing functionality to the application.

Or say the business admired a really cool "beep" function in the widget_bodger and wanted it incorporated into the gernerate_executive_expenses application. Ah resuse you might think, but then you dig into the code and find that GEE application is one of the oldest apps in the company, is written in C, must run on highly available hardware and the only thing that is resuable is the basic algorithm.

James Anderson
+2  A: 

I think that the best approach is to try and design code with good interfaces and separation of responsibilities between classes without worrying too much about reuse. But at least if you design this way you're leaving open the possibility of reuse. A good rule of thumb is to ask yourself "if I come back to this code after 3 months, will I understand it and could I extend it if I had to?"

IMO one of the worst practices in the industry is when a team are given the go-ahead to go off and write their own "reusable" framework....

+1  A: 

There are very different opinions on what makes code reusable. I'd say your time well spent making the code clear and well-factored (i.e. separation between responsibilities).

A side benefit from this is better reusability. The main benefit is making the code easier to understand, change and debug.

To wrap it up. Don't do complex configuration schemes, extension points and events just to make it reusable. Try to find the right moving parts so that the code can be composed in response to new needs.

Cristian Libardo
+2  A: 

I like the LISP model where you are continually extending the language. Eventually you wind up with a domain-specific language for your problem domain. Not that I actually write any lisp, but in the languages I use most often---Lua and C right now---I usually pull something out into a module and reuse it rather than clone and modify.

For a C programmer, the quintessential example of this approach is Dave Hanson's bookC Interfaces and Implementations. Dave took every reusable idea he'd had in writing three or four compilers and put them all in a book---and the software is free. Fabulous stuff. Now if I write C code and I want to use it a second time, I make an interface in Hanson style. Some things I did this term: 2-dimensional arrays, 2-dimensional arrays with blocking, 2-dimensional bitmaps, readers and writers for pbmplus files, and so on. With this infrastructure in place it was easy to write a program I'd been wanting for years, which is to remove black edges from scans of photocopies of book pages.

So I agree with whomever said when you want to reuse it, pull it out---but not before.

Norman Ramsey
+1  A: 

IMHO, certain code is likely to be reused often, and it makes sense to prepare it for frequent reuse. Other code isn't, and probably doesn't need to be developed beyond solving the immediate problem.

Of course, do be aware that telling the difference is NP-hard. :)

J.T. Hurley
+1  A: 

Often "reusable" code is code that is abstracted and modularized, and, to me, the main benefit is not reusability but rather increased testability. Because when you isolate and modularize code it usually becomes more testable. Reuse is a convenient but often unused side effect.

And on another note, Juval Lowry advocates interface-based programming since he maintains that interfaces are the sole component of reusability. Anything else has implied functionality (hard to re-use) while interfaces define a contract only which is implicitly reusable.

Aaron Lerch
Reuse makes big projects much more maintainable but adds additional complexity to simple fragments of code.
Din
A: 

Another benefit with reuse is that you can easiliy track where things happens in the oode base. if you got a million lines of code it can take hours to find all places where the application behaves in certain way. With a modern IDE you can just click "find references" and you'll find, within a couple seconds, all places where your component/method is used. This can be useful when you want add new features, fix bugs or just want to learn how the system works.

Kire Haglin
A: 

We have a few, but what we have many more of are projects with the functionality you want but done in their own way, so more often than not you end up cannibalising features from old projects and reimplementing them in your new one. I'd argue that this still counts - you're still getting the benefit of having written the code before, and you still save the time.

Besides, I've found that it's only the second time that you try and use the functionality that it becomes obvious where the reusability is, and if you try and generalise something speculatively you almost always get it wrong and have to change it next time.

A: 

Like other posters have said if you are going to copy the code then re-use, you will be glad you did this once you start debugging your copied code.

hhafez