What I Look For
This page is intended as a resource for recruiters and hiring managers to understand whether I'm likely to be a good fit for your team.
[NOTE: I wrote most of this in late 2022, then received an offer before I finished it. I've updated parts of it as I've thought of them—but, of course, some of the details may become less accurate over time. If anything in here raises a question for you, please feel free to ask!]
I'm a backend software engineer with deep roots in the Ruby community. I've been working in tech for millenia (okay, since 1999), and I'm looking for a remote role as an individual contributor at a reasonably mature organization, with teammates within ±3 time zones of the west coast. I've been a Staff Engineer since early 2022 and would love to continue exploring that level; I'm also very comfortable working as a (Very) Senior or (Tech) Lead.
While I enjoy the occasional greenfield project, I specialize in cleaning up legacy Rails codebases (and their test suites!) so they can be sustainably developed for years to come.
If you're an early-stage startup, I'm probably the wrong hire for you—for now. Keep me in mind when you're ready to retool for the long haul.
What I Do
I got into programming so I could use my problem-solving and technical skills to help people. Early in my career, that meant automating boring work so I could help a coworker save hours every week for more interesting challenges. As I've progressed, my work has taken me further away from end users, so these days I find deep satisfaction in lifting up the engineers around me.
Here's what that looks like:
I've been practicing Test-Driven Development since 2004. A few years later, I was very lucky to be assigned an undergrad advisor who introduced me to Refactoring, which is the chocolate to TDD's peanut butter. I've used Cucumber more than once (video, slides). In 2022, I set aside time to pair regularly with Llewellyn Falco, creator of Approval Tests, to maintain the approvals Ruby gem. (Scheduling got away from us, but those sessions definitely helped me understand some of the power of approval testing!)
I test for many reasons, but one of the most important ones is that...
I dive into the deep, dark areas of code that require shotgun surgery and rework them into systems that even early-career engineers can use and extend.
I think code should reflect the team's best understanding of the problem it solves. If some unit of code is brittle, buggy, confusing, untested, or all of the above, engineers tend to make the smallest change they can to accomplish their short-term goal. That works for a while, but each "minimal" change makes the code a little bit harder to understand each time. Eventually, the cost of change exceeds the team's capacity.
I've cleaned up a lot of complex code that nobody else would touch. Fortunately, the same skills I use to simplify code can also be used to keep it from getting out of hand in the first place. Which is why...
I help people learn.
Once in a while, I have an "Aha!" moment, and then I get to distill it into a tutorial, screencast, or presentation. I recorded over 70 episodes of the Greater Than Code podcast (and 20-ish episodes of some other podcast). In 2022, I took on two students in a formal Technical Apprenticeship Program at Real Geeks.
I enjoy those kinds of formal teaching, and they can be incredibly useful within their contexts. But overall, I'm most effective when...
In my experience, two engineers working together are far more productive than two engineers working solo. I use pair programming:
- to quickly onboard someone (possibly myself) to a new project.
- to break down silos (solos?).
- to level up on a skill, practice, or tool.
- to discover better designs than I could find on my own.
What I Don't Do (Well)
The last time I spent a significant amount of time working in the presentation layer was 2009. Even then, I was generating more PDFs than web pages. Since 2010, I've been on teams with enough other engineers who enjoy frontend work that I've been able to focus on backend code. I'm open to learning, but modern UI work is shockingly complicated, and I'll need an experienced pair partner to get up to speed. If you're looking for a "full-stack" engineer on day one, I may not be a good fit.
One of the many wonderful people I know through the Ruby community has been nudging me for years to get into management. I get where she's coming from, but a life of bouncing from one meeting to the next is not for me. Meetings can be useful, but I've found that I need time before to prepare, and time after to process.
Also, I have a deep-seated need to craft things. I've seen quite a few engineers step into their first management role without understanding that they've started an entirely different career. They're easy to spot: their calendar is back-to-back meetings all day, but they're still trying to ship code late into the evening. The lucky ones figure it out before they burn themselves—or their teams—out.
I'm a big fan of conferences and engineering summits, but the pandemic is still going. I may occasionally be willing to take a short flight, but if your job requires travel, please look elsewhere.
Move fast and break things.
I genuinely love working on legacy code that other developers are afraid to touch. Those kinds of messes don't happen overnight, and they don't get cleaned up overnight. I also have a brain that tends to work in ways that are, shall we say, nonlinear. I do my best to make small, safe, incremental changes, and I rarely solve complex problems until I've lived in them for a while.
Or, as a coworker once put it: "Sam has one level of thoroughness, and that's 'very'."
Drag stories to the right.
Don't get me wrong: I can ship features. But here's what happens when you drop me in to a team that's gotten used to doing paint-by-numbers Scrum under schedule pressure, and they don't regularly do pair/mob/ensemble programming:
- I pick up the next story and start digging in to the code. Being the "new guy", I find parts of the code confusing. As I start understanding each piece, I refactor it so that it's easier to understand: a Rename Variable here; an Introduce Explaining Variable there; an Extract Method or two; maybe even a Move Method if there's a particularly strong Feature Envy code smell... you get the idea.
- After enough of these little changes, I find that I've lowered the cognitive cost of understanding the code enough that the implementation of the new behavior becomes obvious.
- I deliver the story, including all of the small improvements I made along the way.
- Meanwhile, the other engineers on the team have learned to keep their heads down and "just make it work," and they keep doing what they know.
This shows up in the team's velocity in two ways:
- At the end of the current iteration, if you total up the points each engineer delivered (which, to be clear, is a terrible idea), my number will almost certainly be lower than the rest of the team's.
- Over time, everyone else who works on code I've touched will find it easier to work with, so they'll deliver a little bit faster. Meanwhile, I'm off cleaning up something else... and, iteration after iteration, my numbers will consistently be lower than the rest of the team's.
(This is one of the reasons I'm wary of "velocity" as a metric: it's easy to misinterpret, and can cause spectacularly dysfunctional behavior even on well-intentioned teams.)
What I Look For
Kind, collaborative teams.
For me, the most important and interesting factor about a job is the team. And when I say "team," I don't just mean "a collection of people, all working on their own projects." I mean a cross-functional whole team where people routinely pair or mob to spread the knowledge around as widely as possible.
A good team lifts each other up, cares for each other, and can make the most boring problem interesting. In contrast, one asshole can ruin an entire company.
If you make me an offer, it should be to join a specific team, and I'll want to have met the engineering manager, the product manager, and at least two teammates before accepting it.
Sustainable development practices (or a genuine desire to adopt them).
My biggest motivation in programming (aside from just generally solving problems) is to make things easier for myself and others. I test so I can find a design that makes sense, and so I don't have to keep fixing the same problem over and over. I refactor to make code clearer, which reduces the cost of change. I teach others so they're empowered to keep things clean. And I collaborate because people working together can solve bigger problems, for more people, than I could tackle on my own. All of this helps keep a codebase livable for the long term.
If you're already doing this, great! If you're not, but you're ready to start, even better!
I invest a lot in my team and my work; I'd like to see that investment pay off. I spend the first several months in a new job learning a bunch of new concepts, conventions, and names. Once I've got enough context loaded into my head, I can spot patterns, put pieces together in interesting new ways, and talk to the right people about how to go about fixing things. Starting that process over again every year or two can be interesting, and sometimes even fun... but it's not where I do my best work.
Ideally, your engineering team should be as diverse as the populations you serve. Given the strong selection biases involved in career selection, though, your engineering team should at least reflect the demographics of tech overall.
By the time I reply to you, I've probably searched for your company on LinkedIn, clicked on the "People" tab, filtered it to show engineers, and scrolled down through the list of headshots to perform "The Count". (And, yes, many forms of diversity aren't visible, especially disability. Looking at faces is an imperfect metric, but I find it useful as a first-order filter.)
For me, a big part of DEIB is...
Honestly, pay is the most boring aspect of a job—at least, it should be. If the salary isn't enough for me to live on, there's no point in further conversation. If it is, there are much more interesting things to talk about. But "boring" isn't the same as "unimportant," so:
Your job descriptions should disclose the salary for the described role.
Not just your engineering roles, either: all of them. This isn't just a DEIB issue. It's also a morale and retention issue. Sure, companies can "save" some money in the short term by lowballing candidates, but when people eventually figure it out (and they do), the resulting backlash is a truly spectacular waste of time, energy, credibility, and talent.
Ideally, that salary should be a single number that depends only on title/level.
If you haven't yet done the work to standardize this, or if you've built a flexible compensation scheme that lets people choose between, e.g., salary and equity, a range is also acceptable (but expect questions about the factors that go into that range).
My Ideal Org
Is remote-first, concentrated in or near the Americas.
I'm in Portland, Oregon. I've been working on distributed teams since 2012, and have considerable experience doing remote pair programming. I'm a big fan of synchronous collaboration, so I'd like at least a few teammates whose schedules overlap mine by at least 4 hours. If the whole team has "core hours," that's even better—as long as they don't start before 9am my time. (A morning person I am not.)
Has been around for a few years, and will still be around five years from now.
Nonprofit, for-profit, bootstrapped, startup? Whatever. I'm open to possibilities, but I can't honestly say I'm excited about early-stage startups. More importantly, if you're an early-stage startup, I will probably slow you down.
Especially when VC funding is involved, early startups are under a lot of pressure to throw spaghetti at the wall and see what sticks—and, when something does, to put everything into a drive for growth. In that environment, a "good enough" solution is usually the correct one. I've learned to accept this, but I don't think I'll ever actually enjoy it.
Rails is great for startups, because it lets you try a lot of different things really fast. If you hit the end of your runway before you find something that works, then investing in high-quality code will have been pointless, because nobody will be around to maintain it. On the other hand, if you do find a winning product, you can throw more servers at it while you ride that growth curve. After the smoke starts to clear, then you can start paying down your technical debt. I'd love to hear from you then, because I honestly do enjoy cleaning up legacy code. :)
Has a headcount in the 20-200 range.
I love the autonomy and speed that I often find in small organizations—but tiny orgs tend to be unstable, and I don't particularly enjoy job hunting. Also, orgs that only have a few engineers need generalists, and at this point in my career, I'm somewhat specialized.
At the other end of the scale, as organizations grow, power slowly shifts from people to policies. In my experience, large companies lose the ability to change their rules—even when following those rules leads to nonsensical outcomes! (If you enjoy rants, ask me about my "travel" monitor some time.)
As a software engineer, my job is literally to teach rules to computers. I have no inherent respect for rules; I see them as tools. When they don't work well, I change them. I do this for the computers in my care, and I expect my employer to do this for the people in their care.
Doesn't make the world measurably worse than it already is.
I'll evaluate opportunities on a case-by-case basis, but here are some things I can't ethically participate in:
- Supporting ICE in any material way.
- The "gig economy". (This includes "app-based" delivery of physical or mental health services.)
- Anything related to cryptocurrency or "blockchain" tech. (As of mid-2023, "blockchain" seems to finally be losing ground, but I'm seeing a lot of silliness around ✌️AI✌️, so if that features heavily in your job description, expect some questions—for example, "why?" and also "WHY?!".)
- Senior: I stayed at this level for a very long time, and I can almost do it in my sleep.
- (Tech) Lead: I don't see a lot of companies using this title now, but I've held it a few times. As long as the role is strictly technical, I'm quite comfortable setting standards and practices and leading by example.
Staff: Will Larson identified four Staff Engineer archetypes, but "Staff Engineer" seems to mean something different at every org (and often within the same org).
My first Staff role at Real Geeks was literally created for me, and formalized the de facto "Solver" role I'd been in for 6+ years, along with a significant mentorship aspect with the Technical Apprenticeship Program (RIP).
At Valimail, I'm again working mostly in the Solver role, with a side of Tech Lead in that I do my best to model and advocate for sustainable technical practices. With clear expectations and support—ideally from peers as well as management—I'd love to continue developing my fluency and effectiveness at this level.