7 practical actions to write better and more effective user stories
May 06, 2022
Here’s what I’m thinking: you probably already use user stories. Otherwise you’d not be reading about ways of improving their effectiveness. You’re also not satisfied with how your team is managing the work with user stories. Otherwise, why bother reading this? It's time to take action to bring the most out of these little cards, and this article will tell you how.
Perhaps you are not satisfied with how fast your team is moving? Or perhaps the user stories are just a nice coating on dry software requirements? Maybe the team is coding like crazy but the end users are not really making use of all the amazing stuff you are releasing? Or maybe some of the stories are gathering dust in the backlog or in a pre-release branch instead of delivering the value they are supposed to?
I also visualize those who have read five different articles about how to write better user stories, only to end up re-reading five different paraphrases of the same underlying ideas. So I’m gonna save you the effort and avoid repeating much of the stuff that is out there. If I do end up writing something on the same lines of what you’ve already read, it’s because I think that’s really good advice.
So here is what I propose: let this be the last article you’ll read on the topic. It’s time to stop with theory, and try the things you’ve read so far. All sounds great in theory, but day-to-day challenges and team’s muscle memory can quickly bring us back to old habits and inefficiencies.
For us to get started on the same page, let’s pick a relatively simple example for a feature in an e-commerce website: users want to save items on a wishlist and be notified via e-mail when unavailable products on the list become available again. We’ll cover questions like “where did this story come from?” and “what is the scope of this story?” in due time, for now we are just setting the stage.
Why user stories in the first place?
I’ve seen many teams approach user stories as an afterthought. They come up with a feature, have pretty much the whole thing figured out in their heads, down to the little technical details, and then stop and say “alright, now let’s document this as a user story and put it in our backlog.” Feels to me like the business version of developers saying they follow Test-Driven Development (TDD) and then saying “now we just gotta write the tests and we’re done with the task”.
User stories should be the driver of any new feature, the same way that tests should be the driver of any coding activity in TDD. In other words, user stories should not be an afterthought: they should be the primary source of value that clarifies why a specific feature is needed. Atlassian’s definition of a user story as being the smallest unit of work in an agile framework resonates with me, and highlights the fact that these little index cards are far more important than we may consider them to be. Perhaps we should stop using index cards, since they give the impression user stories are something temporary, something that goes into the trash once they are done and removed from the board? Maybe plating them in a nice golden framework and hanging them on the wall would make us pay more attention to them? Anyway, that’s a discussion for another time. For now let’s stick to index cards and move to the first, and most important, action.
0. Discover user stories rather than define them
Oh, the very first action is the basis of everything. Ergo, action zero.
Where do our user stories come from? Who defines them? Who (or what) is our source of truth? If you’re tempted to answer “the PO” or “the BA”, it’s time for us to revisit our understanding.
Our job is not to define user stories: it is to observe our users behavior to discover user stories and work on prioritizing them correctly.
Here is an axiom: end users are an endless source of problems. From their perspective, there is always something that could be improved in our products. There is always a missing feature. There is always a complaint or two about something not working as it should. While many people make memes and jokes about this, I like to think a bit differently: by being an endless source of problems, our end users are an endless source of user stories. Remember: user stories are nothing more than a solution to a problem which delivers value to the customers. It follows that our job is not to define user stories: it is to observe our users behavior to discover user stories and work on prioritizing them correctly.
Let’s start leveraging our example of e-mail notifications. How could we have come up with this feature? How could we leverage customer behavior to discover it? Here is one possible sequence of events. We were monitoring user activity as usual, and we started noticing an interesting behavior on the pages of unavailable products on our e-commerce website. They had way more visits than other products within the same category and price range, and the visits were way shorter than the average. We found that curious, and decided to talk to a couple of end users we have established a good relationship with. The answer? You may expect: the traffic flow was mainly to check whether the product was already available or not, and nothing else. By looking at the ways our users were interacting with the already available product, we stumbled upon a user story: a feature with the potential of delivering real value to our customers.
There is much more to this topic, and I’m working on an article on how to improve our products to help us better identify customer needs. If you are interested in reading that,
!1. Focus on value and be specific
The next tip is to focus on value above everything else. In the traditional “as a ____” format, the value statement comes last, and as a consequence is often poorly written. It’s our job to dedicate time to understand why a certain piece of functionality is valuable. Therefore, the last part of the user story is the most important: why is this feature important for the customer? Which real problem does it solve?
Now that we have nailed down the value of the feature, the next question is: what is the smallest amount of functionality I need to be able to deliver this value? Get everything else out of the way, and focus on the smallest set of changes that your team needs to implement in order to validate the value hypothesis of the story. This refers to the story being specific: it touches a single feature, and it includes only the necessary functionality to properly validate that feature.
How small should a user story be?
Perfection is achieved not when there is nothing more to add, but when there is nothing left to take away. Antoine de Saint-Exupery
A natural question is: “alright, but how small should user stories be? Is there an upper / lower limit?” If you open ten articles on this question, you’ll likely find ten different answers. Most of them will gravitate around the concept of a user story being achievable during a single sprint. I disagree.
Here are my two cents on the topic: digressing on how small or large a story should be is pretty much the same as discussing how many lines of code a function should have. There is no right answer, and there are valid justifications for pretty much every opinion out there. Even worse: by defining a hard limit (say, a sprint), we will inevitably end up breaking up larger features into multiple stories which all need to be implemented sequentially before the feature is considered done. What is the real benefit of that? None from what I can see. So why waste our time trying to figure out how big or how small a user story should be? And even after hitting our heads against the wall, how can we be sure we have reached the pinnacle of optimal story sizing?
Here’s what I suggest: keep user stories specific to a single deliverable feature. This will naturally lead to smaller stories, but will not start with "we should always have small stories" in mind. It will prevent putting the horse before the cart. Quick disclaimer: this does not refer to nor encourages treating epics as stories. Epics are sets of related features, such as Authentication or Payment System. Each epic has a series of individual features that can be independently developed, and these should be taken as the user stories.
2. Deliver a complete functionality per user story
Now that we got the size of the stories out of the way, let’s move on to discussing functionality. Here is a bad example of a user story:
As a frequent shopper, I want to receive e-mail notifications when unavailable products on my wishlist become available again, so that I can quickly purchase my most cherished items.
Why is this a bad story? Very subtle, but here is my opinion. As a dev, I can tell you that most devs will not implement the option to turn off e-mail settings as a part of this story. It involves UI changes, backend logic, DB updates, etc. etc. etc. As a result, the team will probably come up with another story: “as a ..., I want to turn e-mail notifications on and off, so that ...”
The problem? Exactly! This feature is incomplete. The two stories are actually part of a single cohesive whole. They were probably split because having a single story would be “too big”, but that split really left all the users receiving spam e-mails for the whole time between the release of the e-mail alerts and the settings to turn them on and off. Ok, but what if we were to implement the settings before the actual sending of e-mails? Well, then the user would turn that on but not receive any e-mails, right? Doesn’t really solve the problem. Alright, third try: why don’t we implement the settings, put it behind a feature flag, and make it available once the actual sending of e-mails is implemented? Great idea! But then, why split that into two user stories if the first one cannot be released until the second one is completed? Same problem as above... See, when a user story is marked as done, it should mean that the final user is deriving value from that story. If they are not, then there is waste in the process. (I sense another article around the corner,
!)Hopefully the idea is clear. Let’s have a look at another common bad example (it’s actually a set of bad examples which happen to appear often together):
As a frequent shopper, I want to add products to my wishlist, so that I can quickly save interesting products that I cannot immediately purchase.
As a frequent shopper, I want to delete products from my wishlist, so that I can keep my list with only the items that still interest me.
Once again, these two stories are incomplete in themselves and need to be tackled as a single unit rather than two separate stories. Only allowing users to add items will most likely be confusing and lead to discouragingly long wishlists. “Ok then start by implementing the delete story and then move on to the add story”, you may say. Sounds good, doesn’t work. How will you test deleting something that cannot be added in the first place? This would require doing some work towards the “add” functionality, which is overstepping the boundaries between the two stories. Why keep things complicated if we can simplify them by unifying the two stories? Additionally, it makes much more sense from a usability perspective to have both add and remove options. Here’s how I would frame the story:
As a frequent shopper, I want to manage a wishlist by adding and removing products, so that I can maintain an updated list of the products I am very likely to purchase.
3. Slice work vertically
I’ve covered three actions and I feel I already wrote a book. See? There is a large thought process behind defining those little index cards. I’ll try to be more concise from now on.
So far we’ve talked about keeping stories specific and focused on a single functionality, but how do we actually do that? The answer is by slicing the work vertically. While horizontal slicing focuses mostly on a single part of the application (UI, business logic, data, etc.), vertical slicing includes all the layers needed to bring the feature to life.
One way to better understand which areas of your software a single user story touches is to think of it as a synonym for product feature: when the story is complete, it should be the same as saying that the feature is available in the product. Does the story require some DB work? How about backend? Some API updates? Frontend and UX changes? All that should be included in the same story, not in multiple sequential stories. “Won’t that blow up the size of the stories?”, you may ask. If you are careless, yes. If you are thoughtful and understood the underlying principle, no. The underlying principle is: given that we will always slice work vertically, how can we define the scope of a story so that it doesn’t take unreasonably long to finish it?
This will force us to move towards smaller stories (of course, while still keeping the previous tips in mind). There is much more to vertical slicing, so
!4. Prioritize stories through Cost of Delay
Cost of Delay is one of those frameworks that makes you give yourself a big facepalm and say “why didn’t I start using this earlier?” It’s so simple, yet so powerful. So let’s get our feet wet and understand the basics of how Cost of Delay works.
When navigating a full backlog, prioritizing which stories will be implemented first becomes essential. If our stories are sliced vertically, we can drop the famous “we need to implement these 5 stories because they are all necessary for feature X”. That’s not the case anymore: each story is self-contained and can be independently evaluated regarding its priority.
The Cost of Delay framework asks two questions:
- What is the value, in monetary terms, of having such a story released?
- How long does it take to implement this story?
We then calculate the ratio of value over time and, BAM, have a single number that we can use to rank user stories. Pick the ones at the top, and you are most often good to go.
But of course it’s not that simple. Each question above has a troublesome part: in the first one, how do we estimate the value in monetary terms? In the second one, how do we estimate the size of the story? I will not cover the details about Cost of Delay here (I’m in the process of writing about Cost of Delay extensively, so very insightful source on the subject if you want to find out more about it.
), but here is a5. Differentiate between validation and optimization
Despite our now considerably more robust process for discovering, shaping, and prioritizing user stories, it is still the case that we don’t know for sure whether the story is valuable until we release it and observe how customers interact with it.
This is what I call the difference between validation and optimization. We often want to release something beautiful to our users. Lots of animations and the likes. Dynamics elements all over the screen. So cool. I’m all in for that, but please make sure you’re putting the time after you have confirmed your users are actually using the feature. The first step is to validate the user story. Strip down everything that is not necessary for validation. Cool effects are not necessary. Extreme fast performance or super smooth UX is very often not necessary. Remove everything that is not necessary, and get the feature out there. Collect feedback. Evaluate whether it was worth the investment. If the feedback is positive, then we can move to the optimization part. We’ll then write user stories relating to improved UX. We’ll write stories about dealing with those flickering elements due to fast network connections. We’ll focus on trimming the edges and making sure we deliver the most value we can. When we move into optimization, we are taking a validated idea to the next level.
And when optimizing a feature, keep asking ourselves the important questions:
- What makes us believe that this or that customization is desired?
- Why do we need more complex business logic?
- Will an animated UI lead to higher customer engagement? How are we measuring it?
It may be the case you are optimizing the wrong part of your feature, or that you are unnecessarily optimizing something that is already very good from the user perspective. Do your changes lead to higher engagement? If not, why wasting effort and money on them?
6. Release them
This is a one-liner: for god’s sake, get those ready user stories out to your users and gather feedback!
If you followed the actions above, most of the time you should have nice little packages of features that can be continuously delivered to your end users. So just do it.
That’s it. These were my seven tips to how to write more effective user stories and how to use them to actually understand how value flows from conceptualization, through development, and into delivery. I hope they helped you understand their fundamental importance, and pushed you to make better use of them!