tags:

views:

455

answers:

16

We all know that refactoring is good and I love it as much as the next guy, but do you have real cases where is better not to refactor ?

Something like time critical stuff or synchronization? Technical or human reasons are equally welcome. Real cases scenarios and experiences a plus.

Edit : from the answers thus far, it looks like the only reason not to refactor is money. My question is mostly relative to something like this: suppose you would like to perform "extract method", but if you add the additional function call, you will make the code slightly less faster and hinder a very strict synchronization. Just to give you an idea of what I mean.

Another reason I sometimes heard is that "others used to the current code layout will get annoyed by your changes". Of course, I doubt this is a good reason.

+2  A: 

When you've got other stuff to build. I always feel like refactoring an existing system when I'm supposed to be doing something else.

karim79
+4  A: 

When it is not cost-effective. There's a guy at the place I work who loves refactoring. Making code perfect makes him very happy. He can check out a current project tree and go to town on it, moving functions and classes around and tightening things up so they look great, have better flow, and are more extensible in the future.

Unfortunately, it's not worth the money. If he spends a week refactoring some classes into more functional units that may be easier to work with in the future, that's a week's worth of salary lost to the company with no noticeable bottom-line improvements.

Code will never, ever be absolutely perfect. You learn to live with it, and keep your hands off something that could be done better, but perhaps isn't worth the time.

zombat
I disagree. Ruthless Refactoring is the absolutely best way to make a project work and if you are working on an Agile and not ruthlessly refactoring everything, then you are doing it wrong and should switch methodologies ASAP. 100% ruthless refactoring is the ONLY way to keep your code base under control as it grows. If you want to make better use of this guy's time, put him on a much harder task, or put him on design where refactoring is even more benificial.
Bill K
Yeah, unless you own the company and you find out that bugs are being introduced into code that worked just fine because someone "made it better". There is a line, and refactoring every line of code you see is just dumb. *You* care about code quality, *customers* care about getting software that works in a timely manner. There is a balance between the two.
Ed Swangren
And also, your time costs $$$. If I am paying you, I want you to add value with everything that you do.
Ed Swangren
Sure, if you're doing Agile development on a product that's going forward, refactoring is part of the process. This guy will start working on a minor bug report for a product that's in the support phase, and end up doing days worth of changes. He's come under fire for it several times already.
zombat
@Ed - agreed. It's something you have train developers out of sometimes. It definitely came with experience for me.
zombat
I suppose I could be wrong, but it appears to me that a lot of people severely underestimate the cost of duplicate code. Spending a day to revise a few functions is really not terribly expensive, especially if it ends up commented and more usable. I've never seen code that will not be touched again, and the biggest cost is always re-understanding the code and during that process, refactoring and adding comments is almost free. The cost of editing code where you don't understand all the ramifications can be massive.
Bill K
@Ed If the customer cares about getting software that works in a timely manner, then they care about code quality too, whether they know it or not. You can't have the former without the latter, at least not for long.
Imagist
Refactoring doesn't guarantee code quality. In fact, it often introduces new bugs. There are many more projects out there that *don't* use unit tests than those that do, so refactoring is often a time-consuming process with no unit-test guaranteed backing.
zombat
@Zombat - Refactoring without unit tests is just changing code.
Nate
@Nate: I'm not sure what your point is... that's kind of the definition of refactoring. Refactoring isn't inherently linked to unit tests or anything; unit tests just make refactoring easier. See: http://en.wikipedia.org/wiki/Code_refactoring
zombat
@Zombot - it's the part about "without modifying its external functional behavior or existing functionality" - if you don't have a way to verify this - i.e. unit tests - you're really just blindly changing code.
Nate
@Nate - you're assuming there's no other forms of testing other than unit testing, and that is simply not the case. Companies have entire QA teams to do this kind of stuff. Unit testing is a new set of tools that can save a lot of money and a lot of time, but it's a newcomer to the game, and it certainly doesn't change the definition of refactoring.
zombat
@Zombot - Refactoring also assumes fast turnaround time - a suite of unit tests can be (optimally) run in a few seconds, at the click of a mouse/press of a key. QA takes (optimally) days of turnaround time. And unit testing provides a lot more benefits than a QA department - read this blog post - but *especially* the comments section - http://abstractstuff.livejournal.com/60388.html
Nate
@Nate: I know what unit testing does, how it works, and what the benefits are. I'm *not* arguing *against* it. I **love it**. You made the comment "Refactoring without unit tests is just changing code", and I am trying to tell you that this is not the case. As much as we love unit tests, refactoring is a completely separate notion, and **not all refactoring involves unit tests** in the real world. As well, refactoring does *not* assume fast turnaround time. It is just a programming technique.
zombat
@Zombat - Google "refactoring without unit tests" - are there any supporting results? or are they things like "don't do refactoring without unit tests", "refactoring without unit tests makes me uncomfortable", "Don't even think of refactoring without unit tests", etc. I could also do continuous integration by emailing my code to someone and have them manually compile and run test cases on it and email me back the results - this is continuous integration - but it's not beneficial - might as well be using punch cards...
Nate
@Zombat - also, please read Martin Fowler's bliki entries http://martinfowler.com/bliki/RefactoringMalapropism.html and http://martinfowler.com/bliki/RefactoringCringely.html - though it sounds like you would agree more with http://www.pbs.org/cringely/pulpit/2003/pulpit_20030508_000771.html :P
Nate
@Nate: What is the point you are trying to make? That **all** refactoring uses unit tests? As I've indicated, that is not true. I am **not saying that it shouldn't**, I'm saying that in the real world, it **doesn't**. My only disagreement here is with your definition of refactoring.
zombat
@Nate--there may be a language barrier here. If @Zombat is using a language like Ruby or Perl, he is actually 100% right. You can't begin to do anything in a dynamic language without unit tests. If you are using a statically typed language, refactoring without testing is simply dangerous, but it's very likely that in @zombat's experience it's literally impossible.
Bill K
+8  A: 

Hmmm - I disagree with the above (1st response). Given code with no tests, you may refactor it to to make it more testable.

You do not refactor code when you cannot test the resulting code in time to deliver it such that it is still valuable to the recipient.

You do not refactor code when your refactoring will not improve the quality of the code. Quality is not subjective, although at times, design may be.

You do not refactor code when there is no business justification for making an alteration.

There are probably more, but hopefully you get the idea...

cmdematos.com
Refactoring without tests is not refactoring, for you can't check that you haven't broken anything.
dhiller
+1  A: 

If the code seems very difficult to refactor without breaking, that's the most important code to refactor!

If there aren't any tests, write some as you refactor.

Honestly, the one case is where you are forbidden to touch some code by management/customer/SomeoneImportant, and when that happens I consider the project broken.

Bill K
+1  A: 

If you're stuck maintaining an old flakey code base with no future beyond keeping it running until management can bite the bullet and do a rewrite then refactoring is a lose-lose situation. First the developer loses because refactoing bad flakey code is a nightmare and secondly the business loses because as the developer attempts to refactor the software breaks in unexpected and unforseen ways.

sipwiz
but refactoring allows the developer to learn the system, which is a gain when the rewriting happens. So unless you are maintaining a disposable legacy code, it could still be beneficial somehow.
Stefano Borini
And it's often a good idea to rewrite old, flakey code bit by bit, one module at a time, instead of throwing it out and starting from scratch.
Steven Sudit
Disagree completely! maintaining and refactoring "an old flakey code base" is where you really learn how to program (how the app works, how the bits do as opposed to should fit together, etc), not to mention if the customer can put off a multimillion dollar rewrite for 5 or 10 years cause everything works to their satisfaction then you are doing your job. Refactoring and incremental re-engineering can make old marginal systems much more valuable to your customer and that (not getting to play with the new toys on a full rewrite) is the goal.
kloucks
@kloucks: There is this old wooden bridge across a fast flowing river that has started to rot away at the bottom of its support beams. Daily use of the bridge is essential for people to get to and from their work. The choice is try and repair the old bridge while it is in use by trying to chop out the rotting sections, a dangeorus and risky operation, or alternatively build a new steel bridge. A new bridge costs 5 times as much as the attempt to remove the rotting beams. The people using the bridge have to pay a tax for whichever approach is chosen. What would you do?
sipwiz
@sipwiz I'd shore up the wooden bridge so that it doesn't fall (You have to do that anyway!). Once it's safe and you're familiar with it, patching it should be easier than starting over. It's a known quantity, I've seen many re-writes FAIL with a big-fat capital F while the original "Bad" code just kept on chugging.
Bill K
@Bill K: I wouldn't argue with you, "Bad" code that's chugging probably really isn't that bad at all. My point is to do with degrees of effort and how that influences refactoring. In my bridge example the patching you mention would be replacing the rotten wood on the bridge walkway, a relatively minor operation. Replacing the support beams at the bottom of the bridge is a much more difficult operation, analagous to refactoring. In his answer cmdematos.com has made the argument that there are times when refactoring does not make sense much better than my clumsy metaphor.
sipwiz
+3  A: 

To reinforce the other answer (and touch on issues you mention): do not refactor a part of the code until it's well covered by all relevant kinds of testing. This doesn't mean "don't refactor it" -- the emphasis is on "add the necessary tests" (to do unit-tests properly may well require some refactoring, particularly the introduction of factory DPs and/or dependency injection DPs in code that's now solidly bolted to concrete dependencies).

Note that this does cover your second paragraph's issues: if a section of the code is time-critical it should be well covered by "load-tests" (which like the more usual kind, correctness-test, should cover both specific units [albeit performance-wise -- correctness-checking is other tests' business!-)] AND end-to-end operations -- the equivalent of unit tests and integration tests if one was talking about correctness rather than performance).

Multi-tasking code with subtle sync issues can be a nightmare as no test can really make you entirely confident about it -- no other refactoring (that might in any way affect any fragile sync that just appears to be working now) should be considered BEFORE one intended to make the synchronization much, MUCH more robust and sound (message-passing through guaranteed-threadsafe queues being BY FAR my favorite design pattern in this regard;-).

Alex Martelli
Good point about making synchronization more robust. I've also been faced with that in one project: first the project used locking and shared mutable state, but that produced fragile tests and some concurrency bugs, so now I'm going to refactor its architecture to be based on message-passing.
Esko Luontola
@Esko, excellent! As an aside, one sync technique I'd like to try if I ever get an opportunity (and a good implementation;-) is STM, cfr. http://en.wikipedia.org/wiki/Software_transactional_memory -- seems like it would offer robustness and speed -- but so far I have no real-world experience with it.
Alex Martelli
+7  A: 

I'm a big fan of refactoring to keep code clean and maintainable. But you generally want to shy away from refactoring production modules that work fine and don't require change. However, when you do need to work on a module to fix bugs or introduce a new feature, some refactoring is usually worth it and won't cost much since you're already committed to doing a full set of tests and going through the release process. (Unit tests are very helpful, but are only part of the full test suite, as other posters noted.)

More significant refactorings may make it harder for others to find their way around the new code, and they may then react unfavorably to refactoring. To minimize this, bring other team members in on the process using an approach like pair programming.

Update (8/10): Another reason to not refactor is when you aren't approaching the existing code base with proper humility and respect. With these qualities you'll tend to be conservative and do only refactorings that really do make a difference. If you approach the code with too much arrogance, you may wind up just making changes instead of refactoring. Is that new method name really clearer, or did the old one have a name with a very specific meaning in your application domain? Did you really need to mechanically reformat that source file to your personal style, when the existing style met project guidelines? Again pair programming can help.

Jim Ferrans
+1  A: 

When you don't really know what the code is doing in the first place. And yes, I have seen people ignore that rule.

LRE
Then again, refactoring is a great way of getting to know what exactly a piece of (unclear) code does. *Provided that* you proceed carefully in small steps and add missing unit tests along the way.
Jonik
+2  A: 

Here is my experience:

Don't refactor:

  • When you don't have test suite accompanying with the code you want to refactor. You might want to develop the test suit first instead.
  • When your manager doesn't really care about the maintainablity and extensibility of current code base, instead they care much about if they would be able to deliver the product on schedule, especially for the project with short and tight schedule.
pierr
Regardless of what a manager SAYS, code never seems to go away. So if your code isn't going to go away, aren't you always better off improving it?
Bill K
+6  A: 

As Martin Fowler writes, you shouldn't refactor if a deadline is near. That time in project is better suited to flush out bugs instead of improving design (refactoring). Do the refactoring ommitted this time directly after the deadline is over.

Mnementh
Don't you guys often feel like an internal voice that tells you to do right the opposite, like "Oh tomorrow I need to deliver this. Let's make it more beautiful and refactor."
zedoo
I often hear this voice. But shortly before the deadline this is deadly. Make notes and refactor directly after you tag the release-version. And should really time left before the release - write some more testcases.
Mnementh
+1  A: 

Refactoring is not good in and of itself. Rather, its purpose is to improve code quality so that it can be maintained more cheaply and with less risk of adding defects. For actively developed code, the benefits of refactoring are worth the cost. For frozen code that there is no intention to do any further work on, refactoring yields no benefit.

Even for live code, refactoring has its own risks, which unit tests can minimize. It also has its own place in the development cycle, which is towards the front, where it's less disruptive. The best time and place for refactoring is just before you start to make major changes to some otherwise brittle code.

Steven Sudit
+2  A: 

There's always a balance to be had between fixing or adding to code and refactoring. However, this balance is so far in favor of refactoring that I don't think I've ever been on a team that refactored too much. Chances are, if you think you're erring on the side of refactoring too much, you're right on the money.

Of course, the biggest determining factor is how close the deadline is. If a deadline is imminent, requirements come first.

Imagist
+1  A: 

Isn't the need to refactor code largely based on the propensity of people to cut and paste code rather than thinking the solution through, and doing the factoring in advance? In other words, whenever you feel the need to cut & paste some code, merely make that chunk of code a function, and document it.

I have had to maintain way too much code where people found it easier to cut and paste a whole function, only to make one or two trivial changes, which could easily have been parametrized. But like many other's experience, to try to refactor some of this code would have take a LOT of time and been very risky.

I have 4 projects wherein a 10K line collection of functions was merely copied and modified as needed. This is a horrid maintenance nightmare. Especially when the code has LOTS of problems, e.g. hard-wired endianness assumptions, tons of global variables, etc. I feel bile in my throat just thinking about it.

xcramps
+2  A: 

If you stick to the principle that everything that you do should add value for the client/ business, then the times you should not refactor are the following:

  • Code that works and no new development is planned.
  • Code that is good enough / works and refactoring simply represents gold plating.
  • The cost of refactoring is higher than living with the existing code.
  • The cost of refactoring is higher that rewriting the code from scratch

Some of the other answsers say that you should not refactor code that does not have unit tests. If code needs refactoring, you should refactor it, you must however write tests first. If the code is written in a way that makes it difficult to test, it should be rewritten (in a perfect world).

Shiraz Bhaiji
The interesting part about that is that last bit--The cost of refactoring is higher than living with the existing code. Generally nobody but a very experienced engineer can calculate the value of refactoring. The more I see, the more valuable factored code is, and unfactored code (IMO) actually has a pretty high negative value--meaning you are better off throwing it away and writing it from scratch than trying to interact with it even once or twice.
Bill K
+1  A: 

It's just a cost-benefit tradeoff. Estimate the cost to refactor, estimate the benefits, determine if you actually have the time to refactor given other tasks, determine if refactoring is the best time-benefit tradeoff. There may be other tasks more worth doing.

Larry Watanabe
+1  A: 

Don't refactor if you don't have the time to test the refactored code before release. Refactoring can introduce bugs. If you have well-tested and relatively bug-free code, why take the risk? Wait until the next development cycle.

Dan Diplo