Yield Thought

it's not as hard as you think
formerly coderoom.wordpress.com

A year ago I said goodbye to my trusty MacBook Pro and started working exclusively on an iPad + Linode 512. It was an experiment at first - one that I never thought would last.

Twelve months later and I find I’m still working like this. A combination of Vim and GNU Screen for development, Pages for writing, Keynote for presentations, Jump and VNC for unavoidable X windows work, Mobile Safari for web apps and a hefty dose of python scripts to smooth off all the edges. I use it for development, for presentations, for my side projects, for everything. 

I really mean everything, by the way. A high-speed baby bottle demolished my MacBook Pro screen months ago and I still haven’t got around to getting it fixed yet.

I love this setup, but it isn’t perfect. I’ll be making some changes for in the coming months. Before I get into that, I want to share what this extraordinary year has been like.

In my original post - just one month after I started - I was still using the setup as a light, silent laptop replacement. Now I use it in ways and places I never even considered using a MacBook. It’s no exaggeration to say that, this year, the cloud has set me free.

Freedom

It’s a crisp summer morning. The clear blue sky promises a hot afternoon, but there’s a hint of freshness on the breeze that ruffles my hair. I smile in the dappled shade of the tree and lean back against the rock. My fingers lazily stroke the screen, scrolling through the feature spec, but my mind is a thousand miles away weighing up design decisions for our new product.

I’m constantly surprised how readable the iPad screen is outdoors. Despite being glossy, it’s much better than the anti-glare MacBook Pro screen. It makes working outdoors not just possible, but enjoyable.

A fine mist of tiny droplets falls over the screen and I casually wipe it clean; working next to the fountain is refreshing but I doubt I’d have risked $2000 of hardware here. The iPad’s proven to be a rugged little thing; it doesn’t seem to care if it gets wet and as my files are remote neither do I.

A buzz from my iPhone tells me my build and tests are finished. I pull it out and glance at the push notification, courtesy of Prowl. New test failures. I finish jotting down my thoughts so far into the Pages document I’m using for the spec then swipe back to iSSH. The tethered 3G connection from the iPhone is great, there’s no noticeable lag as I flick to my Vim screen and hit a shortcut that opens and formats the test results.

Hm, the “quick fix” I came up with on the ride here this morning has caused problems elsewhere. I dive into the code for a while, effortlessly navigating around our million line codebase with an instant code search web app I hacked together using python and flask. Happily, iSSH allows me to forward ports through to the iPad, making it easy to securely use HTML for my scripts and helper tools without exposing any HTTP ports to the outside world.

I finish correcting the fix and push it to our main repository. Jenkins will tell me if it passes on the test cluster in due course. I glance at the time and realize I’ve been sitting here for two hours now. I find I can work almost anywhere for two hours at a time, but to stay in one place for longer I need more comfort than a jumper to sit on and a rock for a backrest! Our mid-morning devteam meeting will be starting in fifteen minutes so it’s a good time to go somewhere quieter for the call.

I throw the iPad and keyboard into my rucksack, wade back across the stream and hop onto my bike. A brisk ride later and I’m back on foot, strolling through trees and flowers with my hands-free headset on in a vast landscaped garden that cuts right through Munich. The call is taking some time to set up. As I’m on 3G, I asked the office team to call my mobile number, but one of our developers is at home and doesn’t have a landline in his study, only Skype. An unexpected hiccup - I feel bad; if I were in an office this wouldn’t have happened.

While waiting for him to start the call with SkypeOut, I discover a rose bush and spend a moment enjoying their rich scent. It feels almost like cheating, working in such a beautiful environment, combining meetings with summer walks through the park. And yet, it doesn’t seem to have affected my productivity at all.

I wish the rest of our team could enjoy walking and talking about the last and upcoming week out here surrounded by nature instead of being stuck in a drab air-conditioned box the best part of a thousand miles away.

Then it strikes me: they could. And yet I worked in that office for six years and I never did. There’s a beautiful castle near the office set in vast landscaped gardens; I could have switched to an iPad + server (one of the office servers would have been fine) and spent a day working there, or any of the other beautiful places I loved to be in.

Of course, back then I used a graphical IDE and the iPad didn’t exist, but surely it would have worked with a laptop, too. Well, unless I ran out of power after an hour or two of multi-core compilation. Or it got too sunny. Or it started to rain. And then I’d have had to worry about finding a nice cafe that also has a free space on a large enough table near a power outlet. So many conditions. So much to fear. 

The 10-hour battery life, 3G connection and small form-factor of the iPad + wireless keyboard combination frees me from so much; today I can work wherever I can sit.

A chime from my phone snaps me out my reverie and we begin the call. The wind has picked up, so I mute myself when not speaking and cup the microphone in my hand when I am. It’s not perfect, but the fresh air filling my lungs and the rustle of the leaves in the trees overhead are worth it.

After so much nature I feel like sitting down with a proper seat and table when the call is done, so I cycle down through the park until I reach the Chinese Tower - a beer garden with fantastic benches in the shade. The perfect place to finish my morning’s coding.

At 1pm I leave the park and cut into the city, spending 45 minutes chatting with Matthias from MunichBeta over lunch in a tiny little Chinese place he knows, followed by a visit to Munich’s best ice cream parlour across the street. Matthias lives much as I do, flitting around the city trying out new places to work with his trusty Macbook Air.

This afternoon I’m giving a webinar to prospective customers; I need a quiet conference room and a rock solid internet connection for Skype. My location of choice: Combinat56.

I find a change of scene and some exercise are perfect to ward off any post-lunchtime lethargy and when I arrive at the stylish Combinat56 offices fifteen minutes later I’m feeling refreshed and ready to go.

Running the webinar from the iPad works just fine - Cisco have an iOS app and in any case we’re only sharing slides and dialling in. Usually I just email people the deck and call them on the phone, though; it’s simpler for all concerned.

After the call I catch up with my friends from the Combinat over a cup of tea in the lounge area. You can’t explore on your own all the time; working from home and in cafes is isolating after a while and I enjoy the community here as much as the decor.

While I work, afternoon becomes evening and I sign off from our team chat servers. On a whim, I kick off another round of data analysis on the million song dataset for a side project, then close the iPad and drop it into my bag. Knowing the Linode will keep working away at it, uninterrupted, while I cycle home and enjoy dinner with my wife and children gives me a warm, fuzzy feeling - my tireless robotic assistant, working away out of sight.

Trouble in Paradise

And yet not everything is perfect. I love having my data on a remote server and I’m deeply happy with my indefatigable Linode. Surprisingly, the weak link in all of this has become the iPad. And not just because of what it by design can’t do, but because the internet is moving towards richer and richer web apps and Mobile Safari still feels like a toy browser. 

Using Google Docs has been a pain all year and it isn’t getting any better. 

Having used the fascinating LightTable on the desktop, writing Clojure without it feels like wading through treacle, but Mobile Safari doesn’t have what it takes. I’ve even looked at hacking the engine out of the source and integrating it with the console, for goodness’ sake.

Luckily, splitting my devices between the server and a client means that I am free to change devices whenever I wish. I can work just as well on the twisted remains of my Macbook, a 3-screen office desktop or anything else with a browser, a terminal and a VNC app. My switching costs approach zero. And switch I will.

You see, a surprising alternative has appeared: the Microsoft Surface.

Surface + Linode 512

For a while now I’ve been telling people that Microsoft will become the new cool, the inventive underdog, and I still believe that. Windows 8 may be a huge gamble for Microsoft, but Windows 8 RT is a clear win for me.

Microsoft understands the keyboard. I can start, switch and control apps without leaving the keyboard. The device even comes with one.

Sometimes it’s really nice to have two windows open, especially when using video output to a larger monitor. I think the Windows 8 side-dock idea will suit me very well.

Love or hate Internet Explorer 10, I have every expectation that we’ll see the real rendering engine on Windows RT. I don’t care what they call it, if I can run LightTable and Google Docs without gouging my eyes out, I’ll be happy.

Last but not least, the Metro vibe feels fresh and new and I’m intrigued by Microsoft’s choice to make Javascript + HTML5 a first-class way to develop for the system. I’m already looking forward to hacking my own tiles together to smooth my workflow and simplify my day.

Perhaps in a year’s time I’ll be switching to another client. It doesn’t matter, and that’s the beauty of this setup - its flexibility. For me, though, this coming year will be the year of the Surface.

The Experiment is Over

Last year I started this as an experiment, but it stopped being that a long time ago. Today the entire city is my office - its parks, its countryside, its cafes and its workspaces. I have worked on river islands, half-way up trees and on exclusive rooftop terraces.

My side projects are simpler, more flexible and more exciting now my development machine is connected to the internet by a big fat pipe, 24/7. Want to run statistics over 5 years of Gmail messages? Just do it! No need to worry about how long it takes or whether someone will reset the wireless router part way through. It’s simple. It’s pure.

Feeling free to set off into the unknown, assured that I will find a place I can work, to explore and enjoy my surroundings… no, this isn’t an experiment any more.

It’s liberating, rejuvenating. It’s a way of life.

I will not give it up.

Postscript: Intrigued and looking for more? Tempted to try it out one afternoon? I’ve decided to start a mailing list - I plan to write one or two emails a month about my experiences; the highs and lows of this desk-free lifestyle. I’ll also share more practical tips such as setting up a VPN or keeping in touch with the team. You can join the list here.

Breaking news: Today Allinea ordered me a high-end laptop with a massive SSD for doing CUDA development on. Stay tuned to see how the iPad+Linode combination stacks up against top-of-the-range hardware!

Update: Light Table reached its funding goal, and Chris promises to release the source as soon as is practical (see the comments) - everybody wins!

I love the principles behind Light Table, Chris Granger’s excellent IDE concept based on Bret Victor’s incredible vision. It’s up for funding on Kickstarter now, but it might not make it’s $200k goal:

Honestly? I’ll be happy if it doesn’t get funded.

So is it Light Table you don’t like, or is it personal?

Are you kidding? I love Light Table and I think the world will be a better place for it. I don’t know Chris, but I’ve read some of his code and have a deep respect for him and his work.

Why don’t you want it to get funded, then?

I’ll be happy if Light Table isn’t funded because Kickstarter feels like the wrong thing to do. Chris writes:

I haven’t thought about everything - and I won’t be able to… Light Table is meant to be a platform and it will be open source for that very reason… This is the power of a community full of builders… In the end, the only way to move us forward is for the community to rally behind something.

— Chris Granger, On Concepts and Realities

I couldn’t have said it better myself. To me, this makes the choice for how to proceed with the project crystal clear, but Chris seems to have chosen poorly. There are two options:

You can also get rich playing poker

Option 1: TEN MILLION DOLLARS!

As the concept video reached 80k hits and the blog post 200k, I’d have been thinking:

Wow, two hundred thousand hits, that’s like - if every one of those bought a licence for $50 then I’d have TEN MILLION DOLLARS and a dream job and would never have any worries ever again! Hooray!

— What I’d have thought, if I were in Chris Granger’s position

There’s nothing intrinsically wrong with this. Clearly there’s a need for a product like this, and if a (finished) version of Light Table for Python existed today I’d drop $100 on it without even blinking. Perhaps even $500 for C++. And I’d be happy to do so.

Chris has chosen this route - trying to build a profitable business - and to his credit he’s also chosen to open source the core of Light Table, albeit in May 2013 after its release. And you still have to pay for a license.

Which brings us to his mistake.

Start a fire

Option 2: Change the World

Instead of putting up a kickstarter page, Chris could have put his source on GitHub, written about the principles he hopes the IDE will enshrine and started accepting patches. It would have instantly become incredibly active; he’d have his work cut out reviewing and accepting pull requests, discussing UI design and principles and making his vision real.

Perhaps it would have been valuable enough to the community for him to go full-time, in which case he could have opened a kickstarter to fund himself as the leader of the open source project. Set a low goal (one month’s worth) and then see what the community wants to pay him to do. There are other options too, such as looking for corporate sponsors, or just doing what he can in his spare time and delegating the rest.

The end result is less certainty for Chris, but much more certainty for everybody else.

What’s Wrong with Option 1

Compare these two projects, for a moment:

  1. Nothing happens for a year while two to three people work together. People get to play with beta release and give suggestions, but every single line of code comes from that handful of minds. Most of the world has to wait for 12 months and then they get to buy a Clojure IDE. Yay.
  2. A veritable explosion of activity as everybody forks the project, tries to get it running for their own favourite language, adds the features they need to make it useful in their day-to-day life. From day one, whoever you are you can find a fork adding support for your language, the better of which are progressively pulled back into Chris’ main repository. Conservatively, hundreds of developers working together. What will this look like after 12 months? Will there be Python support? Ruby support? Java? Integration with other tools? Vim bindings? Emacs? Themes? Yes, yes, yes, and more.

Clearly option #2 is going to be better, both immediately and after 12 months. Trying to develop a community-style project like this with a small team and closed source is a ridiculous mismatch.

Living Costs Money

There are ways for Chris to get paid to work full-time on option #2, but they ask for a lot of trust - a leap of faith that a community will develop that’s willing to support him. It means taking the chance that the project won’t need him and that it will get along just fine without his full-time attention.

What about later on? Chris and team might get rich selling option #1 licenses for years to come; how can they do that if everything is free and open source with an active, vibrant community?

Here’s the choice reframed: either your time on the project is valuable enough for other people to give you money to do it, or it isn’t. You can open source the project and find out directly, or you can attempt to distort your value by creating a false scarcity, only licensing it to people who pay you.

I don’t know if I could make this leap of faith. It’s still the right thing to do.

Your Choice

If you love something, let it go

Do you really want to extract money from people to work on something the world doesn’t need you to? If not, what are you afraid of?

If you believe the world needs your ideas, if you want to spend some of the few years given to you bringing them to life, then do whatever you can to share them and make these concepts real. In this case, it’s clearly to open source Light Table and trust that the future will bring good things.

Don’t be afraid.

Believe.

Teamwork is a tricky business. I write software for a living and teamwork amongst programmers tends to be defined as splitting up the work such as to minimize the need for any actual teamwork or, indeed, communication of any sort for the remainder of the task.

As a direct result of this, there’s often a short, socially-charged moment in any meeting in which the ‘team’ work is divided up into my work and your work, aka your problem. I’m lead to believe this isn’t unique to programmers.

There are so many little games played here as we jockey for social position, each wanting to get an interesting or easy piece of the work and to avoid the awful, blatantly difficult and unpleasant part that nobody wants to do. Don’t let it be me, we pray.

Those with social clout in the group use it now to quickly snap up the high-prestige-yet-surprisingly-easy work. Occasionally someone without enough influence to snatch a safe piece of work for themselves will throw a victim to the wolves. Well, Jane has always been good at random-terrible-thing, haven’t you Jane, so I guess it makes sense if I do unglamorous-but-safe-task.

Poor Jane.

And like this, Jane - perhaps the youngest, newest, or simply least-liked - ends up doing the work nobody else wants to do:

  1. Legacy work. Cleaning up a mess somebody else made long ago that has been rotting away for years, becoming so bad that it can’t be ignored any longer and yet is extremely likely to devour the soul of anyone who disturbs it. 
  2. Ill-defined work. Nobody’s thought through exactly what’s going to be involved, but everybody says it should be straightforward because they’re sure that by the time it becomes clear it’s actually giant can of writhing, flesh-eating worms that it won’t be their problem any more.
  3. Restructuring work. Everyone agrees it needs to be done, but customers will never see it, management will never understand it and your colleagues will complain loudly if you get in the way of their work while doing it. Afterwards, everyone will say the old way was better. 

In other words, nobody wants to do work that’s difficult, risky and thankless. If there was a map of the landscape of work, this bit would be the vague, sketchy part marked simply with here be dragons, where the unfortunate are sent to their fate. I’ve played the don’t-get-burned game and even got rather good at it, which is easier when you realize some participants don’t even know that they’re playing, but that’s irrelevant right now.

You see, I don’t want you to play this game. Yes, you can wheedle your way into a position of some authority by building up your little corner, looking good to your superiors while betraying potential rivals with each step, always making sure someone else gets sent to the flames. And when you reach power, that’s the person you’ll be and the sort of people you’ll be working with.

There is another way. When deadlines are looming and the project is in trouble, people don’t turn to little empire-builders for help and leadership no matter how shiny they are. We don’t want someone to delegate away the dragons, we want a dragon-slayer. In tough times we follow a dragon-slayer because we know he won’t abandon us to our fate. We trust him because he’s proven his worth time after time while others tried to get away. And we love a dragon-slayer, because he makes it work instead of parceling out blame to the weak. A dragon-slayer has a freedom and authority that no amount of empire-building will ever match. That’s who I want you to be.

So when you find yourself in one of these nervous meetings where the work is being divided up, look for the part that everybody’s afraid of being given. You need to stand up and take that before anyone has a chance to react; take it and make it yours. Yes, it’ll be hard and risky and thankless, and sometimes you’ll get burned, but your colleagues will remember that if you hadn’t stood up it could have been them, and they will respect you when you stand up a second time, and a third, and a fourth.

Eventually, you’ll stop getting burned and start emerging victorious, because practice makes perfect and the experience you’re getting is the very best there is - always working on difficult, risky, problems instead of avoiding them and passing them off to the weak; those least equipped to deal with them. One day, you will begin to succeed and nothing will ever stop you again.

But that’s in the future and this is the here and now. Look around you and you’ll see what it is out there that nobody else dares to face. If you want to become a dragon-slayer then you’d better get started - and there’s only one way to do it.

You have to fight the dragon.

Last week I promised to share all the details about my cloud development setup - this is how I did it, in ten soul-crushing liberating steps:

Step 1: Get a Linode

I chose a Linode 512, which has been perfect for my needs. You get all phenomenal CPU power and an itty-bitty RAM. Surprisingly, this is enough as we’ll be doing most of our work on the command-line; you can always upgrade it later.

I also turned on the $5 a month backups. Zero-effort data safety for less than the price of a hot chocolate? Yes, please!

Step 2: Configure your Linode

Linode’s interfaces walks you through adding your new node. Pick a region close to yourself - you want to minimize the roundtrip time to the server. I spend most of my time in Munich, so I have mine in London and get a 30-40ms ping, which is great.

I also picked one of their default 32-bit distributions - if you’re not sure or don’t care then just choose the latest Ubuntu and you won’t go far wrong.

After a few minutes the machine will be installed and booted, ready for use! Time to log in and set things up!

Step 3: Build Vim

I found Ubuntu’s default vim didn’t have everything I wanted, but don’t worry! It’s easy to download and build it yourself:

install-vim

Step 4: Install lots of juicy plugins

I honestly can’t remember which plugins I installed and which ones I actually use. My currently-installed list is:

  1. acp.vim
  2. asynccommand.vim
  3. a.vim
  4. cctree.vim
  5. clang_complete.vim
  6. color_sample_pack.vim
  7. command-t.vim
  8. compview.vim
  9. cscope_maps.vim
  10. fuf.vim
  11. l9.vim
  12. NERD_tree.vim
  13. scratch.vim
  14. searchfold.vim
  15. taglist.vim
  16. tasklist.vim

You probably don’t want all of those; I wouldn’t be without command-t though. You can get them all from vim.org/scripts - you might want to install pathogen and get them that way; I just copied the existing .vim folder from my MacVim installation, hence all the cruft.

Note that command-t requires you to build a stub - follow the install instructions in command-t.vim and it just works.

To use the clang_complete plugin, you’ll need clang: “apt-get install clang” should do the trick. I had to play around with it a bit to get it working on my project, which included adding all the -I and -D command-line options to a .clang-complete file in the project directory.

Step 5: Create your .vimrc

Here’s my .vimrc - some of the things here relate to e.g. our internal tracker system and won’t be interesting for you, but it should be clear what most of these things do and which keys are bound to them:

.vimrc

Step 6: Configure GNU screen

I don’t recall where I got this from, but it works well for me:

.screenrc

You’ll also want to create a few aliases to connect to different screen sessions painlessly - my .bashrc contains:

.bashrc

You can probably change screen’s escape key in the .screenrc file too; I never bothered to look it up. Here, ‘s’ or ‘t’ will attach me to my work or personal sessions respectively.

Many people have recommended tmux - I haven’t tried it yet; screen hasn’t given me a reason to want anything else.

Step 7: Configure VNC

install-vnc

Feel free to pick a display that makes you happy but make sure it matches the DISPLAY=:5 line in your .bashrc!

Step 8: Get a super-sweet thin client

I chose an iPad2, (the 16Gb Wifi model). I haven’t tried working over (tethered) 3G yet, but ssh from my iPhone works well so perhaps that’s also an option if you’re often out of wireless contact.

If you already have a tablet that you like, use that instead - all you need is a good SSH client and a good VNC client. On the iPad I use iSSH and Jump for SSH and VNC respectively. I haven’t tried Prompt or Screens, if you already have them then let me know how well they work out.

Whatever you do, get an external keyboard. The Apple bluetooth one is amazing, I can thoroughly recommend it.

You’ll also want an adjustable stand / case for your tablet. Amazon offers plenty to choose from.

Step 9: Configure your thin client

The hardest part of setting up a SSH client on a tablet is getting your private SSH key on there without entrusting it to a third party. I split mine across multiple services and removed it after recombining it; maybe you don’t really care.

If you didn’t add the export TERM line into your .bashrc then remember to tell your SSH client to report its TERM type as “xterm-256color” - providing it supports this (iSSH does) then you’ll get to enjoy beautiful soft shades in your remote Vim sessions - joy!

To begin with I used iSSH’s VNC client, which worked perfectly well but was a pain to switch to quickly. Last week I started using Jump instead and love it, it’s a super-smooth experience with lots of cute little touches that make me smile. Swiping to it with the new iOS5 gestures is much easier than changing the view in iSSH and the next update will make it auto-reconnect after the 10 minute background timeout, making the whole experience seamless all the time.

I learned a lesson: take a bit of time and money and try out various different clients. You’ll be spending most of your working day in them; try to smooth out every aspect of the experience.

Step 10: Enjoy life in the cloud

There’ll be many other packages you want to install - Dropbox and Google AppEngine spring to mind - both can run in console-only modes.

If you’ve followed this far then you should have a fully-connected remote server and tablet client - welcome to the future!

Update: I’m still using this setup a year later - you can read on at iPad+Linode: 1 Year Later

On September 19th, I said goodbye to my trusty MacBook Pro and started developing exclusively on an iPad + Linode 512. This is the surprising story of a month spent working in the cloud.

It all started when I bought my first MacBook a couple of years ago. Frustrated by the inconsistent usage of ctrl/alt/option/arrow keys to jump words and screens and lines, I searched for a new IDE. Instead, I found Vim and fell in love. This isn’t another gushing post about Vim-oh-how-I-love-you-my-sweet-darling, but it’s important to the story - as we’ll see in a moment.

Although I like to use Python and GAE for my own projects, at work we write heavyweight C++/Qt code that runs on clusters such as the 200,000 processor Jaguar machine, so most of my time is spent in Linux and a lot of it on remote systems. Typically I’d develop in MacVim locally and run my code in VMWare Fusion or remotely.

One fateful day, VMWare and OS/X conspired to trash my shared filesystem, losing several days of uncommitted code in the process. I was angry.

While dd was recovering as much as it could, I started toying with the idea of giving up on local filesystems altogether. To my surprise, it seemed possible - even plausible.

I just had to try.

The Setup

It turns out you need a little more than just an iPad and a dream, but not too much more:

  1. iPad 2 (16Gb, WiFi)
  2. Apple wireless keyboard
  3. Stilgut adjustable angle stand/case
  4. iSSH
  5. Linode 512 running Ubuntu 11.04
  6. Apple VGA adapter

Total cost: around $800 + $20 per month

I Wandered Lonely as a Cloud

I typically start my day by catching up on the bug tracker chatter, mercurial diffs and other emails with the iPad in one hand while lying on the Combinat56 sofa.

I actually hate the Mail app for this; the stupid animation when archiving posts adds unnecessary delay and the archive button is uncomfortably placed at the top of the screen. More recently I’ve been scanning mails over IMAP with a python script instead.

Next, I lazily swipe to Safari and review my tickets for the day in our web-based bug tracker then return to the keyboard and fire off a couple of emails before settling back into coding - the new four-finger swipe gestures in iOS5 have really improved my life.

But we were talking about coding, which brings us back to Vim.

Vim: My Home from Home

Perhaps the only reason this transition has been so smooth was because my favourite editor / IDE looks and feels almost exactly the same running on an iSSH console as it did running locally on my Macbook. iSSH supports xterm-256color, which means you can still have pleasant colour schemes despite working in a terminal. All my plugins are there, my code-completion, quick navigation and so on.

In short, it’s a seamless transition from my MacVim envionment. If I were developing OS/X apps with Xcode, or used Eclipse or Visual Studio regularly this change would probably have killed me.

As it happens, working in the terminal on a remote Linode is even better than working locally, thanks to the magic of GNU screen.

GNU Screen is Magic

GNU screen is like a window manager for your terminal sessions, giving you multiple tabs, searchable history, activity/idle notifications and - best of all - persistence.

So I fire up iSSH, tap on my Linode connection and reconnect to the already running screen session. All my terminal tabs are exactly where I left them. Other SSH tunnels are still set up. My cursor is still in the same position. The clipboard is as I left it. It’s as if I never left, because for my side projects, I have a different screen session with a different set of tabs and editor instances running. Perfect separation.

It’s hard to overstate how pleasant it is to be able to return to exactly the same session each day; on a MacBook there’d usually be some other distracting programs left that I’d opened in the meantime, and of course any remote connections would have been dropped. At the very least I’d have used MacVim for something else in the evenings. It might be a largely psychological benefit, but it feels as if I can drop back into flow almost as easily as I left it.

The Good, the Bad and VNC

At work we develop a graphical parallel debugger, so I can’t spend all my time in the terminal. For hands-on tests and GUI work I need X. Luckily, iSSH has a workable, if not perfect, solution:

I tap on the VNC connection and up pops the GUI in shocking 1024x768 fidelity and a painful 256-colour palette. I could have 24bit colour, but somehow I prefer the extra speed to beauty. Although it’s a far cry from using a mouse to interact with a traditional GUI program, the on-screen ‘touchpad’ works better than I’d expect. And as it happens, being limited isn’t all that bad:

One good way to evaluate the usability of a program or dialog is to… try to use the mouse with just one finger.

Joel Spolsky

iSSH’s VNC isn’t quite as bad as pushing the mouse around with one finger, but it does make you consider users with lower screen resolutions, larger font sizes and mouse control that hasn’t been honed by countless years playing Quake and Starcraft. I’d be lying if I said I hadn’t wished for bluetooth mouse support some days.

Maybe It’s a Lifestyle

Today is not one of those days. I unwrap a chocolate croissant, make a fresh cup of tea and settle down to work; a quick hg pull -u && make to start the recompile, then ctrl-x to my editor tab and carry on coding while the rebuild happens. Ctrl-X is my screen’s ‘hotkey’; it defaults to Ctrl-A but on a wireless keyboard that leaves unicode characters in the terminal - I assume this is related to Apple’s support for some common Emacs key bindings in iOS. Strange, but easy enough to work around.

After a few minutes of coding the bar at the bottom of the screen notifies me that my compile has finished; I ctrl-x back, start a sanity test suite running just to be sure nothing horrible was broken overnight then carry on coding again. Compiling on the quad-processor Linode is around twice as fast as inside VMWare on my MacBook was. It’s also completely, blissfully silent. The only sound is the raindrop-like patter of the keyboard as I work. It doesn’t even get warm, a surprisingly refreshing change from the MacBook keyboard!

I swipe to the DuckDuckGo app and look something up in the Qt APIs, then swipe back. It’s becoming second nature, but I still miss a keyboard shortcut for task switching.

After an hour or two of uninterrupted development the UK team wake up and the first instant messages arrive. Thank heaven for the iOS 5 update! I use the imo messenger app, which is fine but of course before the notification center each pushed message would interrupt whatever I was doing with a frustrating popup. Now, the new notifications center behaves much more like a growl notification would; it lets me know and it gets back out of the way again.

I finish the function I was working on then four-finger swipe to the chat app; it’s my boss reminding me about our 11am conference call.

Skype-based conference calls work fine on both the iPad and the iPhone; at least, as well as VOIP calls ever work, i.e. fine after a few false starts while someone reconfigures their linux audio drivers. I appreciate not to having to think about that any more.

During the Skype call my iSSH session timed out in the background; it’s only held for 10 minutes or so. Fortunately a single tap reconnects me, and through the magic of gnu screen I’m back at exactly the place I left off again.

As is always the case, while fixing one bug I encounter another, apparently unrelated one. Time to submit a quick bug report - in the past I took screenshots on the iPad and emailed them to our tracking system, to get around not being able to attach in Safari. Now, I’ve switched to grabbing them and any log files or stack traces with a command-line app on the Linode itself. We use the Best Practical RT tracker (for our sins), which conveniently comes with a perl script to interact with it from the command line. Doing this is actually quicker and easier than uploading via a browser used to be; one command noting the ticket number and the attachments and I’m done.

The Cloud is Always With You

Lunchtime already! I close the iPad and head off with the others. The remote rebuild I left going will still be there; no need to worry about any uploads getting interrupted, it’s all happening in on the Linode, after all.

During lunch I pull out my iPhone and connect to the Linode again; damn, the build failed early on - out of disk space on one of our office machines. The iPhone keyboard is somewhat painful to use, but for rm -rf /tmp/build-2011-* it suffices. I kick off a new build while waiting for dessert to arrive.

Now I’m feeling nicely fed and just a little dozy; to keep awake I move to a standing workstation and set off some longer-running performance tests on a remote cluster. I find I move around between a lot of different working configurations with the iPad; much more frequently than I when using a laptop. I’m not sure why; perhaps it’s something about having a separate keyboard and screen that makes it easier to find a comfortable typing position, or perhaps it’s just the novelty.

The tests will take an hour or so; I close iSSH and review the latest spec / schedule changes my colleagues have made to an upcoming spec, stored in Google Docs.

Oh, Google Docs, why do you hate me so?

In a bitterly ironic twist, the only part of working in the cloud that doesn’t work smoothly is using Google’s cloud-based MS Office replacement. The mobile word processor is a joke, frequently losing the cursor position and sizeable chunks of text. The spreadsheet version is better, but is still a pathetic experience compared to the desktop version. Of course there are no native apps, and the desktop versions of the sites simply report script errors. I’ve even thought of trying to convince my team to switch back to OpenOffice.

Maybe it works better on an Android - no, wait, that’d be anti-competitive behavior and Google would never do something evil, right?

The tests have finally finished and the results are in; I move to the lounge area and connect up to the big HD TV with the VGA cable; something about seeing console-mode VIM in giant HD makes me smile every time.

There are some oddities in the logs; I copy and paste a few snippets to a colleague and discuss them in chat. I’m glad copy and paste work smoothly, although having 3 different sets of buffers (iPad, screen, vim) does lead to confusion from time to time. Idly, I wonder if any of my colleagues have noticed I’ve been using an iPad instead of a laptop for the last month.

6pm rolls around and it’s time to head home for the day. Despite a full day’s intensive use, my iPad’s still showing 15% battery life. I never bring a charger to work and I’ve never needed one. That in itself is a taste of freedom.

At the End of the Day…

Later that evening I pull the iPad out and open up Pages to finish a blog post. The house is quiet; only the distant sounds of the city drift in from outside and mingle with the gentle patter of keypresses on this delightful wireless keyboard.

I started this experiment because I fundamentally believe that most people don’t want to rearrange windows, babysit their own general purpose computers or back up their data. Sooner or later, almost everyone will work like this and I wanted a taste of what that might feel like. I expected to find something that didn’t work, but as the days turned into weeks and the weeks gathered into a month, I found I hadn’t returned to my laptop even once.

I don’t miss the weight. I don’t miss the keyboard getting warm when I’m compiling. I don’t miss its fragility, both physically and virtually. I don’t miss running out of power. To my surprise, I find I am happy. Coding in the cloud isn’t for everybody, but for my workflow it’s a perfect fit and I love it.

After a few minutes the perfect peace is rudely disturbed by the twin jet-engine that is my MacBook fans spinning up to full power on the shelf behind me. I can’t believe I used to put up with this all day and night. 

Despite that, I leave the MacBook running - it’s doing the only thing I still need it for on a regular basis.

It’s ripping DVDs.

Update: I’m still using this setup a year later - you can read on at iPad+Linode: 1 Year Later

Recently I started optimizing my workflow with various scripts and tools. I measured my performance and found it increased a lot.

Some people asked to see stats behind the story so here they are, calculated retrospectively from log files for 5 months before the change and 5 months after it.

4x more productive overnight

I’ve been tracking 3 easy-to-measure metrics:

  1. Bugs fixed
  2. Change sets committed
  3. Number of functions changed

For your viewing pleasure and mine, I’ve tweaked my script to render graphs with the GChartWrapper python module:

Bugs fixed

I started trying to improve my own performance sometime in mid-January; unfortunately I didn’t keep track of the exact date.

The data are scaled to show bugs fixed per man-month rather than calendar month; from February onward I’ve been in parental leave (Germany’s extremely generous Elternzeit to be precise) and have been working exactly half-time at 18 hours a week.

As a rough measure, let’s compare my performance in Aug-Dec to that in Jan-May, ignoring the fact that I started this scheme mid-way through January and not at the start of the month.

Performance boost: 55.4 / 9.4 = 5.9 times more productive

Changesets committed

A changeset can be anything from a bug that was too minor to both putting through the bug-tracking system (such as a message box typo) or a little tweak or extra feature added in passing. Static analysis tends to throw up lots of small fixes that I address with direct commits, for example.

Performance boost: 100.4 / 28.0 = 3.6 times more productive

I started tracking functions changed just out of curiosity; the numbers of tickets fixed and changes committed are open to various levels of manipulation - I thought the total number of functions touched by a change would be an interesting check to make sure I wasn’t just solving all the easiest tickets or committing lots of tiny, pointless changes.

Performance boost: 344.8 / 85.6 = 4.03 times more productive

Hey, is that awesome?

Nothing about the above measurements or calculations is perfect; simply ignoring December artificially depresses the performance boost, as does treating all of January as the post-boost phase. On the other hand it seems incredibly unlikely that working half-time is exactly half as productive as working full-time.

We could argue that the email and communications burden remains the same when working part-time, so we’d expect less the time to be available for productive efforts. Or on the other hand that most of a full working day is wasted anyway.

We could argue a lot of things, but none of these concerns can account for a 400% increase in productivity.

Not only that, but the number of bugs fixes (5.9 times increase) - is a metric of real value to our company. Generally our software director chooses the set of bugs to be fixed for each release and gives them priorities, which means all those bugs had to be fixed and I wasn’t at liberty to pick all the easy ones.

I do like fixing the easy ones, though.

Whether my measured productivity has doubled or increased ten-fold is really neither here nor there; even just doubling your productivity by any set of measurements over a sustained period of five months is incredible.

I’ve also been a lot happier, which is like winning twice.

Wait! There are 3 reasons not to do this!

"I changed my editor bindings, and now I’m a super-hero coding monster. Also, my breath cures cancer. Hooray for Command-T!"

I’m tired of posts like this too.

I want to make something clear: there are really good reasons that you can’t write a commit script, track your performance and expect it to quadruple. There are good reasons not to even try:

Reason #1: I was intrinsically motivated; that’s why it worked

In psychology and the study of education it’s well-known that intrinsic motivation is everything in learning and self-improvement. I already yearned to improve my own effectiveness, that’s why I started doing this. It fascinates me, it calls to me. That’s why it worked.

If you already long deeply to improve yourself, you will do with or without my advice. If you don’t, then drawing little graphs won’t help either. There’s no reason to believe that blindly going through the same motions I did will produce the same result for anyone else.

Your motivations can and do change over time though and maybe reading this will help to motivate you too - I hope so!

Reason #2: never replace intrinsic with extrinsic motivation

It turns out that offering employees bonuses or performance-related pay can be harmful. In some cases - such as programming - an external motivation, such as a bonus, produces measurably worse performance than an internal motivation, such as the love of coding.

Worse still, such an extrinsic motivation will often replace an intrinsic one, damaging performance and job satisfaction.

If you start measuring your performance, you may end up replacing your intrinsic motivation to do a great job with an extrinsic one to make the numbers go higher.

If you start measuring other people’s performance, you certainly will.

Be very, very careful.

Reason #3: these stats don’t measure programming excellence

So, should I ask for a 400% pay rise now? Am I four times as valuable to the company than I was last year?

No and no. I like to think I’m somewhat more valuable to the company now, but not by a factor of two, let alone four! You see. these stats don’t encompass everything a programmer has to do to produce awesome software; they don’t actually try to - they have another purpose.

It’s like running and football: professional players care about how fast they can run 50m. They even practice sprinting during training. It has some value to them. Yet if you ranked all professional football players by how quickly they can run 50m, you wouldn’t find all the top players at the top.

How would a football team composed entirely of olympic sprinters fare? Exactly. Running fast is one tiny part of playing football. Resolving bugs efficiently is one tiny part of writing excellent software.

Stats such as these are useful for your own training, for measuring and improving one specific aspect of your competence but they are worthless other purposes. Don’t use them for:

  1. Comparing developers to each other
  2. Measuring or motivating a team
  3. Hiring new people

It should be clear that single-figure statistics are useless for these goals, but people love graphs and they love putting numbers on things so I’ll state this as clearly as I can:

It doesn’t matter how many bugs you fix per month if your code sucks and the UI looks like a Fukushima control panel after the explosion.

The bottom line is that you can use these stats to measure your own performance increases, but once your goal becomes to increase the stats, you’ve already lost.

Good luck!

Postscript: If you’re interested in seeing my sorry collection of hacked-together python and bash scripts, leave a comment to that effect and I’ll put together a “Metagame: Nasty Hack-Filled Scripts” post for you with all the sources. I’m happy to talk about this on twitter, too.

Edit: Here’s a link to the HN discussion and the Reddit thread for this post.

I’ve been bored at work for many reasons at many different times, but three things stand out as real killers:

  1. working on the same project with the same people[1] for years and years,
  2. using the same old languages and tools (statically-typed: yuk!) instead of the new hotness,
  3. being forced to work on maintenance instead of new features, or on small parts of an existing product instead of creating something new.

These are the symptoms of a problem, not the cause, and I think most jobs will have elements of them. But surprisingly it turns out that - for programmers at least - boredom is a choice. Recently, I chose not to be bored. I chose to think one abstraction level higher. I chose to play the metagame.

Awesome copper comic

Me: a case study

I started thinking about programmer performance a while ago. Everybody will tell you that you can’t measure programmer productivity, but this is at best a half-truth. We can, and we should. Perhaps what we shouldn’t do is use those measurements to compare programmers to each other, but we can definitely measure ourselves.

When I started trying to measure my own productivity, it g

ot me thinking a lot more about:

  1. my workflow - I check email, pick a tracker ticket and work on it.
  2. the most repetitive parts of my work - why does it take 10 clicks and 3 windows to commit a change?
  3. the core of my job - I’m paid to solve non-trivial problems, not to sort email and adjust ticket priorities.

It really doesn’t matter what anyone’s day job is; whether you’re working on sporting result clips for Google mobile or maintaining a 20-year old internal accountancy package the metagame is the same. The product may be pointless but the metagame matters to us all. It’s about:

  1. surrounding ourselves with tools and systems that make us more than human, a cyborg-like super-programmer - who doesn’t want that?
  2. automating away the boring parts of work, so that we’re left with the interesting, non-trivial decisions and problems.

When I started I was working on bugfixing before a major release, which is very amenable to this sort of thing because there are lots of small, well-defined packets of work. We were about 9 weeks from release and my typical day looked like this:

  1. Check and respond to my emails
  2. Check the test machines and fix any system or build failures
  3. Take a high-priority bug from our tracking system
  4. Try to reproduce it locally
  5. Track down the cause and write a fix
  6. Commit the fix, update the ChangeLog, resolve the ticket
  7. Repeat from step 3

It was quite easy to measure my own performance in terms of the number of bugs resolved per week. Sure, it’s not a perfect measurement - I could also have factored in the priority of the bugs and so on, but getting an accurate figure wasn’t nearly as important as getting some measure, however rough.

With the goal of increasing my rate of bug fixes motivating me, I started laying into my workflow and adding automation wherever I found an opportunity to speed things up:

1. Don’t waste clicks navigating email

Email checking was clearly not related to my core metric (bugs fixed) but I couldn’t just ignore emails, however much I wanted like to. Instead, I added a bunch of extra filters to brutally cull all the emails I didn’t really need to read, then found out how to get keyboard shortcuts working in Gmail (hint: add &kbd=1 to the URL). Now I was whipping through the emails by pressing [ to read-and-archive for 95% of them, occasionally opening extra tabs to remind me of various actions I needed to take later in the day.

2. Don’t type ChangeLog entries by hand

Next up was the ChangeLog. I don’t know if you keep a ChangeLog at work, but we have done for a while. The idea is that with each commit you log the broad reason for the change, then write a one-liner for each function you’ve changed, along with the filename, class and method. Writing these by hand was incredibly tedious. Rather than dump it altogether (for it had its uses) I invested a few hours in writing a 147-line python script that generated the entry stubs automatically with inline diffs for each function changed. I added a handful of vim bindings to jump between the ChangeLog entries and replace each diff with a one-line description of it’s purpose. Suddenly, writing ChangeLogs was ten times faster even somewhat fun.

3. Yes, I said Vim

It’s no coincidence that I started using MacVim shortly before my metagame trip. Vim is awesome for exactly one reason:

  1. A vim script is exactly the same as the keypresses you use when editing

Writing a script in vim is a simply matter of typing the same characters you normally would to achieve that effect (which is why using hjkl for movement isn’t as stupid as you thought it was). I cannot imagine a lower barrier to customizing your editor. The end result is that vim makes it trivial to optimize all sorts of little common operations; it’s the first editor whose macro functionality I’ve used on a daily basis. It’ll change your life. Learn it. Love it. It’s worth it.

4. Make reproducing bugs trivial

My previous attempt to make my job more interesting had been to volunteer to rewrite our clunky, frustrating GUI-click based test system with a new, streamlined one. Since we use Qt, I added a QScriptEngine which essentially lets you write a small C++ API for your application and then call that from javascript files.

This was a lot faster and less error-prone than manually baby-sitting fragile GUI-based testing as we’d done before, but the real benefit was that I had complete control over the system. Every night it ran tests across dozens of platforms and reported any new failures directly to our tracking system. I started adding extra code to our test-runner (a 1,500 line python script) to make reproducing and fixing bugs stupidly easy. Each test report now includes:

  1. the stack trace and variables for any segfaults
  2. the core files for any segfaults in external programs during the run
  3. all log files, stdout and stderr
  4. screenshots of the GUI should a test timeout
  5. a one-line, copy-and-paste command to re-run the test

Adding this one piece at a time wasn’t a lot of work, but it has saved us hours and hours and hours.

5. Add ssh and bash shortcuts

I spend a lot of time on our test machines, so I added hostname auto-complete to my bash shell, added single-line aliases to change to the test directory, check out an overnight build, view the build and test logs, change to the test user and so on. I learned to love .ssh/config, and so should you.

Saving a few keypresses doesn’t sound like a big deal, but it makes me happy every day when I type:

cs
smoketest -kri 14956

to switch to the latest test directory, update its license file and re-run the bug reported in ticket 14956. I could write an essay just on this:

every single element of cognitive burden removed makes it easier to stay focused on the task in hand

Not having to remember a hostname, or a compiler directory, or keep track of which system I’m on, streamlining all that away makes it trivial to keep thinking about the problem and not the distractions.

Vim!

6. You can’t have too much Vim

I ended up adding lots of vim shortcuts specific to our systems. It’ll look up and fill in the title of any bug ticket for me. It’ll commit my current changes, automatically taking the ChangeLog entry I just wrote as the commit message and optionally resolve the bug ticket associated with that change using the same message. In one command.

Typing that one feels really good.

Bundling up all the points at which I’d otherwise have to switch to a browser, wait for a page to load, this was accidental but brilliant. Waiting is the death of focus. By wrapping it all together into one fire-and-forget command, I can just say the word and then start choosing the next bug to fix, keeping my momentum and focus intact.

I’m not done

Every week I find new places to tweak my setup or semi-automate more tasks. I’ve started producing beautifully-formatted HTML change diffs for code review on my iPhone, while reclining in one of Combinat56’s Sumo bags with a cup of tea. I’ve added extra notifications when a build fails or a test machine runs out of disk space.

I will never be done, because I can always keep moving one abstraction higher until I’m purely working on the most interesting problem of all: how much of a programmer’s job can be automated?

A nice side-benefit is that much of the code I write to automate things is not production code; I can write it however I like, using whichever languages and tools take my fancy. Yet it all goes towards making me - one day - into an extraordinary programmer.

Playing the metagame: advice

After working like this for six months or so, the following pieces of advice seem like the most important to remember:

  1. Don’t be afraid. Spend time improving your efficiency instead of hacking away with a blunt axe. There can be a lot of pressure “just to finish this first”. Resist it. Take just one hour and use it to write a script to help you in some simple way, or improve your bash aliases, or your ssh config, or your mail filters. Once you’ve seen how much impact it makes, you’ll feel a lot better about doing it again.
  2. Semi-automation is better than full-automation. It’s easy to get carried away and try to write your own email client, or use bayesian filtering to answer all your emails. Don’t bother. Write the simplest, smallest thing you can to speed you up and then get back to work. If it helps, you’ll find yourself building on it naturally over time. It’s better to have one-key read-and-archive than a custom email client for your iPhone.
  3. Keep scripts specific. Don’t try to over-generalize them and solve everybody’s problem; that’s not going to be practical on the side. Make your scripts specific to you and your workflow. If they’re great, you can extend them to the team. If they love it, you can extend it to the world and put it on GitHub. But do it in that order.
  4. Use vim. It feels weird at first. It takes a couple of days to get used to. Set it up with nice plugins and themes right away; after a couple of weeks you’ll never look back.
  5. Optimize the things you hate, not the things you love. The goal is to build up scripts, commands and systems that feed you a flow of meaningful decisions to make and interesting problems to solve, while automating away the dross. Resist the temptation to start by optimizing programming or code-writing; attack all the distractions first.
  6. Never let yourself wait for something. If you catch yourself typing a command then waiting for it to finish before you can type the next one, then that’s an ideal place for a script. Waiting will kill you; make the computer wait for you. For some tasks, like compiling, write scripts that’ll automatically launch the program when compiling finishes, perhaps even re-running the test case if possible. Make your computer notify you when it’s ready, audibly or by throwing something up on the screen. In the meantime, you can be reviewing code or looking for a second bug to start work on, or taking a walk with a cup of tea. Anything but HN and Reddit!
  7. Write in all the fun languages you can’t use at work. I can’t recommend python enough for this sort of thing, as it’s huge supply of libraries combined with pleasant syntax make life a breeze. I guess Perl would be great too. But get used calling external programs and input / output streams and you can write in Node.js or whatever interests you most this week.
  8. Measure your performance. Write a simple script to measure the number of commits you’ve made. Or the number of lines you’ve changed. Or the number of bugs you’ve fixed. Or the number of customers you’ve helped. Just pick something that’s trivial to measure even if it’s far from perfect, and start. Add more things whenever you’re afraid you’re over-optimizing or gaming the measurements you’ve got so far. Seeing your own performance climb gives a real sense of satisfaction that might be otherwise missing in your daily work. Even if you don’t enjoy or value the internal actuarial calculator you’re writing, you should care deeply about making yourself a better programmer - this will stay with you your entire career.

That’s it - print this list out, stick it next to your monitor then close the browser and start playing the metagame! You weren’t going to do anything more productive in the next hour anyway, right? ;-)

Update: just in case you’re not heading off to work, the HN thread is here and the Reddit thread is here.

[1] Disclaimer: I work with absolutely first rate programmers, people I learn from every day and yet there’s still an attraction to meeting new people too; I shudder to think what it must be like to work with dull people for years and years…

While visiting BuddyCloud Towers over the Christmas break I finally sat down and started something I’ve wanted for a while: up-to-the-minute notifications when one of my posts is submitted to Hacker News:

Timing is everything: the HN newest page is a cruel and capricious master; there are lots of posts being submitted and not a lot to distinguish between them. If you take the time to respond to comments early and add your vote to that of the original submitter, it gives your post a much better chance to be read.

The window before dropping off the all-important new submissions page? 30-60 minutes, give or take. Google Alerts might as well be sent by snail mail.

Other times, an old post is resubmitted (as RiderOfGiraffes was recently kind enough to do for one of mine). When that happened, I wanted to reopen a closed poll, update some old links and join in the discussion. Luckily Mat emailed me when it hit the front page but I could just have easily missed it altogether.

So I hacked together http://youreonthenews.appspot.com/ to solve the problem. It’s a simple two-page app on a GAE stack that does just what it says - emails you when a post from your domain is submitted to Hacker News.

Give it a go and let me know what you think, what you’d like to see and what doesn’t work!

A fortnight ago I wrote 10 Embarrassing Flaws That Made My ‘Weekend’ App Possible, which was about my two-week project to recommend new board games. As it turns out, that post was picked up by Reddit and HN a couple of days later in a big way, bringing in over 50,000 hits in a matter of hours. This is what that looks like:

At peak around 4,000 hits per hour were coming in, or just over 1 per second. The effect was pretty noticeable on twitter and in my inbox, too:

About an hour into this it suddenly struck me that this would be a very good time to add the Amazon affiliate links to findanewgame that I’d been meaning to. I was in a rush, so I just added a link to the search page, something like this. I wanted to link directly to the products but hadn’t got around to implementing the ItemSearch API yet. I didn’t have time! The site was getting traffic:

Maybe 12% of the blog readers checked out the findanewgame site and some of them bought games! It was working - I’d helped people find cool new board games! By the way, if you’re one of them then I hope you’re having fun with it - I’d love to hear how it’s going.

Fourteen Days Later

Traffic from HN and Reddit doesn’t really stick around - life returned to normal pretty quickly:

The findanewgame site itself was actually submitted to reddit on its own a few days ago (which I completely missed); here’s what its traffic looks like now:

Strangely, most of the traffic to the game site is ‘direct’, which can mean almost anything in analytics. Privacy-aware browsers, links sent thorough offline email programs, who knows? Not Google, that’s for sure:

So 100 Facebook likes drives less than 100 visits? Wow. Is that normal? I don’t know. Maybe I should care, but there’s something more pressing on my mind at the moment: I broke something.

I Should Have Used A/B Testing

You see, the Saturday after the post went big I made some more time to work on the site. Top of my list was sorting out the Amazon links, which I did. Now most games link directly to the product page - saving my visitors an extra click. Great! Great? Well, here are the Amazon stats. Can you tell when I made the change?

Yeah. That’s a lot of 0.00%, huh? Actually I deployed the change on the 23rd, which enjoyed a bumper 4,48% conversion rate. I thought this was fantastic, until the next day. And the next. And every day since.

What happened? I’ve no idea. People are still coming through to Amazon, so the links can’t be broken. They seem to be linking to the right products. For some reason, though, nobody’s ordering games now. Even with a 1% conversion rate I’d expect to have seen 2-3 orders since then.

If I’d been A/B testing every deployment, I’d know whether this was something I’d done or not. I actually can’t imagine why every deployment isn’t rolled out via an A/B testing process. Does anyone know of a really slick way to integrate this with the AppEngine workflow?

Choose Your Own Adventure

Where should I go from here? There are several options:

Roll back the Amazon link changes - maybe people will start placing orders again; it’s a quick change to make, but it’ll take a while to see if it has any effect.

Add A/B testing to my workflow - I’d love to push every deployment into an automatic A/B trial and then later decide which versions to keep and which to rework. Do you know of anything like this for AppEngine?

Post recommendation links to forums - I don’t know anything about marketing, but the stickiest traffic I get seems to be from forums. I’ve recently added short urls; I can spend a few hours visiting board game forums, reading the recommendation posts and using findanewgame to offer suggestions.

Make it easy to create and share lists - this has always been a goal, because sharing things we like is fun and because Christmas is coming up. At the moment you build up a list of games you want to play; I could make this easier, then let you email yourself or someone else the list, share it on facebook or whatever. Perhaps this option could also be called ‘market the site socially’.

This adventure is fun to do and even more fun to share, so which two tasks are should I do next? Vote below - I’ll do whatever wins and write about it again in a couple of weeks!

Browser not showing the poll inline? Try http://polldaddy.com/poll/4033559

Update: Hacker News discussion