I'm a big fan of April Wensel and her talks on "compassionate code". I love how she drives home the point that software engineering is fundamentally about working with other humans. Yes, it is incredibly important that we have technical expertise, but we also need to be experts in collaboration.
In order to collaborate effectively we need to be engineers that have a high degree of emotional intelligence. And while this certainly means decreasing workplace toxicity, emotional intelligence also extends to the code we write. That's what we'll be exploring in this post—writing code with empathy in mind.
But how can code be empathetic?
It's a good question to ask. After all, we often think of empathy as something connected to our interactions with other people, and we think of code as the time when we get to be "purely technical".
However, as authors of the code we write, we have an opportunity to practice empathy for our code's future maintainers. When we write code that takes into account how future maintainers will feel reading it, we approach our job differently. All of a sudden it become less about just getting things to work or pushing out feature after feature. Instead we start to care about maintainability, readability, and simplicity.
There's a familiar programming quote from Code For The Maintainer that emphasizes this aspect of empathy (along with a little melodrama).
Always code as if the person who ends up maintaining your code is a violent psychopath who knows where you live.
What I love about this quote is that it taps into our survival instinct to remind us that it's important to think of the future people that will maintain the code we write today. Sometimes that future maintainer is yourself, sometimes it's someone you've never met. And while it's rare that the future maintainer is gonna come stalking you with murderous intent, they are still human. It's vital that we write code that makes their job a joy—not a living hell.
So how do we write empathetic code?
A lot of the software industry loves this idea of code being "clean", first introduced by Robert Martin in his book "Clean Code". And while I like a ton of these clean coding principles, I think we miss a lot if we only focus on "best practices" or a list rules to make our code "clean" or "unclean".
Instead, I think it's important for us to frame these software "best practices" through the lens of empathy and how they affect the people that consume our code (perhaps other developers using an internal module's API) or make updates to our code. That way it becomes less of a checklist of things that we "have to do" and more established into the way that we do things.
Let's take a quick look at some of these software practices, framed through the lens of empathy:
Automated Tests
Tests are a great way to provide long-term safety to a module of code. By automatically verifying that the code works, they serve as one of the first line of defense against costly bugs and regressions. When I open up a file for the first time and see that it has some comprehensive test coverage, I feel complete freedom to make whatever changes I need to—without the fear of breaking things! By contrast, opening a file without any tests can be downright terrifying. When we write tests we're not only saving our business time and money, we're making sure that the future maintainer of our code can feel safe about modifying it.
Consistent styling
Having a consistent code style goes a long way towards making life easier for future maintainers. Syntax and formatting issues tend to be low-hanging fruit that can usually be automated with tools like ESLint and Prettier (if you're writing JavaScript, for other languages you might need different tools).
Having a consistent code style is empathetic because it allows your teammates to understand the code faster. Not forcing them to spend extra brain cycles reading through inconsistently formatted code allows them to focus on what actually matters: the problem they are trying to solve.
Choosing good variable names
There's another quote from "Clean Code" that goes along the lines of "you should name every variable with the same care that you would give to naming your firstborn child".
While the metaphor may be a bit hyperbolic, the point still stands: how you name things matters. By spending that extra (often small) effort up-front to choose a descriptive name, you help your team (and your future self) gain context about the code. In the moment we know extra context about why our code is the way it is, so that's the best time to choose a descriptive variable name to remind future maintainers of that context.
Adding comments
If you can't fit all of the context inside a variable name, leave a helpful comment along with whatever name you chose!
You might have heard some people say that "code should be self-documenting so comments are unnecessary". While it is true that we should strive to make our code as clear as possible, a well-placed comment can pack a ton of extra context that you wouldn't really be able to fit inside a variable.
I'm a big fan of using comments to explain the why behind the code. We don't really need to comment that a for
loop iterates through the list, but if it's there to solve a specific edge case it's helpful to know what that edge case is. Adding a comment can be super valuable when some future developer stumbles across that code and is trying to figure out exactly why it's in the codebase. That way they know whether it's safe to delete that code or not.
Documentation
A great way to measure the empathy of your codebase is to watch what happens when a new team member comes on board. How long does it take for them to get the app running locally? What types of questions are they asking? What types of things are they "doing wrong" in their first few PRs.
If you don't have any new team members coming onboard for a while, put yourself in the shoes of a junior developer starting their first day at your company. What types of things about your codebase would be confusing or unclear?
One of the best ways to fight unclarity is through a good set of documentation. Having clear, well-written docs about getting the app running or performing certain tasks can go a long way towards making a codebase friendly and inviting instead of unclear and daunting.
However, docs also have to be written with empathy in mind! Making sure that documentation is extensive enough to provide clarity while not coming across as belittling is a fine balance. One way that I try to assess the clarity of my docs is to "optimize for copy-paste". Assume that the person reading your documentation is going to copy-paste your examples into their code because they're trying to solve a complicated problem on a time crunch. Thinking about docs in this way forces you to write examples that are fully fleshed out.
And many more!
This is definitely not an exhaustive list of the ways to make our code empathetic. In fact, any of the "best practices" out there could be looked at through the lens of empathy. Take a couple of the best practices that you're passionate about and think about how they positively impact future maintainers and you'll see what I'm talking about!
Conclusion
At the end of the day, engineering is about communication—we tell the computer what operations to execute, and we tell our teammates what the code is supposed to do. And while the computer doesn't care about how empathetic our code is, our teammates and future maintainers do. By focusing on empathy in the code we write, we will produce higher quality software as a byproduct.
Top comments (10)
It feels like the empathy here is being forced into an engineering discipline and I don't understand why. It seems like the writer has an emotional response to aspects of code (no tests -> fear) whereas it can simply be phrased in terms of uncertainty.
On the other hand, I'm now tempted to write a similar post but with the focus being on pride rather than empathy.
Hi! Like I said in the post, I like to think of empathy as a way to frame our engineering practices—more of a "why" to fuel and inform how we do things.
While software disciplines can definitely exist without empathy but my goal with this post was to explore and examine how empathy could fuel and catalyze these engineering disciplines.
Why do you call "sanity", "consistency" and "maintainability" with the word "empathy"? I see how you tried to convince everyone, that doing your job well is actually caring about others, when in fact you just do whatever you have to do and do it well. If someone with less experience makes a mistake will you blame him for being selfish or trying to make others feel bad?
I don't think we should be mad or angry at someone who is less experienced for making mistakes! That definitely goes against the vein of being empathetic.
Just like any other skill, empathy can be learned and improved upon. The best senior devs I've met help teach less experienced devs (like myself) how to consider the future maintainability and long-term effects.
There's a lot to be said for craftsmanship and doing our jobs well. I guess why I wanted to frame maintainability and code sanity with empathy is because I think empathy can help fuel our thinking about producing quality code that is easy for others to step into.
My point is - this is basically common sense. Applying emotions to engineering is like describing mathematics with feelings. Sounds weird to me.
While I agree with most of your points, I don't believe they have to do with empathy.
Imagine a team of software developers where everybody is a total jerk. The manager sets up strict rules about writing tests and documentation, clean code, reviews and so on. Team members who don't adhere to the rules will be paid less or get fired. I do believe that such a team can be just as productive as a team based on empathy.
Don't get me wrong, I would not like to work in such a team. But I guess that there are people who would, if they are paid well enough.
I agree with you, I'd definitely not want to work on that type of team! And there's probably people that would be ok with it.
We can have all of the software disciplines I mentioned without empathy—that's completely true. And I'm sure a team like the one you described would see some success from adopting the things you mentioned—even if it was out of fear. However, I don't think it's wrong for us to take a look about how our software affects the people we collaborate with. That's why I wanted to examine how empathy can be fuel for engineering discipline (:
Wrong! It will be A WHOLE LOT more productive.
This was fantastic, thank you for it
I agree with you, developers need even more to take attention on how a program interacts with the user, not only with its interface but also with its tone (to create empathy).
A great post! Thank you, Benjamin.