Rebuilding vs Refactoring
Recently at work, I was approached by my boss and was tasked with estimating how long it would take to fix a list of bugs. I accepted and said I would have the estimation come end of day. Then I found out which project this was for. It was *THE* project. Every company has this project. It’s the project that no one likes working on. The codebase is horrible, poorly designed and could be described as brittle at best. The problem isn’t just the code looks bad, it is just that to fix a bug in here causes a rippling effect through out program.
Instead of offering a time estimation, my manager got something pretty much every manager hates to get. She got a list of what needs to be rebuilt and how long it should take. Almost everywhere you read, they say rebuilding an application should never happen. I can agree with this to a point. When developers use that word “rebuild”, they often use it like a child who just found their father’s gun in the closet. It can be dangerous and not treating this with careful planning and consideration, you will be rebuilding yourself right into a corner.
When do you start considering rebuilding
This is a difficult choice to make. Sometimes it may not be the only viable option and nine times out of ten, you SHOULD be refactoring instead of rebuilding. However, just because it is a difficult choice to make does not mean you shouldn’t make it. One of the main reasons for rebuilding is the code has become so mangled that you can no longer maintain it. The code has reached a point to where you are having rippling effects every time you have change one little thing and it is next to impossible to stabilize.
In my recent example, not only was it impossible to stabilize, it flat out did not work. Not like “Hey the application does not start”, but their were faults at the core design of the codebase. To fix something in a timely fashion was no longer possible. At this point in the project lifetime, not only have the past bug fixes touched so many different hands, they were all band aids on top of band aids on top of band aids. That helped contribute to making the codebase less and less readable.
Getting feature requests from the client happens often. Everyone gets annoyed when they ask for something that the code was not designed to do. Normally this is fine, because we can just refactor it. However, if the existing codebase is far too brittle, this is not an easy job. When the cost of fixing or enhancing your program starts getting out of hand, it might be time for a rebuild.
The dangers of rebuilding over refactoring
Choosing rebuilding over refactoring should be road less traveled. As I mentioned, it can be dangerous if taken lightly. Noted in this article, programmers love getting the chance to work with that “green field”. When given the chance, they often toss out the old codebase and ignore it. The is an extremely dangerous thing to do. The code can be ugly, but it was done for a reason. This does not mean it is all crap code. You need to analyze the old codebase. This is to find hidden fixes/gems that might be hiding in there. Bug fixes may be in the wrong place, but they are there.
This brings me to another risk that you encounter, which is reintroducing old bugs back into the system. History tells us that if you ignore the past, you are doomed to repeat it. This is no exception. The bandaids were put there for a reason. We might think that wiping the slate clean will make those bandaids disappear, but this isn’t always the case. If you are lucky enough to still have someone on the original team close at hand to ask questions, do so. If you aren’t sure what that chunk of code is doing, find out. Like I said, it was put there for a reason and you can’t simply overlook it.
Another danger of rebuilding is time management. If you wipe the slate clean, you are starting from scratch, not just on the codebase, but on the entire process. This includes user testing, regression testing, etc. New projects have a tendency to slip behind deadlines. However, when something that already exists and it slips behind deadlines is never good, especially when you have a client waiting for fixes. The problem is a lot of programmers do not factor in the COST of a rebuild. It can often be difficult to estimate the cost of a total rewrite. If this is a relatively small project, it may not be that expensive. On an enterprise level, these costs can get out of control. Keep in mind, usually a rebuild equates to nothing new for the customer, which means no revenue to your company.
Advice on rebuilding
After listing off the dangers of rebuilding, its easy to see why it is often avoided. If we do take the path of rebuilding, what are some things we can do in order to help ease the pain. First bit of advice is DO NOT LEVEL the program. Try to break off parts are going to be rebuilt and do it one at a time. Isolating these components gives you the chance to utilize unit testing, which is one of the most important tools you have when refactoring.
Try to get as much documentation on this project as you can. If you are lucky enough, try to work closely with anyone who originally worked on the project. Unfortunately, by the time the project has reached the state of needing the be rebuilt, anyone on the original team is usually gone. Questions are bound to come up and just having the original program to run does not give you enough information about how to rebuild it. The pain is that when you are dealing with legacy code, both of these are difficult to come by.
I will be honest, rebuilding legacy code is pretty dangerous. “If its not broke, don’t fix it”. I feel this is something that needs to be followed with legacy code. Legacy code is code that has been in place for a long time and it is standing up to the tests of time. Personally, I feel that you probably should never rebuild legacy code. Usually digging up documentation for legacy code is out of the question and depending on how old it is. Original coders at this point are probably dead by now, so finding that is probably out of the question.
If you find yourself with out a choice, one this you could do is try to use strong encapsulation to wrap the existing functionality. This will allow you to create more of an api with the existing codebase and just build on top of that instead.
How to avoid having to rebuild
As you can tell, rebuilding can be a dangerous and I feel its an option only if you are backed into a corner. How do you avoid it though? I think we have all coded until time constraints that led us to writing something that we look at, say ‘wow, this is some ugly code’ but do with it anyways. We say to our coworkers “ha. this is getting refactored later”, then never actually do it.
You need to allocate time into your schedule to actually go back and clean up that code. If it is ignored (as it usually is), whoever comes back to put in bug fixes is going to work on it, see that ugly code and in all likelihood, put a band aid on it. Now it is stuck because there are two bits of functionality tied to it. As time goes on, its going to get worse. Mark it with a TODO tag, or find someway to remind you that ‘yes, this code is bad and you are going to clean it up.’
If you can avoid rebuilding an application, you probably should. There are times where that is not an option though, especially when the project has hit a point to where it is more costly to maintain it than it would be to rebuild it. Adding new features to brittle code can be a nightmare, not to mention your low self esteem from putting band aids on band aids. If rebuilding comes to an only option, you need to be aware of the work that follows it. It is dangerous to say that it is better than refactoring and it needs to be taken very seriously.
Agree? Disagree? Have your own advice? Feel free to comment!