A few weeks back we had Dennis Jackson on the show (Episode 94), ostensibly to talk about UAV development. While we did cover the drone topic and speculate about the future of hovering self-guided robots, we eventually drifted into another topic, one that has come up previously under different names. Dennis called it “simple code”, Chris Svec called it “empathy driven development”, and Jack Ganssle talked with us about “being a grown up engineer.”
I am struck by how often these similar concepts have come up on our show. It seems a lot of folks are thinking hard about the engineering profession. Not just about what’s wrong with the industry and big broad issues like diversity and pursuing meaningful applications, but also about simply what it means to be a good engineer.
We all have a general sense of what it means to be a good engineer. Ask your average EE or software developer and they’d probably say some mixture of technical savvy and skill, insight, time management, and wisdom. Maybe a few would mention having the ability to communicate, perhaps with both technical and non-technical team members. A few more might say something vague about discipline. So far, so good. I wonder though how many would mention cleverness or use monikers like “code ninja” or “rock star” or (heaven forfend) “hacker”?
Once we start using descriptions like that, I think we’ve lost our way a bit. Let’s take “rock star” for example (a word I’ve seen on many job descriptions and heard from many HR directors). It sounds cool. I mean, who doesn’t want to be a rock star? Standing up on stage illuminated by spotlights, being stared at by other wannabe rock stars in the audience, trying to make sense of your awesome skill! Or think about what “code ninja” implies. Creeping along silently, alone, using unmatched and mysterious skill to accomplish the mission, in ways that mere mortals can’t quite fathom. Sounds great!
However, there are a couple of big things wrong with these stereotypes. First, no engineer is a true loner. Not even the indie developer working completely on his own. Most of us work in teams, some of them cross-functional teams. We have to be able to communicate what we do to others, and sometimes we have to be able to hand off a project to someone else to finish or maintain. The ninja/rock star that creates something amazing that no one else can understand is a liability, not an asset.
Even a lonely indie developer still has to answer to her users, and, as Chris Svec and Dennis Jackson pointed out, she still has to answer to herself six months down the line. How often have you picked up a piece of old code, ridiculed it for being terrible (or so clever it can’t be unwound), and then discovered it was your own?
The second thing wrong with these stereotypes is that they encourage the notion that raw technical skill should be prized above all else. In practice, this attitude leads to over-optimized, unreadable, untestable code that “normal people” aren’t smart enough to understand. In reality, it’s merely bad code. Engineering is not a competition, it’s a collaboration. Ninjarockstars whose primary life goal is to prove their superiority (usually by indicating you can’t possibly understand what they’ve done) might be in the wrong business.
Enough about the wrong approach though, what are some attitudes we can foster to make things better? Not just for others who have to work with us, but for our future selves as well?
I’d say four things: discipline, maturity, simplicity, and empathy.
Discipline, to me, means having the self-control to slow down, to fully understand a project or a problem. It means possibly writing out a state machine by hand instead of just starting to write the code. It means methodical development instead of hacking. It also means following a set of guidelines for development. Maybe the company set these down in the past, or maybe you came up with them yourself (or use some set of universal ones). Understand why they were instituted, so that following them makes sense. Things like code reviews, revision control, static analysis tools, and doing proper design work before coding all can contribute to better products, though they may sound like chores.
Which brings me to maturity. Maturity often means sometimes doing something unpleasant so that the future is a little better. That could be sticking to the development process even when it seems inefficient. It could mean not taking code review comments personally if a colleague says your code is unclear or overcomplicated. Perhaps it’s just that your code needs to be read by others who might not have your experience or the opportunity to ask you for details. Being a grown up also means dialing back the urge to demonstrate your skills when it is inappropriate.
For simplicity, we have many sources to draw from: “Keep it simple, stupid”, “Everything should be made as simple as possible, but not simpler”, “Simplicity is the ultimate sophistication”, etc. Though too easy and trite, the fact that these kinds of quotes are so popular illustrates that there is power in not overcomplicating things. I think the Donald Knuth statement (often misinterpreted) says it best for computer science:
"We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil."
He is not saying that optimization is bad, but that optimizing code at the expense of being methodical about design is an error. It’s easy to fall into that trap: optimization is fun. It’s satisfying to squeeze out that last 5% of performance. It’s also time consuming and if you step back and understand your problem and system resources, potentially unnecessary. Optimized code can also be the most difficult to read and explain. As software engineer Dennis pointed out on his episode, “I want you to be able to explain it to me over lunch in a few minutes” [38:20]. I agree that’s a good metric for simplicity.
These ideas fall together if you think about it in terms of empathy, as iRobot’s Chris Svec has been advocating. Think about the next person to come along and read your code, maybe years after you wrote it.
“Empathy is putting yourself in someone else’s shoes”[21:35] – Chris Svec
Unless you want them to struggle to understand what you were doing, expend some effort at making it as clean and simple as possible. Document well what cannot be easily gleaned from reading the code. Don’t have special scripts and tools that only you know about: share them. Above all (and this may seem odd) be nice to yourself. Think ahead about how you will encounter your code later, about what tools you might wish you had. As a maker or an engineer, consider how difficult it would be to pick up a (home) project six months to a year after taking a hiatus. What can you do to make that easier?
This turned into a bit of a lecture, but I think it’s worth sometimes thinking about how we approach work. Not from a technical point of view, but as human beings. As we go about trying to formalize methods to be better engineers like with Agile, we should remind ourselves that those methods aren’t on rails, they establish the ground rules. It still takes effort and compassion to work with others every day.