How Remote Ensemble (Mob) Programming Is Working for Me 

 March 24, 2020

by Jon Reid


Ever since I experienced ensemble programming (also known as mob programming), it became my primary teaching tool. But due to COVID-19, it's suddenly time for me to support remote workshops. Can ensemble programming work remotely?

Due to COVID-19, it's time for me to support remote workshops. But can #EnsembleProgramming work remotely?

Click to Tweet

To date, I've taught over 230 students about unit testing and Test-Driven Development. Almost all of it has been in person, with everyone in one room.

My last TDD for iOS workshop was going to be in Amsterdam. But with the unfolding health crisis, my host Jeroen Leenarts and I decided to make the workshop fully remote. I'd been intending to start remote workshops someday, but this forced my hand.

In this post, I want to share how my remote ensemble programming is evolving. And you can add your own ideas.

4 joined hands

On-Site: How I Use Ensemble Programming

When I first started teaching, students worked solo on their computers. Then I had them work in pairs. But after a workshop taught by Llewellyn Falco, I got hooked on ensemble programming.

Here's how I do ensemble programming when on-site.

There is one computer, hooked up to a projector. The IDE is set to a light appearance (not dark), with a large font. In Xcode, this means I go to Preferences > Fonts & Colors, and select "Presentation (Light)". I usually also go to System Preferences > Displays and use a Scaled display to make things larger. Otherwise, the text might be legible, but the controls will be too small.

Then I establish 3 roles:

  • Driver: The person controlling the computer. This person's job is to listen to the Navigator, turning their instructions into code. For some Navigators, this might be, "Add a new line. Type f-u-n-c." For others, it could be, "Make a new test, called Evaluate With 3 Should Return Fizz."
  • Navigator: The person deciding where to take the code next. This person's job is to give instructions at a level that works for the Navigator. The Navigator stands apart from the Driver. This causes the Navigator to speak clearly so that everyone can hear. (No whispering instructions to the Driver.) If they get stuck, the Navigator asks the Observers for suggestions.
  • Observers: The rest of the folks, watching what's going on. Their job is to offer help to the Navigator when requested. Only rarely should they interrupt, because my on-site groups tend to have 10 people or more.

I use 3-minute rotations. It may sound fast, but it works well with 10 people. When we start, I use the Timer app on my phone. This gives me the ability to pause the timer so that I can use the latest changes to teach something.

When I'm no longer pausing the timer to point things out, I shift to using MobTime on the computer. MobTime pops up a window to interrupt the current rotation. Counter-intuitively, a strong interruption keeps things moving. And if I want to pause the timer to discuss something, I can ask the Driver to do so.

This configuration works great for a group learning together in one room. Everyone is looking at the same code. Discussions happen in the context of the shared code. Everyone observes, gives instructions, and feels the code come out of their fingers.

(Mac keyboards vary greatly from country to country. When teaching in another country, set System Preferences > Keyboard > Input Sources to "Show Input menu in menu bar". Add different keyboards for whatever languages the students use. It's also helpful to connect an external keyboard for the local language.)

Remote-Driving a Single Computer

At one point, I did a remote workshop as a pilot experiment. I applied the same ideas but used Zoom to give remote control of my computer to the next Driver.

The experience for the Drivers was often less than ideal. Operating a remote computer has some lag. The feedback loop from fingers to eyes becomes delayed. As this lag increases, the experience gets worse.

I've seen folks trying to delete a few characters. Due to the delay, they'd often hit the delete key too many times. The unwanted results would break the flow of collaboration.

This was quite bad in one workshop where one group was in the room with me, and another group was elsewhere. It led to an inequality between the local group and the remote group. (After this, I decided my workshops should be local or remote, not mixed.)

Screen-Sharing Your Own Computers

With the Amsterdam workshop suddenly going remote, I wanted to avoid the problems I saw with remote driving. Instead, my goal was to have each Driver work on their own computer, sharing their own screen. To pass the code from one Driver to the next, I set up GitHub repositories. (This meant upgrading my account so that everyone could have write access.)

This eliminated lag and worked pretty well. But it did introduce other problems:

  • Every time I created a new repository, I had to invite each person as a collaborator. There was one repo where I missed one person, oops.
  • Not everybody cloned the repo. Some folks downloaded a copy instead. But it needs to be a clone, so we can push & pull.
  • Not everyone had command line tools installed.
  • Some folks used large monitors, which are hard to see when shrunk to a regular MacBook Pro display. Next time, I need to ask those folks to scale their displays.
  • When working on an iOS app, the first local test run takes longer. It has to launch the Simulator and copy over the entire app. So the first turns were painful, until I told everyone to pull the code and run tests to warm up their systems.
  • Even then, Xcode sometimes fails to communicate with the Simulator. The quick fix is to quit both and relaunch. But that's painful if everyone is waiting on you. When that happened, we asked that person to skip driving until the next turn.
  • When you do screen sharing in Zoom, you can choose to share only one window. This is appealing for privacy but led to problems. When I asked folks to demo the running app, we couldn't see their Simulator. It looked like the cursor was moving around doing nothing. Share your whole screen.

Despite the problems, the basic idea of avoiding lag worked well.

Things I'll Do Next Time

Most of the problems we had were around one-time configuration. So the next time I teach a remote workshop, I'll turn this list of problems into a checklist. I'll ask participants to go through the checklist before we meet.

One thing I did right was to have a practice round. No timer, no programming. Everyone takes turns sharing their screens and adding their names to a file. This helped iron out the initial kinks.

But this practice round didn't necessarily help when we switched to a new repo. So instead of separate repos for each project, next time I'll make a single parent repo containing all projects.

Every time there was a handover, the current Driver had to commit and push, and the next Driver had to pull. From the Remote Mob Programming website, I learned that we can use a tool made to simplify this workflow.

I was already planning to start remote workshops at some point. But COVID-19 accelerated my plans. Thanks to everyone's patience in the last workshop, we can all be more effective going forward.

Do you have any suggestions on how I can make things even smoother? I'd love to hear your ideas for remote workshops!

Jon Reid

About the author

Programming was fun when I was a kid. But working in Silicon Valley, I saw poor code lead to fear, with real human costs. Looking for ways to make my life better, I learned about Extreme Programming, including unit testing, test-driven development (TDD), and refactoring. Programming became fun again! I've now been doing TDD in Apple environments for 20 years. I'm committed to software crafting as a discipline, hoping we can all reach greater effectiveness and joy. Now a coach with Industrial Logic!

  • I follow you since the speech that you do in La Rioja on NSSpain. Looking forward to join to one of your remote sessions greeting from uk and stay safe.

  • {"email":"Email address invalid","url":"Website address invalid","required":"Required field missing"}