Teamwork is a complex social activity. Even more so are complex software development teams, given the complexity of software development itself. In this newsletter, I explore some useful perspectives for improving team performance in software development.
Adding more typing hands hurts software development teams
Do you feel your team could do more or better?
There’s a popular belief that a team is a collection of individual contributors, who gather from time to time to share progress status.
However, effective SW dev teams are quite the opposite – they are tightly engaged problem-solving groups.
You can use this tip to quickly improve your team’s performance:
Stop splitting work and assigning it to individuals only to gather their individual results after they are finished. It results in individuals facing the most important activity of SW dev on their own – problem-solving.
Play to the group’s strengths instead. Address problems together (domain understanding, design decisions, defining experiments, facing issues, etc.). Put everyone’s brain to use at the same time.
If mob/ensemble programming or pairing is not your thing, at least do functional analysis together and do it just before the typing starts. Define code paths, use cases, and test cases together.
Define APIs and make design decisions together, and do that frequently.
Soon it becomes clear that it is much better to do it WHILE you type, all the time.
Having a software development team is not about having more typing hands. It is all about having a bigger brain. Combine team members’ brainpower – that’s how you get a bigger brain!
So, if you are adding new team members, do not add them as individual contributors, and don’t consider typing to be their biggest strength. Get the team members together as frequently as possible. It pays dividends.
SW dev teams usually approach work in a reasonable divide-and-conquer manner
However, it often backfires, and the WORK itself divides and conquers the team instead!
Understandably, teams tend to split the work at hand. The usual approach is to distribute the resulting pieces across the team. Again usually, each piece is assigned to a single person. And that is the usual culprit.
However, this approach leads to at least:
▪ Congestion of the process flow
▪ Poor design choices
▪ Messed-up priorities
▪ High possibility of rework
▪ Loss of overall quality
▪ Ineffective knowledge sharing
▪ “My work / your work” mentality
One easy fix to this issue is to split the work, and address the resulting pieces, one by one, as a team – together.
Most likely, your team will not be working slower or less efficiently. On the contrary, the work has a better chance of smoothly flowing through the system, according to set priorities, and having the whole team engaged. As a side-effect, the issues listed above have less probability of occurring.
Do you get responses such as “Peter will do it because he knows that part of the system best” too often from your SW dev team?
It sounds like your team’s “team knowledge” does not actually belong to the team – it is kept within individuals instead.
Breaking out of this vicious cycle can be surprisingly easy, and here is a way to do it:
What is considered to be “team knowledge” about the product, system, and domain is often a collection of rather separated knowledge (experiences and facts) located within individuals.
If we keep the work segregated by individuals who “know the best” then individuals gain more specialized knowledge, while others miss out on it.
We do this typically by creating tasks or user stories assigned to and executed by individual team members.
This perpetuates the dysfunction further, leading to less collaboration and poorer results.
How to break out of it? Try this simple rule: NEVER let any problem be solved individually.
Even if only one team member is capable of solving the problem at hand, keep others closely and actively involved.
They will gain knowledge through experience this way.
Let them experience what doesn’t work, rather than just show them what works in the end.
It’s the way to build the necessary knowledge and experience so that everyone on the team feels more confident about further work.
This is how you actively build your team’s “team knowledge.”
Does it look like your team members compete with each other?
Review and verification activities often have such an effect – “here’s what is wrong with your results!”
It is wasteful and costly, but you can easily do something about it. Here is how:
Most SW dev teams have distinct review and verification phases of their SW development process. Those come in form of process gates – usually “Code Review on each push,” “Testing at the end of the process,” or similar process gates.
Individuals are left to run alone, having their results (e.g. code changes) verified AFTER time and effort have already been spent. At that point, all the important decisions have already been made as well.
The result is a cat-and-mouse game, with an ongoing “Spot the Error” dread. Team members are not working as a team, and are rather pitted against each other. Either individually or in smaller groups.
Breaking out of these wasteful and costly habits is luckily simple!
Simply have the team members solve problems together in these few easy steps:
1. Just before the individual’s work (typically coding) starts, get together as a team, and identify a use case that the implementation will address.
2. Having the use case, identify all test scenarios and test cases you can come up with – all the code paths you need to implement.
3. Select one test case and make all necessary technical and design decisions, and define the technical details needed for the test case to pass successfully.
4. Do the coding necessary to implement decisions for that one case. If you have to, split up and write code and automated tests in parallel, but at least try to do it in pairs.
5. You have a fully implemented and passed test case, so you can refactor the code if needed.
6. Chances are that you will identify new cases, so add them to the suite.
7. Go back to step 3. and repeat the steps for the next case.
What are the results? At least you will end up with:
▪ Use cases understood by the whole team
▪ Automated test cases for all code paths/usage scenarios
▪ Unnecessary bugs avoided (no ping-pong at the quality gate)
▪ Design understood by the whole team
▪ Code constantly reviewed and improved
▪ Test code constantly reviewed and improved
▪ Domain knowledge of the whole team increased
▪ Team skills increased (by increasing individual skills)
▪ Wasteful process gates are removed
▪ Significantly reduced reworks due to misunderstanding (e.g., code review findings, or emergent bugs)
It does sound a bit waterfallish but works better than the phase-gated approach.
It is very fast work in micro-increments, so it looks like quite the opposite.
Anyhow it gets you to a better place so you can improve further.