As a line manager one of my responsibilities is to level up developers. This is something very challenging that I started to like a lot. I have a primary goal on my 1on1s: how can I level up this person? How can I follow the work that is being done and give good, candid, actionable feedback? How can we know that in fact we’re improving?
This starts by trying to understand what my mentees value and where do they see themselves. I try to do that is by asking:
Imagine that you are 10x more better. What does that look like?
It’s very interesting that usually I don’t receive a straight answer. This is something that we seem not to think about. We may have plans to get better, but having a concrete vision of what that looks like is a different thing. If I ask for other developers they look up to I’ll have several references. But it seems to me that even if we interact with top performers, we may not know what it looks like for us to be much better. Our personality, tastes and experiences will be different.
The next step will be to ask what makes a top performer more valuable. What skills and practices do top performers have? And this is also hard. We may point to some colleagues and pin point what makes them great, but not be able to have a clear definition of a top performer.
And if we don’t know our destination, it’s harder to get there more efficiently.
How to grow top performers?
There are tons of improvement points we can spot on a developer, if we take the time to pay attention. With so many things to improve, how can we tackle it? A good approach I’ve seen is what sport coaches do. We may doing some movement badly, they see us and note about 100 things to improve. But will say: Okay, you’re doing good. Now try to focus on this specific thing. The next day, we’re better at that thing and they’ll say: Awesome progress. Now try to focus on that other thing. And step by step we get improvements. We always have a positive feedback loop. But sometimes they will also show us the hard reality and say: That performance could be much better. We’ll need to work on it.
First we need to understand and decide that we want to be better. Then we need to change our day to day processes towards that goal. We are what we repeatedly do. But there’s sometimes inertia or beliefs that constrain us. I may suggest some change and get a “I don’t have time for that” excuse. Usually this means:
- I don’t think that the change brings enough value for me to invest time in it
- I believe the change is good, but it will compromise my productivity
Regarding 1), usually I didn’t sell my suggestion well. Sometimes I may actually be presenting solutions to problems they never had. Or I may even need to question my own beliefs and consider if the change is really good.
Option 2) is more common. To change we need to invest. We leave our comfort zone when we’re learning new things and naturally that will affect our productivity. But that’s part of the process. We invest time, we change, and we get improvements.
This is also an investment on my part. If I commit to focus on improving developers, I’ll need to invest time in following what they are doing. This is not easy and takes time. So I also expect commitment in return. The next section will be about all the little things I try to pay attention and will bring to the table for discussion.
Give me your opinion
This post is the result of my observations. Naturally it’s biased and based on my point of views and the experiences I’ve had. In my own quest for improvement, I’m applying the scientific method here. This is my hypothesis, and now I’m taking it to be tested with my readers. Then I’ll gather that data and use it to improve my process.
So I’ll ask you to share your opinions with me (contacts on the bottom of the page). How can I improve my process? What are those things that I value that you don’t believe are that important? What else am I missing?
What makes a top performer?
From my experiences I started to register what I consider to be a list of skills and practices that top performers share. I try to have a long term practical training plan to suggest. But I also focus on day to day common tasks and how to improve them.
Most of these things are debatable and depend on the environment, project and on people themselves. But it does foster debate and acts as a starting point.
Communication and Collaboration
We usually work in teams. Knowing how to communicate, discuss our ideas, and collaborate is very important.
Communicate in writing
Writing is very important. It allow us to properly structure our thoughts and leave context for the future. A top performer will take care in everything that its registered in writing, so that other people can understand.
This means RFCs, postmortems pull requests and commits, for example. There’s always a set of reasons why we need to write something. We should take time in properly explaining those whys so that other people can understand our reasoning.
My mantra for remote teams is: “What is not written does not exist”. - Interview with João Cavalheiro
Welcome feedback, have empathy and humility
When we share information we’re exposing ourselves and our ideas. We will be subject to criticism. That’s actually to be expected and to be well received. We may have people that didn’t understand our reasoning or maybe that don’t agree with it at all.
Knowing how to receive and give feedback, specially when the feedback is harsh, is hard. We’ll need to understand the point of view of our colleagues and accept it. We’ll need to understand that sometimes we’re wrong and deal with it.
This process may be slower and sometimes frustrating, but the outcome is that our deliverables will be battle tested and overall with better quality.
Flexible and pragmatic
Sometimes we need to compromise. We may have the best idea but it may not be possible to accomplish it. We may need to take some shortcuts to get there. We work in groups of people and for companies. There are lots of ideas and objectives on the table and we need to be political in dealing with all that.
Everything has its tradeoffs and we need to be aware of them.
We need to have a mindset of continuous learning. A good strategy is to come up with learning sources and make the habit of using them. I usually lean to books but I also know developers that find other ways to stay up to date (podcasts, meetups, conferences, peer networks, social media, …). And this is very important.
We need to do research and learn new things. Or else, how are we going to know what’s the best strategy to address new unseen problems?
Continuous teaching and information sharing
Learning, feedback handling, being pragmatic, etc, are all useful tools a developer may have. But to really potentiate this knowledge we need to be able to share what we know and what we’re doing with our team and company.
A good way to do this is when reviewing pull requests or RFCs. Trying not only to focus on verifying quality, but also trying to find improvement points our colleague may have and present them in a healthy way.
Behave like role models
Leading by example is a great way to share best practices and to induce change. If we start changing our behaviours to better alternatives other people will follow us.
A top performer aims to deliver assets with good quality. This involves all steps on delivering code. Trying to really understand what’s to be done, how to test, and ensure that the deliverables are reliable and with few bugs, and focusing on documenting when necessary.
By delivering with quality from the start, we can prevent that ping pong that may occurs when we’re verifying the deliverables.
We should have the necessary knowledge to perform our tasks. We should know about the business domain overall and aim to understand how all parts interact.
In technical terms, we should know the project ecosystem. This means where things are done, or how to find out where they are done. How to handle dependencies and how to troubleshoot them. How to deploy and how is the production environment (and the others) configured.
It’s also helpful to understand a bit about the work of our peers from other roles. For example, if we’re working on the backend, we should know a bit about the frontend, QA processes, DevOps and infrastructure, etc.
How do we know that we don’t have the best idea if we don’t welcome feedback? We need to accept all inputs and see the value in them. If we are closed to outside considerations we’ll have poorer outcomes. Even if we in fact have the best strategy and are more experienced than our teammates, just having the process to reason and explain the whys will make our proposition better.
Just because we’re the best in the neighbourhood doesn’t mean we’re good.
Sharing what we know and growing our teammates is the best thing we can do to grow ourselves. When we share knowledge and best practices, we turn those around us into better developers. And, in turn, we’ll become better developers because we’re working with top performers.
(…) you help people grow through mentoring, because mentoring = I was there, I can share with you how I did it, what I learned and what I believe can help you (…) - Interview with Monika Wojtasinska-Felicio
We should see ourselves as mentors every time we have a teammate that is less experienced or proficient in something that we’re comfortable with. Sometimes I have something to do and I have a less experienced developer teaming up with me. When that happens, I usually ask my teammate to lead. To act as the tech lead and commmand me. And naturally I’ll be there to help on every step of the way.
I’ve mentioning mostly soft and social skills. But naturally our processes while we perform our craft are also very important.
We should write code that is easy to change, that uses proper abstractions, that is easy to understand and copy paste friendly.
But what does that mean? How do we know we’re getting there? This comes with experience. Even top performers will struggle with making code that is easy to understand and change. This is why peer review is very important. Because sometimes we think it’s okay, but our teammates may not agree. And then we iterate until we reach a better version of our deliverables.
The most important thing is to decide that we want to write good code. Sometimes we just have some habits, and they seem to work. But we may be using patterns that are a recipe for trouble. We need to constantly question our beliefs.
Know several programming languages
I see a lot of people that focus on just one programming language and are advocates for it. But knowing several languages and ecosystems has lots of advantages.
We learn about different ways of doing things and this will shape our day to day coding processes. Different languages may have different strategies and ways to represent how we model problems. Knowing about those strategies broadens up our perspectives.
For example, take the Rust Programming Language. By studying it I learned about ownership and borrowing, that are approaches for managing mutable state that I never had seen before. I don’t know if this concept will be useful for me in the future or not, but I really feel there’s value there and I’m happy to have learned about it.
Use functional programming concepts
Learning functional programming languages totally changed the way I code. I remember a time where I was not happy with what I was delivering. Even if I took special care, I’d have bugs and issues to solve. Code would be hard to change and adapt. I started to wonder: is there a different and better way of doing this?
Learning Clojure taught me so many things that I use
whenever I code, even if I’m not using a functional programming language
anymore: pure functions, immutability, function composition, no side effects,
modeling data with
There we have these mechanisms that prevent whole classes of bugs for appearing on our code.
I find it strange that today we sometimes need to debate the value of tests. Honestly I wouldn’t know how to program without tests. Whenever I need to do something, I start with the tests. This is a habit and, again, we need to decide it’s something we want to do. And then iterate on being better at it.
When we’re comfortable with unit testing, we can start to consider other tools, like end to end testing, contract based testing, mutation testing and generative testing.
Mutation testing is the process of heuristically determining semantics of your program that are not covered by tests. - Interview with Markus Schirp
We may not have the need for all these, but knowing how they work and how these techniques can add value is very important.
“I can’t recall ever getting a call to help a department or program get its application back on the rails and discovering a nice, healthy unit test suite.” - Interview with Erik Dietrich
We should not focus just on our code and its delivery, but also on how that’s going to be used, how it’s going to be supported and how it connects with the current infrastructure. We may do something that causes problems elsewhere: on the build pipelines, on other services, performance issues and even putting production down.
Monitoring and the ability to inspect what we’re doing is very important. And when things go wrong, let’s not forget a postmortem.
Debug and troubleshooting
Top performers are usually great at troubleshooting. They properly understand what they did and how that relates with other moving parts. They can triage and go from the overall problem to the specific issue that caused it. This means knowledge not only of the code, but also having a tool belt of skills and tools for when problems occur. This is specially useful when we’re dealing with code and infrastructure that we don’t own.
One way to improve this skill is to have a production incident training program.
We use several tools every day. From our code editor to bash commands. We should
take time to understand and customize those tools. For example, I’m a
user. I don’t get in editor wars, but I do try to optimize it to my needs.
I’ve seen developers with several types of editors that are able to take the
most out of them. Know and customize your editor.
Another example is
git. It’s useful knowing not only the basic operations, but
also how to revert actions, how to rewrite history with interactive rebasing, and
how to build a good commit timeline.
And finally, we have the process to understand how things are done by looking at the manual and/or the source code. It’s said that we can save minutes of reading documentation if we invest hours of trial and error.
A good attitude is the most remarkable trait of a top performer. When I’m doing interviews I like to ask: “Imagine that you are now the boss of your project, that you have the power to do anything, what would you do?”.
Typically I get some standard responses: following the roadmap, continue to deliver features, business as usual.
But top performers will have a ton of things to say. They’ll want to improve this and that, they would refactor a system, they would focus on making tools for the team to be better, on changing and improving processes, etc. Note that it’s important to check if they would commit to doing those things. There’s where the value is at. Having ideas for other people to implement, without experience on that regard, is not what I’m looking for.
I’d like to share some stories of developers that I interacted with that have the top performer mindset. What were their attitude and how they grew. Let’s call them David, Olivia and Thomas.
This is a very cocky guy that worked with me. We booted a project and I remember that on our first day he told me that he would be better and more productive than me. We had never worked together but we knew each other from the office.
Whenever I created a pull request, it was as his life mission was to find problems with my code. He’d question everything, and even discuss when something was not easy to understand. If he actually agreed with something, we’d play the devils advocate. He was on a deep learning quest and wanted to extract the most out of me. I do recognize that sometimes this was frustrating. Always being questioned is not something easy to handle.
But the truth is that we both grew a lot in the process. We later went different ways. He applied to a company that only hires experienced developers (10+ years) and he was still junior (3+ years). Not only did he join them, but a year later they offered him a role with even more responsibilities.
It was his drive to become better that allowed his career to sky rocket.
Once I was doing recruiting consulting. I would get candidates and would do triage and give back a report. At this one time I got someone that became memorable. She was also cocky and had 3 years of experience doing an application single handed. She did backend, frontend, operations, etc. Was very versatile and with a get things done attitude. I liked her a lot. I asked her to assess the quality level of her code and she said it was great.
Confident, resourceful, and also eager to learn. Time to check her personality. I told her: I’m going to report back that you are a junior developer. She looked puzzled. I noted that she was struggling to choose what to say next. After some time she said something amazing: why do you think that?. She didn’t strike back, she didn’t try to defend herself. She only wanted to know my reasoning.
And I told her that working alone doesn’t provide as much skills. She isn’t doing much testing, she isn’t doing code that is easy to change and peer reviewed. She lacked experience in pull request etiquette. I also asked her to consider this scenario: she would imagine another version of herself, but who had worked 3 years with 10 other developers, all of them top performers. And she replied back: okay I understand now, I still have a lot to learn.
This was already amazing. But what happened the next 5 days was even better. Every day she would go to the chat and ask me things:
- How did you get to be where you are?
- What’s the most important thing you’ve learned?
- What books do you suggest for me to read?
She was trying to learn as much as possible to make herself better.
I had started working on a project that had many quality issues. There was this guy that worked there and followed the stream but was not okay with that. This is very interesting. Even if we care about quality, we may relax it if we’re in an environment that is not quality friendly. Quality is like a muscle, we need to train it constantly.
When I stepped in I came with all my ideas and suggestions and little by little we started to change the quality of our deliverables. And Thomas would question my suggestions and sometimes say they were cumbersome.
This is very typical. I remember when I started working in Java and I didn’t know Java at all, that I created a test project and setup a linter/code analyser check on the build. And that thing was nagging me all the time. But one month later it stopped. I actually assumed that it had stopped working, but when I went to fix it, I realised that it was in fact still working, but it was me that had changed by code writing practice to accommodate the linter.
In this project we had this experience many times: starting to write good commit messages, start to delivering patches with good code coverage, all bug pull requests need a test that covers the issue, code should be clean and easy to understand and change, we should document the whys when necessary, we should have a build system that double checks everything we can, etc, etc.
Thomas adapted and little by little he transformed. His pull requests are now a work of art. And he grew and he is now pushing me to be better.
You may have noticed that not once I mentioned proficiency. Usually top performers are very skillful. But when talking about growing I’m more focused on the journey than on the final destination. It’s by practicing every day, by focusing on having better processes that we evolve into better developers.
This is an ongoing process for me also. Many times I struggle and fail at growing developers. So don’t forget to give me feedback to help me get better.
Another thing to consider: what is the end game? If a developer achieves all these processes and even more, is that the end game? No. I’d say that is just the beginning. When we reach a higher level of performance the important thing is how to scale it. So if someone is a top performer, the next step will be: how can I mentor other developers to be better than me?
And when we reach that point? Well, this compounds: how can I train someone that will train other people to be even better at growing top developers?
Author Pedro Pereira Santos
License CC BY-NC-ND 4.0