Software teams and organizations today are looking to scale faster than ever. The pressure to release features at an increasing rate, while keeping bugs to a minimum is only exacerbated by the growing size of dev teams needed to deliver said features. We add more and more devs to a team, but only get incremental returns, all the while the experienced, senior devs seem to be delivering less and less of their high-value code, which can make or break the product.
The approaches that have gotten us this far have stalled. Instead of adding people to a team, in order to grow we need to look differently how people, already in a team, work together.
Before we dig into that, let’s look at the story so far.
The Waterfall model was essentially the first project management method to be introduced to the software engineering industry. At the time, software was just a small part of larger infrastructure projects.
RELATED CONTENT: Agile at 20: Where it’s been and where it’s going
Due to the rigidity of specifications for those projects, there was little room for variation in the process. Any changes made to the specifications during development would have resulted in high costs, so the very rigid and structured approach of Waterfall worked well.
As software became more prominent in business use, and ultimately personal use, there was a rise in the number of much smaller software applications. This, in turn, resulted in a rise in the number of software companies creating such applications, and a rise in the issues with the rigid and deterministic approach of Waterfall.
Agile was born out of the need to address these challenges. Software teams identified that it was far more useful to have a process that could respond to changes in customer requests, and to get something basic working quickly, and then adjusting and iterating from there.
Sprints, the most applied aspect of Agile development, enabled software companies to create value for customers much quicker. It also enabled teams to be more responsive and reduce the amount of rework that resulted from changing specifications.
And here we are in the present times. Despite the evolution of software development approaches through the years, and the benefits that have come with it, issues that arise from team and organization growth remain unresolved.
So, what is going on?
Let’s take a small development team and follow them as they scale.
Our dev team, part of a start-up, has five developers. Of the five, one is an extremely experienced senior developer, another couple are senior devs, and the last two are juniors with far less experience. Before the juniors came on board, the three senior developers would coordinate themselves and just get on with it. But as the team has grown, they have needed to add a bit more structure into their sprint planning and execution, so that the whole team had plenty of work to do for the fortnight.
As well as this, the most senior dev started to spend his time assisting the two new juniors. Naturally, this limits the other work that he can do.
Coincidentally (or perhaps not a coincidence at all) two new pressures have arisen: to produce more features; and, at the same time, to fix up the quality based on the bugs resulting from the new developments. Our most senior dev, who has become the de facto team leader, complains to the founder about needing more assistance. They are, of course, old mates who have been in the business from the start, so convinces the founder to authorize more hires.
At this point the team has a real structure and is sure to plan out everyone’s work to ensure they’re getting the most out of the team. This growing team requires a fair amount of the senior dev’s time, but that’s to be expected to keep the machine running. On top of this, the founder gets calls with ‘urgent’ customer requests and ignores the sprint load to expedite them into the senior dev’s workload.
Back to the question: What’s going on? Why would teams all over the world do this?
These issues don’t arise from malice and they certainly don’t arise from stupidity (given the calibre of minds involved). Instead, they come from two assumptions we make about how teams should operate.
Firstly, we assume all team members’ contribution is equal. At the end of the day there is no “I” in “team” and we all do our bit around here.
This assumption is evident in the way we plan work. We hold planning meetings where everyone has a say in what work they should be doing. The focus in these planning meetings is on the inputs and an even spread of load, rather than on the output of the team.
Secondly, we assume time not working is wasted time. The more everybody does, the more we get done as a team. Right?
This becomes obvious in situations where we have a team member who has an hour to spare in a day. Instead of being comfortable with letting that team member twiddle their thumbs, we will find something ‘more useful’ for them to do. Maybe start investigating a quick bug fix?
These assumptions are based on reasonable efficiency drivers we have as human beings, but these assumptions don’t apply effectively to software teams.
Let’s examine them more deeply!
1. All team members contribute equally to the output of the team
Every team has one person who is the most skilled person in that team. This gap in the skill level is magnified by their experience with the code base and the product, which creates a very large discrepancy in value of the code that is written by them, as opposed to that written by the most junior person. This does not mean that junior devs are not valuable, but instead it simply clarifies the type of work, and the value-add that is able to be done at each tier of seniority.
This is crucial because, by default, the most skilled senior dev acts as the bottleneck for the work the team can deliver as a whole, and even more so for the high value work the team can deliver, which leads us to conclude that NOT all members’ contributions are equal.
2. Idle time is a waste of time
A team of people working together is not like swimmers in a pool, each swimming in their own lanes. There are many interdependencies in the work the team members do, which means we will never have an even load across a single sprint, and some people will be idle from time to time. Forcing an even load is planning to fail.
If the first assumption is wrong, and not all team members’ contributions are equal, we should then be maximizing the contribution of the most skilled resource. This may be done in many ways, one being that they are idle for 30 minutes in between tasks because picking up another task would make them late to do a handover to the bottleneck resource.
Sometimes, not working is the best contribution a team member can make!
How do we fix this?
The answer is conceptually simple, but much harder to implement.
What the team needs is more capacity for the bottleneck end of the bottle (the most senior dev), not for the body of the bottle (the team as a whole). By increasing the capacity of the body, we are just putting more strain on the bottleneck, as opposed to focusing on widening the bottleneck, which increases the output of the whole team.
So the answer is to coordinate more effectively around the bottleneck, then to protect the team’s work from the impact of variation, and finally to accelerate the flow of work through the team. These three initiatives make up ‘Pace,’ an Agile-friendly framework that replaces Scrum in many teams. To take something tangible from this article, here are 4 immediately applicable Pace rules to minimize bottlenecks and maximize team performance:
1. Ensure there is a steady supply of work for the bottleneck
- As the bottleneck controls our output, and time lost from the bottleneck is lost for the team, we ensure there is always valuable work for the bottleneck.
2. Offload the bottleneck from unnecessary tasks
- All work that can be done by others is assigned to them, freeing the bottleneck to only do work they must do. Check for the efficiency trap of planning tasks for the bottleneck because they are faster.
3. Plan others’ work around the bottleneck
- The bottleneck’s work (including others’ work that requires the bottleneck) is planned first. Then, others’ work which does not interact with the bottleneck’s can be planned.
4. Ensure quality inputs into the bottleneck
- To minimise the risk of bottleneck rework, extra quality steps such as tests or checklists are introduced immediately before the bottleneck.
Pace applies these proven rules and ensures they produce significant benefits – almost instantly, and certainly over the longer term.