views:

347

answers:

8

We have all heard of Premature Optimization, but what do you thing about Premature Refactoring? Is there any such thing in your opinion? Here is what I am getting at.

First off, reading Martin Fowler's seminal work "Refactoring" quite literally changed my life in regards to programing.

One thing that I have noticed, however, is that if I start refactoring a class or framework too quickly, I sometimes find myself coded into a corner so-to-speak. Now, I suspect that the issue is not really refactoring per se, but maybe premature/poor design decisions/assumptions.

What are your thoughts, insights and/or opinions on this issue? Do you have any advice or common anti-patterns related to this issue?

EDIT:

From reading your answers and reflecting on this issue more, I think I have come to the realization that my problem in this case is really an issue of "Premature Design" and not necessarily "Premature Refactoring". I have been guilty of assuming a design and refactoring in that direction to early in the coding process. A little patience on my part to maintain a level of design agnosticism and focus on refactoring towards clean code would keep me from heading down these design rabbit trails.

+1  A: 

I think any "1.0" project is susceptible to this kind of ... let's call it "iterative design". If you don't have a clear spec before you start designing you're objects, you'll likely think of many designs and approaches to problems.

So, I think overcoming this specific problem is to clearly design things before you start writing code.

overslacked
+4  A: 

I actually think the opposite.

The earlier you start thinking about whether or not your design needs refactoring, the better. Refactor constantly, so it's never a large issue.

I've also found that the more I refactor early on, the better I've gotten about writing code more cleanly up front. I tend to create fewer large methods, and have fewer problems.

However, if you find yourself "refactoring" yourself into a corner, I'd expect that is more a matter of lack of initial design or lack of planning for the scope of use of a class. Try writing out how you want to use the class or framework before you start writing the code - it may help you avoid that issue. This is also I think one advantage to test driven design - it helps you force yourself to look at using your object before it's written.

Remember, refactoring technically should NEVER lock you into a corner - it's about reworking the internals without changing how a class is used. If your trapping yourself by refactoring, it means your initial design was flawed.

Chances are you'll find that, over time, this issue gets better and better. Your class and framework design will probably end up more flexible.

Reed Copsey
Thank you everyone for your input. I have learned a lot from your collective insight. I selected this as the "answer" because I think it matches my current situation; admittedly, a fact that would be difficult to decipher for anyone but myself.
Swim
+1  A: 

There are a couple of promising solutions to this type of problem, depending on the situation.

If the problem is that you decide something can be optimized in a certain way and you extract a method or something and realize that because of that decision, you are forced to code everything else in a convoluted way, the problem is probably that you didn't think far enough in the design process. If there had been a well written and planned spec, you would have known about this problem ahead of time (unless you didn't read the spec, but that's another issue :) )

Depending on the situation, rapid prototyping can also address this problem, since you'll have a better idea of these implementation details when you start working on the real thing.

mandaleeka
There is no suggestion in the question that design effort is lax. The question also rules out pre-mature optimization which is a different ball of wax.
AnthonyWJones
+2  A: 

I think it is possible to refactor too early.

At the nuts and bolts end of design is the code itself. This final stage of the design comes in to existance as you code, it will at times be flawed and you'll see that as the code evolves. If you refactor too early it makes it harder to change the flawed design.

For example its much easier to delete a single long function when you realise its rubbish or going in the wrong direction than it is to delete a nice well formed function and the functions it uses and the functions they use etc, whilst ensuring you're not breaking something else that was part of the refactor.

It could be said that perhaps you should have spent more time designing but a key element in an agile process is that coding is part of the design process and in most cases, having put some reasonable effort into design, its better to just get on with it.

Edit In response to comments:-

Design isn't done until you've written code. We can't solve all problems in pre-coding design, the whole point behind Agile is that coding is problem solving. If the non-code design solved all problems up-front before coding there would be no need to re factor, we would simply convert the design to well factored code in one step.

Anyone remember the late 80s early 90s structured design methods, the ones where you got all the problems solved in clever diagrams before you wrote a line of code?

AnthonyWJones
I see your point, but refactoring shouldn't change your design... A flawed design is flawed whether it's a 500 line long function or a 20 line function calling into other routines. I find refactoring helps crystalize the design itself, so you can tell what's required by the outside world vs. junk.
Reed Copsey
But maybe that's just my personal workstyle. +1 for making me think about it, though :)
Reed Copsey
Yes. But take an example - you start writing your code, and then you find you have a huge function. If you don't refactor it then, it'll be nearly impossible to write clean tests for it, let alone have other people understand what it's doing any why it's clean.
Reed Copsey
@Reed: One aspect of refactoring is you would write a test for a function at least _before_ you refactor it or even before you write the original.
AnthonyWJones
I'm not suggesting we should abandon common sense and write "huge" functions (not that that is natural anyway) just that it is possible to get too hung up on creating clean code rather than creating working code.
AnthonyWJones
+1  A: 

I am a strong believer in constant refactoring. There is no reason to wait until some specific time to start refactoring.

Anytime you see something that should be done better, Refactor.

Just keep this in my mind. I know a developer (a pure genius) who refactors so much (he is so smart he can always find a better way) he never finishes a project.

Sruly
+1  A: 

The reason why premature optimization is bad is that optimization usually leads to a worse design. Unlike refactoring, which leads to a better and cleaner design, if done thoughtful and right. What I learned to be useful for me to analyze the usefulness of a refactoring was first looking at our UML diagram to visualize the change and then writing the code-doc (e.g Javadoc) for the class first and adding stubs ahead of any real code. Of course experience help a lot with that, if in doubt, ask your favorite architect ;)

Hamid
+4  A: 

We have all heard of Premature Optimization, but what do you thing about Premature Refactoring? Is there any such thing in your opinion?

Yes, there is. Refactoring is a way of paying down technical debt that has accrued over the life of your development process. However, the mere accrual of technical debt is not necessarily a bad thing.

To see why, imagine that you are writing tax-return analysis software for the IRS. Suddenly, new regulations are introduced at the last minute which break several of your original assumptions. Although you designed well, your domain model has fundamentally shifted from under your feet in at least one important place. It's April 14th, and the project must go live tomorrow, come hell or high water. What do you do?

  • If you implement a nuts-and-bolts solution at the cost of some moderate technical debt, your system will become more rigid and less able to withstand another round of these changes. But the site can go live and proceed onward, and there will be no risk of delivering late; you're confident you can make the required changes.
  • On the other hand, if you take the time to refactor the solution so that it now supports the new design in more sophisticated and flexible way, you'll have no trouble adapting to future changes. But you run the risk of your company's flagship product running up against the clock; you're not sure if the redesign will take longer than today.

In this case, the first option is the better choice. Assuming you have little previous technical debt, it's worth it to take your lumps now and pay it down later. This is, of course, a business decision, and not a design one.

John Feminella
Fowler even states that the week before a deadline is not the time to undertake anything but a small refactoring.
Alex B
Refactoring is about changing the internals of your code without altering the external interface and API - "pure" refactoring should have no effect. The design changing from under you and reworking your code to match a new design is a different beast - that's a redesign.
Reed Copsey
On the other hand, for example, if I'm working on a function, and it gets too large, I will always refactor it right then if possible. Otherwise, it's impossible to test it thoroughly, etc.
Reed Copsey
The problem is that a pure refactoring must itself be an atomic operation. Consider something simple like renaming a field -- you have to find all the places to be renamed, and you can't stop halfway or it'll break. That's not a design change at all.
John Feminella
So if your pure refactorings must be atomic, but the size of the atomic change is large, you're going to run into problems.
John Feminella
+1  A: 

Premature refactoring is refactoring without unit-tests. You are at that point simply not ready for a refactoring. First get some unit-tests and then start thinking about refactoring. Otherwise you will (might) hurt the project more than help.

David Pokluda