Awhile back I read an article that was all about justifying separate refactoring stories on the product backlog. The author was suggesting that having separate stories for refactoring was a good idea and that the stories should be justified on the basis that completing the refactoring story would result in future business changes requiring less time. He explained that refactoring will not give immediate return but in the long run adding features will be less expensive as code would become more maintainable.
While I don’t disagree with anything said there, there is definitely something about this approach that smells a little fishy to me.
Simplicity — the art of maximizing the amount of work not done — is essential.
Remember that principle? The entire argument above is about possibly making future features easier to implement. Let’s be honest, we don’t know for sure that our refactoring changes are going to make the future features easier. We have no idea what these future features will be, for all we know we may refactor in such a way that actually makes them more difficult. Maybe they are such a radical change that we still have to more or less throw out what we have and start over. Maybe there won’t be any future features. Maybe there will only be future requests on one small part of the software. This justification is all about possible future gains, which inherently means it is also possible wasted time and effort.
Before my team shows up at my desk with pitch forks and torches, let me say I’m all for refactoring. I think we should be refactoring all the time. I am even okay with having separate refactoring stories on the backlog occasionally. However, there was something about the approach that seemed to be suggested in that article and this justification that just didn’t seem to fit with me.
Honestly, to me this smells a bit like an excuse for “cleanup”, following poor initial coding practices and then going back and cleaning up the code. I’m sure there was a lot more context around the examples the author was discussing that wasn’t in the article that may justify this approach, but I am definitely not comfortable just presenting that justification as a blanket statement. To me that blanket statement sends the message of lets just code it fast and dirty to get our points, then go back and add refactoring stories.
I think there is really a two pronged approach to this. First and foremost, the team should be writing well structured, maintainable code from the beginning. This means the team should be following good programming practices like doing TDD, ATDD, and/or BDD, and refactoring should be built into the initial story. Get the functionality working while writing tests around it, then refactor what you just wrote to make it more maintainable. The story isn’t done until the code you just wrote is well structured and maintainable for the current purposes. If a team is doing this and being disciplined about it, I would not expect to see very many separate refactoring stories on the backlog.
So when might I expect to see separate refactoring stories even if the team is being disciplined about implementing their stories well? I would expect to see separate refactoring stories if the team is dealing with legacy code, or if there is an unexpected shift in the product backlog.
If the team is working with legacy code and they have enhancements and/or bug fixes on that code coming up in their backlog (or they have been dealing with a series of defects from the legacy code), spending some dedicated time going back and refactoring that code, so that the team has a better understanding of what it is doing and making the code more readable would definitely be acceptable. However, I would not expect to spend that time on legacy code that the team was not specifically planning on enhancing in the near future (next couple of sprints) or that hasn’t been a thorn in the team’s side causing distractions and issue during prior sprints with defects and production issues. If you are working with legacy code and are trying to refactor it, I would definitely suggest taking a look at Michael Feather’s book, Working Effectively with Legacy Code.
If there is an unexpected shift in the product backlog, I could also see the need arise for a separate refactoring story. I would expect a team to have at least a high level view of where the product is heading and be designing stories with that end goal in mind (not building the entire architecture up front, but making smart decisions knowing the direction in which we are heading…don’t paint yourself into a corner). If that’s the case, and everything progresses as planned, I generally wouldn’t expect separate refactoring stories. I would expect any refactoring necessary would be able to be done as part of implementing the next story in the backlog, allowing the architecture to emerge as we move toward our goal. However, if the goal has a significant shift (which definitely does happen) then maybe I can see the case that a large enough refactoring effort would be necessary to justify a separate story. I would still prefer to find ways to get there more incrementally, maybe there are different ways of breaking the stories that will allow for smaller refactoring efforts along with incremental functionality changes.
So, should refactoring stories exist? In my opinion, the simple black and white answer would be a no. Of course, we don’t live in a simple black and white world though, so to me they are a smell that could indicate poor programming practices or a lack of discipline in the team. That’s the beauty and the curse of agile. We accept the fact that we don’t live in a black and white world and there are exceptions to every rule. Everything requires context, so when we see those exceptions we should ask questions. If I am working with a team and there are a lot of refactoring stories on their backlog, I’m definitely going to be asking that team a lot of questions and watching to see if they are following good programming practices, especially if they aren’t working on a legacy system. However, if I’m working with another team and see a refactoring story here or there on their product backlog, I’ll probably ask some probing questions to see if they considered other approaches, but I’m not going to lose any sleep over it.
What do you think? Are there valid cases for separate refactoring stories that I’m overlooking here? I’d love to hear what you think and hear of some of your examples.