Julio Merino recently described his coding workflow and invited others to describe theirs. My previous workplace development environment looked a whole lot like Julio’s, but my current one necessarily looks pretty different. Having needed to revisit some of the reasons for my preferences, I can more readily distinguish my current nice-to-haves from my can’t-do-withouts.

Development environments

When? Then Now
Team Remote Local
Role Developer, etc. Coach
OS Unix Windows
Build Radiator Standalone VM with a custom cron job IBM uBuild
Backlog Markdown files in Git Rally
Source Control Git AccuRev
Architecture CLI/GUI client/server web services
Language Perl Java
Editor vim IBM Rational Software Architect (Eclipse-derived)
Pairing tmux same desk

I had been an nvi fuddy-duddy until my teammates finally prevailed on me with their fancy colors and configs. Thanks, guys.

Mere strong preferences

I grew up as a computer user on classic Mac OS and NetBSD. When Mac OS X Server 1.0 came out, all clunky and expensive, I bought it just to have it; when the Mac OS X Public Beta came out, I knew my worlds would usefully merge, and I could look forward to not having two computers on my desk. As a developer, when I don’t have these at hand, I sometimes fumble to compensate:

pkgsrc (”package source”) gives me an easy way to install most any other tools I might need on any Unix variant with any level of system access. I gave a lightning talk about it at CodeMash 2013.

On my own time, I choose a Unix-centered environment whenever possible, to which the two open-source projects I spend the most time with (pkgsrc and ikiwiki) happen to lend themselves very well. I’m sure there’s cause and effect in both directions.

When I’m stuck on Windows, where I don’t feel as comfortable or productive, I usually wind up arranging for a Unix environment, and using it from time to time to keep myself from getting sidetracked too often figuring out how to do some small thing.

When I’m stuck with a weird revision control system, I often use Git in parallel. The administrative overhead of syncing with the source control system of record is more than paid for by the speed and clarity of diffs, which I check quite often as I go along.


When I’m programming, I’m more attuned than usual to bottlenecks in the flow of my work, because I’m more accustomed than usual to having the agency and the means to ease them. I’ve learned that while not having Unix tools is often a bottleneck, it’s not always so, and I can wait until I’m having that problem to do something about it.

In software development, there’s a problem I always have: I make lots of decisions, some of them are bad, and I need to know about those ASAP. So I don’t wait until of-course-I’m-having-that-problem-again to do something about it. Unless the code’s getting thrown away in a few minutes, I always start by arranging for a fast red/green feedback loop.

It doesn’t have to display actual red and green, or use an established testing framework, or finish before I can blink. It does have to start with a keystroke, finish with a clear indicator, and return me to my context. These affordances ensure that I’ll reliably make at least one decision well: whether to run the tests. Because I’m sure I will, it’s worth the marginal effort to add more tests as I go. And because I’m sure those tests are the fastest way to catch my mistakes, it’s worth the marginal effort to start with tests and use them to drive my design decisions.

It’s not about tools

I don’t worry about optimizing test speed until I’m adding tests often and running them often and the run is starting to feel slower. I don’t want to solve it before it’s a problem (it might never be), or after it’s a hard problem (I don’t care for those).

It’s about flow, both kinds — my state of mind and my delivery of outcomes — because they’re tightly linked. If I let problems grow large, they’ll impede my flow later, so I avoid knowingly creating future hard-to-ease bottlenecks. If I let myself be bothered by problems that aren’t yet impeding me, they’ll impede my flow now, so I avoid any further worrying about future bottlenecks.

My coding workflow is continually being optimized for speed and predictability. I look for the present bottleneck, work to ease it, and repeat. Every time I pay for smooth, my investments yield strong returns.