Developers Need To Make Mistakes

Think about the last time you learned a skill. Were you awesome at it right off the bat?

Or did you make a series of mistakes, learned from each one, and adjusted what you were doing to improve?

Anyone being truthful would say the latter. A core part of learning is trying something new to see if it works. Most of the time, it won't work. That's ok. We look at why and try something else.

This feedback loop is critical in learning and growing a skillset. It's useful even if you've been practicing a skill for decades. People who get out of this loop end up having their skill stagnate. This is especially true for software developers.

Software developers who have learned a lot (and consequently made a lot of mistakes) often get promoted to a leadership position. It could be a management role or it could still be an individual contributor role with leadership responsibilites.

What do those developers (including myself) do immediately as they enter that role?

We create processes to try and minimize mistakes other developers make. We try to prevent every mistake in our code reviews. We suggest design and architecture decisions that avoid the mistakes we've made in the past.

We hinder our teams' ability to learn.

And in the process, we inadventantly make them dependant on us. They're not learning so they are reliant on our experience. We start down the slippery slope into hero culture.

Now you may be thinking "but they're learning from your decisions!" Sure. But how often are two decisions exactly the same? How many times have you silently criticized your manager for making a decision because "it worked for them years ago" ?

Knowing the outcome of a decision, even if the justifications are provided, is not learning. There's more to it than that. There is all the alternatives that were not picked. There is having to practice the creativity needed to come up with all the options. There is having to live with the consequences of a decision. Opinions tend to change when a person has no one to blame for the outcome but themselves.

These days I put a heavy focus on making sure my team is capable of making decisions even when I'm not around. The most critical part of that is giving them the freedom to make mistakes.

There's a lot of ways to do this. One way is to ask questions in code reviews instead of making demands. Have you considered X? How does this code work if we hit situation Y? Why is this better than this alternative implementation? So long as there are good justifications to those questions, the code review is approved. It doesn't matter if it isn't how I would do it. It doesn't matter if I think the error message could be a little more robust. It doesn't even matter if an edge case is purposefully ignored, so long as there is a good reason to ignore it. If the developer is proud to own that code, then it gets approved.

Worst case, I knowingly let some "bad" code through. But if the author had good justifications to all my questions, then they'll be able to find a way to recover from the issue. They'll also have their assumptions challenged and learn better for next time.

Best case, I'm wrong about what I considered bad code and I learn something. Either way, learning happens.

There are obviously some lines that have to be drawn. A piece of code that will corrupt data permanently can't be approved. Code that will cause production outages can't be approved. Some mistakes have major consequences and can't be made. But most (potential) mistakes don't fall into those categories.

Stepping back from code reviews, the people who write the code should make the initial design and architecture for that project. Those are more impactful decisions than any of the ones that come up in code review. Making all the decisions here requires understanding the full context for the project. The combination of having context and having made the decisions will set those developers up to write better code. They'll also be more capable of handling any issues or bugs that come up with the software on their own.

Of course, reviewing all these decisions during code review is way way too late. They need to be reviewed early. The same advice with code reviews apply though. Ask questions instead of making demands. Help those developers gain the context they need to make good decisions. If you feel they are about to make a mistake, think about what the consequences of those mistakes will be.

Is a large amount of technical debt about to be introduced that will plague the team for years? That's a big consequence and the mistake should probably be prevented.

Is the team going to add a few days of work when they realize one approach won't work and they have to backtrack? Believe it or not, that's a small consequence. I've allowed that numerous times in my career. The result is always a short term hit to productivity in exchange for a huge amount of learning for those developers, which translates to massive productivity gains. Those developers learned in a few days what I wouldn't be able to achieve with months or years of nagging.

When people say "invest" in your team, they usually talk about training courses, 1-1 discussions, or time to work on their own projects. Those are all important, but they aren't enough. The biggest investment you can make in your team is giving them room to make mistakes with real projects in real situations.