Almost seven years ago, I was honored to give a keynote at RailsConf. I knew this would be my only shot, so I picked a sufficiently broad topic: how to program computers.
The conceit of the talk was that I had cooked up a personality quiz that would tell you what kind of programmer you are. As a wink to its being playfully unscientific, I called it the Searls-Briggs Type Indicator®. At the end of the talk I shared a Google Form that emailed you your result (my type was, naturally,
Well, I never took the form down and people never stopped taking the quiz. Every few days for the last half decade, I’ve looked at my Sent mail to see that another handful of developers had been categorized as
FINE. I was impressed and confused when someone stopped me at RailsConf earlier this year to tell me he makes every new hire take “your salt test.” Even though I jokingly refer to quizzes like these things as workplace horoscopes, I have witnessed firsthand how assessments like this can serve as excellent conversation starters. They provide a way to discuss what makes each of us unique and to better consider one another’s differences. (Internally at Test Double, Personalysis has proven tremendously valuable.)
The other takeaway here is that people just love quizzes like this, even when you tell them it’s all bullshit! These were the only instructions that accompanied the form:
Rather than draw on decades of occupational psychology research, this test calculates your developer type in classic software industry fashion: by assuming there’s nothing that can’t be improved by a programmer hacking something together over a weekend.
Of course, another industry tradition is not reading the manual, so I guess it shouldn’t surprise me this didn’t scare many people off.
DEADLINE_EXCEEDED errors whenever the form is submitted. So I guess it’s finally time to take this thing down.
For posterity, I decided to export the responses for each question in the quiz. Because nearly 7,000 developers filled out the form before I closed it, it’s—if nothing else—an interesting look at the world as a lot of folks in the broader Test Double-inflected Ruby on Rails world see it.
Below, I’ll take a moment to reflect on each of these questions and what our answers might tell us about ourselves and the particular era of software development we exist in.
Also, worth pointing out: each chart below is on a 1-to-5 Leikart Scale, where 1 means “Strongly Disagree” and 5 means “Strongly Agree”.
Having been on a team where obvious solutions were routinely ignored in favor of clever code, I’m heartened to see that “boring” is hardly a four-letter word around these parts.
It is true that too much repetition is usually a sign that something can be abstracted away. And I do wish others copy-pasted code a little less and spun abstractions out into open source libraries a little more. But the simple truth is that while every complete software system is unique, almost every individual feature has been done countless times before. No need to reinvent the wheel.
Speaking of Personalysis, when we had the entire population of consultants at Test Double take the assessment in 2020, we quickly learned that we’re heavily dominant in the dimension it describes as needing to know why we’re doing what we’re doing. And it’s not just us, most developers bristle at being told what to do without sufficient context, but will utterly immerse themselves in their work once the purpose is clear. As a result, it’s no wonder that most respondents would rather know the full plan up front, even if it can feel overwhelming.
In general, programmers tend to place a high premium on preserving their autonomy. At Test Double, we often say “trust the people closest to the work to decide how it should be done.” When consulting with new managers, I advise them to emphasize the “what” and “why” of each problem to solve, but leave room for whoever will be doing the work to identify and own the “how” of each solution. People who feel ownership over how they work are generally happier and get more done.
That being said, when you’re in a team setting, the implementation is a shared resource. Setting baseline expectations so that everyone can be productive and share that sense of ownership often requires finding consensus with others, which requires compromise.
Back in 2017 when I performed this talk, I had already been toying with the idea of reducing the cost of code style consensus on Ruby teams, and in late 2018 released Standard Ruby to encourage more productive uses for teams’ social capital than arguing over how to align variables and whether to use trailing commas. Adopting Standard Ruby limits one’s expressive freedom in some ways, but in the context of a larger team, it frees up enough mental energy to focus on bigger issues to be worth the trade-off in autonomy.
I was surprised by this one. I spent the first ten years of my career hopelessly afflicted with blank page syndrome. Why ten years? Because it took me about that long to reach the level of competence where I felt comfortable writing code without an existing reference point or pattern to follow. How did I overcome it? I made a point to intentionally practice writing new things—scripts, gems, and apps—from scratch.
I imagine that respondents who feel more gripped with fear from a blank editor are also likely to have less experience overall and less experience specifically with starting new things. Many people who read this post will have spent years working in large Rails applications without ever having run
rails new themselves—and while there’s no shame in that, there is considerable value in being comfortable spinning new things out of existing things. (If you’re interested in getting practice starting something new, check out my how-to on writing your first Ruby gem from RubyConf 2021.)
I felt quite validated to see that most developers share my admiration for code that’s presented well. My friend Nadia gave a talk years ago that played with the analogy that we take turns as guests and hosts in one another’s code and I’ve always strived to write code I would enjoy encountering as a guest. When I stumble on a repo with conventional script commands, layered directories that reveal complexity gradually, and code that is designed to be approachable to outsiders, I often literally exhale in relief.
More than simply looking good, when an author succeeds at making their code feel inviting to change—fast tests, pure functions, small units in which a private method can be safely introduced—I’m on cloud nine.
I’ve worked with a number of managers and executives who oversee developers, and a sentiment I often hear is that programmers tend to be perfectionists, happy to obsess over arcane implementation details without regard for how their work ties back to the software’s ultimate purpose and intended value.
On one hand, developers are the only people who understand software’s intrinsic qualities, so it makes sense that we’d care more about its inner workings than others. But at the same time, my starkest memories of programmers expressing righteous, professional anger are of moments when they discover they’ve just spent months of their lives working on something that nobody actually needed. We may take a great deal of pride in our work as practitioners, but an excellent implementation is hardly an ends unto itself when it turns out the entire endeavor wasn’t necessary.
I was hardly surprised by this result—most developers seem to love long, detailed commit messages and carefully-coiffed revision histories—but I’m still dubious.
My own take is that role-players at every level seem to value the creation of documentation far more than they value consuming it. It’s as if people worry their future selves will be helpless without them while simultaneously holding their past selves’ knowledge and expertise in relatively low regard. Perhaps it’s a consequence of Western temporal focus bias, wherein people are more preoccupied with the future than the present or past. I’ve also long-suspected there is a sort of survivorship bias at play: while we can all think of a few cases where a good commit message really saved our bacon, nothing prompts us to consider the cost of writing the tens of thousands of paragraphs-long messages that nobody will ever actually read.
Before we founded Test Double, I read Pragmatic Thinking and Learning by Andy Hunt. It’s a brisk read, but—and I mean this as high praise—by 2023 most of its points have become well-trodden, familiar territory. One phrase Andy used when summarizing how creative thinking is blunted by the human stress response wedged itself permanently in my brain: “pressure kills cognition.”
I empathize with the project managers tasked with completing software projects within a given time constraint. First, Fred Brooks quipped in the 70s that, “adding manpower to a late software project makes it later.” Now, a growing body of research shows the most surefire way to doom a project is to put undue pressure on the people you already do have. Once things start going sideways, there are only so many knobs to turn and, try as you might, you can’t push on a rope.
Granted, more than a few programmers got into this racket because they love computers and wanted a front row seat to technology’s advancement. But even more broadly, a theme has recurred for decades: installable tools that promise to cure whatever ails us proliferate like wildfire, but timeless truths about software design ebb and flow with the tide.
Frankly, I spent too much of my career trying to persuade people away from chasing new tools as if they were shiny baubles and toward my preferred set of gnostic design principles. Tom Dale once joked that my entire approach felt like I was, “telling developers to eat their vegetables,” and I still think about that a lot.
At some point, I realized that the winning strategy is to embrace the fact that people love playing with new tools and, crucially, that the most impactful tools are those that gracefully intertwine function with philosophy. Ruby is a C program that accommodates an almost absurd degree of expressiveness in running interpreted programs, but it is also a story about programmer happiness being linked to the surprise and delight of basking in unfettered freedom. Rails is a large, batteries-included web application framework, but it is also a story about how a one-person team with a fresh start can outpace entire departments tangled in tools rooted in the bureaucracy of the past.
If you look at any of the tools I’ve published in the last 5 years, there’s almost always a story I’m trying to tell you through the code. Standard Ruby is about conserving your energy for more meaningful conflict than syntax disputes. TLDR is about continuously drawing our attention to the broader consequences of isolated code changes.
Having observed the industry long enough to see several cohorts of programmers come and go, there is an oft-repeated career arc I’ve witnessed that might explain uneven responses to this question.
Many people enter the industry with an incredibly wide aperture for information. Becoming a software developer requires an inordinate amount of time absorbing knowledge, developing fact-finding skills, and distilling large datasets. Through that lens, transparency is more than a preference, it’s an imperative to success. It was for these reasons I was so excited about agile software practices in the late aughts and eagerly built “information radiators” all around my team rooms—from charts of how much work we were doing each week to scorecards of that work’s underlying code complexity. I think a lot of programmers have had an analogous “a-ha” moment at similar moments in their own careers. I think back on it whenever someone describes themselves as a “data-driven” person.
Of course, in my case, it wasn’t long before I encountered a VP of Engineering who was using JIRA ticket cycle time to determine bonuses for QA engineers. Or a CIO that demanded every team record their completed story points (a unit of measure that varied by team) into a spreadsheet that benchmarked team performance by how many totally-made-up points they were delivering in comparison to one another. Or a company that tracked increases and decreases in code coverage on a per-commit basis and sent an organization-wide broadcast that identified anyone who pushed a commit which lowered that code coverage percentage.
Experiences like these naturally dampen people’s enthusiasm for radical transparency, but it’s not like a culture of secrecy that siloes information would be any more successful. The reality is that thoughtfulness about the context and subtext of what and how we share information is required for it to be interpreted and acted upon in productive ways.
The first time I was ever invited to give a keynote address anywhere was RubyConf 2014 in San Diego. The talk was about how new distribution platforms like GitHub and npm were changing open source and how open source was changing how teams built applications. I spent the lion’s share of my preparation focused on dependency management, particularly how our newfound ability to automatically and instantaneously slurp down hundreds of direct and indirect dependencies with a single shell command was changing the relationship between what programmers perceived as “their code” versus somebody else’s problem.
It feels like ancient history now, but prior to GitHub centralizing open source discovery and before dependency managers like Bundler and npm tackled the NP-Hard problem of resolving version conflicts, the burden of finding, fetching, vendoring, and deploying third-party code was just high enough that it prompted many people to think twice before adding new dependencies. Before this era, application frameworks were even more common than they are now, because doing anything ambitious required framework authors to manually assemble dozens of subordinate open source components. What we never fully appreciated was the burden framework maintainers shouldered for us by ensuring each dependency’s compatibility, efficacy, and security.
My worry in 2014 was that we were entering an era in which each individual team would only inadvertently assume that liability by haphazardly ingesting more and more dependencies while failing to budget the time and attention needed to curate and update them. Those fears, which were echoed in the responses to this question, proved to be well-founded.
You are currently on a web site with “test” in the domain name which is run by a company called “Test Double”—a name most people take to mean either the bit of jargon that it is or that we, “test two times” (either is perfectly acceptable). Regardless, I’m not sure we can read too much into the fact that people in our orbit would sooner ascribe to a “measure-twice, cut once” ethos than promote
I don’t know if most developers writ large agree with this sentiment, but the ones who filled out this survey say they look forward to new challenges. I suspect people who are driven to attend conferences or take the time to watch programming talks online are more tenacious than the general population. And I applaud them—this is certainly a fantastic outlook to have! But I gotta say, I am personally the polar opposite and have always dreaded joining new projects and teams.
I can say two things with confidence, however:
- Accruing a wide variety of experiences will rapidly accelerate one’s path to competence in this profession
- However you’re wired to feel about changing projects frequently enough to acquire that experience, it gets easier with practice
As I was wrapping up my internship at Gordon Food Service in college, I was really hoping they’d offer me a full-time position. Instead, my manager escorted me out of the building and told me to go into consulting. If I wanted to level up as a programmer, he said, I could get my hands on ten projects as a consultant in the same time it’d take to complete just one at a large enterprise. The thought was terrifying to me. I was finally starting to feel like I belonged and he was kicking me out of the nest.
When I entered consulting and realized that every few months I’d be working in a new place, with a new team, and on a new system, I was overcome with fear. Every new project felt like I was drowning in a sea of complexity I’d never understand, surrounded by a team I’d never win over. But after five or six bites at the apple, I became almost as good at rolling with the emotional punches as the technical ones. Call it exposure therapy.
Test Double is home to a lot of similarly unlikely consultants who were reluctant at first, but overcame their fears to become absolute operators. Maybe it’s because we, as relatively sensitive people, have experienced so many of the high-stakes moments that punctuate life on a software team that we’re able to empathetically coach others through a lot of the hard stuff, too. That we’ve built a company where people can face those fears—with safety and support—and develop expertise at a level they might not have otherwise is something I’m really proud of.
As someone who literally catches myself holding my breath while attempting tricky refactors, I was relieved to see a majority of respondents feel similarly.
The popular conception of computing is that it’s “like math” and that it mostly entails doing very fancy operations to variables like
y over the course of long procedural functions to, well, compute things. Of course, if you’re among the 99% of professional programmers who build high-level applications, the work is rarely like this. The hard thing about programming, it turns out, isn’t to spell out each step of complexity so computers will understand, but to organize it comprehensibly so that humans will.
The real work of programming, therefore, is organizing all that complexity in ways that are highly discoverable, usable, composable, and maintainable. And on that score, one-letter variables like
x and function definitions that are dozens of lines long simply won’t cut it.
If you haven’t noticed how terrifically bad my question design in this survey was yet, my use of the word “waste” in this one more or less determined the outcome that had most respondents disagreeing.
At the time I wrote this survey, I would have agreed with this statement in many cases. Sandi Metz’s book POODR was incredibly popular in the Ruby world and I was seeing a lot of teams absorbed in applying as many of its patterns of object-oriented code as they could. As a way to form a common language to describe the phenomena we observe in code, I think design patterns are a tremendous tool. However, whenever a pattern book has risen to the level of required reading—as POODR did in the mid-2010s for Rubyists or as Martin Fowler’s enterprise patterns book did in the mid-2000’s or as the gang of four’s book did in the mid-1990s—the median team has interacted with design pattern books less as glossaries of neutral observations and more as recipe books outlining the One True Way™ to write code.
Here in 2023, we’re not due for another intensely-popular patterns book for a couple more years, so all this might sound a little silly. But at the time I wrote that question, I had just visited several teams in a row that were saying things like, “we should refactor this into a factory,” for no apparent reason than they hadn’t added many factories lately. In fact, if you go back and watch How to Program, the code style I ultimately espouse is itself an outright rejection of object-oriented exuberance and an embrace of really boring trees of functions at varying levels of abstraction. Functions which just so happened to be defined as Ruby methods wrapped in classes as thin candy shells. (If you’re curious, you can see this outside-in style in practice in Mocktail’s code and exemplified in its docs.)
Given that my reputation in 2017 was primarily that of a grump on Twitter complaining about neat bugs and cool travel delays, I was delighted to see that so many people expressed a positive outlook for the future of software! (Even if I don’t share it.)
I should note a bit over half the responses were recorded before 2020, but we shouldn’t let that stop us from ending things on an optimistic note!
I’d love to hear from you if you remember taking this survey and, with the benefit of hindsight, might change any of your answers if you were to take it again today. 💚