tags:

views:

809

answers:

27
+7  A: 

In order to keep a maintainable code base ?

Code is more read then written, so it is necessary to have a code-base that is readable, understandable and maintainable. When you see something that is poorly written or designed, it can be refactored to improve the design of the code.

You clean your house also regularly, don't you ? Although it may be considered a waste of time, it is necessary in order to keep your house clean, so that you have a nice environment to live in.

Frederik Gheysels
+6  A: 

You may need to refactor if your code is

  • Inefficient
  • Buggy
  • Hard to extend
  • Hard to maintain

It all boils down to the original code not being very good, so you improve it. If you have reasonable unit tests it shouldn't be dangerous at all.

Greg
it doesn't mean the original code was not very good. The original code may have been awesome but subsequent modifications due to impact of other features or requirements changes may have made things messy. If _new_ code needs refactoring that's your indictator of "shit dev", old code almost always needs refactoring if people aren't architecturally tidying when they're bug fixing/feature changing (which in my experience they rarely do).
Quibblesome
@Quarrelsome Good point
Greg
A: 

I refactor because:

  1. often my code is far from optimal first time around
  2. hindsight is often 20-20
  3. my code will be easier to maintain for the next guy
  4. I have professional pride in the work I leave behind
  5. I believe time spent now can save a lot more time (and money) further down the track.
Galwegian
+3  A: 

Because hindsight is easier than foresight.

Software is one of the most complex things created by humans, so it is not easy to consider everything beforehand. For large projects it can even be impossible for the team (at least for one consisting of humans ;) ) to consider everything before they actually start developing it.

Another reason is that software isn't constructed, it's growing. That means software can and has to adapt to ever changing requirements and environments.

Michael Barth
A: 

Upfront: Refactoring does not need to be dangerous when a) supported by tools and b) you have a testsuite that you can run after the refactoring in order to check the functioning of your software.

One of the main reasons for refactoring is that at some point you find out that code is used by more than one code path and you don't want to duplicate (copy&paste) but reuse. This is especially important in cases where you find an error in that code. If you have refactored the duplicated code into an own method, you can fix that method and be done. If you copy&paste code around, there is a high chance that you don't fix all places where this code occurs (just think of projects with several members and thousands of lines of code).

You should of course not do refactoring just because of the sake of refactoring - then it is really a waste of resources.

Heiko Rupp
A: 

For whatever reason, when I create or find a function that scrolls off the screen, I know it's time to sit back and consider whether it should be refactored or not - if I'm having to scroll the whole page to take in the function as a whole, chances are it's not a shining example of readability or maintainability.

A: 

To make insane stuff sane.

I mainly refactor when the code has suffered so much under copy + paste and a lack of architectural guideance that the action of understanding the code is akin to re-organising it and removing the duplication.

Quibblesome
+1  A: 

Another scenario where you need refactoring is TDD. The textbook approach for TDD is to write only the code you need to pass the test and then refactor it to something nicer afterwards.

Adrian Grigore
+26  A: 

Why do we Refactor?

Because there's no actual substitute for writing code. No amount of upfront planning or experience can substitute actual code writing. This is what an entire generation (called waterfall) learned the hard way.

Once you start writing the code and be in the middle of it, you reason about the way it works on a lower level you do notice things (performance, usability or correctness things) that escaped the higher design view.

Refactoring is perfecting.

Ask yourself: why do painters do multiple strokes with the brush on the same spot?

Pop Catalin
I'd also add that your customer requirements, or their understanding of their requirements will always change over time. Your brillant upfront design may not last...
morechilli
@morechilli, can I quote you on that: "Your brilliant upfront design may not last ..." ? :). I like the way you said it.
Pop Catalin
May I restate morechilli's law? "Your briallian upfront design WILL NOT last . . ."
Binary Worrier
sure, you've put a smile on my face :)
morechilli
"Ask yourself: why do painters do multiple strokes with the brush on the same spot?" ... that's a money perspective.
Chuck Conway
A: 

It is human to err, and you're ALWAYS going to make mistakes when you develop software. Creating a good design from the beginning helps a lot, and having skilled programmers on the team is also a good thing, but they will invariably make mistakes, and there will be code that is hard to read, tightly coupled or non-functional, etc. Refactoring is a tool to mend these flaws when they've already occurred. You should never stop working on preventing these things from happening to begin with, but when they do happen, you can fix them.

Lucas Lindström
A: 

Refactoring to me is like cleaning my desk; it creates a better working environment because over time it will get messy.

Jasper Bekkers
A: 

I refactor because, without refactoring, it becomes harder and harder to add new features to a codebase over time. If I have features A, B, and C to add, feature C will be finished sooner, with less pain and suffering on my part, if I take time to refactor after features A and B. I'm happier, my boss is happier, and our customers are happier.

I think it's worth restating, in any conversation involving refactoring, that refactoring is verifiably behavior-preserving. If at the end of your "refactoring" your program has different outputs, or if you only think, but can't prove, that it has the same outputs, then what you've done isn't refactoring. (That doesn't mean it's worthless or not worth doing -- maybe it's an improvement. But it's not refactoring and shouldn't be confused with it.)

Greg Fleming
+11  A: 

Refactoring is the way to pay the technical debt.

mouviciel
A: 

Refactoring is a central component in any agile software development methods.

Unless you fully understand all the requirements and technical limitations of your project you can't have a complete upfront design. In this case instead of using a traditional waterfall approach you're probably better off with an agile method - agile methods focus on adapting quickly to changing realities. And how would you adapt your source code without refactoring?

lithander
A: 

All your points are common descriptors of why people do refactor. I would say that the reason people should refactor lies within point #1: A Big Design Up Front (BDUF) is almost allways imperfect. You learn about the system as you build it. In trying to anticipate what could happen you often end up building complex solutions to deal with things that never actually happen. (YAGNI - You ain't gonna need it).

Instead of the BDUF approach, a better solution is therefore to design the parts of the system you know you are going to need. Follow the principles of Single Object Responsibility, use Inversion of Control/Dependency Injection so that you can replace parts of your system when needed. Write tests for your components. And then, when the requirements for your system change or you discover flaws in your initial design, you can refactor and extend your code. Since you have your Unit Tests and Integration Tests in place, you will know if and when the refactoring breaks something.

Johan Öbrink
A: 

I've found code design and implementation, particularly with unfamiliar and large projects to be a learning process.

The scope and requirements of a project change over time, which has consequences on the design. It may be that after spending some time implementing your product you discover that your planned design is not optimal. Perhaps new requirements were added by the client. Or perhaps you're adding additional functionality to an older product and you need to refactor the code in order to sufficiently provide this functionality.

In my experience code has been written poorly and the refactoring has become necessary to prevent the product from failing and to ensure it is maintainable/extendable.

I believe an iterative design process, with prototyping early on is a good way to minimise refactoring later on. This also allows you to experiment with differing implementations to determine which is most suitable.

Not only that, but new ideas and methods for what you're doing may become available. Why stick with old, fallible code that could become problematic if it can be improved?

In short, projects will change overtime, which necessitates changes in structure to ensure it meets new requirements.

+1  A: 

...because coding is like gardening. Your codebase grows and you domain changes as time passes. What was a good idea back then often looks like a poor design now and what is a good design now may well not be optimal in the future.

Code should never be considered a permanent artifact nor should it be considered too sacred to touch. Confidence should be garnered through testing and refactoring is a mechanism to facilitate change.

John Nolan
A: 

From my own personal experience I refactor because I find if I make software the way I want it made from first go that it takes a very long time to create something.

Therefore I value the pragmatism of developing software over clean code. Once I have something running I then begin to refactor it into the way it should be. Needless to say, the code never devolves into a piece of unreadable tripe.

Just a side note - I did my degree in software engineering after reading some material from Steve Mcconnell as a teen. I love design patterns, good code reuse, nicely thought out designs and so on. But I find when working on my own projects that designing things initially from that point of view just doesnt work unless I'm an absolute expert with the technology I'm using (Which is never the case)

steve
A: 

There is a difference between large refactorings (restructuring modules, class hierarchies, interfaces) and "unit" refactorings - within methods and classes.

Whenever I touch a piece of code I do a unit refactoring - renaming variables, extracting methods; because actually seeing the code in front of me gives me more information to make it better. Sometimes refactoring also helps me to better understand what the code is doing. Its like writing or painting, you extract a fuzzy idea out of your head; put a rough skeleton onto paper; then into code. You then refine the rough idea in the code.

With modern refactoring tools like Resharper in C#, this kind of unit refactoring is extremely easy, quick & low risk.

Large refactorings are harder, break more things, and require communication with your team members. It will become clear to everyone when these need to happen - because requirements have changed so much that the original design no longer works - and then they should be planned like a new feature.

My last rule - only refactor code that you are actually working on. If code's functionality doesn't need to be changed, then it's good enough & doesn't need further work.

Avoid refactoring just for refactoring's sake; that's just refactorbating!

David Laing
A: 

Refactoring is done to help make code easier to understand/document.

  • To give a method a better name - perhaps the previous wasnt clear or incorrect.
  • To give variables more descriptive / better names.
  • Break up a really long method into many smaller methods representing the steps involved in solving the problem.
  • Move classes to a new package(namespace) to assist organisation.
  • Reduce duplicate code.
mP
+6  A: 

I'd like to briefly address three of your points.

1. "A result of insufficient up-front design"

Common sense (and several books and bloggers) tell us we should strive for the simplest, cleanest design possible to address a given problem. While it's quite possible that some code is written without sufficient work on developing an understanding of the requirements and the problem domain, it's probably more common that "poor code" wasn't "poor" when it was written; rather, it is no longer sufficient.

Requirements change, and designs have to support additional features and capabilities. It's not unreasonable to anticipate some future changes up-front, but McConnell et al. rightly caution against high-level, overly-flexible designs when there's no clear and present need for such an approach.

3. "A dangerous activity that needlessly risks destabilising working code"

Well, yes, if done improperly. Before you seek to make any significant modification to a working system, you should put in place proper measures to ensure that you're not causing any harm - a sort of "developmental Hippocratic oath", almost.

Typically, this will be done by a mixture of documentation and testing, and more often than not, the code wins out, because it's the most up-to-date description of the actual behaviour. In practical terms, this translates into having decent coverage with a unit test suite, so that if refactoring does introduce unexpected problems, these are identified and resolved.

Obviously, when you seek to refactor, you're going to break a certain number of tests, not least because you're trying to fix some broken code contracts. It is, however, perfectly possible to refactor with impunity, provided you have that mechanism in place to spot the accidental mistakes.

4. "A waste of resources"

Others have mentioned the concept of technical debt, which is, briefly, the idea that over time, the complexity of such systems builds up, and that some of that build-up has to be reduced, by refactoring and other techniques, in order to reasonably facilitate future development. In other words, sometimes you have to bite the bullet and go ahead with that change you've been putting off, because otherwise you'll be making a bad situation appallingly worse when you come to add something new in that area.

Obviously, there's a time and a place to pay off such things; you wouldn't try and repay a loan until you had the cash to do it, and you can't afford to go around refactoring willy nilly during a critical stage in development. Nevertheless, by making the decision to address some of the problems in your code base, you save future development time, and thus money, and maybe even further into the future, avoid the cost of having to abandon or completely rewrite some component that is beyond your understanding.

Rob
Nice answer. I'd add, under point 1, that we usually don't know exactly what we want until we have something similar. It's not just that planning for exactly what we want at first is impractical; it's usually impossible.
David Thornley
A: 

1) Poor Understanding of the requirements:- If developers dont have a clear understanding of the requirements, the resulting design and code cannot satisfy the customer. Later as the requiremens become more clear, refactor becomes essential.

2) Supporting new requirements. If a component is old, in most of the cases it will not be able handle the radical new requirements. It then becomes essential to go for refactoring.

3) Lots of bugs in the existing code. If you have spent long hours in office fixing quite a few nasty bugs in a particular component, it becomes a natural choice for refactoring at the earliest.

Canopus
A: 

While a lot of other people have already said perfectly valid reasons, here's mine:

Because it's fun. It's like beating your own time in steeplechase, having the stronger bicep in armwrestling or improving your highscore in a game of your choice.

Esko
+1  A: 

A straightforward answer is, requirements change. No matter how elegant your design is, some requirements later on will not buy it.

Joset
A: 

Does point number one even matter? If you're refactoring, the up-front design was obviously flawed. Don't waste time worrying about the flaws in the original design; it's old news. What matters is what you have now, so spend that time refactoring.

Adam Jaskiewicz
+1  A: 

As Martin Fowler says, the only thing surprising about the requirements for software changing is that anyone is surprised by it.

The requirements will change, new features will be requested. This is a good thing. Enhancement efforts succeed most of the time, and when they fail, they fail small, so there is budget to do more. Big up front design projects fail often (one statistics puts the failure rate at 66%), so avoid them. The way to avoid them is to design enough for the first version, and as enhancements are added, refactor to the point where it looks like the system intended to do that in the first place. The lifespan of a project that can do this (there are issues when you publish data formats or APIs - once you go live you can't always be pristine anymore) is indefinite.

In response to the four points, I would say that a process that shuns refactoring demands:

  1. A static world where nothing changes so that the upfront design can hit a non-moving target perfectly.
  2. Will result in ugly hacks to work around design flaws that aren't being refactored.
  3. Will lead to dangerous code duplication as the fear of changing existing code sets in.
  4. Will waste resources over engineering the problem and building large design artifacts in anticipation of requirements that never end up getting built, causing large amounts of code and complication to drag the project down while not providing any value.

One caveat, though. If you don't have the proper support, in an automated tool for simple cases, and thorough unit tests in the more complicated cases, it will hurt, there will be new bugs introduced, and you will develop a (quite rational) fear of doing it more. Refactoring is a great tool, but it requires safety equipment.

Yishai
A: 

I refactor because proper refactoring makes maintenance SO much easier. I've had to maintain a TON of bad, awful code and I don't want to hand down any that I've written for someone else to maintain.

Maintenance costs of smelly code will almost always be higher than maintenance costs for sweet smelling code.

Terry Donaghe