Ensemble Programming: Tips for Software Teams to Survive and Thrive

Ensemble Programming: Tips for Software Teams to Survive and Thrive

Rani Zilpelwar
Rani Zilpelwar

October 19, 2023

Ensemble programming is a way for teams of developers to collaborate in real-time. A group usually consists of three to five developers. The group performs collaborative coding, all focusing on a single task at a time and benefits from collective knowledge to find the optimal working solution.

I recently had the opportunity to perform software development in an ensemble and the experience helped me identify needs that were important for any type of team to flourish and excel. If this sounds like something that your team may benefit from, read on.

Our Implementation of Ensemble Programming

On this client, our team of five developers performed driver-navigator in rotations. One person is designated the initial driver, shares their screen, and implements the code changes directed by the navigator for a set period of time. Once that period of time is up, the driver becomes the next navigator. Another person is chosen as the driver and the process repeats until everyone has their turn. Then the rotation starts again.

Each navigator is free to decide the direction for the next set of code changes, which sometimes picks up the changes from the previous navigator or changes directions completely, such as performing a refactor. The navigator gains help from the other team members on the call, if needed.

Once a week, we perform spikes, where we could spend the afternoon researching a new tool, library, or idea that benefited the client in some way and then present the information to the team the next morning. If the team deemed the work beneficial, any code changes would require integration into the code base via ensemble programming. No code changes resulting from solo work were allowed to be merged.

The Benefits of Ensemble Programming

  • Pooling knowledge means that teams find the optimal solution from the start. No time is wasted trying something new, submitting a PR, and then finding out that the team doesn’t agree with that implementation.

  • New team members have quick ramp up time. Because everyone is working together, new team members don’t need to spend time trying to understand a process before they can get started. They simply listen, learn, and participate.

  • Everyone feels involved. I felt immediately part of the team from day one. It was very clear that we were all contributing, working together, and making progress — together.

The Challenges of Ensemble Programming

  • When making decisions, you need to respond very quickly. Some people take time to process information and come up with a valid counterargument. If you are in your head trying to understand an idea, it is quite possible the team has already decided and moved on before you chime in.

  • Having everyone work together all the time means it is challenging to deep dive into an area that interests you. This is especially true for people who learn better by being hands-on-keyboard. I personally like to experiment and try different things to get a deeper understanding of how and why something works. There isn’t time for this during an ensemble. You can propose an idea but you decide on consensus and move on.

  • Programming feels very slow. Everyone working together all the time means that you only work on one thing at a time. You can slice features into smaller slices to get things out faster, but they are still just smaller slices.

The 7 Needs of Successful Teams

With any programming approach, it's important to adapt to the team's needs. Here are some learnings our team took away from ensemble programming that can be applied to other teams or even other delivery approaches.

1. The Need for Engagement

After the first week of ensemble, I felt extremely exhausted. As someone with introverted tendencies, the sheer amount of brain power and socializing skills I needed to exude to listen to four other people on a call for seven hours every day was more than I thought I could muster. Despite this challenge, I made sure to listen to every single person on the call, their insights, their coding techniques, and their questions. I also made sure to stay engaged as much as possible. I participated in the conversations, asked questions when I was confused and provided suggestions when people got stuck, even when I didn’t know the code base very well.

Takeaway: Being engaged reduces ramp up time, helps to understand the culture and allows you to contribute to the work quickly.

2. The Need for Routine

After a few weeks of ensemble, I noticed that some of the team members, including myself, were showing signs of burnout. It was hard for me to understand the task at hand, I was dreading the rest of the afternoon, and people who were neither driving nor navigating on the call were completely disengaged from the conversation. After some self-reflection and observation, I realized the source of the exhaustion. We would work for hours at a time, with no breaks, and blow past lunch without even realizing it. I can get hangry with the best of them.

After some discussions with the team, we tried a few different techniques to alleviate this issue. I found that the best version of the ensemble that our team practiced was by applying the pomodoro technique to our workflow. We would code for 50 minutes, take a 10-minute break, stop at noon for lunch (or as close to noon as possible), and then end the day on time. This became a more sustainable pace.

Takeaway: Implementing a routine of taking breaks before exhaustion ensures the team has energy to keep going without compromising on pace or progress.

3. The Need to Phone a Friend

One of the benefits of ensemble programming is the ability to tap into the skillsets of the experts on your team. For example, we would have to create a new AWS lambda, or modify a Dynamo db schema, or figure out some strange UI refresh issue in our React Typescript front end. In all these cases, I never hesitated to navigate an issue that I was completely unfamiliar with because I had the ability to shoulder tap anyone on the team that was more familiar with the technology than I was. I would be in the middle of navigating a feature and pause to ask the Lambda expert what was the best AWS command to use, the Typescript expert why I couldn’t get something to compile or the Jest expert why my mock wasn’t working. I had immediate access to mentors and I made sure to leverage it. We made forward progress and I still learned a lot.

Takeaway: Leveraging the skills of the more experienced members on the team and getting near-immediate feedback makes people feel supported and keeps them productive.

4. The Need to Offload Mental Tasks

Our team handled sprint meetings with a daily call in the morning with the product manager, who gave us the direction of work for the day. Team members often stated, “We don’t have meetings but we can talk about anything, anytime.” However, during the ensemble, there was a balancing act between making progress and having conversations. Asking more questions meant the whole team had to stop and address the conversation. This was the same for concerns. I knew certain discussions would take a while and it would be nice to focus on getting something to prod that day instead. However, the mental load was still there — I kept thoughts in the back of my mind to find the right time to bring it up so that we would have effective conversations. These ended up taking space in my head that could otherwise be used for other focus tasks.

On other projects I’ve been on, we would designate time for discussion topics, such as backlog grooming or retro. Retro allowed the opportunity to bring up concerns, discuss them with the team, and identify action items to address them. It was an opportunity to offload the mental task to a designated time and place. I didn’t have to talk about it now, because we would talk about it then. It also served as an opportunity for everyone’s concerns to be brought up, regardless of your working style.

In this current project, a few months after joining the team, we finally held a retro which proved extremely insightful. A number of concerns were brought up and it made me realize that having a routine for these types of discussions was more valuable than expecting people to bring it up “anytime.” We decided to have retro once a month. Some teams will have retro at the end of every day for 15 minutes and others have it once a week. It is important for the team to discover what works for them.

Takeaway: Reducing mental overhead by having designated space improves productivity.

5. The Need for Knowledge Sharing

One interesting aspect of ensemble programming is that no one is singularly important. I know that is a strong statement and likely a huge ego blow. Let me clarify. Because everyone works on everything, siloing of information doesn’t occur. When someone left the team or went on a weeklong vacation, the team knew we would keep making progress. If I had a question, I could ask anyone else on the team for help.

Now, certain people served as experts in certain areas because of their background and interests in certain technologies, but there was never a sense that we couldn’t work on a feature because someone was out and was the only one who knew how something worked. This was a huge benefit to the client and a huge weight off of developers’ shoulders because when they needed time off, they took it.

Takeaway: Teams are more productive when access to useful information remains prevalent and clients benefit from not being bound to “sticky” team members.

6. The Need for Autonomy

It was very normal for our team to try something new, stick with it if it worked and discard the idea if it didn’t. For example, we started with 20-minute driver/navigator sessions and found them to be too long. For our team, 5 minutes became the sweet spot. As another example, we initially used a kanban board to identify work tasks but it didn’t allow for ease of organization, so we switched to discovery trees. With this, we were able to identify the requirements more easily and align implementation with use cases.

As a team, we made decisions that benefited the team without having to go through an approval process; the whole team was the approval process. When things didn’t work, we pivoted. We didn’t lose time being frustrated with a constraining process and a technology that didn’t benefit the teams’ or the client’s needs.

Takeaway: Teams need to be able to make decisions that improve their productivity, protect their mental health, and secure their ability to make forward progress.

7. The Need for Good Communication

Ensemble really exercises a developer's communication skills. Just from a coding standpoint, I could no longer rely on my muscle memory when refactoring a component or test driving a feature. I had to explicitly explain what to do in order to control someone else’s muscles — the person typing on the keyboard. I had to explain it in a way that made sense to them.

From a communication standpoint, it was important to explain why I decided what I did and how it added value. The best experience I had during the driver-navigator rotation was when the navigator, at the start of the rotation, would explain their thought process at a very high level and then went into the nitty-gritty details of what was needed to achieve the work. This gave everyone an understanding of what we were doing and allowed people to follow along more easily.

I also found that it was important to overly communicate what was going on in my head. When I was a navigator and got stuck sometimes, people would chime in and provide help, which was great. However, if I didn’t acknowledge their suggestion explicitly and instead just kept talking to try to implement it, especially when I managed to do it incorrectly, people expressed behaviors reflecting that they felt ignored. Explicit acknowledgements such as “thanks for that suggestion, let me try a couple things to see what works” or “that's a great suggestion, what's the best way to implement that?” really hit home.

Listening skills are also important. In an ensemble, I’m not listening to one other person. Often, I am listening to four other people, who may offer suggestions, ask questions, or even counter the direction I decide to go, at any given time. It is important to acknowledge what was said so that people feel heard and understood. Everyone’s voice matters.

Takeaway: The performance and vibe of a team greatly improves with strong communication and listening skills.

In Conclusion

Ensemble programming is a software development approach where the whole team works together, builds on the principles of extreme programming, and works for distributed teams. Note that the basic fundamentals of any high-performing team is teamwork: a group of developers working together, supporting each other, and making progress toward a common goal. Ensemble programming accomplishes this through shared code ownership, knowledge sharing, and collaborative coding.