Published January 7, 2021
by Doug Klugh
Facilitate DevOps by starting with user stories that are small enough to complete within a few hours, or at worst, within a few days. While this often feels counter-intuitive, working with small stories will accelerate delivery while reducing WIP, promoting frequent feedback, facilitating early error detection, reducing variability in workflow, and increasing quality. Small user stories also reduce the dependency on code branches, further supporting Trunk-Based Development and CI/CD.
As a developer, I understand the desire to work on several changes at once — especially when they're all in the same file. I mean, if I'm already in the code, I may as well make all the changes at once. That only makes sense, right?
On the surface, that is the only thing that makes sense (to a developer). But as software engineers, we must look beyond the efficiency of writing code. We must optimize the entire delivery workflow. While making multiple changes at once may speed up writing the code, it does not accelerate delivery with high confidence in predictability and quality. Software delivery is about more than just writing code — our goal should be to optimize the entire SDLC.
Within an Agile organization, it is much easier to plan with small user stories than it is with large ones. And that is true whether you're using Kanban, Scrum, XP, or any other Agile framework — and it applies to RUP too. How many times has your team struggled with sprint planning when you're carrying forward multiple cards that are partially done? How do you stay within your planning velocity without reducing the assigned points on those stories? Remember, story points represent the value being delivered to your customers. Does that story deliver less value because you had to carry it over to another sprint? Of course not — so why would you lower the points? Remember, points represent value delivered, not effort expended.
With small stories, you are less likely to carry cards over from one sprint to the next — making sprint planning much easier. It is also much easier to ensure that everyone on the team has multiple cards they can work on — especially when your team is supporting multiple products and/or platforms. Planning within your team's velocity will be easier with many small stories as opposed to a few large stories. The smaller the stories, the easier it will be.
Predictability is an important aspect of software delivery. Stakeholders must be able to accurately predict when a particular feature (or set of features) will be delivered to your customers. Long lead times make that difficult — which is usually the case with large user stories.
When large stories continually carry over from one sprint to the next, or when the cycle time extends beyond a week, it is often difficult to determine when they will finally be done. A lack of predictability will also affect your Product Owner's ability to prioritize the work.
Since small user stories typically have short cycle times, it is much easier to predict when they will be done. This provides greater transparency to your stakeholders and helps to instill trust between them and your team.
It is always easier to estimate small things than large things. We can more accurately estimate the distance from our house to the street than we can from our house to the state capital. Or the amount of liquid in an arbitrary cup of soda compared to the amount of water in Lake Erie. And while we may be able to estimate large stories fairly well, we can usually estimate small stories more accurately and more precisely. That is why most teams estimate using the Fibonacci scale — because we are better at estimating small things than we are large things. As we move up the Fibonacci scale, larger numbers become separated by greater and greater distances, which accounts for our inability to accurately estimate things are they get larger and larger.
When creating user stories, try to keep them as small as possible. The best scenario is to have all your cards small enough to be just one (1) story point — although that is much easier said than done. But when all your cards are that small, most everything else will be easier. Aim for single-piece workflow and you will be well on your way to becoming a mature DevOps team.
The flow of value through your SDLC can be greatly accelerated by minimizing the size of work items (story cards) in your value stream. The quicker you can complete individual cards, the greater the flow you will experience in your development pipeline. That not only requires small stories, but also requires single-batch flow. It is not enough to have small stories, you must ensure you only work on one story at a time. You must resist the common urge to work on multiple cards at once — even if they are closely related and/or part of the same code file. Yes, this is counter-intuitive, but you must limit the Work In Progress (WIP) to achieve maximum flow, and thus maximum productivity. This is the basis for continuous delivery.
Small user stories help to ensure high quality in many ways. Since we are testing thin slices of functionality, small stories optimize behavioral quality by making all levels of testing easier and quicker. Since we are verifying small pieces of functionality, unit testing is easier because there is less code to test. Component testing is easier since we only need to append test scenarios to (usually) just one component — given that the stories are sufficiently small. Integration testing is easier as we only need to verify integrations that are affected by a small piece of functionality — which in most cases, should be very limited. And as with any new or updated code, system tests will be impacted the most — although even that should be minimal with small pieces of functionality (compared to large changes or extensions).
Small user stories also promote Structural Quality. Adding small slices of functionality makes it easier to employ continuous refactoring as code is added — keeping your code loosely coupled. Small stories help to keep your code SOLID by facilitating the Single Responsibility and Open/Closed Principles, further helping to maintain a loosely-coupled architecture. It is also easier to manage side effects within your code through Command-Query Separation.