Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

This question already has an answer here:

We have a legacy classic ASP application that's been around since 2001. It badly needs to be re-written, but it's working fine from an end user perspective.

The reason I feel like a rewrite is necessary is that when we need to update it (which is admittedly not that often) then it takes forever to go through all the spaghetti code and fix problems. Also, adding new features is also a pain since it was architect-ed and coded badly.

I've run cost analysis for them on maintenance but they are willing to spend more for the small maintenance jobs than a rewrite. Any suggestions on convincing them otherwise?

share|improve this question

marked as duplicate by gnat, Bart van Ingen Schenau, GlenH7, david.pfx, MichaelT Aug 23 at 19:27

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

9 Answers 9

I believe there's two factors you should consider that you at least didn't cover in your Q. Let me define these as I use them, then I'll get onto the business of answering your Q.

  1. Risk
  2. Opportunity cost

Risk is probably obvious: The chance that they pile a mountain of money into something that goes nowhere. Risk is compounded by what Brooks called "Second System Effect" and the rest of us call "Gold Plating". Every rebuild I've seen carries risk from people who add every feature they didn't add the first time around.

Opportunity Cost in this context is the cost associated with you rewriting functionality that from the business perspective was working fine. It is Opportunity Cost because it means you don't have the opportunity to add features.

To sell something that is purely a refactor is hard because Risk and Opportunity Cost both have money attached to them from a decision making perspective. What I generally recommend is that instead of selling a rewrite of the system, you sell an "improve as you go" at a component level. It costs more because you have to build adapters/facades/proxies, but it's less risky and easier to sell. I've been there on the "we need to rebuild it all" and it just doesn't go well.

And here's the rub: Over time, all systems turn into garbage unless you are disciplined enough to keep them from doing so.

Which leaves me with this question back to you: If you can't sell them, or even your team, on doing the right thing day to day, what makes you think you can actually see a rewrite through?

It really does take some serious introspection to answer that question honestly. Sometimes you've been handed a system from someone who had no clue. Sometimes you've been handed a system by someone who started with the best of intentions and on the right foot but got compromised by a poor corporate culture along the way. If you can't tell which it is, you need to find out soon!

share|improve this answer
    
Thanks for a good response. Well our team has developer many applications and we've seen other rewrites through on much smaller applications though. My team is also convinced we need a rewrite. I agree with the improve as you go model, but we've done as much of that as we can without a rewrite already. The code isn't well designed for component updates though. –  Wil Sep 15 '10 at 12:14

Here are some ideas, all of which I've done more than once.

  1. Nothing succeeds like success: show up with it one day. One of the key reasons things get turned down is that decision makers feel like it's not really going to be much better afterwards, or that you're not likely to be able to actually do it. If you can put together a compelling proof of concept, and show it to them, it's easier to sell them on it.

Some of the best things I've ever written started off as stealth projects. Things that people said were not possible. Another one I hear a lot is, "people smarter than you have tried that and failed." When you show up with a compelling proof of concept, it pretty much decimates those arguments.

I can't tell you how many times people have denied letting me work on a project, rebuffing every reasonable argument, just hearing none of it. Then I show them a demo, and suddenly they think the project is a great idea. But do be careful: the more you needle someone and the more they insist the answer is no, you need to be careful: they have to have an honorable way of changing their mind without resenting you for it or feeling wrong. So be diplomatic, ideally try to make them think it was their idea. or have a good relationship with them, alternatively.

The key to a great demo is planning. Don't start by thinking of what the product should be. Start by thinking of what the most awesome demo would be like. You have to do enough engineering that your demo isn't just pure vaporware, but what you want to implement first is whatever it'll take to make that demo rock their socks.

  1. Open up new possibilities with the new design. There was a system I rewrote that fit your situation exactly. It was a terrible pain to work on the system. We didn't have to chagne it very often, but when we did, it hurt my soul and made me want to cry. The system was written in VB.Net, and had all the business logic interspersed all over the GUI code (which was a a heavyweight .NET app). Management didn't want to redo it. I redid the backend using a webservice, and then showed how doing that would enable us to add more than one UI to the product. This was a product for managing telephone calls in call centers. I sold management on the idea by showing them a mockup that worked on both a web site and also on a smartphone. They started immediately thinking of other kinds of new products they could use by having multiple UI's on this thing.

  2. Establish a beachhead / Don't eat the elephant all at once: build your perfect system a little at a time. Spend a little time envisioning what your ideal system would look like. Envision what that architecture is. Draw a block diagram of it on a piece of paper, and lock that image in your mind. Then next time you need to fix something, try to build one piece of that ideal system. You can then build an adapter that will let you plug it in to the old system. The adapter will insulate your beautiful new piece from the ugly vagaries of the old crappy code. Piece by piece, you can replace the entire system that way. The first little piece is the hardest part-- it's like establishing a beachhead on enemy territory. But once your beachhead is established, moving forward gets progressively easier.

For example, we had this huge body of code written in PHP one place I worked. My team and I wanted to use Python, but management didn't want to fund us to do that. We started adding new functions using a Python webservice, and using curl to access those from PHP. It wasn't a total rewrite, but once we built the facilities to make it easy to integrate the codebases we had established a beachhead, we were able to move the rest of it forward more easily from there. I've done the same thing with doggy legacy systems in languages like COBOL and RPG/3, calling out to Java.

share|improve this answer
1  
Dang it, forgot the stealth project == successful project rule. +1 –  MIA Sep 15 '10 at 4:33
    
What about when we just don't have the time to stealth project? I agree that is a good method, but these days we're pretty understaffed and would be difficult to find time to pull that off. –  Wil Sep 15 '10 at 12:16
    
1a) Stealth project, or 1b) compelling demo, 2) Establish a beachhead and improve a little at a time... You mentioned idea 1a won't work. Perhaps you can look harder for opportunities to make ideas 1b or 2 a reality. I've been through this a bunch of times, but each of the times I succeeded it was one of the flavors I outlined. I'be been trying to think of other success stories that fit into a different category, and am coming up blank. –  Unoti Sep 16 '10 at 23:29
    
I would never try to make someone "feel like it was their" idea if it was not. That is simply a lie and flattery. –  Mark C Oct 19 '10 at 17:23
    
@Mark - or an insult - the implication of someone trying it is that they think you're stupid enough to be taken in and manipulated that way. –  Steve314 Oct 26 '11 at 0:15

Think extremely carefully before any rewrite. Read Joel Spolsky's blog post, Things you should never do.

There's a subtle reason that programmers always want to throw away the code and start over. The reason is that they think the old code is a mess. And here is the interesting observation: they are probably wrong. The reason that they think the old code is a mess is because of a cardinal, fundamental law of programming:

        It’s harder to read code than to write it.

This is why code reuse is so hard. This is why everybody on your team has a different function they like to use for splitting strings into arrays of strings. They write their own function because it's easier and more fun than figuring out how the old function works...

The idea that new code is better than old is patently absurd. Old code has been used. It has been tested. Lots of bugs have been found, and they've been fixed. There's nothing wrong with it. It doesn't acquire bugs just by sitting around on your hard drive. Au contraire, baby! Is software supposed to be like an old Dodge Dart, that rusts just sitting in the garage? Is software like a teddy bear that's kind of gross if it's not made out of all new material?

...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...

share|improve this answer

I have had the opportunity for a complete rewrite twice (different jobs).

The first was a rather small app. The rewrite was estimated to take two programmers six months. We made the deadline and the customer was very happy. Unfortunately despite the demand, marketing dropped the app so the effort was wasted.

The second was the main app of a small company. The rewrite was completely underestimated and almost ruined the company. In the end the project was a succes.

The problem with rewrites is that it does not add any functionality to the app. Which means it is hard to sell. So it is better to rewrite small pieces at each time. Refactoring++.

share|improve this answer
1  
I am intrigued, how do "almost ruined the company" == "success". That's a tip I really could find useful on day..... –  mattnz Oct 26 '11 at 3:27
    
@mattnz, success == the program was ready to be sold before we ran out of money. It was a big risk, but in the end, it was the right decission. –  Toon Krijthe Nov 24 '11 at 6:48

Don't re-write - the risks and costs are too high for your business. See the Joel Spolsky article referenced by @Grokus for reasons why.

I proffer an alternative option - a combination of refactoring the code that is suitable plus the introduction of a complementary technology alongside. For example, start writing new pages in ASP.NET, gradually migrating more and more code into the .NET world. We've done this successfully - new features are a great opportunity to do this, but simpler parts of the system that can be migrated quickly are also candidates. It may be necessary to concoct some level of abstraction or kind of bridging system (add an API layer to the 'old' system) to get there.

Only you can make the call whether to go for MVC + AJAX, MVC + SilverLight/Flash or similar, but you don't have to park one thing before going forward.

Yes, there'll be some pain and confusion along the way, but you'll have a shippable product the whole time, rather than a long, long, long time 'in development' with an established product becoming obsolete and losing market share to competitors.

share|improve this answer

Do you mean sell it to your business, as in convincing managers to go for it? There's no magic trick, unfortunately, to make managers who view everything in the short term to recognize long term problems. Especially if they arent technical, they may not appreciate the technical reasons for such a thing. The single best thing to do is what you've already done - demonstrate that its the right thing financially. If they dont go for it, there's not much you can do other than sit back and watch things implode.

On the other hand, if you mean how do you sell it to a customer who is a business, thats easy. Re-write the thing, and tell them that if they want feature X, they need to use the new system. Sometimes, to help a customer, you need a little tough love.

share|improve this answer

First, create a category for typical changes in terms of SLOC (and function points if it involves changes to UI elements.)

Then look at previous code changes and see where they fit in the category model described above.

Do the same for new features (that is, treat code changes and new features differently unless a new feature involves significant change/cost on the existing code base.) If integrating a new feature is trivial, separate it from code changes. If its integration with existing code base is significantly costly, lump it with the code changes.

Then, for each categorized code change (or new feature), determine 1) how long it took to complete, 2) how long was it supposed to take to complete, 3) how many people were actually involved in the completion, and 4) how many people were initially thought to be required for its completion.

So now you should have a tabular presentation of delivered artifacts (code changes and new features), each with columns indicating estimated and actual resources (hours, people) consumed.

You can then assume a ballpark average engineer salary/hour (say $40/hr). Multiply that by 2 to indicate total cost of engineer/hour (an estimation of hourly salary, electricity, office amenities and rental, etc.) It doesn't have to be accurate, just realistic enough.

For each delivered artifact A, you can compute the following:

estimated_cost(A) := avg_hr_salary * estimated_hours(A) * estimated_people(A)

approx_cost(A) := avg_hr_salary * (actual_hours(A) + estimated_hours(A))/2 * (actual_people(A) + estimated_people(A)/2

max_cost(A) := avg_hr_salary * actual_hours(A) * actual_people(A)

With these relations (which must be based on actual code changes or new items... otherwise they are meaningless), you can can calculate (per category size), what is the % of a code change of that size to deviate from the estimated size (a % of failure), the approximate cost as well as the % the code change might actually reach a max. cost.

Chances are the % for maximally deviating from the estimated (minimal) cost resembles more and more a exponential distributation the larger the code change is.

With that date, you can tell your customer the following:

You to your customer:

This change you are requesting (A) might take 10K SLOC, on the old code base. Historical data indicates that it might take 2 people at a minimum (estimate_people), possibly escalating up to 3 people (actual_people). The probability of the change to cost (estimate_cost) is A%; B% for approx_cost, and %C for max_cost.

Now, this is key. You have to do the same computations for new requests (the type whose integration with the old code base involves not-significant changes on the later).

If you find that the estimated, approx and max costs for new requests of a given size is (hopefully) significantly less than the costs of old codebase changes of the same size, THEN you have an argument for a code rewrite. You have given sufficient evidence that the old code base is expensive to change compared to changes of the same magnitude in new code.

But if the costs of new code requests do not greatly diverge from old code changes of the same magnitude, you will have a hard time justifying a code rewrite (and it might indicate that the problems are not only to the code base, but also in your development practices.)

share|improve this answer
1  
Only downside I see is if it is a trivial change, then the cost could be too low and the customer would request trivial changes constantly (for instance, if the fee comes out to $320 for a $40/hr salary at 8 hrs and 1 person). Setting the fee large (such as $1000 per engineer hour) discourages trivial changes and encompasses all phases of changes including tech support should something go wrong –  staticx Oct 25 '10 at 0:38
    
@OAOD - that's a good point. The problem with setting up such a large fee per hour is that it is fictitious and cannot be backed with data - it could be done for external development, but not for development done in-house. Also, it's not just $40/hr; it's that * 2 to account to ancillary costs. One way to counter-measure such micro-request changes (if there are many) is to deliver at periods no shorter than 12 weeks. This creates a back-log of micro-changes that you can put a ballpark cost on them. –  luis.espinal Oct 25 '10 at 12:45
    
@OAOD - Also, development units must have a right to reject requests (barring those are are truly critical path). For the most part, requests should be non-trivial, atomic, verifiable and must come from a valid business concept. In-house development is an intrinsic part of business and needs to have the power to negotiate with other internal business units. This negotiating power should be established as a critical part of the internal business process. If that's not the case, then there is no way with which to implement valid cost estimation and trade-off analysis. –  luis.espinal Oct 25 '10 at 12:49

If at all possible do what you can to make the application better as it is right now.

If you are dissatisfied about the documentation, then after you have spent time figuring things out WRITE THEM DOWN for the next maintainence session. Frequently when you see a code base for the first time, just a short lists of "therefores" (to answer the whys the code cannot) can help immensely understanding what goes on.

Improve incrementally!

share|improve this answer

Figure out a way to do it a bit at a time.

If you try to rewrite the whole thing from scratch, you'll probably never release it.

If your bite size chunks are small enough, you may not even need to sell this to the business at all: you may be able to simply go ahead as you implement new features.

share|improve this answer

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