Become A Senior Developer
Become A Senior Developer
Become a
Senior Developer
Welcome 5
Learn the cheat codes of veteran developers that make them more valuable 10
Autonomy 11
How do you learn autonomy? 11
Read the metrics 12
How to get better at metrics? 12
Writing well 12
How to get good at writing? 13
Epilogue 50
Welcome
I’m glad to have you as a reader. I hope you enjoy this book.
I’ve gathered together all my top resources on becoming a senior developer. Expanded and
updated with up-to-date content. This is my best guide for how to climb the levels and advance
your developer career.
Reaching the ranks of senior developer can seem challenging for many engineers who are new
to the field. With these resources, you’ll understand the parts of working as a senior engineer.
You’ll see what it takes to get those promotions and fly through the levels.
What’s on the other side? Well, more money is the obvious answer. But the better reason to
become a senior engineer is bigger, more engaging problems. When you own a feature or
business problem all the way to completion, it’s really satisfying.
As always, let me know what you think. I love getting feedback. Just send me an email -
bennett@developerpurpose.com
Enjoy,
Bennett
You’re showing up every day, but it feels like you’re not making progress. The work keeps
coming, but the promotions don’t.
At most organizations, the career ladder for engineers is fairly standardized. Below, L3 you’re a
junior/intern. Above L5, you’re a leader as a technical contributor.
But the middle phase, between L3 and L5, can be hard to get through. For many developers, it
takes years of failed attempts. Some never get through the levels at all.
It’s okay if you don’t want to advance! Some people are happy just doing simple work and going
home. But if you want to get into the interesting architectural discussions and meetings with the
smartest people, you’ll have to get over the hump.
What’s standing between you and staff/principal engineer? (Aside from years of experience?)
You need to put in reps to get your coding muscles in shape. With experience, you get better at
identifying solutions, avoiding pitfalls, and resolving challenges.
But that doesn’t mean you need to stay a mid-level engineer for forever.
● Software engineer
● Senior software engineer
● Staff software engineer
The distinctions between these titles are vague, at best. There’s a lot you can do to push through
quickly to senior. And even staff.
When you do, the pay gets better, obviously. But the work also gets more interesting! You get a
higher level view of the business. You see the problems earlier, when they’re still in the idea
phase.
The more senior you are, the more you help to influence the work of the team.
When you have a question, your first instinct might be to ask around on your team for help.
While that’s not a bad idea, there’s definitely more you can do to investigate the issue on your
own.
Figure stuff out on your own. Learn how to test solutions, read the docs, and figure it out. Try
something first. Then, when you need to ask a more senior engineer say, “I tried x, but I found y,
and I think it’s because of z.” That’s a way better way to phrase a question than a lame “How do I
do it?”
Get curious. Learn the business. Talk to users. Start to work independently and develop your
own problem solving skills. That’s what takes you to a “senior” engineer. Working on your own.
Instead of owning individual tasks or user stories independently, you’ll now need to take the lead
on entire initiatives. Start thinking in terms of epics, dependencies, and how the team can work
together.
Part of thinking in terms of epics and entire feature sets is identifying cross-team collaboration.
Start to grow your influence outside your team to other engineers adjacent to you. Coordinate
changes across teams to make sure new features release smoothly.
During this phase, you’ll contribute more during refinements and retros as you ask good
questions that dig deeper. You should be keeping tabs on what the whole team is working on,
not just you. Identify potential conflicts or areas where developers need to work together.
A big part of leadership at this level is mentoring down. Stay on top of code review and give
good feedback. Offer to pair program. Help out with interviewing. Be someone’s onboarding
buddy.
Sure, you’ll still contribute code. You’ll still review PRs and clarify needs in refinement.
You’ll still do many of the things you did before. So, juggling the transition can be difficult. Be
careful not to stretch yourself too thin.
This is a time when you need to start asking for help in a different direction. Delegate tasks.
Even if they’ll only take you a short amount of time as an experienced engineer. It’s often worth it
for team members to implement the details and learn more about how the code works.
As a staff+ engineer, your time is best used thinking bigger. How are we going to solve the hard
challenges? What do our users need? Where are the bottlenecks in the application? How can we
unlock value for the business?
Most people take the long road to becoming a senior engineer. It’s a slog. Shipping tickets and
debugging features as a junior is a challenge.
To some extent, there’s benefit in the experience. Some skills you’ll only be able to learn through
repetition. Some errors you’ll learn to avoid through making them.
But there are many senior skills that you can learn today. You can think of them as cheat codes,
or as Occam’s razor. The shortest path between where you are and the next rung in the career
ladder.
Autonomy
Autonomy is by far the clearest marker of a veteran engineer.
In a new environment, can you figure things out? When given a new task, can you identify the
parts of the code that need to change? Given a generic description of a task, can you work out
the details?
Experienced developers generate so much value because they can work autonomously.
That doesn’t mean you should go off and work on your own, exclusively! The best developers are
great communicators and collaborators. But when it comes to the details of the work — the
implementation — senior developers can figure things out.
● Stop relying on senior devs to answer your questions. Take an extra 5–10 minutes of
research before you ask a question of your team. Often, I write the question, and while
writing I realize something I didn’t think of before.
● Get good at searching. We don’t talk about this enough, but experienced developers are
really good at navigating the code base. That’s what makes them quick. Learning how to
search and track down references / code snippets is an important skill, and the first step
to autonomy.
● A corollary — get good at searching the web. When you don’t know how something
works, your first questions should be to Google (or DuckDuckGo, or Ecosia), not your
teammates. Try to put the pieces together yourself first. Then, you can ask, “I think it
works like this… Is my understanding correct?”
● Tests give you confidence. Experienced developers know to check the tests for coverage
of the feature they’re changing. They also write tests early, so they know if the new code
works. Running the tests often is a sign of a veteran developer. Coding is all about
feedback loops & shortening them.
Why? Because they’ve been in situations where they had to debug a problem with no visibility
into what’s happening. That sucks. And once you’ve been there, you don’t want to go back.
Then, get good at reading logs, metrics, and reports. A lot of the work done by veteran engineers
revolves around performance, solving thorny production bugs, and setting up new services. We
use monitoring tools to make sure everything is working as expected.
● If you’re not currently logged into your team’s monitoring tools, get access! These are
typically products like DataDog, CloudWatch, Sentry, Honeycomb, New Relic, Elastic
APM, etc.
● Learn how to use the tools to generate information. Create your own dashboards and
reports. Get familiar with how to query the data.
● When you’re working on an issue, you can now use these tools to illustrate that you’ve
resolved the problem. Solved a bug? Generate a report that shows decreased error rates.
Improved performance? Build the graph that shows how much.
● These tools only become more important as you move up the engineering ladder. Having
a solid foundation early on is an important step you can take to unlock senior skills.
Writing well
Experienced engineers write. A lot.
Writing is an underrated skill amongst developers. But writing well will quickly set you apart
from the crowd.
If you can explain complex ideas using clear language, that’s a major benefit to the team.
Writing for the public directly creates value for your company, because it helps users get stuff
done.
Some coders do the bare minimum: write code that meets the requirements. However, great
software engineers know their job involves much more than writing code.
If you want to be a great engineer (and get ahead in your career), it pays to know all the “hidden”
work that goes into being good at your job. In fact, for most top engineers, writing code is just
one small piece of their overall job.
Unfortunately, most of this work is never taught or talked about formally when you’re learning to
code. That’s a shame, but in this article I’ll show you all the “hidden” work great engineers are
doing to build awesome products, and careers!
Coders like to write code and sometimes they’re good at it! Give them a problem and enough
time and they’ll write you some code to solve your specific problem.
Engineers also like to write code, but they mostly love to build useful things for people! Give an
engineer a problem and they’ll immediately ask you questions about why the problem exists,
what you’ve already tried, and if there are any other related problems that could be solved all at
once.
Coders are great for a limited set of tasks, but they often miss the big picture. Engineers on the
other hand always look for the big picture first. They write code once they understand the
problem space.
Often, building a new feature for an application requires more than just adding a button or some
logic.
The Product Manager can’t possibly know all the technical details, so the job of great software
engineers becomes discovering the underlying technical challenges that need to be solved:
● Does this new functionality require us to add a new table or column to the database?
● Should we resolve this issue using JavaScript to build the feature perfectly on the front
end or should we instead update the API to support the new functionality holistically?
● When planning out a group of features, what order should they be developed and do any
tasks block others?
There are hundreds of ways great engineers help discover requirements and make sure they’re
surfaced so that teams can plan and release better features faster.
Most companies have testing standards for new code. In order to be merged, the new code has
to meet some coverage threshold.
Decent coders will throw together a quick set of tests that check the happy paths work as
specified in the requirements.
Great engineers will think of edge cases and larger scenarios where the code might produce
unexpected results. The best engineers write really robust tests (and they often practice
test-driven development).
Designers and product managers can’t possibly anticipate every detail of a new feature. In many
cases, a requirement will be missed or a design might exclude some detail.
In these cases, a good engineer often has to make a judgment call about the intention of the
feature and what a user should expect. Maybe it’s a missing button, a dialogue to prompt the
user, a confirmation email, handling of a specific error…
When you’re developing a new feature, you’re often the first person to see it fully working. As a
good engineer, you have a responsibility to consider UX at every step and resolve any issues that
the design team didn’t foresee.
Perhaps you have a brilliant proposal for how to solve a thorny technical challenge at work —
problem solved, job done, right?
Not so fast! Great engineers don’t just think up solutions, they also think about how those
solutions will be adopted, deployed, and maintained.
A well-planned adoption strategy for a decent idea is better than a botched execution of a
perfect idea.
Moreover, when an engineer encounters a piece of code or architecture choice that no longer
fits within a larger understanding of how the product should work, the engineer is capable of
explaining the problem and its implications to the team and stakeholders in the company.
Note: A good engineer does NOT go rogue on large refactor work. Taking on a large refactor
without asking is a sure sign of a coder with a big ego. Instead, good engineers talk it over, plan
it out, and prioritize the refactor with the team.
Documentation about how the code works is so important for sharing information and
onboarding new developers. Great engineers understand the value of documentation and write
documentation for the projects they work on.
● Great variable, function, and class names that make it clear what the code is doing.
Naming things well is one of the hardest parts of software engineering.
● Inline, function, class, and file-level comments and docstrings that explain why the code
works the way it does.
● READMEs and other internal documentation that explains larger concepts and usage in
the project
● External documentation like API docs, public packages, and help articles
Good documentation doesn’t have to be long or complicated! In fact, great engineers know the
best documentation is short and clear.
Code review is a huge part of an engineer’s job! During code review, great engineers look for:
Being a good code reviewer helps set a standard of quality for your team. Of course, great
engineers should be expected to meet their own standards in the pull requests they open!
What’s more, code review is a great opportunity to mentor other developers and expand their
thinking/skills. Good engineers provide empathetic, actionable feedback in their code reviews.
8. Interview candidates
Engineers that understand the whole software development lifecycle are much better prepared
to interview candidates to join the team.
They understand that it’s not worth hiring a great coder if that person isn’t a good team player.
By the same token, they’re willing to see the promise in a weaker coder if that person shows
potential.
Hiring is hard, and being an interviewer requires a high level of emotional intelligence. Being a
good interviewer is just another way that great engineers contribute to their team in hidden
ways.
Truly great engineers want to share their knowledge! They help others on their team get better at
building useful products with code.
Sometimes that means pair programming. Other times, it’s one-on-one mentoring. Even code
review comments can be considered a type of mentorship.
Coaching other members of the team and collaborating on work is a big part of an engineer’s
job. While it means the engineer isn’t spending time developing new features, coaching leads to
better facilitation of work across the team. Even though individual throughput might go down
slightly, the whole team’s throughput improves when engineers share best practices with one
another.
Engineers do their best to thoroughly review and test code, but incidents and bugs can still arise
for customers.
A coder might be able to respond to an incident, too, but engineers take their response a step
further. Great engineers ask:
● Why was the incident able to occur in the first place? What are we missing in our unit
tests, QA process, code review standards?
● Who else might be affected by this incident? Could other customers possibly experience
the same issue? Do other services rely on the affected component?
● How do I document the incident, its resolution, and followup steps? If something similar
happens in the future, how do I make it easy to find the solution?
Hopefully, this article sheds some light on what it takes to become a truly great engineer.
However, this is certainly not a definitive list. There are even more tasks that software engineers
undertake!
Take this article as a challenge to focus on all the work that’s adjacent to coding and just as
important! Getting great at the hidden work of engineering sets you apart from the pack in your
ability to build great products and get ahead in your career.
I don’t mean writing code. And I don’t mean talking about how existing code works. Those are
important, but they are far less important than communicating about code that doesn’t yet exist.
What sets senior engineers apart is their ability to collaborate on ideas. They can discuss an
architecture decision, scaling strategy, or design pattern without needing concrete examples.
Working together, senior engineers can come to a solution with nothing more than words (and
maybe a whiteboard diagram).
Let’s look at how senior developers communicate and how you can learn to talk like them.
Tech-agnostic
This is a big giveaway of a junior engineer.
When senior developers talk, it’s usually agnostic of the tech stack or programming language.
Sure, we can get into the implementation details later. But, the problem is primarily a “software
engineering problem,” not a “React component problem” or a “Django REST API problem.”
Different backgrounds
Senior developers have been around a while and seen the same problems in multiple languages
& frameworks. They know that this problem isn’t unique to the current tech stack. It’s more
general than that, and the solution can be as well.
While senior developers don’t all share the same background, they do share the ability to
recognize certain patterns they’ve seen before.
If you introduce implementation questions — about the specific tech stack — when we’re still
planning the overall approach, then we could miss the forest for the trees!
Senior engineers want to make sure they’re solving the right problems and taking the best
approach. The implementation details can come later.
There’s a whole language available to you when you stop thinking about software in terms of
Python, Java, or Go and start thinking of it in terms of logical problem solving.
Senior engineers know about “factory methods,” “long-polling strategies,” “message queues,”
and “write-through caching.” Talking in these abstract terms, different senior engineers with
different backgrounds share a common language.
We can talk about those details — if there are questions or concerns — in code review. As long
as the engineer followed the overall approach correctly, then the implementation can always be
refined later.
You can also learn a lot by talking and working with the senior developers on your team. Try to
engage with them as much as you can. See if you can keep up as a peer, not in some type of
watered-down “mentorship.” Throw yourself in the deep end.
Then, study the things you don’t understand. Maybe you heard a new term — look it up, learn the
answer, and save it somehow. Get curious about more than just code.
Learning how to become a great collaborator and talk like a senior engineer is an important step
on that journey.
You’ve worked as a software engineer for a few years. You’ve become comfortable:
Nothing looks new anymore. The problems aren’t as interesting. Of course, you still research
things, visit Stack Overflow, and pick up a few tricks. But building software starts to lose its
luster.
Today, let’s talk about those plateaus, how to keep improving, and becoming a great engineer.
Hierarchy of competence
In psychology, there’s a model of skill acquisition called the “four stages of competence.”
● At the bottom is “unconscious incompetence” — you don’t know how to do something &
you don’t recognize your lack of skill. You may also deny the value of the new skill.
● Next, is “conscious incompetence” — by now, you’ve recognized that you don’t know how
to do something and that the skill is worth learning. This is the real learning phase.
● Upon gaining some skills you enter “conscious competence” — you know that you can
perform the skill, but it takes effort. You have to concentrate & you still make mistakes.
● Only after a long time you develop “unconscious competence” — the ability to perform
the skill intuitively & fully absorbed in the task. At this level, you’ve developed mastery so
that performing the skill is second nature.
Many young programmers hit a plateau in their learning and assume that they must be
incredibly smart. They have such a high opinion of themselves that they think they’ve already
become experts.
In reality, they just don’t know how much they don’t know. They’re really suffering from
unconscious incompetence.
When those engineers don’t realize their mistake, I call them “professional incompetents.”
These engineers are difficult to work with, because they’re so sure they’re brilliant. In my
experience, many so-called “10x engineers” suffer from unconscious incompetence.
To keep learning and growing as a developer, the first step is to recognize that you’re probably
still incompetent at a lot of skills. The world of software development is incredibly vast and
deep. There are so many skills to explore and refine. There’s no possible way any one person
could know them all.
Next, if you’re feeling bored and dispassionate, engage with other developers!
Start with your team. Learn about your peers, pair program, ask questions about the things they
know about and their development practices. Then, reach out to the wider community —
contribute to open source, mentor new developers, and attend conferences.
● There’s more to learn, explore, and be curious about. You’re not stuck being bored.
There’s so much to discover.
● The plateau is temporary. Now that you’ve recognized you’re incompetent, you’ve passed
from “unconscious incompetent” to “conscious incompetent.” You’ve already moved
along on your journey!
● You’re not one of the professional incompetents. Since you’re willing to admit you don’t
know everything, that means you’re probably a good team member and contributor.
You’re not self-absorbed.
Inspiration
This chapter was inspired by writing from Erik Dietrich on “The Rise of the Expert Beginner.”
If you liked this chapter, you should read Erik’s. I highly recommend the DaedTech blog and Erik’s
book Developer Hegemony.
Software developers often fail to realize that their job is not simply writing code. It’s more than
that. The code is worthless to the end user without someone to turn it into a working, reliable
application.
Learn this lesson early in your developer career. You’ll be far ahead of your colleagues.
Incomprehensible code
Have you ever given some code to a non-developer?
A friend of mine was manually updating a ton of CSV files. It was taking them hours. I knew I
could write a script in 15 minutes that would save them hours of time. It was fun actually!
This person wasn’t a developer. They had no idea what to do with the code I wrote them.
Even though it could save them hours of time, the code was worthless. They didn’t know how to
run it.
To make a valuable solution, I had to write some documentation about how to run the script.
Then, I trained my friend on what to do. Together, we discovered some CSV files had different
requirements. My script had a bug or two as well.
We eventually saved a lot of time, still. But the code itself was only valuable with some
documentation, maintenance, and support.
We take it for granted, but our expertise in deploying code is actually what makes software
developers such valuable employees.
It’s all the other things around the code that make it usable:
I like to think of our job as part of a value chain. As you move up this chain, you also move up
the ranks of the organization (Jr. Engineer to CEO).
Start thinking about your code as part of the value chain. It will change your perspective and
how you approach your job.
When you work as a software developer, you solve difficult problems that are valuable. That’s
why startups see valuations of millions or billions of dollars.
Today, let’s talk a little bit about valuing developers and self-worth as a software engineer.
Damaging self-talk
Recently, I’ve heard some self-defeating talk from developers I know. They say things like:
● “I’m self-taught”
● “I don’t have enough experience”
● “I don’t know much about ___ technology.”
They convince themselves that they should be paid less or don’t deserve a role at a top
company. However, I know these people. They have the skills to make meaningful contributions
to an engineering team!
Perhaps they’re not ready to make architecture decisions or lead a team, but they have the skills
and the willingness to learn that it takes to be a great contributor.
By writing code, you’re creating value for your company. The code you write powers an
application that the company can then sell many times, for a marginal cost per sale.
Think about it. You write the code once and then you can run it as many times as needed for as
many customers as you want. The scalability of software is what makes it such a valuable
business proposition.
It’s why companies pay software developers $100k+. Once they have the software, companies
can re-sell it for millions of dollars in recurring revenue.
It matters that you’re paid well because software engineering is not a commodity. Working on a
team to deliver software is valuable. And software engineers do a lot more than just write code.
More personally, it matters that you negotiate strong salaries because it impacts the way
management views you. If you cast yourself as a junior developer, you’re less likely to be offered
opportunities to work on larger projects. Your performance will be more closely monitored. And,
unfortunately, many managers will look down on you.
By contrast, if you negotiate a high salary and a job title, in many cases the job actually becomes
more fun! You’re trusted to complete tasks on your own. You get respect when it comes time for
your team to make decisions.
A pep talk
Avoid the mental barriers of considering yourself a “junior developer” or that being self-taught is
somehow lesser.
On the contrary, in my experience self-taught developers are often better equipped than CS
grads and bootcampers because they have developed the skills of searching for information on
their own and building things without help or tutorials.
If you can build projects on your own, you have enough knowledge to work as a valuable
member of an engineering team. The fact of the matter is that having a degree in computer
science doesn’t actually teach much about the job of being a Django developer, for instance.
My advice: Never describe yourself as “junior.” Ban that word from your vocabulary. Feel assured
that you know enough and can learn the rest.
When it comes time to review a pull request, I’ve seen beautiful code that completes the
requirements and is immediately approved.
I’ve also seen long rounds of back and forth, asking for changes. Code that’s confusing or trying
too hard.
Here’s what I look for in code review as a senior engineer and tech lead. I also try to hold my
own code to these standards.
Size
At first glance, my initial reaction to a pull request is:
1. The first is selfish. I need to know if the PR review will take 10 minutes or an hour. If your
PR is really big, I might have to review it later. If you want quick reviews, aim for shorter
PRs.
2. The second is thinking about change management. When you create a big change in the
code base, there are more opportunities for things to go wrong. Often, for a big pull
request, there are ways you could have released parts of the code separately, in phases.
Those types of incremental changes are much preferable.
The lesson is to keep your pull requests as small as possible. As needed, create followup PRs
that branch off of your initial PR to allow the code to be released sequentially.
Tests
Next, I look to see that the pull request includes tests. The tests should clearly demonstrate the
behavior and expected outcome of the new code.
I’ll try to think of edge cases that might not already be tested and comment about them. As part
of CI/CD, I encourage the teams I work on to run code coverage against the repo to be sure that
all the new code is tested.
Tests help me as a reviewer to understand the code. They’re also essential before any code gets
merged, in my opinion.
Structure
Now that I’m ready to look at the new logical code, I’ll start by assessing the overall structure of
the solution.
Since I just looked at the tests, I have an idea of how the code works together to solve the
problem. I’ll browse through the files, classes, functions, etc that have been committed to
answer some questions:
Logic
With those big questions out of the way, I’ll dive into the actual meat of the code.
On most of the teams I’ve worked on, we use static analysis tools to check code quality
automatically. Those tools pick up on most of the obvious mistakes, security holes, and
inefficiencies. It’s useful to have an automated first pass and know that any PR you’re reviewing
at least meets a basic threshold.
When I’m evaluating a function or class, I look for a few key things in this order:
● Does it make sense? — If not, that’s a red flag. It means the code is more complicated
than it needs to be.
● Is it wasteful? — Developing intuition for algorithmic complexity is a difficult but useful
skill. Often, that means something simple like using a dictionary instead of a list,
iterating only once and memoizing results, or something similar.
● Can it be simpler / cleaner? — It’s not uncommon to see an unnecessary line or a way of
doing something that could be much simpler. In most cases, chalk it up to the developer
working on the same problem for hours on end — not being able to see the mistake
because they’ve been inside the problem for so long.
Naming
Your first line of documentation for the new code is good naming.
All my code reviews include a portion where I think about whether the variable, function, and
class names make sense. Are there shorter names we could use? Do all the names clearly
communicate what they are or what they do?
My one rule is no abbreviations. While they seem smart in the moment, they become untenable
over time. All names need to be spelled out and clear what they mean.
Documentation
Finally, I check that the code has proper documentation.
I don’t mean that the developer needs to write paragraphs about the code and what it does. Just
that each piece of the code should have a simple description of how it works.
In Python, for instance, we do that with docstrings. Every new function or class needs to have a
docstring. In JavaScript, I’ve used an inline comment right before the function definition for the
same purpose.
I also encourage teams to use typing for their arguments and return values. Type annotations
are another piece of documentation that I look for.
Proper documentation also means updating existing documentation when you’ve changed
things. In code review, I try to remind developers to update docstrings and comments when
they’re out of date.
Another big piece is external documentation. If the changes affect an external API, then the API
docs need to be updated with the new information.
When you’re conducting your own reviews, feel free to use this as a guide to analyzing other
people’s code.
Deliver them consistently, and you’ll get noticed on your team. They’re the foundation of creating
real value as a software developer.
● 14 windows, hundreds of tabs, and Run the Jewels blasting in the headphones. That’s the
workflow of my former CTO.
● I know a senior developer who needs a clean desk, staring at a wall, with noise canceling
headphones in order to focus.
Working as a senior engineer can take all kinds of forms. They all look different and match the
personality of the developer.
I don’t think you should listen to Run the Jewels, stare at a blank wall, or watch YouTube in the
background in order to be a great developer.
1. Notetaking
All of the top engineers I know have some system for notetaking.
I’ve seen them use fancy tools like Notion. I’ve also seen simple text files. Doesn’t matter. Great
engineers take notes.
● The questions
● What they learned
● Key data
● Follow-up items
Just start the habit of notetaking. It can be simple at first. In the future, you might be interested
in personal knowledge management techniques.
● When you change the code, you need to run the tests.
● When you’re debugging an issue, you need to run the code repeatedly.
● When you’re releasing a product to market, you need to try things and iterate.
All the best engineers I know are zealots for reducing feedback time.
● They prioritize fast tests to give rapid feedback when you’ve broken something. They
also commit and run the tests often.
● They write miniature scripts to run the code that needs to be debugged. Those scripts
automate the feedback loop as much as possible: loading data, running the code,
catching errors, pretty printing outputs. Bonus points: the debugging scripts often serve
as the basis of new tests!
● They know how to release an MVP. They encourage feedback at every step: design, PR
review, QA, release. They actively want to hear from the Product and customer-facing
teams about how the feature is getting used. They build for observability into metrics
about usage.
3. Prioritization
As you get promoted, you get more responsibility.
The senior engineers I know have multiple demands on their time. When you’re a great engineer,
you become valuable to multiple parts of the organization.
● What are the politics of what I want, what my team needs, what my boss expects, and
what creates value for the company? (Hint: those 4 are rarely the same thing)
These aren’t easy questions to answer. But the best engineers I know have the habit of
prioritizing, picking one thing to focus on, and creating time to get it done.
4. Ask why?
Top engineers ask “why” a lot.
● When a new idea is presented, they ask why to examine its foundations. The
assumptions behind the idea need to be questioned, too. “Why” is amazing as a
simplifying/clarifying question.
● When sales or customer-facing colleagues request a feature, “why” helps get to the
bottom of the use case. It uncovers missing requirements and eliminates unnecessary
features.
● When the code isn’t working, great engineers ask why to find what they don’t know.
They’re inherently curious and always learning, stretching their knowledge.
5. Go beyond engineering
The best engineers are technical leaders for sure. However, they know that their job is to create
value for the organization by solving difficult problems.
The valuable problems often aren’t located within the engineering team.
Often, to find valuable problems, senior engineers have to go to the source. They talk to the
product, customer-facing, and sales teams to learn more about what users need.
They also know a little bit about what all the different engineering teams are working on.
Avoiding silos and going outside engineering is a mark of an engineer that understands
business value.
By bringing problems and themes together across the company, top engineers create big
opportunities.
If you want to be a great engineer (and get ahead in your career), you’ll need to learn the work of
real engineering.
In fact — for the best engineers — writing code is a small part of their overall job.
Disclaimer: No cheating
I hate that I even have to say this…
Baseline — you need to be good at coding. Knowing how to write clean, maintainable code with
good tests is a prerequisite before anything here.
This article is about getting ahead in your developer career. If you’re just starting out, there may
be some valuable things here for you. But you should keep it in the back of your mind and
primarily focus on refining your coding skills first.
From here on, I assume you know how to code and are good at it.
Coders vs engineers
Don’t call yourself a programmer. — Patrick McKenzie
Coders think their job is to write code. They get assigned tasks and they complete them. Often,
they write decent code that fulfills the requirements. I’d venture that the majority of developers
consider themselves “coders.”
Engineers, on the other hand, know that they were hired to create value and solve challenges.
Instead of a task, you can give an engineer a problem. They’ll ask lots of questions to see where
the problem comes from, who it affects, how often it happens, what you’ve already tried, and
how valuable the solution would be.
Coders can write some code that gets a specific job done. Engineers see the big picture and you
can trust them to fix an entire problem domain.
Opportunists vs idealists
Opportunists recognize that the only way to win the corporate game is to play by
their own rules — Erik Dietrich
In my experience, coders correlate with idealists. They believe the company has their best
interest at heart. They think that dutifully completing tickets will result in a promotion. They stay
at teams/companies far too long, after they know they can no longer grow.
Engineers tend to correlate with opportunists. They understand the world of business. Often,
they’re entrepreneurial themselves. They can see that if they want a promotion, they’ll need to
create value and then negotiate the advancement.
To get ahead, the engineers know it’s all about creating value.
Code is one way to create value, but it’s much more valuable to solve an entire business
problem. Usually, that means much more than writing code, and the code is the straightforward
part.
Value != complexity
Just because something is hard doesn’t make it valuable. — Jonathan Stark
Expert engineers know that the greatest value is often created from simplicity.
With experience, you learn to distill problems to their essence. The most seasoned veterans
spend a long time thinking about the problem before implementing anything.
As an opportunist engineer, the goal is create value for your organization and get recognized for
it.
The great leverage of simplicity is that solving a business problem doesn’t have to be
complicated. If you can find a simple solution that will save/earn the company lots of money or
reduce risk, then there’s a great candidate for moving your career forward.
Outlining a simple solution also means you can share the coding work with the team. As an
opportunist engineer, once you’ve outlined the approach you can share in the actual
implementation work with your idealist coder teammates.
I’m not suggesting you farm out your work. But you can write the proposal, RFC, architecture
plan, or guidelines/standards. Then, bring it to the team to vet the idea and get it done.
Some of these will be more valuable than code, depending on your organization:
Being an idealist coder may get you an early promotion or two. You’ve shown that you can
execute on coding tasks.
Eventually, the corporate ladder reaches the point where you need to think strategically. You’re
solving problems at a larger scale. As you advance, you’ll even start to solve problems across
teams and domains.
Being an opportunist engineer is essential to climbing the corporate ladder past the bottom
rungs. You’ll have to make tradeoffs and weigh priorities. You’re constantly thinking about value
and reducing complexity.
Even if you’re not interested in corporate life, consulting teaches all these same lessons.
Value-based thinking, making tradeoffs, and negotiating become critical.
Epilogue
We’ve reached the end!
Hopefully, this book has provided you with a lot of food for thought. Particularly, you should now
have:
- A new framework for thinking about software development & the value chain
- Habits and routines that you can practice to take you to the next level, technically and as
a team leader
- Ideas for how you can frame your contributions and sell yourself to your managers,
execs, teammates, and new opportunities
- A philosophy of software development that will take you even farther in your career
Since each person’s situation is unique, it’s now up to you to implement the knowledge you’ve
gained from this book. Crafting your career is a creative process, and I’m excited for you!
Also, feel free to reach out with any questions you may have along the way. My email again:
bennett@developerpurpose.com
Bennett