325

Just read the question about the Big Rewrites and I remembered a question that I've been wanting answered myself.

I have a horrible project passed down to me, written in old Java, using Struts 1.0, tables with inconsistent relationships, or no relationships at all and even tables without primary keys or fields meant to be primary keys but aren't unique at all. Somehow most of the app "just works". Most of the pages are reused (copy pasted code) and hard-coded. Everyone who's ever worked on the project has cursed it in one form or the other.

Now I had long considered to propose to upper management a total rewrite of this horrendous application. I'm slowly attempting to on personal time but I really feel that this deserves some dedicated resources to make it happen. Having read the articles on big rewrites I'm having second thoughts. And that's not good when I want to convince my superiors to support my rewrite. (I work in a fairly small company so the proposal has the possibility of being approved)

TL;DR When is a big rewrite the answer and what arguments can you use to support it?

3

25 Answers 25

375

Sorry, this is going to be long, but it's based on personal experience as both architect and developer on multiple rewrite projects.

The following conditions should cause you to consider some sort of rewrite. I'll talk about how to decide which one to do after that.

  • Developer ramp-up time is very high. If it takes any longer than below (by experience level) to ramp up a new developer, then the system needs to be redesigned. By ramp-up time, I mean the amount of time before the new developer is ready to do their first commit (on a small feature)
    • Fresh out of college - 1.5 months
    • Still green, but have worked on other projects before - 1 month
    • Mid level - 2 weeks
    • Experienced - 1 week
    • Senior level - 1 day
  • Deployment cannot be automated, because of the complexity of the existing architecture
  • Even simple bug fixes take too long because of the complexity of existing code
  • New features take too long, and cost too much because of the interdependence of the codebase (new features cannot be isolated, and therefore affect existing features)
  • The formal testing cycle takes too long because of the interdependence of the existing codebase.
  • Too many use cases are executed on too few screens. This causes training issues for the users and developers.
  • The technology that the current system is in demands it
    • Quality developers with experience in the technology are too hard to find
    • It is deprecated (It can't be upgraded to support newer platforms/features)
    • There is simply a much more expressive higher-level technology available
    • The cost of maintaining the infrastructure of the older technology is too high

These things are pretty self-evident. When to decide on a complete rewrite versus an incremental rebuild is more subjective, and therefore more politically charged. What I can say with conviction is that to categorically state that it is never a good idea is wrong.

If a system can be incrementally redesigned, and you have the full support of project sponsorship for such a thing, then you should do it. Here's the problem, though. Many systems cannot be incrementally redesigned. Here are some of the reasons I have encountered that prevent this (both technical and political).

  • Technical
    • The coupling of components is so high that changes to a single component cannot be isolated from other components. A redesign of a single component results in a cascade of changes not only to adjacent components, but indirectly to all components.
    • The technology stack is so complicated that future state design necessitates multiple infrastructure changes. This would be necessary in a complete rewrite as well, but if it's required in an incremental redesign, then you lose that advantage.
    • Redesigning a component results in a complete rewrite of that component anyway, because the existing design is so fubar that there's nothing worth saving. Again, you lose the advantage if this is the case.
  • Political
    • The sponsors cannot be made to understand that an incremental redesign requires a long-term commitment to the project. Inevitably, most organizations lose the appetite for the continuing budget drain that an incremental redesign creates. This loss of appetite is inevitable for a rewrite as well, but the sponsors will be more inclined to continue, because they don't want to be split between a partially complete new system and a partially obsolete old system.
    • The users of the system are too attached with their "current screens." If this is the case, you won't have the license to improve a vital part of the system (the front-end). A redesign lets you circumvent this problem, since they're starting with something new. They'll still insist on getting "the same screens," but you have a little more ammunition to push back.

Keep in mind that the total cost of redesiging incrementally is always higher than doing a complete rewrite, but the impact to the organization is usually smaller. In my opinion, if you can justify a rewrite, and you have superstar developers, then do it.

Only do it if you can be certain that there is the political will to see it through to completion. This means both executive and end user buy-in. Without it, you will fail. I'm assuming that this is why Joel says it's a bad idea. Executive and end-user buy-in looks like a two-headed unicorn to many architects. You have to sell it aggressively, and campaign for its continuation continuously until it's complete. That's difficult, and you're talking about staking your reputation on something that some will not want to see succeed.

Some strategies for success:

  • If you do, however, do not try to convert existing code. Design the system from scratch. Otherwise you're wasting your time. I have never seen or heard of a "conversion" project that didn't end up miserably.
  • Migrate users to the new system one team at a time. Identify the teams that have the MOST pain with the existing system, and migrate them first. Let them spread the good news by word of mouth. This way your new system will be sold from within.
  • Design your framework as you need it. Don't start with some I-spent-6-months-building-this framework that has never seen real code.
  • Keep your technology stack as small as possible. Don't over-design. You can add technologies as needed, but taking them out is difficult. Additionally, the more layers you have, the more work it is for developers to do things. Don't make it difficult from the get-go.
  • Involve the users directly in the design process, but don't let them dictate how to do it. Earn their trust by showing them that you can give them what they want better if you follow good design principles.
14
  • 34
    I think Joel's point is that by doing a rewrite, you lose the knowledge accumulated in the old code.
    – quant_dev
    Commented Jan 5, 2012 at 14:11
  • 21
    @quant_dev partly yes, but when you rewrite sometimes you realise that many of the bugs in the old system were because of the way the old system worked, not strictly logic related to how the ideal system should work.
    – Tjaart
    Commented Oct 22, 2012 at 16:07
  • 16
    Joel says it will fail because, during the rewrite, you are adding no new functionality to your application. The only purpose of a rewrite is to eliminate some or all of the technical debt. Granted, this is no small thing, but it is risky if your competitors are adding new features and functionality to their software while you are merely getting rid of technical debt in yours. Commented Oct 22, 2012 at 16:56
  • 30
    I've worked with a codebase that fit all of these criteria+ and yet a Big Rewrite still failed and in some ways made things worse by giving us half-implemented "new deal" code to handle that was very different from the old chaos but not much more manageable. IMO, only if it's become completely impossible to refactor, should you remove all focus from adding features and fixing bugs that are costing you customers today. Unless you're talking truly undecipherable code, a team that can't pull modular bits out for easier reuse as you go probably can't re-architect well enough for the big rw anyway. Commented Jun 15, 2013 at 3:31
  • 17
    This is a useful answer, but far from beeing fantastic, because it gives a wrong impression on some things. For example, "Keep in mind that the total cost of redesiging incrementally is always higher than doing a complete rewrite" - the word "always" in that sentence is wrong, because "redesiging incrementally" gives you the opportunity to reuse at least some parts of the existing design, whilst a "complete rewrite" does not offer you that. I know that for sure, becausw I had been actually in that situation, where we rewrote a >100K LOC application partially in full, partially not.
    – Doc Brown
    Commented Dec 11, 2015 at 21:25
126

I have participated in two big rewrites. First was a small project. The second was the main product of a software company.

There are several pitfalls:

  • rewrites always take longer than expected.
  • rewrites have no direct effects/benefits for the customer.
  • capacity devoted to rewriting isn't used to support the customer.
  • you will lose functionality with a rewrite unless you have 100% documentation.

Rewrites are seldom the real answer. You can refactor much of the code without losing anything and without a lot of the risk.

Rewrites can be the answer if:

  • you are switching to another language or platform.
  • you are switching frameworks/external components.
  • the existing codebase is not maintainable anymore.

But I strongly advise the slow approach using refactoring. It's less risky and you keep your customers happy.

6
  • 12
    +1 for refactor approach. Lots of times there's not enough time or manhours to rewrite AND maintain the existing system.
    – Ryan Hayes
    Commented Sep 22, 2010 at 12:20
  • 4
    @John: As an executive, I would have a very hard time greenlighting a rewrite on an application that my sales team has yet to get a customer for. In all honesty, I'd give it a certain amount of time, and then decide what to do. If interest isn't there, I'd trash the whole thing and pick something else to do.
    – NotMe
    Commented Sep 22, 2010 at 22:13
  • 4
    I recently rewrote a Visual Basic application in Java. This allowed it to be run as a service under Windows (no Java GUI) - benefit to customer.
    – user1249
    Commented Apr 2, 2011 at 18:04
  • 5
    "rewrites have no direct effects/benefits for the customer" - this is often a myth, as the newer frameworks provide "built in" a lot of productivity enhancements that are either impossible or far too expensive to implement. One example, upgrading a vb6 app to a .net app allows users to open larger files (due to a 64 bit architecture) which therefore means that the end users don't have to artificially break up their work.
    – Stephen
    Commented Jun 1, 2015 at 3:28
  • 1
    @Stephen true, but that is the same as saying that a game written for a playstation 4 has better graphical resources than if it were written for a playstation 1. Most server applications, web services, and back-end batch processors will not generally gain such benefits, aside from those afforded to the developers themselves.
    – Kain0_0
    Commented Apr 7, 2020 at 14:53
83

It's time for a rewrite when:

The cost of rewriting the application + maintaining the rewritten application is less than the cost of maintaining the current system over time.

Some factors that make maintaining the current one more expensive:

  • The language is so old you have to pay people that know it a lot of money to program in it (COBOL).
  • (from experience, unfortunately) The system is on a hardware architecture that is so old that they have to scour Ebay and COLLECT parts to add to the machine it is running on because they aren't made anymore. This is called "hardware life support" and is expensive because as parts become more scarce, they (may) go up in price or they (absolutely) will eventually run out.
  • It has become so complex that the //Here be dragons. comment is all over your code.
  • You can't write any other projects and add new value to the company because you're always patching this ugly beast.
4
  • That's exactly what prompted the rewrite in which I participated. The code was so fragile, and the cost of adding new features so high, that not rewriting was no longer an option. Commented Sep 22, 2010 at 13:33
  • 2
    I like this response, funny and true. I would like to add "quantifiably" right before "less." So many times, it's easy to make the claim, but it's important to be able to quantify the wasted time.
    – Kevin Hsu
    Commented Aug 9, 2012 at 0:42
  • Having old hardware happens a lot in industrial environments.
    – Nikko
    Commented Jun 8, 2016 at 9:16
  • One must not forget the opportunity cost due to fewer updates while the rewrite is in progress. Commented Feb 3, 2018 at 10:04
18

Stop! Rewriting is almost never the answer. More often than not, refactoring is a better bet.


Of course, there are times when a rewrite is justified:

  • You're switching to a new platform where migration tools don't exist (or can't be written cheaply enough).
  • The application to be rewritten is trivial.
  • Source code for the original application is lost, and recovery is more expensive than rewriting.
  • The vast majority of the business rules encapsulated by the existing application no longer apply.
  • There are few active users of the existing code.
  • You have the resource (time, talent and tools) to undertake the rewrite.
  • The existing application cannot be run in a production environment, for legal or practical reasons.

To understand why I recommend refactoring over rewriting, consider what is involved in a rewrite. You must:

  1. Understand the nuances of what the existing application does. This is not usually trivial when you take in to account all the subtle business rules that it encapsulates, the environment (both human and technical) in which it operates and the advantages and disadvantages of the current solution. More often than not, the only place that this information exists (if anywhere) is in the source code of the existing application. It is unfortunate that one of the main reasons for performing a rewrite is that existing code is difficult to understand and maintain.

  2. Reproduce this functionality (or an updated version of it) in a new application that is tested and reliable. Existing code may not be understood by developers, but is typically well understood by its users. It may not meet their current business needs, but they can at least tell you what the application does under various circumstances.

Big advantages of refactoring are that:

  • You can take things one small piece at a time.
  • Any changes can be tested in the context of the existing, working application.
  • Hypotheses about the way the existing code works can be tested by making small changes and observing what happens.
  • Changes can often be delivered to users in phases rather than all at once.
  • Learning from early stages of refactoring can inform later stages of the refactoring.
  • If you abandon the process part way through, there will still be benefits in terms of a cleaner code base (as opposed to a rewrite that must be completed to offer any benefits to the user or developers).

Remember, too, that if you do a rewrite you are guaranteed to introduce lots of new bugs and mess into the new code base.

3
  • 2
    Could you expand on this answer by explaining why refactoring more often than not is better than rewriting? And when would a rewrite be the answer?
    – gablin
    Commented Jan 14, 2011 at 14:03
  • Given the fact that a rewrite most often is just the same mess in a different outfit, you are right. If you can eliminate that single issue, then you're wrong. There are no absolutes when the right people do it.
    – JensG
    Commented Oct 8, 2013 at 19:09
  • What about if the current app works but its like spaghetti code you should put that under reason?
    – Lightsout
    Commented Oct 19, 2021 at 23:41
18

If you require a fundamental change in the architecture of the project, it is possibly time to start afresh.

Even with that, there will potentially be large swaths of code that are still worth re-using in your new project.

Heed fair warning though. A current project will have had its business rules tested and refined with countless man hours of actual usage, something that will not be true of a project started from scratch.

I doubt a time frame or gut feeling is an appropriate measure of such a drastic measure. You must have clear, defensible and well understood reasons to partake in this course of action.

3
  • 3
    You need to be very careful 'reusign large swaths of code', this can lead to unused legacy code and poor code structure. Refactoring is a better solution in my opinion.
    – mrwooster
    Commented Jan 14, 2011 at 13:49
  • 1
    Agreed. Part of that statement should be interpreted as 'refactor' into your 'new' project. That is, if you have indeed already committed on that drastic path. As mentioned by others, this is an extreme rarity that should almost never be done. Commented Jan 14, 2011 at 13:57
  • 1
    +1. Also, the rewrite will take time, during which maintenance will have to be done, but the same changes will need to be done on both code bases. Commented Jan 14, 2011 at 14:12
13

Although I do agree with Kramii's answer and Joel's opinion, there are times when it is appropriate to do a rewrite. In long-lived applications (I'm talking like 10-20 years or more), maintenance becomes more and more expensive over time. This is due to the code becoming more and more spaghetti-ish as the original architecture is sacrificed for quick maintenance patches. Also, developers for older technologies become more rare and more expensive. Finally, hardware begins to age and it gets harder and harder to find new hardware, operating systems, frameworks, etc. to run the old application on top of. Also, businesses evolve, and most likely an older system will not be meeting the business needs of the organization as well as a brand new system could.

So you have to weigh all of the ongoing maintenance cost, as well as the potential benefits of a new system to the business, against the cost of rewriting the thing from scratch. Be very pessimistic in your estimates about the cost of a rewrite. It almost always costs more and takes longer than you would think.

1
12

This graphic could help, it's a function of code base quality and business value of the application:

enter image description here

The chart pretends to be a guide on when a re-engineering of legacy software is justified and when it's not. For example, if the software has high business value and the quality of the code is poor, then a re-engineering is justified.

2
  • 9
    Why would you invest in rewriting a project with low business value? Just scrap it! Commented Jun 7, 2016 at 8:41
  • That's why it statess "replace or...". You can replace with something that has value. Or make it into something that has value. But you have a point. I'll edit it to add the "scrap it" option. Commented Jun 7, 2016 at 10:45
8

I had a case very similar to yours only the code wasn't even using Struts. What I did instead was target areas that were particularly crappy AND causing a lot of problems. This targeted approach got us incrementally better.

Over a 2 year period we worked on refactoring bits and pieces alongside enhancement work. We always worked a 'Hardening' task into a project plan. By focusing on the specific areas that didn't work well we got the most bang for the buck. The stuff that worked we left alone. Also critical is that this work was done in the course of normal development and was released. The problem with a big rewrite it you go off for a year or more and then by the time you come back every things changed anyway and some of the nasty bugs got smoothed over and you lost your ROI.

We never did re-write the whole thing. We did stop using that platform for new work though, and pitched a new fresh platform for a big new project. That got approved and we delivered a great product in a reasonable amount of time.

0
8

I worked for a small software company that had a couple of DOS applications that were upgraded to handle Y2K, rewritten as a Windows 16-bit app and then totally rewritten as a 32 bit app with one additional 'small' feature (ultimately only utilized by one customer) that impacted the entire structure.

Moving the 16 bit code to 32 could have been done in a month by one person, but NOOOOOOOOO, we had to rewrite it to make is Soooooooooo much better. This thing could be adapted for other industries, would have full specs and psuedo-code before they even got started. The specs were created, but it took so long there wasn't even time to write the real code. It was released late, with more bugs than the 16 bit 'started' with (it was on v.3.0 and finally to the point where we almost made it a week without someone reporting a new bug).

You'd think rewriting the same application 3-4 times would bring about some improvements, but I just don't think a GUI front-end can be justified that much.

This was my first IT job as head of technical support. I should write a book on how not to develope software for distribution. Obviously we made many mistakes, but the fact that we continued to rewrite applications compounded the incompetancy.

8

I think I'm in the only situation in my career where the big rewrite is the answer:

Company merger, huge overlap in systems functionality. Many, many systems have been merged and retired, and others still in the process.

I've inherited a system from the other company that still lives on. It has a huge code base, which used to support multiple departments very similar to our own, but with a completely different design and frameworks. There is only one business sector left using it, which makes enough money that keeps this thing alive in a zombie state. All the old expertise is gone, there is no documentation. The support burden is high, with failures every week. It has not been merged into our companies systems, because our company never supported this particular sector of the business, so we don't have the functionality or expertise.

It looks like this is the one case where the rewrite is needed. It looks like I'm going to have to figure out this behemoth, pull out the bits of functionality dedicated to this business, and rewrite the pieces that need to be added to our existing systems. Once that is done, our existing systems can support this new sector, and this beast can be put out of it's misery. Otherwise I'm going to lose my sanity.

1
  • Sounds like your employer needs to talk to the customers and explain the situation to find out what the best way to help them might be, even if it means they have to pay more initially, because they will save in the long run.
    – user1249
    Commented Apr 2, 2011 at 18:06
5

So here I am sitting at my desk, I started re-writing the code for this absolute mess of one big aspx file, the database behind it, and replacing the MS Access interface to the MsSQL.

This asp program is littered with things like

  • include(close.aspx) which inside has one line of code that closes the last open database connection.
  • Legacy code just commented out randomly
  • No consideration for security
  • Spaghetti code, thousands of lines of it. All in one file.
  • Functions and variables with no clear meaning behind their names

If we ever need to make a slight change, it's like playing five simultaneous games of kal-toh on nightmare mode.

I was hired to replicate functionality and make a product that could be customizable and salable to others in the industry. The problem is this thing has been written over the past 10 years to fill every single business need (well, I'd say about five or six sigma of them anyway).

If we didn't want to sell the product, they probably wouldn't have needed a re-write as it does most of what they want-- perhaps not elegantly, but it wasn't prudent to spend the money on making nice code 'do the same thing.'

4

The existing solution doesn't scale.

I'm looking at you, MS Access.

3
  • I'm not sure if you are looking at the right one. Jet Red wasn't meant to scale ever, AFAIK.
    – JensG
    Commented Oct 8, 2013 at 19:11
  • how does this answer the question asked?
    – gnat
    Commented Oct 8, 2013 at 19:52
  • Its funny because Im thinking about an access program and I saw this.
    – Lightsout
    Commented Apr 12, 2023 at 1:50
4

Joel Spolsky has an excellent article on this: Things You Should Never Do, Part I

From the title you can tell, its kinda one sided (he talks about why you should never throw code) IMO, there is lot of truth to it, I recently saw a channel9 video on the 25th Anniversary of Excel where some devs said, how even today if you looked into the source you would check the revision and end up going back to code that excel used that was written 20 years ago.

You can't be 100% sure (when even Netscape makes mistakes (from Joels Article)), I felt like the Joel's article was God sent, because I can be pessimistic and love throwing away code thinking I can always write it better a second time, but I've realized only now this just costs a lot.

To give a concrete answer, I would just say you need to do a thorough Cost vs Value analysis.

My Real world : A silverlight app Im developing v0.6 so far has a mess of async calls that make the code so convoluted. Since I discovered Reactive Extensions this week I really want to re-write most of the code, but now what do I tell my customer? The program works perfectly fine (with some memory leaks tho) but they dont care? I cannot possibly tell them Oh Im taking 2-3 more weeks because I want to re-do something. I'm however, going to branch the code and re-write/play with it in my free time.

Just my 2 cents ok!?

3
  • Your first implementation is frequently suboptimal because there are things you do not know yet when designing. This will usually be refactorable into shape instead of starting over, as you most likely have done something right. If not, it is a proof-of-concept, and THEY frequently need to be discarded.
    – user1249
    Commented Jan 15, 2011 at 23:55
  • +1 for branching. A lot of people say "don't rewrite" because it seems like you're throwing away old code - but you aren't. You can have parallel codebases.
    – user26452
    Commented Apr 7, 2014 at 1:45
  • To be fair, if you are a person who asks Joel Spolsky for advice, then you shouldn't do a complete rewrite :-) And otherwise, you should only do a rewrite if you can convince all stakeholders why Joel's arguments don't count in your specific case.
    – gnasher729
    Commented May 31, 2015 at 15:52
3

It's the answer when the rewrite allows the organization to pursue a strategy that affords a competitive edge or allows it to better serve its customers in some manner that the current architecture cannot accommodate.

Instead, rewrites often happen to alleviate management worries:

  • everything should be in .NET,
  • our developers say our code sucks,
  • we're falling behind technically,
  • we won't be able to find resources to support our system or, very often,
  • it's been ten years so it's time.

Most of these worries won't materialize and, if they did, they could be handled. That last one, however, is the worst. It's essentially: we don't have a reason.

Yes, like car, a system will begin to show signs of wear. This can be alleviated by routine servicing. You know what they say about how a little preventative maintenance goes a long way. As an investment, routine servicing (i.e. refactoring and standardizing) will almost always carry less cost than a rewrite.

However, we have to anticipate that a rewrite will eventually be necessary. Set dates and tentatively plan for it, but as the date draws nearer delay in favor of realizing other strategic goals until you have a compelling reason like...

In recent years we've lost the opportunity to win big accounts because we couldn't accommodate their needs in a timely or costly fashion. Our system will be rewritten using an extensible architecture that allows customizations to be plugged in (and not hardcoded as we currently do). This will dramatically decrease the time and cost of accommodating customers with special needs. We'll win more accounts and better meet the needs of our current customers.

1
  • Seems like you ought to be able to refactor in that direction. When refactoring, you have in mind to create the flexibility you need so that the next feature is easy to write.
    – Ian
    Commented Jun 9, 2016 at 15:00
2

Never, always refactor - the truth is if the code was written by you - you won't be able to do any better.

Unless you want to change technology, the code is lacking any structure (i saw it very long time ago in some PHP website, the author just copy/pasted spahgetti instead of include / class / function ) or you taken over something from another person that's very badly written.

Everything should be designed as a blackbox. Modular, Simple API, what is inside... that's less important :) If you have spaghetti you maybe able to close it inside a blackbox, so it won't contaminate good code.

9
  • Awesome, Slawek! extremeprogramming.org/rules/refactor.html
    – Lukas Eder
    Commented Jan 14, 2011 at 16:32
  • +1 I like your opinion, would like to know your thoughts about re-writing to a newer set of API? (See my answer below)
    – gideon
    Commented Jan 14, 2011 at 16:39
  • Yes, these are good points. Microsoft rewrited winXP code and they couldn't even get file delete/copy right in first Vista retail version. While when they were just progressing their code base we're getting better quality constantly (W3.11=>W95=>W98=>ME=>XP), Vista in which they rewrote many core parts was a disaster. For new API... i'd separate the current code to have as much as i could intact, and use the new API on higher layer. Eg. your core classes stay as they are, but integration is done using new API. Unless everything is so messy that nothing else could be done than to start from 0.
    – Slawek
    Commented Jan 14, 2011 at 18:17
  • 1
    "...the truth is if the code was written by you - you won't be able to do any better." Would down-vote this post if I had enough rep. That's defeatest, unrealistic and implies that somehow people cannot progress to the point were the code they write is an improvement on code they wrote in the past. Commented Oct 9, 2013 at 12:51
  • 1
    @JᴀʏMᴇᴇ: Agreed - if you learnt nothing and gained no experience when implementing it the first time and/or if you can't do a better job now that you do have more knowledge/experience/hindsight; then you're a potato and not a programmer.
    – Brendan
    Commented Feb 3, 2018 at 12:35
2

I think the main reason that justifies rewrites are for platform changes. For example, if you have a Windows desktop GUI application and the company owner decides they want the next version to be a web based application. Although not always, in my experience most of the time this will require a rewrite, unless the original developers wrote very modular and reusable code (hardly happens).

2

According to Joel, big rewrites are the single worst strategic mistake a company can make:

Things You Should Never Do, Part I

...It's important to remember that when you start from scratch there is absolutely no reason to believe that you are going to do a better job than you did the first time. First of all, you probably don't even have the same programming team that worked on version one, so you don't actually have "more experience". You're just going to make most of the old mistakes again, and introduce some new problems that weren't in the original version.

The old mantra build one to throw away is dangerous when applied to large scale commercial applications. If you are writing code experimentally, you may want to rip up the function you wrote last week when you think of a better algorithm. That's fine. You may want to refactor a class to make it easier to use. That's fine, too. But throwing away the whole program is a dangerous folly, and if Netscape actually had some adult supervision with software industry experience, they might not have shot themselves in the foot so badly.

5
  • 3
    Every rewrite argument is not complete without a reference to Joel's article. What I say, that the article has some good points, but dammit think for yourself. Maybe you should be saying why you agree with the article. I don't agree with Joel personally - simply because sometimes is better to dig yourself a new hole than bore yourself further into the pit ever ending grief. In any case, a rewrite, I think, would bring those latent business processes to the surface for re-evaluation.
    – Ahmad
    Commented Sep 23, 2010 at 5:34
  • Joels article is good as it carefully explains how bad things can go.
    – user1249
    Commented Apr 2, 2011 at 18:08
  • 6
    Joel uses an example of the Netscape Navigator browser. That's a consumer product that was in the middle of a massive growth curve working against competition with a big budget. It was a strategic mistake for Netscape. On the other hand, internal custom "enterprise" software projects are different. You're not rushing for market share. There's no danger of all your users leaving to a competitive product. It comes down to a business decision: will the cost of a rewrite pay for itself in the long run and/or is it the best way to achieve the business goals? Commented Apr 3, 2011 at 20:59
  • I thought Joel hit the key concept, of "You never know what decisions haven't been documented that you'll have to learn the hard way"
    – MathAttack
    Commented Oct 23, 2012 at 3:45
  • He's not wrong on some points....but I'd say if you're going to rewrite anyway, go through the old code and document its behavior. Write tests to mimic that behavior in your greenfield codebase (because it's new, you can do that painlessly!) and you're off to a much better start anyway.
    – user26452
    Commented Apr 7, 2014 at 1:43
2

There's the classic joke about "if I was going to X I wouldn't start from here".

I took a job once, where the employer's prime motivation was to bring talent aboard to launch a long-overdue rewrite of a business-critical app. The question I failed to ask was, why have you ended up in this situation in the first place? It should have been a red flag, whether the cause was

  • too much pressure to add functionality to maintain and incrementally refactor the beast,

  • too little ability in the department,

  • too little buy-in from clients or management for incremental work,

or whatever, and this cause festering away until the problem reached an intolerable level.

So I'm going to agree with Joel in that a massive rewrite is probably a very bad idea - unless you have firm evidence that all the underlying reasons behind why a major rewrite seems so necessary have been dealt with, you're in all likelihood going to repeat the problem in due course.

0
1

When moving to a completely new technology is needed to provide desired functionality.

"Completely new": if you're planning to rewrite but use the same platform, then refactoring and judicious restructuring is almost certainly the better solution. "Platform," as used here, is somewhat vague -- consider it to include language, and perhaps OS (extending from Linux to Windows or vice-versa comes to mind), but probably not framework (eg, replacing Struts with Spring).

"Needed to provide desired functionality": right around 2000, I initiated a project to rewrite a major server component in Java from C++ to enable out-of-the-box threading, an object cache, and client-controlled transactions. At the time, there were multiple threading libraries for C++ that we would have had to support, and thread-enabling much of our database code would have necessitated a near-total rewrite. As for client-controlled transactions ... not gonna happen with the old architecture.

Even then, I'm not sure that I would have done the rewrite, except that I had detailed knowledge of the current system's behavior, and it was relatively clean code that hadn't developed very many warts in its 11 years of life.

0

To decide the point at which you should start over, you need to work out where the value of continuing on your current project falls short of the value in starting over.

The reason this is so difficult is that you make an accurate estimation of the team's development velocity on the new project until you actually start it. That said, if, using a VERY conservative estimate of your development velocity on the new project, the project is estimated to give a worthwhile return on investment, then you have a business case for starting afresh.

0

With my metric, you have to satisfy two conditions to justify a rewrite:

  1. After the rewrite new features will be easier/quicker/less buggy to write
  2. The rewrite will take less or equal time than adding the current new feature.

Even then you want to limit the scope of your rewrite. For an example, we had some legacy software at a company that was written in C++ with the mindset of a C programmer who didn't know about modularity. The end result was speghetti code in the form of a finite state machine that spanned multiple classes and DLLs. We had a new requirement that was very different from the assumptions built into the code, and was going to be part of the company's patented value-add to its customers.

After spending time with the code implementing other features, I had a really good idea of how long it would take to figure out which of the several switch statements I would need to change, etc. My proposal was to rewrite the section of code that was the huge finite state machine--it should take me less time than extending the existing code. I was able to consolidate into one DLL what used to be three, and provide a much more object oriented structure that would make it a lot easier to do the critical new functionality along with making it easier to add new functionality.

There were three other applications using the libraries that needed the rewrite, so I didn't want to have to completely rewrite those programs. The scope was limited to the library and what was necessary to bind the library to the existing software. My estimates weren't off by far, and the work paid for itself. Shortly after the redesign, I was tasked to add a new feature. What would have taken me a week with the old structure only took me a day with the new structure.

0

The OP doesn't indicate the scope of the project, but the main clue I took was "written in old [language/dialect] using old [libs]" which to me are the primary drivers of a re-write. In fact, most projects I've been on of any significant market longevity eventually realize that accomodating updates to compilers/interpreters/operating-systems is an important task in maintaining the code base.

In short, I would plan the re-write in phases, prioritizing first the update in libs. It might be that along the way, you can sneak in other optimizations, but the fact that you plan to defer some changes to a later phase can be a great way to stay on schedule and avoid getting "stuck."

0

Well I can imagine hypothetical scenarios where I might just throw out the existing code base (hypothetical situations where the bucky balls have zero weight and volume, where no one cares if we lose weeks or months of productivity as we scramble to add overlooked features and bug fixes into the system, and where the system is so trivial and hated by an organization that I can replace the entire thing and army of servers with notepad++ and a netbook in ten minutes and boost everyone’s productivity and moral across the board.)

For almost any real world scenario though I would just recommend refactoring in place. ^_^. There tend to be too many hidden, unanticipated costs to rewrites when undocumented legal and business requirements start to pop-up and the last minute hacking things together last minute starts to ensue.

==Refactoring in Place for greater good, and stuff==

Refactoring legacy code with the regular old incremental approach,

  1. If you have the chance convert to UML and document what little knarly architecture there is.
  2. If you are on version control look into generating some code churn reports and figuring out which files and file sections have been changed the most frequently. Make a note of these as they will likely be the areas you will want to deal with first.
  3. Before you change any code always try to add some test coverage (even ugly full stack functional tests will do). If dealing with large messy procedurial code extract logic you intend on changing into some reasonably named method or function and if possible add some test cases that verify your new method. make whatever god awful hack you have to and if possible paramatize the change if it is something commonly tweaked like margin width or title so it will be a little more straight forward to update the next time.
  4. Use the adapter pattern and work away at hiding the knarly bits of legacy code under a rug of logically named classes and methods so that for most common tasks you and the other developers perform you wont need to worry about the scary bits that are going on behind your back behind those nice little clean methods and classes you've hidden that legacy code behind -- like those nice families that keep deformed murderous zombie former family members in barns so that they don't spoil the day to day going-on’s of the farm . . . normally.
  5. As you continue to whittle away and clean up the sections of the code continue to boost your test coverage. Now you can dig down even deeper and "rewrite" even more code when needed/desired with ever increasing confidence.
  6. Repeat, or apply additional refactoring approaches to continue to improve your codebase.

Branching By Abstraction

  1. Define the trouble spot in the code you want to remove (the persistence layer, the pdf generator, the invoice tally mechanism, the widget generator, etc.).
  2. run (write if necessary) some functional test cases (automated or manual but you know automated) against the code base that targets this functionality along with general behavior.
  3. Extract logic related to that component from the existing sourcebase into a class with some reasonable interface.
  4. Verify all code is now using the new interface to perform activity X which was previously dispersed randomly throughout the code(Grep the code base, add a trace to the new class and verify pages that should be calling it are, etc.), and that you can control which implementation will be used by modifying a single file.(object registry, factory class, whatever IActivityXClass = Settings.AcitivtyXImplementer();)
  5. rerun functional test cases that verify everything is still functioning with all of Activity X throwin into your new class.
  6. Write unit tests where possible around the new activity X wrapper class.
  7. implement a new class with less insane spaghetti logic than the legacy implementation that adheres to the same interface as the legacy class.
  8. verify that the new class passes the unit tests you wrote for the legacy class.
  9. update your code by changing the registry/factorymethod/whatever to use the new class instead of the old class.
  10. verify that your functional tests still pass.

Open Closed Principle and a Common Business Logic/Persistence Layer

To some extent you might be able to get away with separating out your presentation, business and persistence layer and writing a new app that is fully backwards compatible with the legacy solution, or at a minimum can still handle data inputted by legacy solution. I would probably not recommend this approach but sometimes it is a reasonable compromise of time/schedule/resources/required new functionality.

  • At a minimum separate the presentation layer away from the business and persistence layers.
  • implement a new ui and better presentation layer that uses the same common business and persistence layer.
  • Verify that data created with new ui does not break old ui. (you're going to be in hot water if users of the new tool interrupt users of the old tool). If you are striving for full backwards compatibility you should be saving everything to the same persistence layers. If you just want forward compatibility into the new tool then use a new database and new tables or extension tables to track data not in legacy system.
  • For new functionality and persistence layer needs add new tables and methods don't change existing legacy logic, or add columns, constraints to existing tables. e.g. if you need to start tracking employers emergency contact and some other fields don't modify the existing employee table (we have no idea what assumptions the legacy data makes about that table) add an extension table employee_ext id, employee_id, emergency_contact_id, etc_id.
  • Slowly migrate users onto new system. if possible put legacy system into read only mode, or just add some warning telling users it will no longer be available after date X.
  • implement any hi priority missed functionality or business requirements in the new ui
  • roll over users base.
  • continue on to clean-up the business logic and persistence layer users other refactoring methodologies.
0

I would say there is a third category in the Refactor vs Rewrite space... And that's updating your language versions, compilers, and libraries... Sometimes just adopting modern coding techniques has a great benefit.

Take C# for example, v7 code writes a lot cleaner, safer, and more concise than v2.. Things like the Elvis and null coalescing operator help out a ton.

Switching compilers might also breath new life into older code. So might new libraries that might make things easier to work with and implement... Networking is a great example of a spectrum of implementation difficulty.

Also- embedded linux systems... Think about installing new tools- switch to git from svn. or add Vi to your system etc etc.

It doesn't always have to be a refactor vs rewrite.. Your architecture is probably in need of improvement, but it works... maybe you just need to think about how your code is written etc.

-2

I don't think I have ever seen people rewriting a legacy app.

What happens is that people are writing totally new apps with a different architecture, technologies,etc which have some features in common with the previous generation. And it is called app 2.0, but in fact it has very few things in common with the original.

But this is not really a "rewrite" of the original in the sense that you are trying to achieve feature parity.

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