Return of the Horizontal Slice
A vertical slice contains all of the essential layers (UI, persistence, domain logic) necessary for a user to experience a primitive yet working version of a feature.
A horizontal slice usually contains only one layer of a feature, and if it's not the UI layer, a user won't be able to experience any of the completed work.
For many years we've focused on identifying, building and quickly deploying vertical slices.
We like vertical slices because they:
- provide end-to-end, potentially shippable functionality
- allow users to experience new functionality faster
- increase the chance of obtaining more informed user feedback
- decrease the risk of building the wrong thing
- validate that all layers in a feature work together properly
All of those things are good, yet we've recently found that:
Let's consider a real-world example.
Below is a look at a new feature from our Greatest Hits eLearning that allows a user to press a button to resume where they were last studying:
The resume feature is actually a vertical slice of a more sophisticated, frequently requested feature to enable creating and managing bookmarks.
We decided to provide the resume feature first because it was far less work than the bookmarking feature and could quickly teach us whether our users found resume to be sufficient.
Once we settled on the behavior needed for the vertical slice, we wondered how to implement and release the new feature.
For the resume feature, we realized that we could write and deploy the data persistence layer first, since the "last page visited" data for users would eventually be needed when we completed the entire resume feature.
Data persistence was the horizontal slice of the resume feature (the vertical slice).
We test-drove the data persistence code, checked it in and after passing all of our build's automated tests, it went live and started actively recording useful data.
Meanwhile, our users knew nothing about this new development.
Over the next two days we test-drove and released more horizontal slices:
- Domain Logic — The code to handle the resume feature for albums, box sets, playlists and compilations.
- Usage Data — The code to record usage data for the new resume feature so we could evaluate whether it was actively being used.
- User Interface — We released an ugly-but-working version first, then released a better-looking version, then found a defect and released a fix, all within the space of a few hours.
The user interface was the last horizontal slice to be deployed.
Once the UI went live, it was visible only to students whose last page had been recorded.
Fortunately, we had such data available, since we didn't release the vertical slice in one large chunk, but rather in small, horizontal pieces.
That meant that we could immediately begin tracking usage of the new feature, which was fun.
Here are a few lessons learned:
- It was essential to identify a vertical slice before we began horizontally slicing it.
- We did not wait to build the entire vertical slice before releasing it.
- Deploying the first horizontal slice (data capture) was useful even before completing the vertical slice.
- We continuously deployed other horizontal slices from different layers of the vertical slice.
- Usage tracking was accelerated because data capture had already occurred before the UI was visible.
The example I've written about today went with a bottom-up, persistence-layer-first, incremental release.
That won't always be the case.
For a new feature that we believe our user will like, we'll be using a top-down, UI-layer-first approach to help us quickly learn whether users have interest in this new feature, before investing a lot of time in building out all of its layers.