Story Slicing

One challenge of Agile development is the process of breaking down business requirements from Scenarios into a set of clear and distinct User Stories. Evolving software architectures have forced us to adjust some definitions.

Story Craft

User Stories begin with a declaration:

As a <user/actor>, I want to <do something> , in order to <get some result>.

Each Story should describe a small, yet complete unit of functionality sized such that a software development team could code, test, and potentially release that feature within a single Sprint.

By breaking down and delivering an application or new feature in a string of User Stories, usually several each Sprint, the engineering team enables business stakeholders to validate the application in small steps, potentially catching design or implementation defects before they germinate into tenacious weeds (crabgrass). Sounds reasonable. And it is. Except sometimes it’s not so easy to find the perforations.

Strictly speaking, a User Story represents the work required to complete an atomic user action. Stories belong to Epics, larger collections of User Stories that add up to a complete feature. “Managing User Accounts” is an Epic. Saving the user name, password, and related information of a single user is a Story within that Epic, as are “Change Password,” “Delete User,” etc.

The Plot Thickens

User Stories with feature scope work well for stand-alone client software, such as mobile apps. However, in systems of federated components, this traditional definition of a User Story as a self-contained unit of work may become unwieldy.

Many modern applications, especially enterprise systems, are built on multi-tier, service-oriented architectures (SOA). In such systems, one user click will typically trigger a cascade of messages among several specialized services to collect data, process it, and store it in a data repository. An apparently simple unit of functionality, as experienced by a user, can mask layers of clockwork. Because some functions are composed of multiple components, they may be loaded with dependencies that cause the work to stretch into multiple Sprints, delaying sign-off by the business stakeholders.

My friend and colleague, George Dawoud, has redefined Stories and their parent containers. To him “Create a User Account” is not a Story. It’s an Agile Theme. Saving the user name and password is an Epic. Within that Epic are multiple technical Stories, one for each component, such as:

  • A Web user interface.
  • A service to accept and store data from the Web client.
  • Test automation to validate each component and the integrated Epic.

Each unified and independently testable unit of implementation is a Story, without regard for the fully integrated function exposed to a system User. This decomposition makes it more practical to complete Stories within single Sprints, and clears the integration log jams that often occur toward the end of each Sprint. For an application built on an SOA, it also aligns process with structure.

To make it possible to complete a feature in a series of successive Sprints, design each feature from end to end. Technically decomposed Epics require more detailed specifications because there is less opportunity to negotiate interfaces and protocols during development. If you have clear enough requirements to design features up front, which always leads to better results anyway, consider dispensing with conventional definitions of User Stories and build your application in Technical Stories.

Beware: It’s all too easy to slip into Waterfall, with front-loaded design and back-loaded testing. Don’t succumb to the temptation to postpone all testing to the final, integrated Epic, as if it were a User Story. Test the UI, to the greatest extent possible, and then test each affiliated service as it rolls off the production line. You want to minimize the defects that surface during final integration.

Twists & Turns

The contract in Scrum is that business stakeholders may introduce changes between Sprints. In an ideal Agile project, business stakeholders will review completed features and either ask for revisions or authorize continuation to the next most useful function. However, when we implement the service tier of a feature in one Sprint, and then the PO changes the requirements before we implement the UI in the following Sprint, it could invalidate the work already accomplished. Is this any worse than completing the entire feature and then changing it in the next Sprint? It is if you have shared dependencies.

One backend service will likely be consumed by several user-facing functions. Dependencies compound over time, such that a small change may trigger a chain reaction through multiple components. The longer the delay between the start of work and delivery, known as the Cycle Time, the greater the risk of high impact changes. This is a weak argument against technical slicing, however, because the PO could just as easily introduce a new feature in a later Sprint that broadly affects work already accomplished, with similarly dire consequences.

One way to limit late-breaking changes is to build the UI first and obtain stakeholder sign-off before investing in the underlying services. Because the UI is the face of most features, a hands-on UI demo is most likely to prompt modifications or more substantial rethinking by business stakeholders. Nailing the UX/UI implementation first will limit more substantial, costly changes in the services tiers. This is another positive benefit of cleaving a feature along technical boundaries. Build the UI first, with either mock services (costly) or hard-coded test data (cheap).

Epilogue

Superficially, the two definitions of Story look like alternatives. But it’s not really a choice. It’s progressive. We typically slice Features into Functions to create conventional User Stories. Breaking down those User Stories into Technical Stories is just the next step. No need to sweat the terminology change, promoting User Stories to Epics, and Epics to Themes.

It’s a pretty simple trade-off:

  • If you’re working from relatively stable requirements and have the opportunity to design features carefully before you start coding, you’ll save scheduling headaches by breaking User Stories into Technical Stories.
  • If you’re iterating through an evolving set of requirements and solutions, then it’s more efficient to deliver work in increments of fully formed functions.