Incongruence in software development teams


In David Epstein’s book, Range, he outlines the hazards that sticking to the congruence doctrine oft-taught in business schools can surface. Tech companies are just as susceptible to this as any other, here I reflect on some ways that might encourage incongruence as part of our daily engineering practices.

Don’t start with SCRUM

In the world of startup work that I inhabit, teams come and go quickly. They emerge to tackle challenges, change team members and focus quickly and are required to tackle uncertain problems.

Too often, I’ve seen teams that try to treat this uncertain world with the certainty that SCRUM offers. It’s a tool that is good for some teams, but not all and more often than not, SCRUM leads to frustration that the guard rails and certainties that the team are forced to adopt don’t help solve the messy and uncertain problems they’re faced with.

SCRUM is a fairly sophisticated process when done well and requires that a team is firing on all cylinders towards the same goal. Teams need time to build up the trust in each other that this requires, as well as build their shared understanding of the problem they face and the goal they’re heading towards. Give people the time and space to work these things out as a team by ditching SCRUM. Instead, go for a simple kanban or a list. These are tools that everyone understands and using them allows for the most important thing: flexibility. Incrementally adopting parts of SCRUM is a great way to introduce it as the team graduates towards focused delivery.

In the messy and uncertain world of startups, focusing on delivering functionality is a red herring; teams must be focused on unearthing the problems that people face and solutions that might help them get there. People need the space to change their mind about what is right when the conditions are uncertain, they need time to refine and adapt their understanding, they need a healthy level of incongruence to tease out the important pearls of wisdom hidden in a sea of noise.

Sense making, not decision making

To get the best out of a team, you need people with a set of diverse experiences. Those people must also be able to share their experiences in a maningful way. Often this experience will come in the form of criticism, with suggestions for improvements following shortly after. Sometimes only the critisicm will be available and the team must work together to understand how to get past the new problem.

As a leader of a team, one approach to making room for these improvements is to adopt a “sense making” role, rather than the more common “decision making” role.

As a decision maker, you become the limiting factor in understanding. For your team to progress with an idea, it has to go through your brain and be interpreted in a way unique to you. Even with the most exceptional mind on the planet, you create a subtle dynamic that prevents criticism. If a person raises an exception to your decision, it will be interpreted as a criticism of a personal action that you, the decision maker, made. This direct, confrontational criticism is something that many people find uncomfortable. Rather than offer criticism, people will avoid doing so in case it is interpreted as a personal slight.

In contrast, a sense makers role is to pool information from each of the sources available and distill it into a coherent plan. By abstracting the plan from the distillation of information, it becomes something shared by the team. People are free to criticise the plan or add new information to influence the final version without it being interpreted as directed at any person.

By taking up the role of the sense maker, you allow more contributions to the plans gonig forwards without sacrificing responsibility or the ability to rally a team around a specific version of the plan.

Code as an understanding of the world

A person smarter than I once described software (especially the Object Oriented kind) as an encoding of understanding of the world. All of the logic we create and names we provide are in service of one thing: describing and codifying the rules that govern our slice of the universe. For the life of me, I cannot remember who first voiced this interpretation of code (if you can, please get in touch!), but this framing of the systems we build allows us to understand where we can fit in incongruence.

An important baseline before being able to contribute towards a system of any size is the ability to understand what the rules of the system are. This is true when taking any size view of the system, from minute detail to big-picture overviews.

In order to effectively find and contribute to flaws in our understanding of the world or the view of it we’re building with our software, we must be able to understand it with the smallest cognitive load possible. By relieving our minds of the burden of understanding what the code is doing, we allow it to focus what it should be doing. This invites people to refine the understanding of the world that the system provides.

There are reams of articles about how best to do this, but one of the most practical demonstrations of how you might go about doing so can be found as part of the Elixir tutorial on building OTP applications.

By structuring your code clearly, in plain english, with logic and intent clearly defined and highlighted, you create a space that people can rally around and discuss changes to their shared understanding of the world. This is the heart of building incongruence into your team: creating a space for discussion of the facts as you collectively understand them.