I’ve been thinking a lot recently about the difference between the journeyman and master years of software engineering, how you move from one to the other, and how one might accelerate growth. As part of this process, a more fundamental question has come up – what does it even mean to be a “senior” software engineer (SSE)? Put aside titles for a second – there are plenty of “Senior Software Engineers” who aren’t worth the business cards their titles are written on, and we could quibble over whether we should be talking about “Senior” or “Principal” engineers. But really, what we’re trying to do is to describe what mastery looks like for a software engineer. This post is a stab at an answer.
An SSE knows her tools. She has a deep understanding of her OS, command line, utilities, and IDE, as well as the platform the software will be running on. She’s programmed in a dozen or more languages over the course of her career, and has a deep knowledge of those she uses regularly.
Developing expertise in a language can be thought of as involving the following pieces:
- Syntax. Being able to express logic in code.
- Libraries. Knowing what libraries/frameworks already exist and using them effectively.
- Tools. Understanding how to debug, profile, run, automate, etc.
- Configuration. Knowing what options exist to alter the build and runtime environments.
- Patterns. Understanding the best practices, anti-patterns, common errors, and preferred idioms for solving different problems.
- Community. Being able to use the various message boards, listservs, Usenet, StackOverflow, user groups, forums, and conferences effectively.
- Arcana. Knowing the language’s unwritten history – involving feature evolution, compiler versions, security flaws, bugs, workarounds, heroes, goats, forks, etc.
Any competent programmer should be able to learn a new language fairly quickly, but even a great coder won’t start out with more than a shallow grasp of the essentials, not getting much past syntax, basic libraries, and tools. It takes time, even for an experienced and talented engineer, to develop a deeper appreciation for a language’s subtleties. And to some extent this is fine, as even this basic level of competence should be enough for a reasonably good engineer to be able to code effectively.
Language-specific depth matters, though. In her language of choice, an SSE will naturally think in phrases, not individual keywords or statements, and will gravitate toward cleaner, more maintainable idioms. Her eye will be drawn to problems, brittle constructions, and anti-patterns. She’ll have spent so many hours banging her head against infuriatingly obscure bugs that she’ll have a whole catalog of things to watch out for. When starting out, she’ll be able to set up her environment and source tree easily. The tools will be natural extensions of her thoughts. She’ll have done, and seen done, the everyday coding tasks that make up a large part of every project so many times that they’ll be second nature, and she’ll be able to easily see through to where the meat of the problem lies.
Both of these points are important to keep in mind. I.e., a) that strong engineers should be able to pick up languages and be productive extremely quickly, and b) people with deep language-specific expertise can be extremely valuable, especially when hunting down obscure bugs. Issues related to memory management, garbage collection, configuration, concurrency, tools chain, serialization, error handling, and i/o are often mind-bendingly hard for the expert to find, and impossible for everyone else.
SSEs have a ready grasp of CS fundamentals. They don’t necessarily know the more obscure data structures and algorithms, they might not be able to prove correctness formally, or work out the big-O time for a complicated piece of code, but they have a deep understanding of the most commonly used constructs. They could implement any of the basic data structures easily (though they will generally use pre-existing libraries), and know the tradeoffs of using one versus another.
These are the basic tools of the profession, and much in the same way a carpenter or mechanic knows her tools, SSEs know and use them appropriately without thinking much about them at all.
When I was in college, I double majored in Computer Science and Japanese. I’d been programming since I was a kid, so the CS classes came very easily. On the other hand, I almost flunked out of first year Japanese. I didn’t know how to study, and it took me a while to learn a method that worked for me.
An SSE has been through long projects, short projects, new product development, maintenance, and deathmarches. She’s pulled allnighters, raced against deadlines, and worked with many different kinds of people, managers, and business partners, on different kinds of projects, with different methodologies.
She knows how to work effectively. Anyone can put in extra hours, but she knows how to make the hours she’s working count. She understands that consistently pulling long hours eventually leads to dramatically lower efficiency and motivation, and so tries to maintain some control over her time. She’s figured out her own idiosyncratic way of shutting out the world and concentrating on a problem, getting into flow, and cranking out code.
She knows how to break down a project into its constituent parts and estimate time to completion (she also knows she’s probably underestimating, and multiplies time estimates by a fudge factor). She can work effectively either individually or as part of a team. She’s good at spelunking through someone else’s code, either as part of a code review or when looking to make a change to an existing file.
An SSE knows how to get things done. You can give her a difficult, vague problem, and know that she’ll talk to stakeholders, break down the requirements, come up with a plan of attack, and just make it happen. For bigger projects, she’ll report on progress along the way. If she runs into a snag, she won’t try to hide it. She knows what it looks like when a project spins out of control, actively works to keep things organized, and keeps stakeholders in the loop. No one likes working in other people’s code, but a senior engineer knows when to modify existing code, when it needs to be replaced with something new, and how/when to fight for a necessary but controversial change.
Senior engineers are frequently (but alas, not always) good at communicating their ideas. When coming up with a technical plan, they are able to break down the problem in a logical way, and describe what needs to be done. When discussing different options, they can evaluate opposing suggestions objectively and will try to find an optimal solution. They don’t let themselves get trapped into an emotional attachment to a specific implementation, and they know how and when to make the tradeoff between “doing it right” and “good enough for now.” They know when to ask and how to answer questions, and aren’t afraid to say “I don’t know.”
What I left out
There are many paths up the mountain, and not every SSE is cast from the same mold. There are many things I intentionally didn’t include in the definition.
I didn’t include “industry knowledge,” because an SSE can transition from one industry to another with little difficulty (though, as described above, it does take time to gain deep knowledge of new languages and tools).
They aren’t necessarily good at project management.
Some are good at communicating in writing, some are positively hostile to it.
Some are good at mentoring, others can’t be bothered.
SSEs don’t conform to a specific personality type.
Many have had a formal CS education, some have not.
It should go without saying that SSEs do not belong to any particular race, creed, color, gender, sexual orientation, body type, etc. etc. If you have a picture in your mind of what a typical one looks like, you’re wrong. Try reading the section on the Munich Philharmonic in Blink, then come back and let’s talk.
Where does this leave us?
Unfortunately, SSEs are far from the norm. Though the above description isn’t fanciful – I’m privileged to work with many engineers who meet these criteria – I’ve also known plenty of experienced software engineers who fall down in one area or another. Some are great architects, but poor coders. Others are “75%-ers” – i.e., they consistently get the first 75% of the project done brilliantly, then lose interest when the challenging problems are solved and what’s left is cleaning up the annoying details. Some can’t work in someone else’s code. Others fall down on testing. Or they’re great on their own, but can’t work effectively in a team. Some are easily distracted, and lose significant productivity as a result.
These engineers may be experienced, smart, easy to work with, expert in a particular area – but individual traits don’t make you a master of your trade, nor does time in the industry. At the most basic level, an SSE is someone you can trust to get stuff done, and done well.
Talented, experienced, flawed engineers frequently make up a significant percentage of your team. Identifying their weaknesses, working with them to improve while simultaneously guarding against their flaws, and getting the project done despite it all is where managers earn their keep. Having one or more SSEs on your team can make all the difference, and having a whole team of them is like playing a game on the easiest setting.
Having a definition points the way, but ultimately doesn’t say how you get there. I’m hoping to talk about this in my next(?) post, though sometimes the post chooses you, not the other way around.
Lastly, I’m looking for great software engineers – junior, mid, and senior – in Boston, Palo Alto, and Los Angeles! Just email me at dblumenthal at my company. Thanks!
Next up: Anti-Mastery