The Design of Software (CLOSED)

A public forum for discussing the design of software, from the user interface to the code architecture. Now closed.

The "Design of Software" discussion group has been merged with the main Joel on Software discussion group.

The archives will remain online indefinitely.

When not to re-factor and start anew?

The modern creed seems to be: never throw out old code, re-factor it. The question I have is when should you throw out old code, and start anew? Some details:

I'll stay away from mentioning specific technologies. I have a legacy system that has been in use since the mid-90s. It's been used successfully since then until recently, when the underlying principles that if works upon have changed. Since this has happened it has been ripped apart in order for it to "just work" within the new business rules. However this is not a real solution as this has resulted in some old rules being enforced that shouldn't, some new rules that aren't enforced that should, and general system problems as new bugs have been introduced in the course of hacking the thing up and putting it back together.

So this is where I come in, being charged with version 2 of this piece of software. My initial reaction was amazement that this system worked at all. It's not object oriented, it's not functional... It's simply a large patchwork of code that fits together most of the time, and is a royal nightmare to work on (changes of course have ripple effects).

So, the way I see it, a re-factor could be done, likely using an OO approach using the same language and probably some sort of ORM. I'm comfortable with this, but I believe there is another language that has better OO-capabilities. I'm equally comfortable with this. However my understanding is that at this point, it is not a re-factor. I'm not even sure if the first option could be considered a re-factor, but I am fairly certain that implementing version 2 in a new language with a completely new architecture can not be considered re-factoring.

So, I ask you, when is not worth re-factoring?
Josh Zamor Send private email
Sunday, June 10, 2007
One thing I have learned is that the decision is both a technical and an economic one. Refactoring can be done incrementally as time allows in a manner that ensures that you can still ship a working product even before the refactoring is complete. If you start over, your customers don't benefit from the work until the rewrite is complete. Another advantage of refactoring is that it can help with the process of becoming more familiar with the application - knowledge that can be beneficial or even critical if and when a rewrite occurs. From a purely technically viewpoint starting over with a better design and possibly better technology is an attractive option. And if possible, you can do both.
Mike Hopper Send private email
Sunday, June 10, 2007
Joel has at least 2 articles about this; one about not rewriting Netscape, and one about how he refactored something (CityDesk, maybe?) quite successfully.

On the other hand, one of the Steves from Microsoft (McConnell or Maguire) had some data where they plotted bugs per module.  The conclusion was that certain modules were particularly buggy - way above what you'd expect across the entire project - and that the best thing to do in that case was rip the module out and rewrite.

On the pro side for refactoring, you can take it in steps, so you reduce the risk of the project.

Another issue is long term support.  We had a single project that was written in a different technology that what we were using on other projects (we had started doing technology A, then switched to B for this one project, then switched to C for new ones), so when the B one started having severe problems, we decided to port it over to C - that was not a refactoring, but it made long term sense.  And we did it in such a way that we converted it first and fixed some of the most annoying bugs, then added some whiz-bang features in the second iteration, so the users were really on board too.

Part of it depends on the complexity; our porting project we were able to do screen by screen and make sure it worked.  For our other projects in technology A, we left most of them there and made fixes as needed, because the problems weren't severe enough to warrant the porting.

Then the vendor of A technology announced it was not being supported any more, so that changed our perspective too.

So I guess the answer is "it depends."  Hopefully I've highlighted some issues to consider.
Michael G Send private email
Monday, June 11, 2007
The problem is the chances of you delivering are almost zero while you have a working shipping project you'll always be compared with. Inevitably as your schedules slip the hacks for the next release will made and eventually your project will be killed while the old code is even worse than it was.

Try new development in your new framework. Hide as much as you can behind facades or service interfaces. Convert other parts as fast as you can.

You think you will be the one to succeed, but unless your product is very simple you won't be. So just skip that and believe in evolution. The fossil record shows it's true.
son of parnas
Monday, June 11, 2007
I would recommend doing just a basic refactoring.  Refactoring works with procedural languages just as well as OO languages.  The one thread I have seen in common with legacy application rewrites is that they tend to fail horribly (there are a lot of reasons, technical and political), so clean up the code, fix some bugs, and clean up the code some more.
Wayne M.
Monday, June 11, 2007
I would wager that you have a huge amount of "institutional knowledge and rules" that are already implemented in the App and not documented anywhere.  If you throw out the whole thing in one fell swoop, you're going to tick off people for which the system "has always worked that way".

If you can start ripping out and re-implementing individual modules, do it... starting with the most problematic ones.
KC Send private email
Monday, June 11, 2007
A few thoughts to help you with your decision:

1) If you start from scratch you will have to redo the requirements and design phases. Not so necessary if you refactor.

2) Rewriting will take longer, and be more difficult, than you think. Mainly this will be because of cases that you hadn't realised existed, but are handled by the existing code.

3) The first release of the rewritten code will be worse than the existing code. Unless you spend a lot of time on consistency check, and possibly even then.
DJ Clayworth
Monday, June 11, 2007
Normally, I'd say refactor if at all possible.  In light of recent events at my work, I see there are times for a rewrite.  Like when your company has an onsite development team, but the managers outsource the only interesting project, they write very bad code and leave the onsite team for maintenance.  We can barely understand the horrible code we've inherited, yet it's up to us to polish this turd.  When we say we can't understand what the hell they've done, it makes us look bad because, as we've been told, 'we can't do our jobs'.

Unfortunately, sometimes a rewrite is necessary.
Monday, June 11, 2007
Start by coding tests that pass on the current system ... these will aid you immensely when you break the system during refactoring.  (Notice that I said "WHEN")  Breaking the system during refactoring isn't nearly so bad when you have a good mechanism for A) immediately noticing that it is broken and B) tools to point you to where you broke it.

Another important idea is to plan ahead ... if you're going for an OO design, you should determine what objects must be created and what their responsibilities will be.  Then go through the code and "estimate" which blocks you believe will be in each object.

Now what you're ready to start the refactoring, start by extracting the object that is most defined.  Refactoring the easiest parts first helps to shrink the codebase and highlight the real oddities in the original code.  When you extract all the obvious object, you'll probably end up creating a bunch of helper classes, factories and other "auxiliary code".  This is a good time to go looking for design patterns ... it's not the straight-foreward objects that require patterns.

I probably don't need to push the use of source control to this crowd, but make very frequent commits during refactoring.  Make a change, test that it still works and commit the change and move to the next small task.  The security of easily going back to a working system will ease you're mind.
Steve Moyer Send private email
Monday, June 11, 2007
"However this is not a real solution as this has resulted in some old rules being enforced that shouldn't, some new rules that aren't enforced that should..."

It's just an opinion and no less valid than the others, but I suspect this is going to be the most problematic aspect. More specifically, are you being asked to create the original solution that the company desired, or refine the currently existing, unplanned for solution? As JC said, some people have come to depend on the system working the way it does now. A fix in your eyes may be a bug in their eyes.

If you must roll up your sleeves and get started right away, I'd agree with the others and suggest you bite the bullet and refactor. If nothing else, you'll give people time to complain and it will be easier for you to figure out what changes you made and need to undo when something breaks.

Having said that, I really like the rewrite idea based on the circumstances, but I would truely start at the begining of the requirements phrase. Determine what business goals need to be done, get everyone to buy off on it, start training them so they know what they have to do, do a budget and schedule and so on. In this case, the critical question becames whether the costs of developing a new product is cheaper than the costs of maintaining the old spaghetti code?
Monday, June 11, 2007
More from experience: the few times I threw away code because it looked too bad and tried to rewrite from scratch, it turned out not to be a good idea. The code looked better, even performed better in some cases, but performed worse in other. Quality gain: all in all, close to zero.

On the other hand, the more I practice refactoring, the more I like it! When I rewrite, I get the initial kick from being, at last, king and master in my own castle, but after that it's the usual return of the frustration from 1) having bugs that I did not expect, and 2) having angry users/bosses on my back because things are actually not getting better despite my best efforts. I hate that.

But when I refactor, I almost always get the satisfaction of leaving things in a better state then before I came. Every single day. I love that!
Carl Seleborg Send private email
Tuesday, June 12, 2007
If you have version n of a product, you should not refactor for ver n.1

However for version n+1, refactoring or even rewriting from scratch is an option (with other considerations) and is good, imo, especially early on in your product life when the code can be scrappy.

Carmack wrote each iteration of his game engine from scratch each time up to Q3 i think.
Tuesday, June 12, 2007
Obviously, there are a million possible business reasons why refactoring would not be a viable choice, including licensing issues, obscure technologies where experts are rare or expensive, etc. These are no fun but companies have to make money.

However, you should never, never, never start over for technical reasons alone. If you have production code that works (even if it only partially works) don't even think about burning all of those hours of sweat. Period.

Refactoring, however, doesn't necessarily mean keeping all the technologies the same. As our man Martin tells us, "Refactoring is a disciplined technique for restructuring an existing body of code, altering its internal structure without changing its external behavior." You can begin to move a system away from WebObjects or Perl/CGI or your favorite "outdated" 90's technology one piece at a time.

Even if the code isn't modular at all, it still consists of blocks (or at least, groups of lines of code) where you can add unit test points. This means that as you build version 2 out of version 1, you will be able to prove that they do the exact same thing everywhere you want them to.

Buy the Fowler book, if you
Robby Slaughter Send private email
Friday, June 15, 2007
I would refactor, for all the reasons others have stated.
Two books you should keep at your elbow:

Refactoring, by Martin Fowler et al

Working Effectively with Legacy Code, by Michael Feathers

The former provides a catalog of refactorings.
The latter provides guidelines for minimizing the risks associated with refactoring, including where to start.

- Sam
Samuel Reynolds Send private email
Wednesday, July 04, 2007

This topic is archived. No further replies will be accepted.

Other recent topics Other recent topics
Powered by FogBugz