Please help: When to rewrite?



  • With 3 days left to launch and a load of only-nominally-tested changes just added to a tangle of spaghetti code (with no existing unit tests or testing scripts), how do you decide whether to a) try to sort out whether the code still does what it's supposed to, or b) rewrite the whole thing cleanly from scratch?

    I'd really appreciate any suggestions.

    Thanks.
     



  • Hate to be the one to tell you, but in my opinion it sounds like rewriting is out of the question.  Three days before launch, you can either try to untangle the spaghetti or rewrite.  Chances are you're going to take a lot of criticism if you miss your launch date on a rewrite.  YMMV, or course.



  • I tend to be a bigger fan of rewriting when I have the chance than some people...but if you only have 3 days left, my gut instinct is to leave it. 

    If the code is hard to understand, then there's at least a decent chance you'll un-fix an old bug fix that is hiding in the spaghetti.  At least leaving it alone you just have to worry about the new code that's been added.

    -cw



  • This is a good example of why you should always write unit tests.  Once you have tests for all of your functionality you can add a bunch of quick hacks and still be confident that it all works.  Then you can take your time refactor the design back into something sane while still keeping the unit tests passing.



  • Thanks, Oscar and CodeWhisperer, you definitely have a point about the short time to launch.

    The code actually shouldn't be nearly as complex as it is.  Rewritten to actually use (god forbid!) function calls, it should actually be fairly simple to understand and maintain, but as it stands, it's virtually impossible to handle error conditions cleanly.   I'm going to have to maintain this code in the future, but I'm unlikely to get another chance to clean it up.

    It's a 4-screen series of PHP scripts (plus a couple includes) at less than 300 lines each -- maybe 1200-1500 lines of code altogether.  It's fairly thoroughly and accurately, although not always informatively commented.  So probably difficult but not unreasonable to rewrite and retest in 3 days, which is why I'm wavering.

    It's a new site feature, but has been in development for longer than it should have (due to said spaghetti), so there aren't old bugs to worry about that were fixed after the client encountered them, but there might be corrections for spaghetti side-effects (meatballs?) that have been tacked on here and there.
     



  • @burnmp3s said:

    This is a good example of why you should always write unit tests.  Once you have tests for all of your functionality you can add a bunch of quick hacks and still be confident that it all works.  Then you can take your time refactor the design back into something sane while still keeping the unit tests passing.

    Absolutely.  Can you suggest, though, how to develop unit tests for code that doesn't even use subroutines?  (*clubs predecessor with cluebat*)  I can't think of anything except embedding a bunch of debug-style print statements.



  • @gotaq said:

    @burnmp3s said:

    This is a good example of why you should always write unit tests.  Once you have tests for all of your functionality you can add a bunch of quick hacks and still be confident that it all works.  Then you can take your time refactor the design back into something sane while still keeping the unit tests passing.

    Absolutely.  Can you suggest, though, how to develop unit tests for code that doesn't even use subroutines?  (*clubs predecessor with cluebat*)  I can't think of anything except embedding a bunch of debug-style print statements.

    I inherited a similar application.  It consisted of a few 1000+ line functions, no classes, and tons of global variables.

    I ended up writing a bunch of unit tests for each function, trying to cover as much of the code as possible.  At the end of each test I checked all of the global variables to make sure the program was in the correct state.

    After I had a full set of tests, I started extracting parts of the code into functions and classes.  Each time I added a new function or class I made sure all of the old tests still worked and then I wrote a new set of tests for the new function or class.

    By the end I had removed all of the global variables and had a nice design with full test coverage.  The best part is that I could do a release at any time during the process, because I only made small changes and always kept the tests passing.



  • Rewrite as much as you're comfortable taking on.

    If you have an editor that helps with refactoring (extract method will be your savior), then at least start logically grouping things.

    Start by at least laying down a couple unit tests and going from there.

    Personally, I've made significant changes to many systems but I have never, ever had to rewrite from scratch. YMMV. Start with creating unit tests that capture current behavior. Then, start moving code around and ensuring that your unit tests stay green. Rewriting or refactoring existing systems without unit tests isn't smart... it just makes you guess harder.

     



  • It's most likely to late to rewrite it and test it properly, so instead of (mostly) working spagetti code, you'd have nice-looking but buggy new code when going live. IMO not an option.

    Anyway, take a few hours and try to refactor your code so at least it's a bit less spagetti. Try to break it into smaller units (functions, classes, whatever) where possible and necessary. By doing that, it will be easier for you to write unit tests later; and given enough time, you can rewrite the program unit per unit then.



  • Thanks, everyone, for your suggestions.  At this point, I think I'm going to start by checking that everything is still working properly (which I don't think it is).  After that, there's a bunch of untangling to do before I could even start moving things into functions that made any sense (sigh).  Wish me luck!



  • Quick Update:

    I'm not sure whether I regret not rewriting.  The code was, in fact, not only messy but fairly broken, so instead of trying to refactor, I've just spent the past 2 days in conference with the original developer, playing whack-a-mole with bugs.

    It's still not working correctly.



  • @gotaq said:

    Quick Update:

    I'm not sure whether I regret not rewriting.  The code was, in fact, not only messy but fairly broken, so instead of trying to refactor, I've just spent the past 2 days in conference with the original developer, playing whack-a-mole with bugs.

    It's still not working correctly.

    You still made the right decision. Rewriting means having to discover all the same bugs and unexpected pitfalls that the original author had to deal with. No one could do it in three days, unless it's an incredibly small program.



  • @VGR said:

    Rewriting means having to discover all the same bugs and unexpected pitfalls that the original author had to deal with. No one could do it in three days, unless it's an incredibly small program.

    You're right, of course.  I'm just incredibly frustrated right now. 

    And yes, it's a pretty small program (about 1200 lines, could probably be rewritten into 800) that does very simple things (prints an HTML form, reads in form data, validates it, saves it to a database).  The validation rules aren't especially fancy.  The database doesn't do anything unusual.  The bugs aren't special cases or unexpected pitfalls, just stupid oversights and unexpected code interactions because everything is a global variable, and everything happens within the global scope.  (One side effect is that there's no easy way to abort processing on error except with a zillion nested conditionals. I've never, ever wanted to write a "goto" statement until this week -- too bad PHP doesn't support it)

    The only reason there are all these bugs to hunt down in the first place is because it was created in such a brain-dead manner.

    Yeah, there are probably some problems we'd run into rewriting from scratch, but right now I feel like catching and fixing them would take much less time than it currently is, because at least each fix wouldn't introduce 6 more bugs.

    /rant

    Tell you one thing -- I'm learning a whole lot about how not to write a PHP script. 



  • So, after those 3 days, and another two weeks, how did it go?



  • i'm going to take a guess at "Put into the wild, and the customer hasn't complained yet" for 200 points.



  • @Emyr said:

    So, after those 3 days, and another two weeks, how did it go?

    Horribly.  Finding and fixing bugs up to the minute we were supposed to go live -- and two days beyond (after it was set up for the client to test and approve).  The client still hasn't looked at it to give sign-off, though.  Go figure.



  • @gotaq said:

    @Emyr said:

    So, after those 3 days, and another two weeks, how did it go?

    Horribly.  Finding and fixing bugs up to the minute we were supposed to go live -- and two days beyond (after it was set up for the client to test and approve).  The client still hasn't looked at it to give sign-off, though.  Go figure.

    I didn't want to say anything at the time, but I didn't give the project a high probability of arriving on time.  In my experience, that's the point where you continue to put in your best effort even though it won't happen when someone else decided it would.

    At this point, I'd recommend committing a little time to a rewrite on the side.  The project's now officially late, so your refactoring can't be cited as the source of the problem.



  • @Oscar L said:

    At this point, I'd recommend committing a little time to a rewrite on the side.  The project's now officially late, so your refactoring can't be cited as the source of the problem.

    I'd love to.  But now that the project is in "waiting for client approval" stage, my time has (as expected) been officially committed to several new and of course urgent projects.



  • @ammoQ:

     How do you unit test PHP anyway? Just curious, as I am not a PHP developer by any stretch.



  • @kirchhoff said:

    @ammoQ:

     How do you unit test PHP anyway? Just curious, as I am not a PHP developer by any stretch.

    I'm not ammoQ, I don't do php anymore, and don't know how well this works, But tster provided a link to phpunit on sourceforge in the effective unit testing thread.  Here is the link he provided.  http://phpunit.sourceforge.net/

     


Log in to reply