jfroebe has asked for the wisdom of the Perl Monks concerning the following question:

Hi,

This is more a preference question, I admit. At what point do you quit adding features and patches to existing code, give up on it, and rewrite it from scratch the way it should have been done?

Scenerios would include the discovery of a new CPAN module that would have made your life much easier and your code much smaller, a different way of doing what you were doing to clean the code, etc.

When is enough enough?

Update: Most of the responses so far assume that there is a single ownership (whomever wrote/maintains it) of the code. Meaning that the current owner was the original owner. Would any of the answers be different if the code was from a previous owner and the programming style is very different than your own style?

Jason L. Froebe

No one has seen what you have seen, and until that happens, we're all going to think that you're nuts. - Jack O'Neil, Stargate SG-1

Replies are listed 'Best First'.
Re: rebuilding working code
by chromatic (Archbishop) on Jun 02, 2004 at 19:05 UTC
    At what point do you quit adding features and patches to existing code, give up on it, and rewrite it from scratch the way it should have been done?

    When you can afford not to do maintenance on the existing version and spend your time playing catchup by duplicating working (if ugly) features.

    That is to say "not very often at all".

    I think the idea that rewriting from scratch is good is one of the myths open source developers tell ourselves.

      I think the idea that rewriting from scratch is good is one of the myths open source developers tell ourselves.

      That's an excellent point, and I should probably have it tattooed inside my eyelids.

      More specifically (or more agile-methods-dogmatically, I suppose), not being able to change bits and pieces of your code on an as-needed basis probably means that there's something missing from your project: a proper revision-control system, for instance, or an adequate test suite. Instead of throwing out your existing codebase (which probably does a lot of things right) and rewriting it from scratch, you might be better off asking "Why can't I refactor the existing code?" and acting on the answer.

      On the other hand, "Plan to throw one away; you will, anyhow." Arguing with Brooks about software engineering practice feels sort of like arguing with Knuth about typesetting software. If your code does absolutely (or even nearly) nothing right, and you don't mind losing a mildly functional program while you recreate infrastructure, treating the current version as a giant prototype and starting again could be the right thing to do. Chances are good that this sort of thing is easier to do with a personal project than with mission-critical business code.

      --
      F o x t r o t U n i f o r m
      Found a typo in this node? /msg me
      % man 3 strfry

        Arguing with Brooks about software engineering practice feels sort of like arguing with Knuth about typesetting software.

        I'm willing to argue with Brooks and Knuth when they're wrong. :)

        I interpret Brooks' comment above as countering the fallacy that you can know ahead of time exactly what you need to build and that you'll design it appropriately without having built it. In that vein, anything you can do to incorporate useful feedback into the coding process will help you produce the software you really need to produce. Remember, writing an operating system in assembly in the 1960s is a little more difficult than writing a business-logic server in Perl in the 2000s.

        As for Knuth, I'll paraphrase what Bob Frankston once told me. "You can assume that the cost of memory access is uniform, but it's not."

        On the other hand, "Plan to throw one away; you will, anyhow." Arguing with Brooks about software engineering practice feels sort of like arguing with Knuth about typesetting software.

        Agile folk still throw one away. We just do it in teeny-tiny pieces instead of all in one go :-)

        Actually, Brooks had changed his mind at least once since The Mythical Man-Month or wherever his quote is from. This from a teleconferenced lecture he gave in 1996:
        Our designs are so complex we can't do it right 1st time by
        pure thought.  To expect this is to be arrogant.  So, we
        need a design + build philosophy that incorporates 
        evolutionary growth.
        
            * no waterfall design!
            * no plan-to-throw-one-away design either!
        
        
        Perl's fast "compile-link-load cycle" and CPAN library seem to be a big help to me when I'm evoloving applications.
Re: rebuilding working code
by sweetblood (Prior) on Jun 02, 2004 at 18:48 UTC
    I know in my environment we definitely "don't fix it if it ain't broke". That is not always my preference, but we have very limited resources. To rewrite just to make code smaller, would certainly be very low on my priorities. Also to replace functional, readable code with a CPAN module seems like little reason to spend too much time on anything. If the script requires a great deal of maintainance and re-writing will reduce that significantly, then you may have good reason to rewrite. It's really a judgement call only you and your manager can decide on.

    Good Luck

    Sweetblood

Re: rebuilding working code
by dragonchild (Archbishop) on Jun 02, 2004 at 18:49 UTC
    I use the "Pissed-Off" meter. It goes something like this:
    1. I am happily bopping along.
    2. I run into an annoyance.
    3. If that annoyance is really annoying (i.e., it pisses me off), I fix it.
    4. If it isn't that annoying, I live with it ... until it pisses me off, then I fix it.
    5. If I know the annoyance will severely piss me off in the future and I have time now, I fix it.

    But, then again, I love refactoring code I just wrote three months ago. Over and over and over. Kinda like OCD, but easier on the skin.

    ------
    We are the carpenters and bricklayers of the Information Age.

    Then there are Damian modules.... *sigh* ... that's not about being less-lazy -- that's about being on some really good drugs -- you know, there is no spoon. - flyingmoose

    I shouldn't have to say this, but any code, unless otherwise stated, is untested

Re: rebuilding working code
by tomhukins (Curate) on Jun 02, 2004 at 19:06 UTC

    I don't think preferences should determine your decision. It's a matter of judgement based on experience - a personal issue, certainly - but not preference.

    Ideally, you never throw your code away. Agile methodologies such as frequent refactoring and testing help you avoid this: refactoring makes your code less messy; testing checks that your code meets your needs where your needs are specified within the tests.

    Your code should allow the integration of new features, whether from CPAN or not. You need to take good care of it as it evolves. I like the pragmatic programmers' programming as gardening metaphor.

    Taking responsibility for others' badly maintained, disorganised code needs some thought. As does dealing with your own badly written code. No matter how hard you try, it's easy to write rubbish. Sometimes you write bad code deliberately: you evaluate risk, experiment and learn.

    So, when should you rewrite code? It depends on what you want to do. If the code won't evolve significantly, maybe you can throw a few tests round it and hope nobody asks you to modify it significantly. This happens less often than you might hope. Alternatively, you may find you can refactor much of it, writing tests as you break the code up into meaningful routines. If you find it hard to decide initially, why not set aside some time to experiment with refactoring? You may give up on this, but you will understand the code better.

    A couple of months ago I chose to rewrite some code and only discovered its complexity as I got more involved with it. In the end, we gave up after spending too much effort completely overhauling the existing work. This reminded me of the importance of frequently, honestly evaluating work, understanding risk and recognising the positive aspects of failure.

Re: rebuilding working code
by fuzzyping (Chaplain) on Jun 02, 2004 at 18:51 UTC
    For me, that point is when I've grown tired of investing my time in band-aid code. Hopefully this comes early in the design process, if not it might be more fruitful to slowly, gracefully, "steer" the project in the new direction.

    In the case of Hatchet, I learned soon enough that the advanced sorting/search/statistics features that users were begging for would be damn near impossible using the existing design. Fortunately, the project was immature enough that it wasn't too harsh an effort to ask folks to move from the old design to the new SQLite-based engine. Yes, it required that they basically un/re-install the whole shmere, but it also gave them a better upgrade path with exciting new features (that I could incorporate without fear of burnout).

    In short, there is no easy answer, but you'll probably know when the time is right. Just don't be afraid to jump because you might piss off users. Tomorrow might be a day too late. ;-)

    -fp
Re: rebuilding working code
by TomDLux (Vicar) on Jun 03, 2004 at 01:54 UTC

    Plan to throw one away refers to prototyping. If you don't prototype, you'll write and re-write as much code, in debugging and ading features ... except you'll be doing it with released code.

    The other side of the coin is second system syndrome. It's discussed in Joel Splosky's article Things You Should Never Do. The basic idea is that you decide an evolving program has become so crufty that it can't be repaired or improved, it has to be totally re-designed and re-written. Nine or ten years later, Netscape 6 becomes available. The problem is that you are starting over, generating a totally new product, just like your competitors do ... except you have to remain compatible with your features while they don't.

    The correct solution, according to Joel, is to adopt the eXtreme Programming concept of refactoring, that is, extracting code and encapsulating it into a routine. refactoring is inlining in reverse, if you know C++.

    That is, instead of throwing it away, baby and bathwater and all, improve things, one item at a time. Take repeated code and convert it into a routine. Take a bunch of related routines and turn them into a module, or an object. Once concepts are separated, it becomes simpler to benchmark things, and replace a module with a different implementation, a different algorithm.

    Of course, you need testing to determine whether changes break existing requirements. But you'll only regret writing tests until the first time you go back to do maintenance on existing code, and find you can verify correctness in a fraction of the time. Anyway, that's a topic for a different Seeker of Perl Wisdom.

    --
    TTTATCGGTCGTTATATAGATGTTTGCA

Re: rebuilding working code
by sleepingsquirrel (Chaplain) on Jun 02, 2004 at 18:57 UTC
    Some people are of the opinion that you should never rewrite your code. I don't necessarily agree with the conclusion, but I do agree with his fundamental philosophy: "It's harder to read code than to write it."
Re: rebuilding working code
by Preceptor (Deacon) on Jun 03, 2004 at 13:29 UTC
    I'm of the opinion that 'fixing' code is fine - that's what it's for.
    But there comes a certain point at which you're _hacking_ code. By which I mean that you're putting in things to work around other things that don't work the way they should.
    That's about the point at which you start thinking about re-writing.
    It's more difficult with multiple ownership of the code. Provided it's in the public domain, and that there is someone ready, willing and able to re-do it, then as far as I'm concerned, fair enough.
    Now whether this actually _does_ get re-written or not, is largely a factor (from my PoV) of how much I understand the code, it's objectives and how it does it. And how much time I have free.
    Most often it's 'urgent' and needs a fix yesterday, so I'll hack it. And make a mental note to come back to it 'when I have time'. Several mental notes flags it up as 'important' - there's an old systems admin adage - if you have to do something twice, then automate and script it.