It's time at Microsoft for midyear career discussions. I'm often asked what makes a good software engineer. I used to think it was writing quality code, as I describe in Nailing the nominals. Good engineers review their software design with peers (that's right, they think first and consult others), write code and unit tests, ensure tests and static analysis pass, and then put the code through peer review before merging it into the group's codebase.
You can get into all kinds of arguments about the particulars of being a good engineer. Do you write formal design documents or just have whiteboard discussions? Do you use pair programming for the design and code-review benefits, as well as greater focus? Do you insist on a particular coding style? Do you write the unit tests first (test-driven development)? Do you use integrated components tests, unit tests with fakes, or unit tests with mocks? Do you insist on a passing buddy build before merge? These are all good questions, and different teams can make different choices based on their preferences and existing codebase. However, performing the basics—design, static analysis, unit testing, and design and code reviews—is the key to an engineer doing a good job, right? Wrong.
Writing quality code is necessary to be a good software engineer, but it's not sufficient. You also need to work well with others and be obsessed with our customers. You may think being pleasant and caring about customers is sanctimonious drivel. If so, you'll never work for me.
Several years ago, I wrote a philosophical take on being a good software engineer for J.D. Meier's Shaping Software.
We're on a mission
Two of the five cornerstones of Microsoft's mission and culture are being inclusive and being customer obsessed. (The others are a having a growth mindset, collaborating as one Microsoft, and making a difference.)
At this point, we've all had unconscious-bias training and been reminded repeatedly by Satya Nadella that diversity is our strength. Working well with others, including them in discussions and decisions, supporting their ideas and growth, and helping them bring their best to Microsoft every day isn't just nice—it's essential to our shared success.
Looking back on two decades as a Microsoft manager, the biggest shift in my approach has been how quickly I expel jerks from my team. At first, it would take me couple of years to recognize and remove talented yet troublesome people. I'd be worried about losing critical knowledge and capability. Now it takes me a couple of months. As soon as the jerk is gone, the team has new life—like a weight has been lifted. Team members rally together to fill the knowledge and skill gaps and emerge far stronger. The recovery and rejuvenation are so fast and consistent, I regret taking two months, but even jerks deserve a chance to improve.
Love, Love, Love
I've said it so many times: Love your customers and partners. We are nothing without them. I used to think good engineers wrote quality code. Now I realize that quality code is worthless if it doesn't make a difference to customers (or your internal or external partners). Sometimes two days spent exposing, completing, or fixing an old product feature makes a bigger difference to customers than two years spent writing something new.
In today's world of cloud services, you can get customer feedback tomorrow on code you submit today. If a scenario is broken due to a flaw in logic or flow, you can fix it and deploy it on the same day. There's no excuse for unhappy customers and partners. Talk to them, learn from them, empathize and understand their issues, and then design solutions that help them achieve more. You don't need to get it right the first time—deploy, listen, learn, revise, and repeat.
I've written a great deal about customers. A fun column is about customer clichés: When the customer is wrong.
Feeling stronger every day
What makes a good software engineer? An engineer that lives and breathes for her customers and partners. An engineer that rallies with his teammates to produce quality code that delivers delightful experiences every day so customers can achieve more. An engineer that goes home knowing he or she made a difference and wakes up excited to do it again. That's a good software engineer.
While an engineer that writes quality code, gets along with others, and cares about customers is a good engineer today, that engineer needs to learn and grow constantly to remain a good engineer tomorrow (a growth mindset). Read more in Proactive obsolescence.