When faced with the challenge of building software of any considerable size, we rather sensibly tend to begin by breaking down the complexity and fleshing out a design or architecture. Then we break down the work involved in building that design into tasks or user “stories”.
Sometimes we group stories into wider “epics”, themes or stages, but generally we estimate, schedule, and conduct the work of building software at a task level: Tasks are what we assign, place on agile boards, and discuss our progress in terms of.
(I’ll refer to everything as “tasks” from here on, but I also mean user stories, and much of what I’m referring to also applies to bug fixes and other ticketed items)
Tasks are abstractions of the underlying engineering work required, and a task-based view of engineering makes the process of building complex software more understandable, manageable and distributable as a team. But it also tends to ignore certain truths about software complexity, tasks themselves and the ways we actually work on them, both on our own and together in teams. In-particular, the tools we currently use to manage task-based engineering are rather restrictive and cumbersome.
So, given that it seems we need task-based engineering, what is it about the way we approach it, and current task-based tools, that can hamper our efforts?
Tasks Abstract Away Complexity
A task is simply an abstraction of the work involved in building a software feature, a use case, a component or maybe just of fixing a bug. As with all abstractions, it necessarily hides detail that, for all but the simplest of tasks, may be discovered later when we actually work on it, despite our best efforts at planning time.
Sometimes, as the true complexity of the work involved in a task becomes clear, we realise that we should restructure the task to break it into more manageable chunks, and that sub-tasks should ideally replace some (but perhaps not all) of the original parent task. This discovery of structure and complexity may occur several times, to an arbitrary depth, and perhaps only after part of the original task has already been completed. We may even discover aspects of the original design, and the tasks slated to build it, are wrong.
Rather than implying poor planning, this is simply a part of the discovery process and the complexity inherent in building software, particularly in an agile manner where we’re trying not to pre-think too much up-front. We need to accommodate that inevitable change, reflect it in the tasks we are working on and in those slated for the future.
Most current task management tools aren’t great at letting us change anything more than very small numbers of tasks and task-based planning. They certainly don’t help us to visualise the results we end up with. In a sense, they leave us with quite brittle and sizeable task-based plans. With some persistence though, it is usually possible to reflect the required changes, though this may require time that isn’t available and we risk the task-based view drifting away from the engineering reality.
What can also be particularly tough with current tools is arbitrarily defining sub-tasks to any depth, as we discover complexity and break down a piece of work further. We may need to have parent and child tasks representing slightly overlapping and part-completed functionality, whilst being able to see estimates for all of that work. I’m not sure that current tools allow much of this without significant discipline in our use of them. In this sense, they are too brittle to allow us to reflect the engineering reality beyond our (now outdated) initial plan.
Tasks Need Surrounding Context
Our planning process envisioned the whole (a delivery, a completed system, or a bunch of features for a sprint), then broke it down into tasks. Quite often, rather a bewilderingly large number of them. The tasks somehow lose our view of the whole, and it is hard to determine whether those tasks, collectively, still make up a meaningful delivery or omit anything crucial.
It seems like we need to retain some visualisation or record of the structure by which we arrived at the individual tasks, so we can work backwards from the tasks to the whole. Even when working on an individual task, we often need to get enough surrounding context to work on it, as each task rarely describes that in sufficient detail.
Being able to see where tasks fit into the bigger picture is particularly necessary when our plan inevitably changes over time, to avoid us getting lost in a changing sea of tasks, the intended outcome of which we can no-longer visualise clearly.
Current task management tools don’t allow us to retain the more complex structure of groups of tasks. We are limited to “epics”, tags, simple sub-tasks and basic categorisation. We need better ways of visualising how the tasks fit together to form the whole that we’re working towards, allowing us to spot omissions and to track progress. After all, the collective structure of the tasks will probably be as complex as the structure of the overall system we’re building.
Tasks Need Collaboration (Sometimes)
No-matter how much we break them down, often a task requires unexpected collaboration with someone else (together, or a hand off then a hand back), integration with their work or reaching an agreement. That micro-collaboration is hard to model, but crucial to a task’s completion, though we often assume (perhaps hope?) it is irrelevant.
Whether or not one person “owns” the task and the responsibility for its completion, several people may need to do work on it and must find time in their workload. This is particularly true with user stories, as we don’t tend to break them down into chunks any smaller than a story we can define in business / product terms.
Current task management tools suggest a single assignee per task, or multiple assignees but with no record of individual effort required or how the collaboration will occur. We actually need to reflect a more complex sense of ownership and collaboration, even if most of the work will be done by one person with fleeting collaboration at some point. Failing to capture this in a basic form can be a cause of tasks being unexpectedly “blocked” during sprints, or the logical next steps towards their completion being unclear.
Tasks Have Dependencies (Sometimes)
Sometimes, a task depends on other tasks being completed (or part-completed), or a bunch of tasks need to happen in a certain logical order. Often a task that is scheduled to be completed this week or this sprint is blocked by an implied dependency that won’t be resolved anytime soon. We must model dependencies, or risk impacting our progress if we discover them late, or if many tasks get blocked on a key resource that we should have planned around earlier.
Current task management tools can model dependencies clumsily at the task level, but aren’t good at helping us to visualise them. This can often be another cause of tasks being blocked during sprints. They certainly aren’t good at modelling dependencies between groups of tasks, and we tend to have to visualise those ourselves: e.g. All tasks in Stage 2 depend on the tasks in Stage 1.
A visual representation of dependencies at a task and group level, and ability to move them around, would give us a more efficient view on how best to approach those tasks in a sensible order.
Task Completion Often Isn’t Clean
Often a task is almost completed, with a small piece of work to be finished, perhaps when unblocked by another person or after a dependency or decision is resolved. The inability to easily mark the task as partially complete, or to define the remaining work (perhaps in a sub-task), hampers visibility of the true state of the task, particularly on agile boards.
Creating a new sub-task can be cumbersome, and it needs adding into the plan or sprint, in correct relation to the original task, so it isn’t forgotten or confusing when seen in isolation. Often the administrative effort leads to us just leaving the original task open until the remaining work is completed.
Current task management tools assume task completion is clean and atomic, leading to tasks remaining “in progress” when they are often 90% complete and the tool should allow us to easily reflect that. This often hampers visibility of remaining work, particularly close to the end of a sprint.
Clearly, I’m pointing out some broad problems with simplistic views of task-based engineering here and suggesting some very general solutions. Not all of these problems will apply to a project but, particularly with larger teams, I’ve seen many of them and their impact is real. Some teams tackle these problems well as part of the way they work, but others clearly struggle with the realities of task-based engineering.
A quick summary:
- Tasks are valuable abstractions for understanding and managing engineering complexity, but the methods and tools we currently use to manage them are rather rigid. We need to be able to visualise and change large numbers of tasks easily, see their overall status and visualise how they combine to form a planned delivery or feature;
- We need to be able to break tasks down to any level, describe what overlaps and what’s already complete, so we can model our fluid discovery of complexity but retain an ability to estimate and gauge the remaining effort involved. Again, current tools and methods are too brittle;
- We need to be able to model and visualise task and task group dependencies, where they matter (they don’t always), or even just record that entire swathes of tasks must take place in a certain loose order. Current tools make this too cumbersome;
- We need to model the necessary collaboration within individual tasks, both simple and more complex, so we can be aware of it. Current tools are too cumbersome to make this effective or even worth the effort, and agile boards are too simplistic.
- Most crucially… All of this must remain light, easy to visualise and easy to change. Current approaches and tools are way too cumbersome, and often work against us.
As they say, “Your mileage may vary”. So I’d be really interested in hearing how this ties into your own views of task-based software engineering, whether you encounter any of these (or other) problems, and if you think the kind of broad changes I’m suggesting might improve things.
One thing is certain: Task-based engineering is here to stay!