In the previous chapter, we talked about the Plan itself, and the importance of a properly Estimated Task to it. The gap between a Task and an Estimated task is bridged by considering variances and minimizing uncertainties. In this chapter, we’ll be learning how to actually get it done. A practical practice to uncover what is the work that needs to get done. A process which the Task needs to go through.
As this process of Uncovering Work would change the design, it is critical that the owner would be open for change and feedback. So it should be only about 85% done, and not a finalized design. By the end of this process, we’d end up with a collection of certain enough Sub-tasks, executable and actionable items which can be done sequentially. They would all form up something to deliver, a Deliverable with a certain enough value. It is a prerequisite to getting a certain enough Estimation, which we’ll learn how to do in the follow up chapter.
[Note: this is not the only practice out there, nor am I saying it is a best practice for you. You know best. At the very least, follow and understand the principles described and how it fits in the bigger picture of Planning. That would help you to better tailor and change this to your needs.]
[Note (August 2022): while researching on another matter, I came across a methodology called Adaptive Software Development, which from its description sounds very similar to the concepts about to be presented and practiced in this chapter and in The Winding Road series.]
Deliverables
Every non-final design must be divided into Deliverables.
Deliverables have expected deadlines, the one we set our customer’s expectation by, and commit to. Deliverable type can be divide to two, according who the customer is:
- User Story – a change expected and accepted by an external customer, such as end users, customers, API consumers, etc.
- Technical Task – a change expected and accepted by an internal customer (the complementary of User Story) such as other team members, other R&D teams, Customer Success, etc. In Jira terminology it is plainly called Task.
Notice the border between internal and external varies. One team’s external customer may be another team. For that other team, the external customer could be the end user.
Deliverables should be short enough to be delivered within a single Sprint. A Deliverable’s effort must be less than the Sprint’s length. We put such a time constraint to make sure we’d be getting feedback sooner than later. If a Sprint’s length is two weeks, at most we must get Feedback on the Change within two weeks. As it may take time to get it after delivery, Plan for Feedback. Feedback is critical because it prevents us from going down the wrong rabbit hole. Be wary of a commitment of more than one Deliverable per Sprint (of the same design).
A Deliverable must have a value to a customer. If we delivered no value, we’ve done nothing of value. Be wary of Deliverables that might end up with long fruition processes, or uncertain value or without value at all. Both have the potential to be a time waste, which has dire motivational consequences on the team and the company.
By definition, Technical Tasks do not have external customer value. Some of them do enable a specific User Story, which is a more concrete term than indirect external value. For example, some new feature (User Story) would require an entire new database with 20 schemas (a prerequisite Technical Task). Both should eventually fit into a single Sprint. If it really isn’t possible, no more than two consecutive Sprints. Because feedback is a must.
Phase 1: Dividing Deliverables
Now, let’s take our “scalpel” and divide our design into Deliverables by value and feedback. This is mostly done by a product manager, hopefully with an engineer’s aid. A design or an already divided Deliverable should be further divided, as long as one the following applies:
- It helps someone in more than one way
- It helps more than one person/actor
- Provides more than one value
- Enables more than one thing
- Feedback/outcome in not certain enough
- Feedback might save work
Let’s practice this with an example.
Our imaginary application currently allows a customer to browse (paging) an alphabetically sorted list of 10k items. Our design adds a search box to do a free-text search, and then filter the search results by category.
In this example, the design helps a customer to find an item in two ways, search and filter. There is a clear division to be made, to at least two Deliverables. As they preferably should be independent, it suggests that filtering should be done whether search is possible or not. We ended up with three Deliverables, each with a single external customer value.
Deliverables | Sub-tasks |
(1) Search by free-text | |
(2) Filter by category | |
(3) Filter search results by category |
This division allows us to choose whether to do (1) or (2) first. We may do (2) and find out that nobody uses categories, because division creates an opening for Feedback. It creates an option to maybe stop and rethink the whole thing, to save time and not go down the wrong rabbit hole. And that would be sooner than after executing all 3 User Stories combined.
We may do (1) and found out we have helped our customers enough to find an item. Once delivered, it may turn out that (2) and (3) are not as valuable as we thought and shouldn’t be done, for the time being. These are the kinds of results, insights, timing and flexibility we are looking for with effectively divided Deliverables.
The outcome could probably be more than one Deliverable. If multiple ones share a mutual goal, Deliverables can be aggregated into an Epic. The first Deliverable should be certain enough. Once delivered, we’d get Feedback and Change would follow. Meaning, the rest of the Deliverables would Change, which is why currently they can not be certain enough.
Be wary, we may have found out we have a roadmap in our hands.
Sub-tasks
Deliverables should consist of correctly sized executable units (Sub-tasks), or are themselves already correctly sized (No need to create a Sub-task for a ~20 minute effort for a User Story, such as change a CSS color). This would also create a sense of advancement and achievement and would help everyone keep track of progress.
The smaller the Sub-task is:
- The less uncertain it is, because it is short and well defined
- The smaller the mean and variance is. Thus the Estimation’s buffer would be more certain [ref to Variance].
- The more flexible and easier it is to the schedule
- Entail shorter and focused Code Reviews (an internal technical feedback between engineers), which eases up the development process.
A correctly sized Sub-task must be independently deployed to production. If we have three sub-tasks for a single application there would be three deployments. Once after each Sub-task is done. If we need to change three applications (e.g. one database, one server side, one client side) there would be at least three Sub-tasks, one per application. This is first a technical must, and applications must adhere to this by correctly integrating with each other. We must assume they can not be deployed together or sequentially. Otherwise, it would make reverting problematic along with many other issues, and it contradicts how we Design to Fail.
A correctly sized Sub-task once deployed must make progress. It must provide a value (internal or external, preferably minimal) or must eventually enable an indirect external value.
A correctly sized Sub-task must be ‘complete’, ready for usage and consumption in production. Or at the very least, it should not cause harm to the state when the code is executed. Think of “data corruption” as an example of consequences to avoid. Do not count on flags to merge or deploy unfinished or untested code. I’ve seen flags turned on by mistake in production.
Phase 2: Dividing Sub-tasks
Now, let’s take our “scalpel” again and divide our first Deliverable to Sub-tasks. Starting with the first User Story of “Search by free-text”. It is deeply technical, so it should be done by engineers with a product manager’s aid and availability for continuous input and design changes. At least two engineers should take part in this. One who is highly familiarized with the code/system/tech (domain lead, tech lead, etc) to provide necessary thoughts, insights and alternatives. The others would be the engineers defining and delivering the solution. More than one engineering executing a Deliverable would cause a communication overhead during execution. One engineer may not be capable of doing it entirely on his own, yet. Use this opportunity for teaching and growth, to postpone the inevitability of an engineer being eventually gone.
Let’s bring everyone on board for an initial internal feedback process. Start with the product manager (or the technical design owner) explaining what’s behind it, the customer/company’s needs, goals and expected outcome. Getting everyone’s feedback and input is how we reduce uncertainty, make sure that the Task and value are certain enough.
Next, have all the engineers open their computers and have all the relevant code/applications right before their eyes either in their IDEs or Github. Ask the executing engineer “what is the first thing you need to do?”. His answer would be the name and content of the first Sub-task. “Okay, what’s the next thing you should do?”. Validate with him the Sub-task is still correctly sized as we defined above (makes progress, independently deployable and complete). If it’s too big, divide it to another Sub-task and validate that both of them are correctly sized.
It is beneficial and necessary for everyone, engineers and others, to ask for clarifications and validations. To Google and look for answers. That is how more uncertainty is reduced. That’s what changes the non-final design and the Deliverable. It may even lead to further division into more Deliverables.
An engineer might know what needs to be done, but lacks the knowledge of how to get it done. As it takes a significant time and should be taken into account, add a “study and learning” Sub-task. Just like we take into account that Change will happen when we Plan for Change, we can also add a specific “Product Change Request” Sub-task.
Continue with “Okay, what’s the next thing you should do?” over and over again. The process of uncovering works ends when everyone agrees that they know what and how the Deliverable gets done. Eventually, we would end up with the following collection:
Deliverables | Sub-tasks |
Search by free-text | A |
B | |
C | |
D | |
(Another deliverable) | |
(Another deliverable) |
Should we continue dividing the next Deliverable? If they are tightly coupled, one enables the other or executed immediately after, then we should consider doing so. It may further reduce the uncertainty of the first one.
With a Deliverable correctly divided into correctly sized Sub-tasks, it is ready for Estimation. The summation of uncovering work is uncovering the effort required to get it done. We’ll learn the practice of doing so in the next chapter.