This is the multi-page printable view of this section. Click here to print.
- 1: Work Decomposition
- 2: Task Decomposition
- 3: Behavior Driven Development
- 4: Complexity and Estimation
- 5: Contract Driven Development
- 6: Defining Product Goals
- 7: Definition of Ready
- 8: From Program to User Story
- 9: Spikes
- 10: Story Slicing
1 - Work Decomposition
In order to effectively understand and implement the work breakdown flow, the team needs to have the following prerequisites and understandings.
- Definition of Ready
- Definition of Done
- Backlog refinement cadence with the appropriate team members and stakeholders involved
Work Breakdown Process
The goal of the work breakdown process is to decompose work into small batches that can be delivered frequently, multiples times a week, in order to deliver value faster with less rework.
The general work breakdown process involves:
It is important that the team keep these tips in mind when decomposing work:
- Known poor quality should not flow downstream. This includes acceptance criteria that require interpretation. If the acceptance criteria cannot be understood by the whole team then we are developing defects, not value.
- Refining work requires significant brainpower and is the primary quality process. Meetings should be planned around this. Hold them when people are mentally alert and time box them to prevent mental fatigue.
- Good acceptance criteria come from good communication. Avoid the following anti-patterns:
- Someone outside the team writes acceptance criteria and hands it to the team. Since the team was not involved with the conversation, there’s no chance to uncover assumptions and the team has less investment in the outcomes.
- One person on the team writes acceptance criteria. Same problem is above.
- Each team member is assigned work based on their expertise. This removes communication and also ensures that people are only focused on understanding their tasks. Again, the team as a whole isn’t invested in the outcomes. This typically results in finger pointing when something fails. Also, if someone is unavailable, the rest of the team lacks context to pick it up.
- Refining should be focused on outcomes, not volume. If we have a 1 hour meeting and 10 stories to refine, it’s better to have one fully refined story we can work on than 10 partially refined stories that we’ll “figure out during development”. Stop refining a story when we agree on the acceptance criteria or agree it’s blocked and needs more information. Only then should we move to the next story. Stop the meeting at the scheduled time.
Ideas become epics with defined outcomes, clear goals and value. Epics become a list of features.
Common struggles for teams when breaking down ideas into epics and features:
Refining Epics/Features into Stories
Stories are observable changes that have clear acceptance criteria, and can be completed in less than two days. Stories are made up of one or more tasks.
Typic al problems teams experience with decomposition are:
- Stories are too big
- Stories are too complex
- Stories lack testable acceptance criteria
- Lack of dependency knowledge
- Managing research tasks
Refining Stories into Development Tasks
Tasks are independently deployable changes that can be merged to trunk daily.
Breaking stories down into tasks gives teams the ability to swarm work and deliver value faster.
In order for teams to visualize tasks required to implement scenarios, they need to understand what a good task looks like.
Tracking the team’s Development Cycle Time is the best way to judge improvements to decomposition. Stories should take 1-2 days to deliver and should not have rework, delays waiting for explanations, or dependencies on other stories or teams.
2 - Task Decomposition
What does a good task look like?
A development task is the smallest independently deployable change to implement acceptance criteria.
Create tasks that are meaningful and take less than two days to complete.
Given I have data available for Integration Frequency Then score entry for Integration Frequency will be updated for teams Task: Create Integration Frequency Feature Flag. Task: Add Integration Frequency as Score Entry. Task: Update Score Entry for Integration Frequency.
Use Definition of Done as your checklist for completing a development task.
- If a task includes integration to another dependency, add a simple contract mock to the task so that parallel development of the consumer and provider will result in minimal integration issues.
- Decomposing stories into tasks allows teams to swarm stories and deliver value faster
3 - Behavior Driven Development
Behavior Driven Development is the collaborative process where we discuss the intent and behaviors of a feature and document the understanding in a declarative, testable way. These testable acceptance criteria should be the Definition of Done for a user story. BDD is not a technology or automated tool. BDD is the process for defining the behavior. We can then write automated tests for those behaviors.
Feature: I need to smite a rabbit so that I can find the Holy Grail Scenario: Use the Holy Hand Grenade of Antioch Given I have the Holy Hand Grenade of Antioch When I pull the pin And I count to 3 But I do not count to 5 And I lob it towards my foe And the foe is naughty in my sight Then my foe should snuff it
Gherkin is the domain specific language that allows acceptance criteria to be expressed in “Arrange, Act, Assert” in a way that is understandable to all stakeholders. Example:
Feature: As an hourly associate I want to be able to log my arrival time so that I can be paid correctly. Scenario: Clocking in Given I am not clocked in When I enter my associate number Then my arrival time will be logged And I will be notified of the time Scenario: Clocking out Given I am clocked in When I enter my associate number And I have been clocked in for more than 5 minutes Then I will be clocked out And I will be notified of the time Scenario: Clocking out too little time Given I am clocked in When I enter my associate number And I have been clocked in for less than 5 minutes Then I will receive an error
Using Acceptance Criteria to Negotiate and Split
With the above criteria, it may be acceptable to remove the time validation and accelerate delivery of the time logging ability. After delivery, the validation may not be required. If true, we’ve saved money and time by NOT delivering unneeded features. First, we deliver the ability to clock in and see if we really do need the ability to verify.
Feature: As an hourly associate I want to be able to log my arrival time so that I can be paid correctly. Scenario: Clocking in Given I am not clocked in When I enter my associate number Then my arrival time will be logged And I will be notified of the time Scenario: Clocking out Given I am clocked in When I enter my associate number And I have been clocked in for more than 5 minutes Then I will be clocked out And I will be notified of the time
If, in production, we discover that the sanity check is required to prevent time clock issues, we can quickly add that behavior.
Feature: As an hourly associate I want to be prevented from clocking out immediately after clocking in. Scenario: Clocking out more than 5 minutes after arrival Given I am clocked in And I have been clocked in for more than 5 minutes When I enter my associate number Then I will be clocked out And I will be notified of the time Scenario: Clocking out less than 5 minutes after arrival Given I am clocked in And I have been clocked in for less than 5 minutes When I enter my associate number Then I will receive an error
- Scenarios should be written from the point of view of the consumer. If the consumer; either a user, UI, or another service.
- Scenarios should be focused on a specific function and should not attempt to describe multiple behaviors.
- If a story has more than 6 acceptance criteria, it can probably be split.
- No acceptance test should contain more than 10 conditions. In fact, much less is recommended.
- Acceptance tests can be used to describe a full end to end user experience. They are also recommended for describing the behavior of a single component in the flow of the overall behavior.
- Gherkin Reference
- BDD Primer - Liz Keogh
- Better Executable Specifications - Dave Farley
- A Real world Example of BDD - Dave Farley
- ATDD - How to Guide - Dave Farley
4 - Complexity and Estimation
When refining work, teams should focus on reducing complexity, minimizing dependencies, and estimating based on complexity and effort, not time.
Small things can be estimated more accurately than big things because the margin of error is lower and dependencies are clear. Eliminating or reducing hard dependencies is critical because the probability that something will be delivered late doubles for every hard dependency. Those could include database changes, coordination with other teams, or changes that are tightly coupled with another component.
Decompose stories using Behavior Driven Development. This not only helps with feature discovery and with uncovering dependencies, but also aids with story slicing since each acceptance test is naturally a thin, vertical slice.
Prior to refining, use relative sizing to project order of magnitude estimates for delivery. However, these should not be used for commitments. Committing to unrefined deliveries increases team allocation with re-work and “Date Driven Development”, reduces quality, and lowers end user satisfaction.
To avoid hard dependencies, first slice stories as small as possible to minimize the number of possible dependencies. After that, attempt to make any hard dependencies “soft” with feature flags, API versioning, or other coding solutions.
- Use Cynefin to aid in estimating complexity.
- If the team does not agree with the estimate, refine further. Avoid “averaging” the team’s estimate.
- Track estimates against actual to see how consistent the team is.
5 - Contract Driven Development
Contract Driven Development is the process of defining the contract changes between two dependencies during design and prior to construction. This allows the provider and consumer to work out how components should interact so that mocks and fakes can be created that allow the components to be developed and delivered asynchronously.
For services, define the expected behavior changes for the affected verbs along with the payload. These should be expressed as contract tests, the unit test of an API, that both provider and consumer can use to validate the integration independently.
For more complicated interaction that require something more than simple canned responses, a common repository that represents a fake of the new service or tools like Mountebank or WireMock can be used to virtualize more complex behavior. It’s important that both components are testing the same behaviors.
Contract tests should follow Postel’s Law:
"Be conservative in what you do, be liberal in what you accept from others".
- For internal services, define the payload and responses in the developer task along with the expected functional test for that change.
- For external services, use one of the open source tools that allow recording and replaying responses.
- Always create contract tests before implementation of behavior.
6 - Defining Product Goals
Product goals are a way to turn your vision for your product into easy to understand objectives that can be measured and achieved in a certain amount of time.
Increased transparency into product metrics Measurable Outcome: Increased traffic to product page
When generating product goals, you need to understand what problem you are solving, who you are solving it for, and how you measure that you achieved the goals.
Product goals can be broken down into initiatives, that when accomplished, deliver against the product strategy.
Provide one view for all product KPIs.
Ensure products have appropriate metrics associated with them.
Initiatives can then be broken down into epics, stories, tasks, etc. among product teams, with high-level requirements associated.
An epic is a complete business feature with outcomes defined before stories are written. Epics should never be open ended buckets of work.
I want to be able to review the CI metrics trends of teams who have completed a DevOps Dojo engagement.
- Product goals need a description and key results needed to achieve them.
- Initiatives need enough information to help the team understand the expected value, the requirements, measure of success, and the time frame associated to completion.
7 - Definition of Ready
Is it REALLY Ready?
A Definition of Ready is a set of criteria decided by the team that defines when work is ready to begin. The goal of the Definition of Ready to help the team decide on the level of uncertainty that they are comfortable with taking on with respect to their work. Without that guidance, any work is fair game. That is a recipe for confusion and disaster.
When deciding on a Definition of Ready, there are certain minimum criteria that should always be there. These are:
- Description of the value the work provides (Why do we want to do this?)
- Testable Acceptance Criteria (When do we know we’ve done what we need to?)
- The team has reviewed and agreed the work is ready (Has the team seen it?)
However, the context of a team can make many other criteria applicable. Other criteria could include:
- Wireframes for new UI components
- Contracts for APIs/services we depend on
- All relevant test types identified for subtasks
- Team estimate of the size of the story is no more than 2 days
The Definition of Ready is a living document that should evolve over time as the team works to make their delivery system more predictable. The most important thing is to actually enforce the Definition of Ready. If it’s not enforced, it’s completely useless.
- If any work in “Ready to Start” does not meet the Definition of Ready, move it back to the Backlog until it is refined.
- Any work that is planned for a sprint/iteration must meet the Definition of Ready. Do not accept work that isn’t ready!
- If work needs to be expedited, it needs to go through the same process. (Unless there is immediate production impact, of course)
- Using Behavior Driven Development is one of the best ways to define testable acceptance criteria.
- Definition of Ready is also useful for support tickets or other types of work that the team can be responsible for. It’s not just for development work!
- It’s up to everyone on the team, including the Product Owner, to make sure that non-ready work is refined appropriately.
- The recommended DoR for CD is that any story can be completed, either by the team or a single developer, in 2 days or less
8 - From Program to User Story
Aligning priorities across multi-team products can be challenging. However, the process used at the team level to decompose work functions just as well at the program level.
In order to have an effective work breakdown process, goals and priorities need to be established and understood.
Stakeholders and leadership teams must define the high-level initiatives, and their priorities, so that work may be dispersed among product teams.
Leadership teams can be made up of a core group of product owners.
The program roadmap should breakdown into the product roadmap, which includes the prioritized list of epics for each product.
The leadership team should define the product vision, roadmap, and dependencies for each product.
The team backlog should be comprised of the prioritized epics from the product roadmap.
The core group needed to effectively break down high level requirements so that the team may decompose work includes product owners, tech leads, and project managers.
Product teams should use the processes effective for Work Decomposition, to breakdown epics into smaller epics, stories, and tasks.
9 - Spikes
Spikes are an exploration of potential solutions for work or research items that cannot be estimated. They should be time-boxed in short increments (2-3 days).
Since all work has some amount of uncertainty and risk, spikes should be used infrequently when the team has no idea on how to proceed with a work item. They should result in information that can be used to better refine work into something valuable, for some iteration in the future.
Spikes should follow a Definition of Done, with acceptance criteria, that can be demoed at the end of its timebox.
A spike should have a definite timebox, usually within 1-3 days. At the end of this timebox, the team should be able to decide how, when, and even if the work can be considered for upcoming iterations.
- Use spikes sparingly, only when high uncertainty exists.
- Spikes should be focused on discovery and experimentation.
- Stay within the parameters of the spike. Anything else is considered a waste.
10 - Story Slicing
Story slicing is the activity of taking large stories and splitting them into smaller, more predictable deliveries. This allows the team to deliver higher priority changes more rapidly instead of tying those changes to others that may be of lower relative value.
Stories should be sliced vertically. That is, the story should be aligned such that it fulfills a consumer request without requiring another story being deployed. After slicing, they should still meet the INVEST principle.
As an hourly associate I want to be able to log my arrival time so that I can be paid correctly.
As a consumer of item data, I want to retrieve item information by color so that I can find all red items.
Stories should not be sliced along tech stack layer or by activity. If you need to deploy a UI story and a service story to implement a new behavior, you have sliced horizontally.
Do not slice by tech stack layer
- UI “story”
- Service “story”
- Database “story”
Do not slice by activity
- Coding “story”
- Review “story”
- Testing “story”
If you’re unsure if a story can be sliced thinner, look at the acceptance tests from the BDD activity and see if it makes sense to defer some of the tests to a later release.
While stories should be sliced vertically, it’s quite possible that multiple developers can work the story with each developer picking up a task that represents a layer of the slice.
Minimize hard dependencies in a story. The odds of delivering on time for any activity are
1 in 2^nwhere
nis the number of hard dependencies.