views:

86

answers:

3

Hi all,

I am currently studying test driven development. I am inquiring about an improvement in design if we refactor after the development of every couple of units as opposed to dedicated refactoring sessions that are more spaced apart in time.

I am aware that the technical debt will be larger. But I am wondering what other impacts. Maybe the refactoring process is not as effective when there is a larger time interval because...?

Thank you..

+1  A: 

I have found that short iterations combined with TDD/continuous integration works best.

Long iterations have the disadvantages of :

1) You lose track of what you are working on 2) Its hard to estimate what you can do in 2months vs say 1 week 3) It gives the business holders less time to re prioritize the development tasks.

Short cycles are easier: "I have to get a and b done this week". You stay focused. You have shorter meetings. Your TDD and continuous integration keep you informed as to the state of your code.

wrt your refactoring question, i think you should probably be refactoring as you go. You don't do things the wrong way for a few weeks until you get around to refactoring. With your tests in place, you will quickly be able to see where your refactoring breaks things.

edit -- another disadvantage to longer development cycles is that people get complacent: "eh, i have 4 more weeks ill do all this stuff later..."

hvgotcodes
Agreed that these are benefits of increasing the refactoring frequency. BUT I dont know if they hint anything about design specifically. The only thing I can think of is that code may rot and get to a point where it cant be refactored.
Yahya
@Yahya -- i agree. I didn't understand that specific part of your question. But, the other answer includes that being test driven informs your design, which I agree with. I think that code rot can occur regardless of length of iteration....
hvgotcodes
edited for the clarified question
hvgotcodes
I am assuming that based on "wrt your refactoring question, i think you..." that better design decisions are made if refactoring is done more frequently leading to the end software having a reduced design complexity?
Yahya
with test driven development, better design decisions are made because your tests are driving your designs. Your tests should be as simple as possible, and your code to make the tests pass should be as simple as possible. That said, things can only be as simple as they can be. All this said, refactoring should be driven by need. If something works, and there are more important things to be done, you shouldn't refactor for the sake of refactoring. You should refactor if its broken or if its not working, or some other functionality forces you to...
hvgotcodes
+1  A: 

A beneficial collateral effect of applying TDD is that your design tends to be thinner and sounder. So major refactorings become unnecessary. In my opinion, this is the effect of designing the system by tests, from "top" to "down" (where "top" are the external interfaces, constraints and requirements, and "down" are the internal implementations and contracts). Sometimes I'm even confused by TDD meaning "test driven design" instead of "development".

Thus, redesigns are driven by changes in constraints and requirements, not by technical debt, which is mitigated at the innermost interfaces. The scope of the changes will determine the extent of the refactoring -- if this is true, "major" refactorings are expected only when the topmost interfaces change.

You mentioned planned refactorings as a step in a longer term development cycle. I think this is a fragile strategy, not because we shouldn't clean technical debt -- we should do it as soon as possible, and that's a practice at the core of TDD --, but because it's risky. To illustrate: in order to plan your refactoring step, how would you assess the size of the technical debt? What if the estimated refactoring time is not enough? Will the system be healthy if you cut the refactoring to do other important things? These are important questions, and not the only ones regarding technical debt management. From a risk management perspective, TDD means better control.

Humberto
maybe my clarification of the question was wrong, I have edited it now. My question is more along the lines of refactoring code frequently as opposed to prolonging the time period between refactoring iterations.
Yahya
@Yahya I expanded my answer.
Humberto
+2  A: 

For the base definition of TDD, you write a failing test, write the minimum amount of code that will make the test pass, refactor, repeat. There isn't a lot of room there for deferring the refactoring. ;)

I think this is so for a lot of reasons, mainly so that people like my boss won't be correct in assuming that the word "refactor" is a geek-speek code word for rewrite. How much easier is it to write one method, that say grabs some info from the web. You write your test, get it to pass, then say, "Ok, now take this hard coded URL and move it to the top of the class, or a property file." How much harder is that to do once you've got your class completed and weighing in a several hundred or more lines of code.

Where the design portion comes in, is less in the big "D"esign, at least in my understanding and use of TDD, rather its in the good practices it encourages and/or demands. Going back to my use-case, ok, I've got my method written to grab my data, now I need to do something with it, do I go back and start adding code to my getData method? No, of course not, its "done.". I go on and write an new method or three to do something with the data. All the methods are kept short, on task, testable, in short, a much better design for the code.

I think that's where the confusion comes in. TDD produces better designed CODE, which will probably produce better software, but if the overall SYSTEM design is no good, then the best coding practices in the universe aren't going to create a good product/system.

YMMV of course.

mezmo