Skip to content

Instantly share code, notes, and snippets.

@opqdonut
Last active September 20, 2024 09:11
Show Gist options
  • Save opqdonut/a89b05912bbfeeb23014999b3076e22b to your computer and use it in GitHub Desktop.
Save opqdonut/a89b05912bbfeeb23014999b3076e22b to your computer and use it in GitHub Desktop.
On Seniority and Acceptance

Draft for a blog post.

On Seniority and Acceptance

There have been two hard pills for me to swallow as I've matured in my career, moving to more senior positions. What I mean by maturing is widening my impact from my individual contribution to the team level and beyond. Being a multiplier, as they say. Anyway, those hard pills are:

  1. You see more problems than you can fix.
  2. You can't force a team to produce better quality than its median member.

To keep growing, I have needed to accept these new truths and adapt my approach. First, let's unpack these truths a bit before talking more of adapting.

(Terminology note: what I'm calling a senior engineer/developer in this post might be what other people call a staff engineer. Regardless of titles, I think a developer on a career path like mine will hit these topics some time along their career.)

Problems

Let me draw a caricature of a software engineer's relationship with problems along their career.

  • Junior: I can see a problem, but I don't know how to fix it
  • Mid-level: I can see a problem, and I know how to fix it
  • Senior: I can see a lot of problems I know how to fix, but I can't fix all of them myself

The growth of an engineer in the beginning of their career has been all about getting better at solving problems. To become an independent contributor, you must independently solve most of the problems you encounter in your daily work. Juniors are expected to ask for help, but also expected to learn and develop and eventually stop needing help.

A mid-level engineer can competently solve problems. However, their visibility is often limited to the task immediately at hand. They're thinking mostly about their own feature, not of their teammates' features, or the totality of the work of the team. When the engineer matures, they start to look more broadly at the work of the team. This means they'll start seeing more problems, but also new types of problems.

Firstly, there are all the immediate problems their teammates are solving, and the senior engineer can help with these. However, they can't help all of their teammates with all of their problems.

In addition, there are new types of problems. These can include things like inconsistent assumptions between teammates, unclear APIs, duplicate work, or quality problems. As the engineer matures, they'll start seeing even more of these, subtler and more nuanced problems. These kinds of problems are usually harder to fix, take more time, and they can't usually be solved once-and-for-all, but need constant maintenance.

Thus: You see more problems than you can fix.

Quality and taste

Some of the new problems our developing senior sees are related to quality. Things like constant regressions in some part of the code, a flaky integration test suite, a crumbling separation of concerns between to components, etc. These problems can weigh heavily on someone who is used to excellence in their own work.

Also, as our senior has grown, they have developed a taste. They have certain ways of doing things, and certain things they like to avoid because they have been bitten by them in the past. Their teammates probably don't share the same taste – they have developed their own, or are in the process of developing it.

One way of trying to solve both of these issues is adding control and quality gates. Perhaps insisting on code review, a code style, a process or just watching over teammates' shoulders. I think we've all seen team dynamics like this. The team has grown, or a new team has been created, and the most senior developer wants everything done like they would've done it themselves. Code review takes many iterations. Nothing is ever good enough. The results are clear: velocity and team morale suffer.

An engineer who is trying to be the arbiter of quality for their team becomes a bottleneck. If they want everything to be done up to a standard that the team just isn't naturally producing, it's the same as if there was no team, just one engineer. Also, focusing on one person's view on quality makes the team share all of that person's blind spots. Other, unseen, problems will crop up, and teammates won't react to them because they've been passivized by the control applied to them.

The hard truth here is that there are no quick wins for quality. You can't force a team to produce better quality than its median member.

Improving your team

What can be done? If there are more problems than can be fixed and better quality can't be forced, is the project doomed to mediocrity?

Surely not, our senior engineer just needs new tools!

The key to working around both of the hard truths I've discussed is improving your team. Let me highlight the key parts:

  1. You see more problems than you can fix.
  2. You can't force a team to produce better quality than its median member.

If you can inspire your team to work with you to fix some of these systemic problems, it doesn't matter that you can't do everything yourself. If you can improve the median team member by mentoring, guiding, and giving them space to grow (by not standing behind their shoulder!), the quality output by the team will improve. It's not easy: giving the right mixture of support and freedom is difficult. But if you ask people, they might tell you what they need.

Improving your team is slow and uncertain work. You can't try to solve all of the problems you see at once. You need to really think about which problems are the most important, and which problems can't be worked on yet. Also, when it comes to more nuanced problems like quality and architecture, it can be hard to quantify the actual impact of the problem. Is the misleading API actually hurting the business? How much will a faster test suite improve work? Thus it's important to stay humble, and to work on these things in dialogue with the team, not as a dictator. Dialogue is a also a great way to get the team invested in solving the problems.

You can also look at this in terms of building culture in your team. But that too is a topic for another day.

Acceptance and giving up control

With dialogue and involving others comes a final hard pill to swallow: giving up control. As a developer grows from junior to mid-level, they have started relishing their feeling of control. They can solve the problems, they can make the decisions on what code to write. They are an independent contributor. However, as a senior, they must start to accept the loss of control: they can't control the team's quality, and they can't solve all the problems. They need to help the team, and let the team help them. The result is never exactly what our senior envisioned, but it might be something with even better outcomes.

Bringing in more perspectives from team members might reveal that our senior had been too focused on something (e.g. test coverage) while ignoring something more important (e.g. number of regressions). Having to think about the actual impact of things can let our senior analyze their taste. This means trying to move from subjective, intuitive judgements to recommendations grounded in actual risks and tradeoffs. Whereas previously they just had some intuitions on how things should be done, now they can think about what actually matters, and what is just a matter of preference.

By the way, mentoring is a great way to both grow your team, and to sharpen your judgement on matters of taste. Really walking through the pros and cons of different approaches with your mentee and staying open to their suggestions will make both of you better developers.

Something that resonated for me was a comment on the internet along the lines of "don't break your back delivering something nobody asked for". I know I've often tried to make a test suite better than it actually needs to be, and pressed my teammates to do the same.

If giving up control sounds weird, another way to think about it is prioritization. As always in software, we can't work on everything, so we must pick some valuable things to work on. To be able to accurately prioritize which problems need solving, our senior needs to move beyond the team level and understand what produces value in the organization. That might mean dipping their toes into the business side of things, interviewing stakeholders and users, and de-emphasising technology for a while.

Conclusion

I'm still working on adapting to these hard truths as a senior engineer, but I think I've managed to accept them. This has allowed me to be satisfied with non-technical work, and to better understand my value even when I'm not shipping features. One of the best ways to grow for me has been to mentor people, both teammates and co-workers in other projects.

I hope this post gives you some food for thought on your journey, especially if you don't agree with everything I wrote. There are many different careers in software, and I only know mine. I hope you have fun with yours!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment