A piece of software is a patchwork of old and undocumented efforts. There are no comments, no documentation, and the code is hairy -- it involves Unix shell scripts that check for dummy files and then call SQL statements that call database procedures that modify data.

The original developers have left and we score a solid 2 on the Joel Test but I can raise it to at least 4 - yay...

The code is reasonably error-free, but we constantly need to add new features into it which is highly error-prone because of the state of the code, so the deadlines slip and the efforts rise.

We want to rewrite this software in order to reduce maintenance and development efforts. As part of the rewrite, we will introduce specs, comments, test cases -- all things that we currently don't have. It'll still be a bit complex afterwards, but no more than necessary.

This is not a BIG rewrite because we are not going to switch languages or frameworks; we'll still need shell scripts (but fewer) and database procedures (but fewer). The implications are also fairly simple because we're in control of the installation sites and we can fully replace the old code with the new code at the flick of a switch.

I know a rewrite is never good but I think these are reasonable counterarguments. Nevertheless, my concern is the typical danger of introducing brand new bugs instead of the old known ones, and also the danger of not implementing certain details because nobody even knows they exist or are needed.

How can I approach this rewrite in an efficient manner?

  • 4
    make regression tests – ratchet freak Dec 4 '13 at 10:43
  • I'd agree with @ratchetfreak. Make unit testing for the current code (as it has probably not been done at this point), and only push the new version to production once it at least passes the exact same tests. – Pierre Arlaud Dec 4 '13 at 10:57
  • 1
  • @ratchetfreak I wish I couple upvote that comment over and over again. – Ross Patterson Dec 4 '13 at 11:39
  • To expand on @ratchetfreak 's answer. Write those regression test now. Write as many as you can to fulfil all known requirements/use case - and then some. After that, no matter which approach you take to rewriting/refactoring, these tests will be your best friends in all the world. – Mawg says reinstate Monica Jun 8 '15 at 9:51

It's not that rewritten code is bad, it's how you do it. Everyone thinks their case is the exception.

A large rewrite is like climbing a mountain. You don't want to remove the previous safety until the next one is in place, and you take small, deliberate steps. It feels like taking the time to do it safely is keeping you from reaching the top, but you eventually do get there.

Figure out the easiest, smallest, most beneficial part you can refactor, put tests around it, then do it, without changing the rest of the code. Then repeat the process. Sometimes this requires temporary hack code to bridge between the old and the new code. Things might temporarily get worse before they get better, but you will move in the right direction in the long term. The idea is that if you screw up any part of the rewrite, you can get back to a known good state without reverting more than a day or so of work in source control.

  • Yes. This. Incremental rRefactoring > complete rewrite. Thanks Karl! – Torben Gundtofte-Bruun Dec 4 '13 at 15:59

I think you are overlooking something - you CAN'T rewrite it, because you've admitted you have no idea what it's doing!

It's great to realize that you'll need tests, but what are you going to test? You don't know what it does! How do you test it?

Before you can re-write, you have to spec it out, which means sitting down with the existing code for who knows how long and examining every SQL statement, every script and making sure you know what it's doing and why it's doing it. Especially important are identifying any weird side effects that turn out to be intended behaviors. All while maintaining the existing app as well. Good luck with that.

If you can't spend that kind of time on the spec (and most people can't), then you need to fix it piece by piece. When next you get a change order, identify what the function you are changing does, how it does it, write the tests, and re-write that piece.

  • I'm not saying we don't know what it does -- we maintain it and develop it further! On the contrary: we know that it does things in a very roundabout and unnecessarily complex way. – Torben Gundtofte-Bruun Dec 4 '13 at 12:06
  • @TorbenGundtofte-Bruun - Well, if you really DO know what it does (you have an informal spec, and can write a formal one easily), then you should be able to write the tests. That would be a necessary condition for doing a re-write, though I still would advise against it - you're likely to find (when you deploy the new version) oddball side things that no one knew anyone depended on, and you'll have to run around fixing N things really fast. If you refactor, then you'll never have more than one or two fires at a time when you deploy. – Michael Kohne Dec 4 '13 at 12:40

Make sure you have your team and your development processes solidified. I don't see how you can feel confident you're going to improve on this app with a Joel Test of 4. This project could use about 8. You could suffer the same fate this project did with uncooperative management, poor planning, inexperienced team members, lack of best practices, unexpected change requests, unreasonable time-frames. During many projects, "life happens" so you have to be prepared.

Hopefully, your company is paying to rewrite the app because it is important. Apps that are criticial usually have current bugs to fix and a large number of change requests with tight delivery schedules. You don't like the old code because it is difficult to maintain, so you want to compound the time to fix, add new features all while you're writing a new code base? You may save time in the long-term, but you're like a business with no cash flow. How can you deliver on the changes/fixes they need right now (Joel 5 - fix bugs before new code - users will demand this)? You need some efficiencies (Joel 1,2,3,6,7 - builds, source control, schedules, specs).

Your team would be in a better position to take on this project with the right tools and environment (Joel 8 (working conditions), 9 (best tools)). Is your company ready to support this project? Can everyone outside your group commit to testing? (Joel 10, 12)

There's going to be bugs (Joel 4 & 5) in the current code and your new app . Programmer turn-over (Joel 11 - candidates write code during interview).

You seem to be prepared to take on this project. Make sure everyone else is. You may need to run a tighter ship than most teams.

  • I fully agree with you. At the same time, it's my experience that a Joel score of 4 is pretty much as good as it's ever going to be, in any company I've ever worked in. Aiming for more is idealistic but not realistic -- at least outside the big software hotbeds. Backwater businesses as well as big corporate outfits just don't care about this Joel fella and his nifty ideas. We're lucky to have a ticket tracker and SVN, forget about automated builds. – Torben Gundtofte-Bruun Dec 4 '13 at 13:38
  • @TorbenGundtofte-Bruun - which is why most companies/teams shouldn't do a complete rewrite. How much luck is required to have SVN? Now getting everyone to use it properly, may be another story. If you've ever grabbed someone in the hall to try your app, you get one point. – JeffO Dec 4 '13 at 16:32
  • Last comment from me on this: even SVN is not a given in companies where each dept needs to justify every gigabyte of disk usage, mailbox size limits are enforced by policy, and computers&network is locked down for security. I'm talking insurance & banking industries here, lots of internal software projects but not a lot of wiggle room. We can't just go buy a pc and stick it under a desk and say that's our server / wiki / repo / etc. – Torben Gundtofte-Bruun Dec 4 '13 at 21:17

If possible, do it module by module.

If the current system is not "very modular", try and identify pieces that can be modularised, and refactor them 1 at a time, introducing test cases etc.

Start with what appears to be the easiest module. Get it right. Then move on to the next.

You seem to have a pretty good grasp of what you should be doing though, so good luck!

Not the answer you're looking for? Browse other questions tagged or ask your own question.