4

I run a team with a few iOS developers and a few backend developers. Over the last couple of months, we've been experimenting with different ways of structuring users stories for sprints and have generally tried two approaches:

  • breaking a feature into very small, bite-sized stories
  • encompassing a feature in one very large monolithic story, with many small technical tasks

The former is tricky because there end up being a lot of blockers between stories, and it's difficult to visualize all of the information for a feature since it's spread across many stories

The latter solves the centralized source of information issue, but the story becomes so large and overwhelming that the details end up getting lost in it all

Coming up, we're going to be revamping our onboarding flow for our iOS application and I thought it might be a good opportunity to try a new approach. I think the smaller stories worked better than the larger one, but i'm still not quite sure how to structure it such that there aren't lots of blockers, but perhaps i'm thinking of things in the wrong fashion. The high-level (and very terse for the sake of this post) stories could be:

  • a user needs to be able to signup with a phone number
  • a user needs to be able to sign up with email
  • a user needs to be able to choose a username
  • a user needs to be able to connect their contacts
  • a user needs to be able to login with phone or email

However, each of the above has lots of dependencies on one another (ie, you can't really choose a username until you've signed with an account, lots of UI elements and workflow pieces are shared between the above flows, etc)

Should I be thinking about this differently?

  • You have an underlying process problem. What's your Sprint Goal for this set of tasks? What's the feature you're trying to build? How does your team collaborate, and why do your user stories (not tasks) need to be so granular and involve so many hand-offs? – Todd A. Jacobs Aug 9 at 13:32
1

Yes, you should think about this differently because what you have are claiming to be high-level user stories are tasks. Consider reading the question What is the weighting difference between Epic/Story/Task? to understand better the concepts (which are good enough to be used and followed).

In a few words, a task belongs to a user story and, accordingly to Assaf Stone, reflects

(...) the work needed to be done on each of the components that your story touches.

A user story is written from a user perspective that provides some business value and follows a specific format

As a [role] I want [goal] so that [benefit].

In order to create good user stories, start by remembering to INVEST in good user stories. INVEST is an acronym which encompasses the following concepts which make up a good user story:

  • Independent.
  • Negotiable.
  • Valuable.
  • Estimable.
  • Small.
  • Testable.

So, even if they were user stories, by being dependent contradicts the I from Invest, making it a bad user story. Imagine that you have a video streaming application to run on smartphone, tablet or computer and we want to solve this problem, that is, when you switch from device to device when you are watching video streaming in this application that is going to be made, you start again from exactly the point you had stopped before, no matter why you had stopped before, you will start over from that point. (this is an example i'm giving in another answer). The user story can be as following

As a user of video streaming (role), I want to start watching program on my mobile device, then I want to be able to resume the same program on another mobile device at the point I stopped at the previous one (goal), so that I don't miss a second of the show I was watching (benefit).

  • 1
    Thanks for your input. While that all makes sense, in practice, I find that its sometimes difficult to apply. For example: "As a new user, I want to be able to signup for the service with my phone number, because that's the most convenient method" . AND "As a new user, I want to be able to signup for the service using my email address, becuase I'm not comfortable providing my phone number". Those could be two separate stories, and we have designs for all the flows from our designer, but there's also lots of overlap between those flows and designs, so they are not truly independent. – djt Aug 9 at 14:10
  • 2
    @djt, can you implement one of those stories and postpone the other till next year? If so, the stories are not dependent on each other. It can be that the latter story can reuse code from the earlier story, but that should only affect the estimate. If need be, estimate both for the full work and re-estimate once one is planned even if you are in the middle of a planning session. – Bart van Ingen Schenau Aug 9 at 14:48
  • Tha makes sense, and yes, the other story could ship a year later (in theory) – djt Aug 10 at 16:10
2

The short of it, imho:

  • your user stories are too atomic, they're not stories but rather steps
  • it however shows a possible room for improvement in terms of backend design: how "mature" is your API? how modular your backend (microservices vs monolithic, scalability/concurrency, etc)
  • at a fundamental level you're on the right track and if you reverse the flow of thinking — which is the point of user stories in Agile — you would probably know just what to fix/change in your backend to remove some of the problematic dependencies found in stories or between steps. There's no two ways: it's either linear thus dependencies become a non-problem, or it's multi-path and you have to design for that, thus flatten the interface and expose independent "verbs".

I realize it's a bit dry so I'll try to elaborate enough, in practical terms. Also possibly a discussion at the end.


About the atomicity of stories

Here's how I think of it, back to basics: a story is not a sentence (task: "I opened the menu"). A story is a not even a group of sentences — that's a paragraph ("I wanted to change a setting. I opened the menu. I looked for a familiar "settings" or "parameters" icon/text. I found it and opened it. The "theme" setting was first in line.").

  • Each sentence is supposed to express 1 thought,
  • each paragraph is supposed to express 1 idea, 1 "point", 1 "scene" or "shot" (think storyboard, comics, movie editing).
  • A "story" is a collection of such paragraphs or scenes/shots.

Even if they're one liners, at least, we have:

  • a premise (who*/when/where from),
  • a plot (what? why?),
  • a development (how?)
  • and a resolution (where/how do we end? options from there? => paths to other "base" story clusters).

* We want different "persona" to test against, link with BI/analytics if possible.

As a side note, "UX" is when we've got a more-or-less unified set of "paths" whose salient points should be exactly our user stories.

It's important to retain all of that substance in order to "understand" the story. A good idea is to imagine it as a comics: usually 1 page at most, but typically more than 1 vignette (or it better be damn expressive!)

I feel like we could make 1 'main' or 'base' story there, e.g. tell the story of "a user signs up normally"; then make ad hoc variation/fork stories if necessary.


The "maturity" of a backend interface

Our API-s should be as "expressive" as the codebases they link.

There's the backend/upstream on one side, and the client/user "experience" (collection of all their stories) on the other side. In the middle, your API. From a dev standpoint, the API's expressivity often dictates (limiting or enabling) how much you can "play" with the codebase. From the user standpoint, even if it's invisible, it dictates how "fluent" or "stuttering" they feel when trying to express themselves through the application.

I find that when dependencies tend to creep up in the simplest user stories that you nonetheless wish to enact, it's usually due to upstream constrains — i.e. backend either not micro-servicing enough (too "monolithic"), or API not "mature" enough.

The problem is thus possibly not related to how we chunk our user stories — a sign of that is those dependencies showing up no matter what — but deeper to how we structured the backend interface. That would be my intuition.

Avoid "epics" like we avoid "god methods" to solve such problems. Rather seek to solve at the most essential / lowest level: actually remove the dependency through architectural change, rather than work around it — before we know it, it's become a minefield like npm.

Agile/scrum, in that view, isn't the problem but part of the solution: it helped identify the issues (good job, next/new problem = progress). It will help us design the solution.

So it doesn't mean that it's bad, it's a design decision that has to be made.
Hear, hear! (SO, Martin Fowler!)
Oh look, Fowler again!.. this time on the Richardson maturity model.


Discussion (1) Human Centered Design

Is that thinking differently? I'll let you be the judge of that. I think it's simply zooming out, taking some perspective, seeing the flow.

So what is the flow? Think back to a fundamental purpose of Agile/scrum: to design faster so we are closer to the end user. Shorten the cycle, you shorten the "shipping" part of the feedback loop.

Enter "user-centered design".

Basically an offspring of Human Centered Design, itself part of Interaction Design. Lots of good food for thought in those articles,

[Human-centred Systems] involves a radical redesign of the interface technologies and at a philosophical level the objective is to provide tools (in the Heidegger sense) which would support human skill and ingenuity rather than machines which would objectivise that knowledge".

Inception time: Agile too is one such "human centered system" at heart, compared to some diktat of the machine circa UNIX 1980s.

User stories, as a tool (for developers), aim at reversing the traditional top-down "developers mouth-feed whatever they think best down into users throat" (in this model, "upstream" is dominant) towards a "bottom-up" model. Because in Agile we consider user stories first, as a basis, we start from "downstream" and develop "up" so that our work ends up being shaped, from the onset, by its users, or more specifically their experience.

This, imho, is one of the greatest merits of the Agile paradigm (et. al: scrum, devops, etc), and should survive it even. It's just a golden principle of great product design regardless of the field. [Apparently was already true in good old Babylon...]

Again my subjective observation, but it seems the trend towards microservices and beyond (serverless / functional programming), the modularity of virtualization (the success of LXC/LXD containers, from Docker to K8 passing by Red Hat solutions etc.) and software-defined everything, CI/CD or the 'devops' culture... all of this seems to follow/build one silver thread: to enable infrastructure (and its makers, us) to support the above shift towards user-centered design. It's just necessary too, when every living person and their cat has become a walking multi-site network relying on hundreds of remote services.


Discussion (2) The Art and Freedom to Design

There's too much noise out there, and we lose track of the essence... We replay 'human stories' and ironically forget that, as devs, this is a just a tool, for we are literal gods in this application we're writing ourselves. This is a great power and it comes with great responsibility in a bottom-up paradigm: at the end of the day, we design-ed for users whether we realize-d it or not, whether we take/took it into account or not. We might say, for instance:

ie, you can't really choose a username until you've signed with an account

But that's our choice as devs, not a fact. It's only true for some applications/workflows.

Were these decisions motivated by user stories, thinking of user experience? Or thinking in terms of designing a good application, a good backend, a good security practice i.e. make developers happy?

Zoom out. We could perhaps do otherwise. If we want to. Do we? Will we?

What I mean is that our decisions, all of them, tend to impose some constrains on "the set of possible stories". And that's good, as long as we're fully cognizent of that. Sometimes more important than "what does this code change add to the table?", always consider the devil's advocate plea: "what does it remove? what does it deny us that was allowed before/without?"

You've designed in a way that imposes the constrains you now meet. Own that, the 'why' and 'what', because it frees you to plan your next step with maximum agility indeed.

We like "modular" "microservices" because it tends to leave the architecture opened to change, but really there's a happy medium to strike (user stories and API maturity help you find the sweet spots, as you seek/find how to make the two meet in harmonious accordance, and design around the interface, starting from there rather than having it as a distant edge concern).

Again, there is no good or bad, just decisions and results; but owning the whole user-centered/downstream-up process, even if/when we were clearly swimming downwards from our ivory tower, is how we increasingly remove our limiting thoughts (the "can't") and open ourselves to see other possibilities, try other things.

Obviously we can't rewrite the whole thing now. It's a long-term marathon, but the magic of this endless short-cycle self-evidently lies in compound effect, quick iterations, small fixes that build up to major refactorings in time, as integral part of the CD process (we build and maintain at once).

I hope this helps, even at a high level (can't do much more in abstraction). Don't hesitate to ask further questions.

2

There are a few things to keep in mind when following an agile approach and working with user stories:

  • A user story has to deliver some value, it doesn't have to deliver all the value that is in the final product
  • It may make sense to have intermediary steps that you may not have had if you did not follow the agile approach (because you value responding to change)

However, each of the above has lots of dependencies on one another (ie, you can't really choose a username until you've signed with an account, lots of UI elements and workflow pieces are shared between the above flows, etc)

You can have the functionality of choosing a username without the full functionality of signing up for an account. I could create a simple stub that generated a basic account for all users that only consisted of the username and no other details. That stub would be sufficient to implement the story to choose the username.

This isn't the kind of thing that you would ship in a finished product, but it does deliver a small amount of value (i.e. you now have a way to create a basic account and let the user specify their username).

The trick is to carefully use interfaces so that as each story gets completed the stubs / working-code can be swapped out and replaced with more feature rich code.

The same goes for the UI elements you mentioned. I would want my fully featured UI element everywhere in the app when it is released, but as an intermediary step it is perfectly acceptable to have a cut-down version of the element behind an interface so that it can be swapped out at a later date.

It takes a little while to get used to this approach. It can be difficult to think in terms of intermediary steps that may actually end up including some throwaway work. When following agile we take the decision to pay this price so that we can adapt quickly to change.

One way to think of it is imagine if at the end of each sprint there was the chance the team could be switched to work on another product. As such, you want to have a potentially shippable product available at the end of each sprint. The potentially shippable product certainly won't be perfect, but it would deliver some value if shipped.

  • This is a great response too and really clarifies some of those grey areas about what “potentially shippable” – djt Aug 10 at 16:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.