One of the biggest challenges for teams that are new to an agile approach is the change from what we call horizontal splitting to a “vertical slice” approach. Teams often aren’t used to thinking about problem decomposition this way, and I’ll hear comments like “well, our system is too complex”, or “we need to build really big features or our users won’t get what they need”. I always tell people that in the eight years I’ve been using this approach with hundreds of teams, I’ve only been stumped once to where we just couldn’t figure out how to slice something small enough to fit into a two week sprint. Well, we could have split it, but it didn’t add any value.
Below I’ll give a quick overview of why we prefer this approach and four simple strategies for splitting stories into small slices.
Horizontal vs. Vertical Slices
At its core, engineering is the art of decomposing really big problems into smaller ones so that we can start to tackle them.
The traditional approach to building a big feature was to decompose in into the work that had to be done at architectural layers. For example, for a web service, we might break a feature down into the database components, the server components, and the client components. Often specialists in these areas would build their piece of the architecture separately, then we would have an integration phase at the end where we would put them all together and test them to make sure they worked as expected. While this makes sense logically, and allows us to develop high expertise in one of the architectural layers, it tended to have a very slow feedback loop depending on the size of the feature, since we’re waiting for everyone to be done with their separate piece to integrate and make sure it works. The term “horizontal slicing” refers to using this architectural layer approach as the primary method of decomposition of big features.
In order to speed up the feedback loop, we can take a large feature and break it up into several small pieces that slice through each of the architectural layers. In my experience, we can break down almost any feature into slices that take a couple of days at most to get all of the pieces built, integrated, and tested. Each slice is comprised of any work needed to be done in an architectural layer as well as any testing and integration that may need to be done to make it ready to release. If you’re using a scrum approach, each vertical slice meets the definition of done within a day or two.
Is a Vertical Slice a User Story?
It could be, and whenever we can find a vertical slice that is valuable to users, that’s the first preference. However, at the day or two level of slicing, we are frequently getting into slices that are not providing really interesting things to users yet. Instead, we are now going for something that is useful to validate the system in some way. We focus on questions like whether integration works, or are there unexpected results when we build it, or does our design require any refactoring. We often discover defects using this approach MUCH earlier than using a traditional horizontal slice approach. We’ll look at some examples of slices below that will give us an idea of a user story vertical slice vs something smaller that is still a vertical slice.
Four techniques for vertical slicing
Starting with a user story, I’ve found four filters to apply that often result in logical vertical slices: Vague Terms, Conjunctions, Acceptance Criteria, and Workflow Steps.
Often we notice that user stories contain terms that are somewhat vague. That’s ok, user stories are supposed to be “Negotiable” (see Bill Wake’s INVEST acronym). Those vague terms often lead to possible vertical slices.
Example Story: As a frequent traveler, I want the weather application to store several days of weather data and display it while offline, so that I can see the forecast at my destination city when I don’t have cell service.
As a former tester, my first reaction to this story is “what do you mean by “several”? It’s a vague term. So is “display” – how will I know that I am using stored data vs. current data, etc.?. Both of these terms provide opportunities to slice by using an incremental approach. For example we might get the following slices from getting very specific about the display part:
- Create a new UI element that displays a timestamp for the last known weather data snapshot (don’t need to actually have an offline mode yet).
- When the phone has no service, add “Currently Offline” to the UI element.
- Maintain the forecast data for the last known weather while offline.
For “several days” we might get something like:
- Store the next day’s weather data
- Store five day’s weather data
Conjunction -junction, what’s your function?. Conjunctions are words that are connectors: AND, OR, WHEN, IF, for example, and when they’re present in a user story, they are often pretty obvious opportunities to create a vertical slice.
Example Story: “As a return user, I enter the option to save a credit card number and select it for future purposes, so that I don’t have to type in all of the data each time.”
Notice that the “I want” statement of this user story has two parts: save the number AND select it for future purposes. These are really easy to split into two slices:
- Save a credit card number to my profile
- Offer the option of using a saved credit card number on a purchase
The “T” in Bill Wake’s INVEST acronym stands for Testable. How will we know the user story is complete? Many teams, when they have this discussion, choose to document the answer to that question as Acceptance Criteria (also know as Acceptance Tests or Conditions of Satisfaction). Let’s look at a sample User Story and the Acceptance Criteria their team agreed on:
Example Story: As a non-english speaking user, I want the system to read my locale preferences from my profile and display the appropriately localized version of the website, so that I can read it without having to manually choose each time.
Hopefully you’ve noticed that this user story contains vague terms as well as a conjunction – our first two split opportunities. Let’s ignore those for now and just look at the acceptance criteria that the team building this story came up with:
- The system will support all Locale Policies defined in the API
- The system will use a URL switch to indicate the Locale Policy
- The user will see the correct language without manually refreshing the system
Notice that each of these criteria could become its own vertical slice, or in some cases multiple slices. For example the first Acceptance Criteria could be split into two or three slices:
- Support Japanese Locale Policy
- Support the most common Locale Policies for our site: English, French, German, Japanese.
- Support all specified Locale Policies
The second Acceptance Criteria could be broken down as:
- Don’t fail when a URL contains a Locale Policy (in other words, don’t localize but don’t give a Not Found error either).
- When a URL contains a Locale Policy, pop up a page that indicates “we noticed you want to display the page for “Language”, is that correct? (validation step)
- When the URL contains a Locale Policy, display the page for that policy.
The third step could be broken down as well – make the refresh manual as an interim step, then make it automatic.
The final way to split stories is by thinking about how a user will interact with the system, and building one little piece of that interaction at a time.
Very non-agile Example Story: As a manager, I want to assign tasks to workers so that workers know what to work on next.
In this work assignment system, we can break this user story into several workflow steps, each of which could be developed one at a time all the way through releasable:
- Manager assigns task to worker
- Worker sees message that a new task is assigned to them
- Worker can choose to Accept task or Decline task
- If Accept, task is added to their work queue
- If Declined, worker is prompted to provide reason for declining
- Manager receives message that worker accepted or declined, with reason if decline
Once we’ve broken this down into workflow steps, we see potentials in all four categories of slicing opportunities: vague terms, conjunctions, acceptance criteria (that we still need to define), and the workflow steps.
The advantages of vertical slices
When we take the time to slice our stories into very small pieces, a lot of cool agile magic happens.
- The smaller slices are much easier to understand, so there is less likelihood of a lack of consensus between team members.
- The small size also tends to make estimates more accurate, if your team is estimating these slices.
- When we decompose into small pieces, we often realize that not every single piece is really required by the user, so we can take advantage of the Pareto Principle and eliminate from our plan some of the “nice to haves” until we get validation from users that they won’t those pieces.
- Smaller slices give us a faster feedback loop – we find defects in design, usability, code, and integration faster. We can get them to users sooner for their feedback.
- If your team has specialized people on it (testers, DB people, etc.), they’re not sitting around waiting while a bunch of work is done in a previous step – since the slices are small, little pieces of work are flowing through the system quickly.
- According to Teresa Amabile’s awesome book “The Progress Principle” the single biggest factor (by far) in engagement at work is small progress every day. Small slices allow the team to get small wins on an almost daily basis, leading to greater engagement.
- Your daily scrums become far more interesting and useful. Instead of “yeah, I’m 20% done adding all of the new schema to the DB”, you get “we got the time stamps working in the UI, and today we’re going to make the data persist when we go offline”.
We can certainly go too far in our desire to split smaller. If you’re getting things down to a day or two, you’re in the sweet spot. We would typically do this level of splitting in the backlog refinement sessions leading up to the sprint in which the story is likely to be built.
Hopefully this blog post gives you some ideas to try out when you’re splitting stories. What else have you found useful? Have you ever come across a feature that you just couldn’t figure out how to split? Share it in the comments and we’ll have a look at it!
More resources for splitting stories: