I had an interesting twitter debate a couple weeks ago with a bunch of people I really respect and admire. A good number of them totally disagreed with what I was saying though, so in order to maintain my large ego, I’m going to chalk it up to 140 character limitations and try to expand on my thoughts here.
The crux of the discussion is this. Our team had recently imposed a limit on the number of refactoring or technical debt cards in process at any given time in our system. The reason for this was that we had a couple of iterations where we accomplished some significant changes to the code base which will result in longer term savings and easier maintenance, but the product owner and sales organizations that we work with didn’t really get to see much visible progress on the software for a couple of weeks. We felt that we should spread out the tech debt cards so that the product owner and stakeholders could still get to see progress every week, yet still empower our team to play the tech debt cards as they see fit. So my open question on twitter was:
The consistent push back against my comment was some form of “Why do you have refactoring items on your board?”, as my colleagues mention here:
A lot of people felt that we should just have completed the refactoring as we finished the card. I am not saying that we are not doing refactoring as we are delivering stories and I’m not saying we have an extensive list of refactoring items. We have a solid team with many members who teach and coach others on TDD and the red, green, refactor cycle. The refactoring items or technical debt that we’re tracking are typically orthogonal to a user story we’re currently working on. Consider a fictional example to illustrate the point.
Say you are building a website that sells index cards. The website may have some domain objects like a user, product, address, etc… You have decided to use validation framework X to validate the data that users enter for these objects. This works well until you run into the account domain object. Here there is much more extensive acceptance criteria around the validation of credit card information which isn’t easily accomplished using validation framework X. The team completes a spike and determines that validation framework Y is the right approach so the account creation user story is completed with a new validation framework Y. The team collectively decides that having two validation frameworks is confusing and since Y is the superset of X, that they should standardize on using Y throughout the system. What do you do?
I think many of my peers seem to be suggesting that we should just complete the validation framework swap while working on the account creation user story. I don’t like this for a number of reasons. First, the completed account creation user story is delayed from moving through the rest of the system. I’d rather my product owner or exploratory tester start hammering on the new story (and validation framework) before I start expanding this to the rest of the system. We would be able to see any deficiencies in the new framework prior to swapping everything over and avoid a potentially painful conversion back. If the validation framework swap was a day or more worth of work, then we’d also run the risk of not demoing a completed user story to the rest of the team when really that work is done.
I also think the team would be better served to prioritize this work when they feel it is most important. Collectively. Completing large refactoring or technical work in under the guise of a user story is fairly disingenuous to the product owner. Maybe we’re just lucky because we have a product owner who really sees the potential maintenance costs of not doing these refactorings, but we’ve never felt like we needed to be anything but open and honest about the work that lays ahead. Added bonus here is that if a tech debt card, like swapping out your entire validation framework needs to be played, it can be planned in a way that may not cause significant merge pain for the rest of the team.
I think the discussion on twitter may have been largely a semantic argument about what is technical debt versus refactoring, but I want to make sure my points here are clear. Whether calling technical cards a user story, refactoring card, or tech debt card, make sure that they are planned, prioritized, and completed in the same visible manner as other cards in the system. The board should be a mirror of the work, the work shouldn’t have to be forced to fit into the board.
3 comments:
Sounds very pragmatic, Todd. There are small factoring that should be done as part of a story ... Before, during, and after. There are other things that are large and need to be more visible, planned, and scheduled.
I'm torn I guess. In my mind, Tech Debt is something that is know to be suboptimal and has been negotiated with the business as 'work to do' that has value; therefore its a card. Refactoring is just cleanup/mods that come with the completion of a story. Your example of changing out a validation framework/approach is an evolution of the tech-stack used to deliver. That leads to a conversation about the +/- of switching out existing validations (on completed work) in terms of value. There is an underlying value story from the IT organization around the maintainability. That is the driver for those kinds of changes and they need to be represented by an product owner as well. That would require the business person to take some ownership for the software asset in a IT context --or-- someone from IT being represented as a stakeholder in the decision making process. I think you can have what you want, but you should look at when the decision is being made, by whom, and the priority applied to the work.
Refactorable "tech debt" does build up naturally, as well as the unfortunate-intentional debt incurred in collusion with the business.
On my last project any developer was permitted to write up a card when they saw something they wanted to refactor that was either too extensive or unrelated to their current card.
Doing so forces a discussion to occur.
This results in a few outcomes:
* ripping the card up
* giving the card a "5" (too-big in our case), in which case it need to be broken down into more well defined refactoring steps
* estimating the card and putting in the backlog
Even of the cards that made it into the backlog only a portion of them ever were prioritized. The prioritization was usually related to how valuable the effort was in relation to factors such as future velocity, design direction/changes, testability/ci issues, etc.
Post a Comment