1

I've inherited a hosted system (system "A") which can be used to manage products, inventory, and orders, and can send those products to various third-parties.

Quite simply, system "A" doesn't work. The product and inventory systems are slow, convoluted, and buggy. The third-party integration doesn't work at all. The code is an unholy, spaghettied mess, so fixing things is not simple.

My task is to try and salvage the system into something usable, and my original plan was to just refactor, refactor, and refactor some more until the system worked.

However, my company also has a separate system (system "B") that we use to build e-commerce websites. Among other things, system "B" can manage products, inventory, and orders as well - just in a lesser capacity in some cases. System "B" is also constantly being worked on and updated by a team.

My new plan is to essentially throw out system "A", and re-create it based on system "B".

Since my refactors would have eventually restructured system "A" entirely, I figure I can just save time by starting over with a different, existing framework. However, if I go that route, I would still have to re-code the third party integration, and minor functionality that system "A" has and system "B" does not.

Right now, system "A" is basically defunct - nobody is really using it, so I do have the freedom of a slightly extended rewrite period if I choose.

Is this a good idea, or should I stick with the original plan of refactoring system "A"?

Code Slinger
  • 181
  • 8
  • 2
    Would you focus your question on something more specific? As it reads now, you are asking people whether you should choose A or B. I'm concerned answers to this question would be based almost entirely on opinion, rather than facts, references, and specific expertise. – Aaron Kurtzhals May 30 '13 at 21:22
  • rewrite one module at a time – hanzolo May 30 '13 at 23:16
  • 2
    You might want to get a copy of [Working Effectively With Legacy Code](http://www.amazon.com/Working-Effectively-Legacy-Michael-Feathers/dp/0131177052). – Anthony Pegram May 31 '13 at 00:00

4 Answers4

7

It is good you asked before starting.

According to Joel Spolsky (an experienced and respected software developer as well as one of the people behind stack exchange), the number one "biggest strategic mistake" a company can make is deciding to re-write code from scratch.

In that blog post, Joel points out that it is much more fun to write your own code than to try to understand an existing code base -- so programmers have a bias towards writing their own systems instead of re-factoring. The problem with this is that existing code bases have lots and lots of "knowledge" of built in. The existing code almost certainly deals with many specific little issues/details that are absolutely key to making the software actually useful. When you throw away a legacy system, you throw all of that knowledge away. Replacing it is likely way harder and more time consuming than you imagine.

I have personally fallen into this trap. I completely re-wrote a complex legacy system for the same reasons that you cite (many bugs, confusing code, missing certain features). Once I had the system re-built, I ended up having to re-fix a whole lot of problems that had already been fixed in the original system. The non-technical people who used the software did not see my "clean code" -- they just saw a new system that had little problems that had already been (painfully) solved. In retrospect I should have re-factored not re-written.

If the code is buggy--fix the bugs. If the code is disorganized, organize it. But don't throw the whole thing away.

bernie2436
  • 454
  • 1
  • 4
  • 10
  • 3
    +1: 100% agree with your answer. Although he is not proposing a rewrite from scratch, the information provided gives a good 'Stake in the ground' for him to consider his next step..... – mattnz May 30 '13 at 21:24
  • Adding onto this answer: essentially, the decision to rewrite should only be taken if you fully understand everything the codebase does and have concluded it does it in an inefficient way that cannot be fixed gradually. (e.g. the language the solution was written in cannot deliver the performance requirements) – Joeri Sebrechts May 31 '13 at 11:22
3

Your plan of chucking System A and rewriting it based on System B can work, but only if a few conditions are met:

  • System B must already provide a significant portion of the functionality that System A has. Otherwise, you are just rewriting from scratch and the cautions in the answer from @akh2103 apply.
  • The architecture of System B lends itself well to add extensions to the system. If this isn't the case, trying to add the additional functionality that System A needs will create just as big a mess as System A currently is.
  • The excess functionality that System B has (but System A doesn't need) and the new functionality don't interfere with each other, or multiple deployments with subsets of the overall functionality are possible for the updated System B+.

If these conditions are met, it can work to migrate to a system that incorporates both the current System A and the current System B. In doing so, I would try to use a 'copy - refactor' cycle as much as possible in adding the System A functionality to the new System, instead of rewriting all the new features from scratch.

Bart van Ingen Schenau
  • 71,712
  • 20
  • 110
  • 179
0

What you are doing is considering the options of a) Upgrade to "System B" or b), Maintaining "System A".

We cannot give you a straight answer - far to many variables. The most significant is usually the least technical, and requires significant consultation with you managers and financial controllers. Assuming A is deployed and mostly working, the cost of remaining on A is low upfront investment with high ongoing costs. The advantage of B - lower ongoing costs, is offset by an initial (usually not insignificant) cost.

In this context, cost includes all the things a business considers - Dollars, Opportunity cost, Risk, along with tax implications (A might be all maintenance, B, all capitalized for tax purposes).

Into this you can, and should, put in 'soft' things like "No one wants to work on crufty old code", and "It's easy to recruit developers to work on the new shiny stuff", as well as "No matter what we do, A will always be buggy, but we have a choice with B and make is buggy as you like"

What you should do to weigh these up is put together a plan for both options, outlining the the relative costs (Time, Money, Risk.....) and rewards of each option, and make the decision on the commercials.

before you chose going to 'System B' Do read the answer by @akh2103, and read up on "Second System Effect"

mattnz
  • 21,315
  • 5
  • 54
  • 83
  • Right now, system "A" is basically defunct - I've edited my question to reflect that. Does that change your answer? – Code Slinger May 30 '13 at 21:40
  • Not significantly. "System A" may be "defunct",but it may be better to reserect it.. It has captured a whole raft of un document requirments, edge cases and bug fixes. "System B" will (most likely) not meet all the current needs and expectations of "System A" users. – mattnz May 31 '13 at 00:42
0

I absolutely agree with akh2103's advice against rewriting from scratch. You may rewrite isolated pieces of it (if that is possible), but not the complete system. Why?

From my experience, only the code contains the knowledge about the underlying business cases. Even if you would ask all the non-technical guys that work with your legacy application, you wouldn't get all the requirements and your rewritten system would initially fail to met the real demands. And then you have to start patching it...

Although there is no silver bullet in that situation, I think there are some guidelines:

  • Be sure to have automated tests before you start refactoring. Chances are high that your legacy system has none. Writing tests for legacy system can be quite tricky, however, as dependency are often hard-wired.
  • Keep your legacy code running, but whenever it is possible try to implement new features separately (e.g., add new services). The idea is that over the time, your active code base slowly moves away from the legacy system. Martin Fowler calls it Strangler Application.
  • Only refactor larger pieces of code if you have a reason to touch it. The reason can be quite small, e.g. changing a text that is displayed. But don't start to rewrite a component that works perfectly without having been changed over the last 6 months, just because its code looks ugly. Concentrate on the code that you have to modify the most because these are also the parts that will annoy you the most.
Philipp Claßen
  • 1,387
  • 1
  • 12
  • 26