views:

203

answers:

7

Imagine you work for a small lean software company. You know the future competitiveness of the company is in having a good reusable code base to draw upon. It’s going to be very important to manage the company’s re-use policy to ensure you deliver today, at the same time as providing a back-bone for the future.

In my mind there are two reasons to write re-usable code in business; 1) To share within the company to improve speed and efficiency in the future 2) To publish on the web and other people will help improve the code (crowd-sourcing in a sense).

Developers should always apply common sense to re-use of course. But to get a handle on this from a management perspective I want some overall code-reuse guidelines to ensure we are competitive now and in the future. These guidelines should encourage the developer to ask “Is my code a Candidate for Re-use?”. What should these guidelines say?

My initial thoughts: It’s not worth writing re-usable code at the lowest levels (e.g. I have some in-line code which adds a “’s” to the end of a string), there would be far too much of this code to even sift through and find that someone has already done it. It’s also not worth writing re-usable code at the top-most level i.e. the application because your customer reporting application would end up being genericised into a SQL client – useless to most users.

Main barriers to re-usable code: You can’t re-use it unless you know it exists; Trust – It’s been done but do you trust it?; Initial time taken to make the code generic/re-usable (and to document it).

A: 

Only make general code reusable. A function that only appends an s last in a string will not be of value except where it is already used, but a function that can add any one or more characters to the end of a string would be useful for other uses too.

Basic functionality; if you have your own functions and types for lists, trees, sockets and/or file handling, all these can be useful in the shared libraries.

Also, you can comment on all functions and types and use a system like Doxygen (or Javadoc) and then automatically generate the documentation, which would make it searchable even outside an IDE and presented in a somewhat nice way.

Tobias Wärre
A: 

I would reuse and continually support/refactor:

  • all libraries that do a specific task well
  • clients to a specific service, as long as the service doesn't dramatically change
  • the business layer/model, as long as the business cases are not thrown away
  • the web/desktop interface, as long as it can still serve it's function well

I would throw away (delete from scm) and rewrite from scratch:

  • any library that is poorly written; that tries to do several tasks and does them all badly
  • a client to a service when the service is completely rewritten, changed with a different technology (database changed with web service)
  • the business layer/model when it no longer serves anything
  • the interface when the client wants major changes, or when switching to a different framework
Mercer Traieste
+4  A: 

I think the better idea is to never make code reusable.

Instead, when you find two pieces of code that are very similar, refactor them - pull the common code out and leave the differences in. Rerun your unit tests, and when they succeed, you're done.

You did have unit tests, right?

John Saunders
A comment to go along with the downvote would be nice. I don't retaliate.
John Saunders
Voted up since it's the best response here so far
Brian Agnew
I personally think that this will lead towards messy code for anything beyond fairly simple static library functions. re usability (if you want it at all) should be planned in at an early stage so it is designed and implemented thoughtfully. (It wasn't me that downvoted)
Simon P Stevens
+1 Yes, at a micro level, code can be easily changed while guarded by unit tests.
Mercer Traieste
Just to get a bit more info from you. You are saying that a company shouldn't have a re-useable code-base to draw upon? Negative ROI?
Ben Breen
My understanding is that John Saunders says, YAGNI (You Ain't Gonna Need It), but when you do, you should be able to refactor your code. Being able means that you have unit tests.
Ionuț G. Stan
@Ben - he's saying that you don't make it reusable until there's a requirement for reuse
Brian Agnew
I think the reusable code base should develop organically. When the opportunity for reuse is discovered. It should be discovered in working code, so get it working first. If you later find a need for similar code, refactor it to make it cover both the old and new cases. Have both cases covered by automated unit tests.
John Saunders
@Simon: my code is _not_ messy, thank you very much. And maybe it's a matter of experience, but I'm pretty good at refactoring to patterns even when the patterns weren't designed in too soon.
John Saunders
@Simon: At my experience all planning is old after one week into the project. Requirements change, your design doesn't work as expected and need to be changed or something else unplanned happens. At this stage the up-front-planning may even harmful - if you're stubborn and stick to the obsolete plan. In my experience you should be ready for change, and a good test-suite helps here much better than a plan.
Mnementh
+1  A: 

All well-written code is a candidate for re-use.

If you take the time to make code generic and documented, not only can you re-use the code in another project, others will actually look at your code. This will greatly improve the probability of anyone finding bugs/quirks before your users do.

The main thing is to make a good distinction where code should be. To take the 'add an "s" to a string' example - this could be code that is put somewhere in a strings-util library along with the 'add an "h" to a string' and 'add a "b" to a string' functions. When you see those three functions together, you'll probably get the idea of making a more generic 'add any character to a string' function, thus making the code even more reusable - you can also add the letter 'r' to a string now!

The only way that you are going to spot the fact that you are appending characters to a string all the time is to make sure these functions live next to each other - otherwise everyone will have the same functions hidden somewhere in the code.

These kinds of util collections/classes/whatever contain the low-level pieces of code - they are generic, and don't seem to hold any relevance to a specific project.

The higher-end of the scale should also be treated as reusable code. Say for instance you have a customer with a great new idea, like adding images on a website. Nobody else needs this, so you go ahead and add the tag specifically for this client. Two weeks later, you have another client who asks you for the exact same thing.

What usually happens in a situation like this is that the extra code for your first client gets copied into the project of the second client - just because it looks like it is the fastest way to get things working. What is actually happening, is that the maintanability of the code is degraded. You now have the same piece of code in two places, with the same bugs. I think we all know this leads to problems in the future.

If the example was written for reusability, you can use it again in the second project, saving time and effort. Also, the added features that your next client asks are probably something you can offer the first client as an upgrade - (see, you can set the height and width now, woohoo!)

As for knowing that code exists, that is a problem that will always remain there. I think the fastest way to spread this knowledge is to make sure developers don't develop on their own - pair programming is a good example of this. This way, whenever something is written, at least two people will know about it. If you regularly mix up the pairs, the knowledge will spread through the company without any extra effort.

ylebre
I've learned the hard way in my career that you can waste a lot of time producing reusable libraries when you really should have spent your time on useful work. Same with going out of your way applying design patterns because they'll make the code more flexible. The flexibility may never be needed.
John Saunders
ylebre makes a good point here.The key being solid organization can go a long way especially when later trying to understand one code. So even if one will never use a specific library over again having a consistent organization for the code can be useful.
Gordon Potter
+8  A: 

You can spend a long time trying to make something reusable, without anyone reusing it. So I usually follow the maxim that I only make something reusable when it's going to be reused (there are a few exceptions that will stand out).

Often it's only when you come to reuse something that your client says "I want it to do the same, except..." or similar. It's only at that point that you understand which part of your reusable code is reusable, and what needs to be parameterised (e.g. via strategy patterns or similar)

Consequently I don't tend to regard code as reusable unless it's really been reused :-)

Brian Agnew
+2  A: 

In Germany, we say: The truth lies in the middle

You marked two extremes here, but they are a good start. When you are to low-level, you will win nothing. Your reusable code should be worth the effort. When it does something, a mid-class programmer can implement in 3-7 lines or in 1-3 minutes, it might not be worth it, unless it is really, really needed often!

The other extreme is the generic SQL client. Of course, the reuse should not lay any burden on the user. That is a definitive no-no!

In my opinion, you should think about your project and then have a careful watch, what parts could be needed in multiple situations. These are candidates for reuse. But there are also other factors, you should check the candidates against, before you make the code reusable:

  • Will the extra effort (see below) be worth it? (3-7 liners!)
  • Does it lay extra burden on reusers and/or users?
  • How often will it be reused (estimated)
  • Can I decide now? (You might not have enough experience right now -- then better delay it and implement some use-cases as standalone, before making it reusable)
  • Can I really generalize all the details that much, that I can have one single code-line? Special cases can be the death of reuse ...

You might find further factors. I wanted to give some adhoc examples.

I think, "Think first" is the best rule of thumb for reuse ... and of course reuse needs much experience.

Also it needs extra effort:

That is a really main point, many people forget. Reuse does not come free! You have to pay for it.

You have extra costs for:

  • Extra guessing, how to make it really universal
  • Extra-Asking all the potential consumers
  • Extra-Documenting, since the consumers will only use it, when it really is simple to use
  • Extra-Advertising, since potential consumers must know, that there exists something reusable and that is worthwhile to reuse.

Also you have to establish a reuse-culture, what is not easy, since it goes against the fealings of plenty developers. All developers think that only them have found the holy-grail and only their code is good at all. So many people will be offended and resist reusing code. The resistence can be either open but also hidden to the bosses (which might be the worst). Also the management must be aware of reuse. Without management backup, you will not have a substantial reuse-culture in your company.

So, there is a price-tag attached to it. But it is worthwile, when you manage to really pay the price!

Juergen
I think we would say, "the truth lies in the middle"
John Saunders
Thanks John, I corrected that one!
Juergen
A: 

I tend to build reusable libraries only when I'm sure that I'll need the functionality at least one other time, and that the time taken to make the code into a stand-alone library is less than the time taken to rebuild or copy code in. Furthermore, the library being created must solve exactly one problem, which prevents me from building giant balls of code that are too wide in their scope to be of use.

A recent example of this was a plugin designed to provide an interface between an app and the Protx payment system. I's something that solves one problem, and has been used in several different projects so far.

Mr. Matt