How David killed Goliath – Are too-small User Stories killing your ability to deliver?
In my new role I’m dealing with not only an inherited codebase but also an inherited backlog of user stories, and some pretty tight delivery deadlines.
The team had initially taken the stories as being ‘sprint ready’ as it seemed to be a continuation of the previous team’s approach but unfortunately as we worked through them we started to realise a couple of things:
- The stories were too small, you couldn’t release the completed functionality a single story covered
- The stories were highly dependent on each other, as they were too small and the final functionality was made of multiple stories
- While the stories themselves contained a lot of acceptance criteria a lot of this was made up of regression scenarios that were repeated across a lot of stories
The team is also not the only team working with this codebase, there are four other teams working on other functionality that are merging into the same repositories and branches as my team, with any team having to cut a release from develop at any time.
This meant that the team hit a wall as they were unable to merge any changes in and as they were blocked they would then pick up other tickets which would then implement similar behaviour.
These additional tickets would also get blocked and towards the end of sprints we would have numerous branches that were ‘test ready’ but not integrated with each other.
Faced with the issue of how to deliver small stories in a widely shared codebase without rewriting all the stories we had a whiteboard session and decided to implement feature toggles and abstract out as much shared functionality into external modules so we could deploy versions with complete functionality when we needed to.
The impracticality of feature toggles in a spaghetti codebase
When we actually sat down to implement the feature toggle and external module approach we started to realise something we hadn’t factored into our whiteboard exercise – the codebase was highly duplicated and a mess.
In order to implement feature toggles for one piece of behaviour we’d be adding about six times as many conditional statements as we had expected.
Additionally the external module approach wouldn’t work as the previous development company had decided to commit the codebase’s external dependencies to version control instead of using the dependency manager’s lock file support.
We had to come up with a means of unblocking the development team while also ensuring that incomplete functionality wasn’t accidentally released when another team wanted to release something they’d completed work on.
I’d initially rejected the idea of a long lived feature branch as a solution to our problem as it would have been a hassle to handle the rebasing of the main branch whenever another team merged in.
However, faced with the situation we found ourselves in I had to side with the approach, and it’s actually had a very good impact in the team’s ability to get these smaller stories delivered into a branch we can integration test in.
Once we’ve got all the functionality from all the stories tested within the team we can then demo the functionality as a whole and get sign off from the Product Owner before moving to Business Value Testing (BVT) and into release.
This is very important as the current code base has very little in the way of unit and integration tests, so it’s highly reliant on manual testing at the BVT stage.
In order to release we then rebase the branch and merge that into develop from which we then take a cut.
As the use of an ‘epic branch’ has sped up development immensely we actually don’t face that many merge conflicts as the epic branch only lasts a week or so at most.
Solving the real problem
It wasn’t until we started to sprint that we realised the issues with the user stories being too small and at that point we were locked into delivering them which we of course failed to do!
While I was initially getting stressed out, being the person responsible for ensuring the team was able to deliver to the tight deadlines from the client, I started to realise that the bottleneck caused by the stories was actually a good way to visualise the issue and work with the client and improve their user story writing process.
We sat down with the client’s Delivery Manager and explained the issue the stories being too small was causing and how instead of trying to make the stories small enough to be ‘one pointers’ we should look at the stories representing the smallest releasable functional change to implement the epic.
This new way of looking at the stories has meant that while it looks like we’re taking less points into a sprint we’re actually delivering more functionality as it’s no longer stuck on a bunch of independent branches and we can merge directly into develop.
We’ve also now got to a point where our backlog has a bunch of releasable independent stories that can be re-prioritised which has allowed both the Delivery Manager and the Product Owner to start planning sprints to meet key points in the programmes roadmap.