Show all posts
8 years ago

Refactoring vs. Rewrite

Code base of a large project is getting worse over time. I hope there are lucky exceptions, but in general it is true for most projects. The reasons are quite obvious:

  • More and more features. It leads to increased complexity.
  • Shortcuts and hacks to support "We need this fancy search till August. Period!" features
  • Developers rotation. New developers don't know all the fundamental decisions and ideas behind the architecture. Knowledge gets lost with transition inevitably.
  • Development team growth. More people - less communication. Less communication - bad decisions. It leads to code duplication, hacks to make something work without deep understanding of the underlying conditions etc.

Suddenly you can't add new features easily, you can't make significant changes easily, you have tons of technical debts and development team is close to bankruptcy. You want to change that and have just two options: refactoring or rewriting everything from scratch.

Refactoring and Punctuated Equilibrium

Punctuated Equilibrium is a theory in biology, but it is applied to other complex adaptive systems like societies as well. It states that the system has almost no changes in significant period of time and then changes very rapidly. Then it acquires the equilibrium state again. Sounds familiar? Sure, refactoring is almost the same.

Any change in the system introduces chaos in the short term. The goal of refactoring is to eliminate chaos, but often you increase it initially. When you are working on changes you make system less stable, but as the change is completed,  the system can be more ordered. That is not always true for software development. If you use branches,  this makes changes safer. Still significant changes increase the risk of new bugs.

The real danger of refactoring are local optimums. With a full rewrite you may have a better architecture than with refactoring. Solution? If you have a vision of final architecture, use it and try to make a path from current architecture to the new architecture. In general simplicity should emerge from refactoring.

Rewrite and Chaos

When you rewrite from scratch, you add such a large portion of chaos that it is hard to predict the final result. You have a new singularity that will explode to the new product universe. But are you certain that it will be better than the previous universe? How many the 'same bugs' will you fix in the new product version?

However, rewrite may look faster. I mean you may release a new version faster with rewrite, but most likely with more bugs and less stable.

I think we may expect something like that:

refactoring_vs_rewrite1

The green line shows how chaos changes with refactoring. After each refactoring there is a small increase of chaos, but then the system becomes stable and chaos decreases. You see that the final release is quite late, but keep in mind that there have been many releases before, so customers benefit earlier.

Black line is how chaos changes with a full rewrite. We have the old system during rewrite, so chaos is constant. After the public release chaos increases significantly. Quite many new (and old) bugs and quirks are expected, so stabilization period is longer. But the release itself is faster. The reason is that there is no burden behind. For example, there is no need to support all the places when you do a change, while in refactoring it is required  to keep system working and stable all the time, and it demands additional effort.

Adaptation vs. Revolution

There is another angle to this problem. Refactoring is adaptation, while full rewrite is revolution. Again, revolution is a chaotic beast. You may slowly adapt the product for new external conditions or make one revolutionary rewrite.

So, Rewrite or Refactor?

I do think there is no universal correct answer to this question. If time to market is paramount, if you feel that you'd lose business if a new version will not be published in 6 months, you may try a full rewrite. But beware side effects! Quality may drop significantly and long stabilization period may hurt existing customers.

In most cases refactoring is preferable. Slow pace, high quality, constant improvements, happy customers. I like it more. But rewrite is so magnetic...

  • peteredstrom

    There is a point at which it is too late to refactor. Thinking about a system I work on daily, it has 2 big problems.

    Problem 1) technical limitations that prevent any significant improvement. the issues are too deep to simply refactor away.

    Problem 2) Even if we ignore the technical limitations and dedicated ourselves to refactoring, it would easily take 2+ years to get half as far as we could get in a 6-month rewrite. Computer capabilities are doubling every 2 years, and we don&#39t have enough time to take the slow, risk-free, route of incremental changes.

    There are other strategies to minimize the big-bang effect with a full rewrite. My personal favorite: rewrite a single component of the whole thing, stand it up independently, and make it available to a subset of your customers.

  • Michael Dubakov

    By &#39component&#39 do you mean some part of the system vertically? I mean a component that has DL, BL, UI, etc.

    Why do you think your estimates are correct? Is it gut feeling or something more?

    Maybe refactoring term is not very good here. Restructuring may be better. Your approach with partial re-writes indeed looks good. For example, if you do nopt have DAL, you may create it and then refactor application to use it.

  • peteredstrom

    Yes, I&#39m thinking of a vertical portion of the system. Ie, a distinct piece of end-user functionality and all of the bits that make it work (DL, BL, UI).

    I don&#39t know that my estimates are correct. What I do know, however, is that the feature-focused changes we&#39ve implemented over the last 5 years are small and slow to build. Especially when you compare them to the depth and breadth of functionality I was able to rapidly create on two separate proof-of-concept/prototype efforts for rewriting.

  • ytimenkov

    Rewrite may seem much faster than refactoring, but in practice, such estimates are too optimistic, and instead 6 months it can take 3 years with poor quality. And this 3 years – is not a limit, such releases often time-driven: employer just gets tired and releases what it has after some testing and stabilization. For example, look at Windows Vista – where its WinFS (database-like file system) or other revolutionary changes? Same for KDE: it took about 1.5 years from alpha to 4.0 and 1.5-2 years after release to bring it into the shap (but at the same time they did 4-5 maintenance 3.5 releases).
    Yes, these examples – are big applications, but as pointed in the article, small ones don&#39t require rewrite (or rewrite is not a big deal), but I can&#39t imagine that big complex application can be rewritten without the loss of functionality in 6 months.

  • chibacity

    I&#39m more of a refactoring person myself, but if you leave it too long you&#39re stuffed. It&#39s a rewrite or the product may even die.

    Rewrites often take far longer than expected, and you also have to factor in that you need to support the old version at the same time. A pitfall can also be in not fully understanding the original problems and then re-implenting them to varying degrees e.g. lets stick with the crappy schema from the legacy system and write an abstraction layer on top for the new system. The problem is that the old problems are just abstracted rather than solved – problem rearranging.

    Refactoring can be a positive exercise e.g. incrementally taking something which is: old, works well, liked and then bringing it up-to-date with new technologies, features and better design. However, there are also occasions when the need to rewrite or refactor is negative in nature e.g. something is: old, not working very well at all, causes all manner of problems, and has been very neglected. The later areas are usually well known by the developers and are often the cause of much eye-rolling and gallows humour over the years… The problem is that those smelly old features that everyone loves to hate are now a family of smelly features, they are inbreeding, and a crap load of rot has set in. This has cost a huge amount to produce, is holding the product back, the customers don&#39t love your product and neither do your developers. Adding features is now like pushing water uphill with a rake (worst case scenario I know, but seen it happen a couple of times on sizeable projects).

    Best not to let problem areas drift out of control. Try and nip them in the bud.

    There are lots of pressures that lead to neglected areas, but it&#39s when it becomes critical it&#39s a major problem. Don&#39t leave sorting out problem areas till it&#39s too late in the day as there is: less room to manoeuvre and less opportunity to make good and progressive decisions.

    In an ideal world both techniques should be applied incrementally. The main problem is doing neither. Treat refactoring and rewriting as first-class citizens of the development process along with feature development. Incremental improvements may slow delivery of features, but you may be able to continue adding features at a steady pace for a longer period of time.

    It&#39s often the case that refactoring is not seen as a first-class citizen, but isn&#39t refactoring supposed to be one of the core tennets of agile development? Refactor as you go along, and then refactor again as you integrate. Bite the bullet – do some refactoring today! 🙂

  • Bill Sorensen

    If the existing code base has unit tests, refactoring becomes much safer (less chaos).

  • Michael Dubakov

    Well, it is not possible to refactor without unit tests at all. If you do not have unit tests, you have 2 options:
    1. create unit tests first and refactor then
    2. rewrite.

    Without unit tests it seems option 2 is preferable.

  • Michael Dubakov

    I do agree that it is better to rewrite some parts of the system then refactor. I think it is much faster to rewrite UI layer from the scratch then refactor it, for example.

  • Graham Poulter

    Joe Spolsky says that starting from scratch is the first thing you should never do (especially with a live product, i might add).

    “It&#39s 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”

    http://www.joelonsoftware.com/articles/fog00000

  • Michael Dubakov

    Joel not always right.

  • Cantinho do Agile

    Very good!

  • Cantinho do Agile

    Very Good!

  • AndrewGolik

    Rewriting application helps get rid of the bad design habits. It&#39s more mentality problem.
    Usually, you do refactoring at critical parts. You cannot live with them any longer so you do refactoring to move forward. In other words you get rid of the obstacles that save you time near future. You probably encounter the code that needs some refactoring but you ignore it because it&#39s no so bad. It has smells but you can still work with it and you just leave it out. And then it happens again and again. You can do nothing with this. Sure, refactoring practice helps much but somehow it comes down to rewriting.

  • Gavin Leone

    Devs without deep understanding of the underlying conditions should try to consult the application Guru (or main authors) before any new feature/fix is added. That way they can find the best/correct approach before they hack away at it. In other words, consult first, then code, There is no shame in asking how you should tackle something.

  • air jordan 17

    It looks good,I have learn a recruit!
    Recently,I found an excellent online store, the
    sall4.net
    are completely various, good quality and cheap price,it’s worth buying!

  • hilda_dada

    Browsing on Google for something else closely connected, regardless before i ramble on too much i would just like to state how much I cherished your post, I&#39ve added your web blog and also obtained your Feed, Again thank you very much for the article carry on the good work. gps vehicle tracking

  • thomas

    Excellent
    work.. do contact us if you want to have a website like this

  • Tyler Etters

    Always a challenging decision. My rule of thumb is this: “If you’re digging a hole stop. But if you’re digging a hole to get to the oil, don’t be a quitter.” Refactoring can be unpleasant. The idea of rewriting is appealing because code is easier to write than it is to maintain.

  • Dvid Silva

    like when the person that wrote the code left the company in very not-nice conditions some generations of developers ago, and no developer last there longer than 8 months.

  • Phone Transact POS

    ” there is absolutely no reason to believe that you are going to do a better job than you did the first time”

    agreed…

    but the problem is that the “you” that wrote the first version and the “you” that is doing the rewriting should hopefully not be the same person. If you are rewriting someone else code then there is a very valid argument to rewrite vs refactor.

Get started for free

How many people would be using Targetprocess?
  • Myself
  • 2–20
  • 21–100
  • 101–1000
  • 1000+
By clicking Continue you agree to our Terms of service and Privacy policy