Vertical slicing and architecture issues
The other day, I had a discussion with a few coworkers about problems with vertical slicing of user stories. Vertical slicing is sometimes difficult, and I think that it is sometimes caused by architectural issues. This is an example of the code telling you something.
Read more: Vertical slicing and architecture issuesWhat is vertical slicing?
Those who are familiar with agile methods like XP, Scrum and Kanban are known with the concept of user stories. User stories are small sized work packages that can be completed in a limited amount of time. The goal of a user story should always be to fulfill the need for some stakeholder, most commonly the end user of the software. For instance, example user stories for a web shop may be “Create new account”, “Pay using PayPal” or “Redeem discount vouchers”.
As you can see from the example, those describe end user functionality. When the story is finished, the software contains an additional feature that the end user can use.
As you also can see from the example stories: those story titles do not name particular software modules. Implementing such stories means that multiple modules may need to be modified. For example, the “Pay using PayPal” story might need modifications to the database module, the checkout module and the front end. So the story defines an increment to the software that slices through all software layers, hence the term vertical slicing.
Vertical slicing on purpose
Why is vertically sliced user stories so important? That’s because it is immensely difficult to measure the progress of a software project if nothing is being delivered. I remember the waterfall projects from the past, where integration was postponed until the end of the project and most of the time was reserved for the development work. Those projects never met the deadline, and the result was often less optimal, because of the following reasons:
- Only until software integration is done, not before, will the actual problems become clear. Software integration is a project level feedback mechanism.
- Software is a definition of behavior. Only the end user can tell whether the result is useful or not, and only by actually using the software. Since waterfall-style projects postpone this to the end, only in the end the team will learn what was actually needed (as opposed to what was thought that was needed).
This means that delivering software early and often to the actual stakeholders is very important. Only then, we as developers can receive the needed feedback and learn what is actually needed.
And to do this, our work packages must be actual deliverables, and actually provide working software.
And therefore, the user stories must be defined as vertical slices through the software: to get working software in the hands of the user.
Architectural limitations
But wait… is it always possible to split up a story into smaller stories, and still have vertical slices? First I think a word of warning is in order, since in my experience, often much more is possible than you’d think. Defining good user stories requires the skill of thinking from the mind of the user, not the developer, and that is often difficult if you are the developer.
On the other hand, there are sometimes barriers that make it very difficult. That was what our discussion was about. The discussion was about a software product that was split up in two main parts of roughly equal size: a lower level platform layer, and a higher level controller layer on top of it. The layers were developed in different programming languages and there was a thick interface separating them. The problem was in the features that required a change to the interface: every change to the interface required significant work in both modules. User stories that require an interface change are too big to be handled reliably by the team. So they need to be split up.
I think the actual problem here is not actually the user story, but the architectural design. The two modules are tightly coupled, which points at a lack of encapsulation. The interface demarcated a technical boundary, but not a logical boundary. The upper layer could not offload a complete problem to the lower layer, but needed to have tight interaction with it. This is what adding functionality makes difficult, and hence these user stories are inevitably large.
But still proceed
Even though there is a clear problem, the project must obviously continue, and hence the stories must be split. How to proceed in face of such an issue?
I think there are several possibilities. None of them are optimal, but they provide at least some functionality to the end user, and therefore can make progress visible.
- Top down approach: the first user story implements the high level module using mocked data from the lower level module. The next user story replaces the mocked data with actual data from the lower level module. This has disadvantages: the stories cannot be developed independently, and the result of the first story not actually usable by the end user. The end user can only see what the feature would look like, but not actually use it. Nonetheless, little progress is always better than no progress at all.
- Bottom up approach: the first user story implements the lower level module using data from some external source; the next story implements the higher level module and removes the external source again. Such an external source need not be much work: an environment variable or file on disk may work well. Of course this has the drawback that extra scaffolding is required. This approach looks a bit like using feature flags. This approach makes it more difficult for the end user to assess what is possible with the feature.
And finally, if the architecture tells you something, you should take that seriously. This means you need to have a discussion about how to get to a better future.