OK, maybe it’s not always inherently bad, but it is definitely not what it’s cracked up to be. And it’s definitely not the end-all-be-all that most of us were taught.

In my early years, I was dogmatically taught never to write the same code twice. Anytime you see duplicated code, or even similar code, refactor it into a function, right? What if the code was slightly different? Create some parameters. What if you need one extra field in some cases? Add a little logic around that to decide what to return. What if you run into a case where you can’t fix one caller without breaking another caller? Add another layer of abstraction and logical branching to your function. At this point, you started out trying to improve your code-hygiene a little bit, and all you’ve done is spend the whole day creating a monstrosity that is almost impossible to understand. Well sure, you don’t think so, but hey, nobody likes to admit their kids are ugly.

Always, always, always, stop and ask yourself, “Am I creating more problems them I am solving?”

Keep It Simple, [Obscenity]!

The fact of the matter is, when you try to create reusable code, you are inevitably making things a lot more complicated. It’s rarely a case of just taking what you have already written and exposing it to another component or team.

If you are using the code for yourself, you just have to make sure it works for you based on how you are going to use it, and you should be able to clearly visualize all of the possible scenarios. However, in order to make the code reusable, you are creating a black box to be called by another developer; as such you need to make it work no matter what, with any sort of crazy input, and you will need to make sure that it is clearly reporting back to the caller when something goes wrong. You need to make sure that the interface makes sense to everyone, not just you. You may even need to write up some documentation (ugh). And when you are all done and have covered every base, someone will call your component in a way you never expected, and of course it won’t work because all of the code we write is rife with bugs, and everyone will argue about how this component “should” be used, and someone will demand to see the unit test coverage stats, and someone else will schedule a meeting to define the scope, and someone else ramble on about how we need a framework, and the manager rolls his eyes and swears never to let these damn developers try to build something fancy again, and nobody is actually getting any real work done.

Worser Is More Gooder

Of course, some will argue that you should always try to make your components as reusable as possible, because it requires you to work through all of those quality issues no matter what, and will produce better software. This would be great if your sole goal was to create the best software in the world, but nobody is paying you to do that. No, you are being paid to write software of sufficient quality within the time and budget allotted. If you spend unnecessarily time gold-plating your code, it may make you feel cool, but it is outright wasteful. I’m not saying to cut corners when you should not, but I what I AM saying is that there definitely are times when it actually does make sense to cut comers. You need to draw a line in the sand of exactly how good this product really needs to be and stick to that, otherwise you’ll never finish. You can software that is really cool, or you can build software that ships. Only one of those options is actually useful to society.

But, But, But….

OK, so don’t make something reusable if you done need to. However, what if you think you are going to need it to be reusable? I have a secret to tell you: YAGNI.

I can’t tell you how many times I’ve been working on a very specific implementation to solve a very specific problem, and somebody (who usually has initials in his job title) chimes in saying “well, make this and that and the other thing configurable, so when we sell some other product to some other company, we can include it just by flipping a few switches.” This person is figuring that “it’s just an ‘if’ statement, what’s the big deal?”, but that person is not taking into account the increased code complexity and the exponential increase in testing requirements. Often times, this is even a former developer, who actually knows how code works, but has been out of the trenches for long enough that it has impaired their judgment about code complexity and its day-to-day impacts.

But then again, math solves everything. Say your QA department originally had 143 test scripts to run through before release, and now you’ve added some new configurable switch into the system. If you really want to be thorough, you should now have 286 test scripts, because you now have to retest everything with the switch turned on, and then again with the switch turned off. Say you had actually added to different switches? 572 test scripts. That’s a lot of work for a feature that will never get used. And come on, between you and me and the desk, we all know that Mr. Executive SVP COO is never going to close those magical deals with XYZ Bank and ABC Manufacturing, partly because he has no idea what he’s selling, but also partly because you guys can’t ship anything because you now have 1144 test scripts to run through to get a small release out the door.

So How Do I Know What To Reuse?

If you aren’t going stand around and guess what to reuse, how we will know? Easy, stop trying to prematurely reuse anything. Instead, refactor your existing code to reuse that which is already duplicated, where you can reasonably say will actually benefit from reuse and reduce overall maintenance and complexity.

How do you know when that is? Use that fancy experience and judgment of yours, it’s the only thing that separates you from the robots that will be doing your job some day.

Well what if I don’t have the necessary experience and judgment? Easy, pay me to write your code for you. mmooney@mmdbsolutions.com. </plug>

Anyhow, my rule of thumb is: Never build something to be reused until you actually have two systems that actually need to reuse it right now. If you only have one thing that will use it right now, and that other mythical feature will also use it some day, deal with it when that feature comes along (hint: never). Even if that feature comes along, the changes that you actually predicted and designed for it correctly is approximately zero, so you’re still going to have to make design changes anyway. However, if you kept it lean and simple, it’s simply a matter of adding the new code you need to a small lightweight base. But if you tried to build something big and fancy and configurable, you’ll now have to spend twice as much time disassembling all the unnecessarily complicated junk you build around it to support the thing that you were unsuccessfully trying to support in the first place. The easiest code to refactor is the code that doesn’t yet exist.

So yeah, YAGNI.

12 thoughts on “Reusable Code Is Bad

  1. Pingback: Tweets that mention The Mooney Project » Blog Archive » Reusable Code Is Bad -- Topsy.com

  2. Good points.

    I think as developers we all know you can’t get to 100% in one lifetime.

    The difficulty is justifying to non-developers why all software is inherently buggy.

    The perception is that coders intentionally cut corners and do a sloppy job because we don’t care about end users.

    If you make code more single purpose then it goes a long way towards changing that perception.

  3. Mike, interesting article but it only makes sense to a developer who has already been indoctrinated in the reusable code premise. There is no way I would want my jr. developers reading this article. I am in the midst of cleaning up some really old code where a particular calculation has been implemented 7 different ways in 7 different places. End users do not understand when a problem gets fixed in 1 place, how come that same (or different) problem still exists in 6 others. That’s where I explain to my devs the usefulness of reusable functions and until my devs come to that conclusion naturally, only then will I admit to them that there are exceptions. I guess what I’m saying is your article should have a disclaimer: Advanced Developers only! Until you have learned a rule inside and out, you don’t know when it’s ok to break it.

    -VG

  4. I’m finding that I swing back and forth a bit, and am trying the complexity/guessing reusability angle again. I’m frustrated with how many highly similar things we have written around the office and we never have time to go back and combine the similar pieces. The idea was always write once, copy twice, refactor the third. It is significantly faster and easier to copy, and it’s hard to justify the time to refactor to the decision-makers that saw the same feature implemented much quicker before.

    Going forward, we’re trying to make the one giant reusable system with lots of flags to turn all the bits on and off and put new clients on that system. If the feature isn’t generic, it doesn’t go into the system and the client doesn’t get it, so we’re demanding the time up front. If one client wants something that’s not too terribly crazy, odds are someone else may want it, too. If it is crazy, we either find a way to redefine it that isn’t, or we just don’t offer it.

    At least that’s the hope. My guess is two years from now I’ll be back in the camp I was in two year ago when the configuration monster grows out of control.

  5. Pingback: The Mooney Project » The Framework Myth

  6. One thing that reusable code gives is modular code. That means your code and logic will be separated more properly and therefore a lot of other problems avoided. I think modular code is a better goal to strive for, rather than reusability. There’s one problem – it’s not that easy to recognize – but if it’s reusable it’s inherently modular. So for beginners – write reusable code – that way it’s easier to learn about modularity.

    If I start adding some new big feature – I develop it separately from the project. That way I know I won’t glue it in any way I can, but find a good interface for it. Later I’ll do the adaptations if necessary, even if it breaks the reusability.

  7. My take:

    Design libraries for reuse, glue code to bind together, and logic code to call libraries through the glue.

    Only the libraries are reusable, as they have a defined and limited purpose, the glue code is non-reusable and throwaway, and the logic code is copy-pasta friendly for modifications if needed for a different purpose elsewhere.

  8. Reusable code is bad, reused code is good.

    First, build only for your need.
    Then if a close need happens, do the *
    mininum* refactoring to reuse it.
    Rinse, repeat.
    But keep on eye on complexity, maybe this component does too much, maybe it is time to cut it in 2.

    Finding this balance (factoring/cutting) is one of the skill of a professional.

  9. Pingback: Most interesting links of December « The Holy Java

  10. Pingback: You Arent Gonna Need It – Code Reuse — Numiko Labs

  11. No, reusable code is good, specifically say the reusable code the Django developers wrote (on the job, and still got their work done).

    Even on a smaller level – the ‘implementing it in n places’ case mentioned above blows the complexity and testing up so much we shouldn’t even be having this discussion….people need to have some sense about parametrizing things and identifying when 10 problems are just slightly different cases of one problem. It helps write less code and usually is what developers are paid to do…

  12. Pingback: The Mooney Project » MMDB.Shared: Enums Made Simple(r)

Leave a reply

required

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>