My remote pair programming setup
18 Sep 2015Pair programming is one of my favorite things to do, in many ways I feel way
more productive when I pair with someone else and the cliché that Two (2) heads are better than one seems to be right in this case (at least for me).
Remote pair programming is hard, especially if you use the wrong tools. Since
I’ve been doing this for a long time, I developed a workflow around it with
tools that I think is worth sharing.
Note: I will not go into the discussion of “Why pair programming”, I think
it’s irrelevant for this post and there are many posts on the internet
discussing that point to exhaustion. I think this blog post discusses the ups/downs of pair programming well, read it if you want to learn/educate yourself more.
Tmux
I work with tmux a lot. One of the best thing about
Tmux in the terminal is that once you share your session using SSH, the person
pairing with you has access to all the tabs you have open for the project.
For example, if you pair on a rails project, you can see the console, server
logs, Redis and really just about anything else you have in that Tmux session.
I blogged about how I start work using tmux in the past in these posts
-
[My development workflow (vim+tmux+terminal+alfred) Awesomeness ](http://avi.io/blog/2014/08/28/my-development-workflow-vim-tmux-terminal-awesomeness/) - How I start working using Tmux
Essentially, I have a start.sh
file in every project root that opens all the
tabs/splits I need and gives the session a name.
Configuration
You can check out my tmux configuration in my dotfiles repository here
Note: This is only tested on Mac, I know there are some problems with using it
on linux, especially around attach-to-user-namespace
and the use of pbcopy
.
Here’s an example of what a tmux session looks like
Edit: Thanks to Reddit user tuxracer04 for suggesting tmate.io. I have tried it before and it’s a very good option to share your session, it requires less setup but you have less fine grained control. Worth a short to test things out
Vim
I use vim in terminal exclusively as my editor. Over time I tried every editor
out there, from Sublime to Atom and more.
Since I am using the terminal as my main work tool, it’s easy to just use vim
inside tmux and share it, this simplifies the workflow of pairing quite a bit,
since you don’t have to screen share your code and deal with delays.
With screen sharing, it’s hard to pair since you need to allow your peer to
drive as well, anything from copy/pasting code to tying something they want.
Obviously, I do not want to make this post an editor war, but I really
encourage you to use a terminal based editor, whether it’s emacs, vim or any
other tool, it will make your life so much simpler
Configuration
I don’t have any pair programming specific vim configuration, it’s just using my
dotvim configuration https://github.com/kensodev/dotvim.
Running tests
Whether I am coding in Go, Ruby or any other language for that matter, I always
do TDD, no exceptions (Yes, even for Javascript)
Running tests is a huge part of the workflow when pairing and looking at
results of tests is definitely something we do a lot while pairing.
The usual “running tests” workflow is very breaking, you need to look at
another screen in order to view test results, or stop looking at code in order
to do that.
With running everything in the terminal and using Tmux, I can basically send
the result of the testing to another split.
Her’s an example of what this looks like
As you can see in the red rectangle, there’s a file called read_pipe.sh
, here’s the contents of this file
#!/bin/bash
DEFAULT_PIPE_NAME=".plumber"
PIPE_NAME="${1:-$DEFAULT_PIPE_NAME}"
if [ ! -p $PIPE_NAME ]; then
echo "Created pipe ${PIPE_NAME}..."
mkfifo $PIPE_NAME
fi
echo "Waiting for commands!"
while true; do
COMMAND=$(cat $PIPE_NAME)
echo Running ${COMMAND}...
sh -c "$COMMAND"
done
This comes from vim-plumber,
which allows you to send the results of tests to a pipe file
All I need to do is hit <leader>t
or <leader>T
in order to run tests, the
tests will run in the background in another pane and I can continue working.
When pairing this is super powerful since you can just run tests and then look
at them, copy results, look at the code while looking at the results side by
side and more.
This saved me so much time over the period I’ve been programming I cannot
emphasize enough how important this workflow is.
What does TDD has to do with pairing
I know it’s weird seeing TDD in a remote pair programming workflow, however, I
feel it’s absolutely crucial to pair when you pair program since TDDing forces
you to slow down and explain the process of your thoughts.
When you TDD, it’s a perfect oportunity to discuss the design with your pair
and understand how the system works.
SSH
In order to share tmux and your terminal you will need to allow SSH into your
machine. This is a bit tricky and requires just a bit more configuration beyond
your machine as well.
Router configuration
It is more than likely that you have a router in your home office, so behind
your public IP there’s a list of internal ip’s.
You need to configure your router that whenever someone SSH’s into the home
address they will be routed into a specific computer.
Every router is obviously different, but it looks like this
I have it configured that my laptop has a fixed saved IP on the router so it’s
always the same address and it does not change, this way it’s easier to make
the configuration sticky.
Authorized keys
In order for someone to SSH into your machine you have to authorize their
public key.
BUT, remember each tmux session has a name, you can actually limit people into
a tmux session when they SSH, if that tmux session doesn’t exist, they won’t be
able to SSH into your machine
command="tmux attach-session -t SESSION_NAME",no-port-forwarding,no-x11-forwarding,no-agent-forwarding KEY_TYPE KEY
SESSION_NAME
is the tmux session name you set, KEY_TYPE
and KEY
are the
name and the key given to you by your peer.
Binding each key to a session name is a very good way to make sure that peers
can only access sessions open for them, if you don’t have the session open, the
SSH will fail.
What I do is I append _pair
to my usual session names, lets say I have a
session named gogobot
, when I want to pair I will rename the session to
gogobot_pair
in order to work with one of my peers. When we’re done pairing,
I will change the session name back to gogobot
.
SSH Tunneling
One of the best thing about SSHing into your machine is that now your peer can
access your server, so you don’t really need to share screen to see the browser
even.
This blog post explains SSH tunneling really well, go read it.
Voice / Screen
When everything is in the terminal, this is by far the least important part.
Personally, I use Skype in order for voice and screen share, but I have also
used Google Hangouts and other solutions.
When my peer has trouble setting up the tunneling, we can also look at the
browser together.
Closing thoughts
Before I moved to a 100% terminal based workflow, remote pair programming was
close to impossible.
There are many solutions that try to solve this problem, Screen Hero was one of the best ones before they shut down the product.
https://atom.io/packages/motepair looks
nice if you are using Atom as well.
This post will not be complete without mentioning Joe’s Remote Pair Programming website, this was an inspiration to me for a long time and includes many tips and tricks for making it work.
I hope you enjoyed this post, feel free to leave a comment with
questions/feedbacks, I’d love to hear what you have to say