When I learned to drive (more than 20 years ago) and was driving a car for the very first time, I recall sitting in the car with my father after spending 20 minutes driving around the block. I felt exhausted. We hadn’t traveled more than a mile from home and hadn’t gone over 20 miles per hour, and yet I felt like I’d driven the 24 Hours at Le Mans.
Every mechanical movement – the turn of the wheel, the pressing of the pedals, the signaling of turns – required my full attention. I certainly wouldn’t have been able to navigate traffic that day – it took all of my energy just to not hit any parked cars or mailboxes.
Over time and with practice, the mechanical parts of driving became automatic. I pay attention to traffic and my surroundings, but I don’t have to think about how far to turn the wheel or when to brake (except in inclement weather). Those things just happen, and I take for granted that I will arrive safely at my destination with enough brain space to sing along to the Encanto soundtrack with my daughter while driving.
I am a principal software engineer at Launch Scout now. Writing code is fairly automatic for me most of the time. My command of the languages I use is such that I know the tools and patterns, and when I have a question I know where to look in the documentation to find the answer. Sometimes the work I am doing is much trickier than normal, and in those times I can dial in and really focus.
It was not always like this. Transitioning from being an English teacher to being a software developer took a few years, with several false starts along the way. And then it took several more years to gain the fluency I have now.
The risk we run as we gain competence is we also become complacent. The comfort of “I know what I am doing” is deeply alluring, and also occasionally a trap.
The most dangerous driver is one who feels competent but lacks the situational awareness to know when they are out of their depth. This is typically drivers who have had their license for only a few years, but who have driven enough to have attained some level of automaticity. There is a reason (actuarially speaking) why auto insurance premiums drop in cost after the age of 25.
Similarly, the most dangerous software developer is one who knows the right way to do things (writing tests first, for example), but has enough confidence in their own skill that they think their own competence will save them from making mistakes. Cut corners become well-worn paths. Old solutions get applied (and mis-applied) to new problems.
It’s relativley easy to hit a point of competence and turn it into a plateau.
Zen buddhists talk about shoshin, or a beginner’s mindset. The idea is that by detaching ourselves from our preconceived notions and narratives, we can take things as they are and presumably make better choices. It’s the inverse of “familiarity breeds contempt”.
One way we can cultivate that beginner’s mindset is by seeking out opportunities to be the beginner. We can learn new languages, new problem domains, and new tools and techniques.
(I’ve been taking tennis lessons, something I’ve long wanted to do but only recently had the time to try, and it’s been incredibly humbling to see both how much I’ve improved since I started playing and how wide the skill gap is between me and even good recreational players, much less folks who play competitively at any level. Somewhat surprisingly, the feeling of being a beginner at something has helped me become better at my job even though no part of tennis directly translates to writing software.)
The other way can cultivate that beginner’s mindset is by enlisting actual beginners. In my case, this means working with apprentices as they learn to do the work. The things I take for granted are brand new for them, and so I get to see these things through fresh eyes.
It’s somewhat like how my daughter (who will not be able to drive legally for another decade) will ask me about traffic rules while we are driving. She’ll often accuse me of running a red light (all we have done is make a left turn – our light was green, but not every light in the intersection was green). It’s how I imagine my father felt when he was teaching me to drive.
By remembering what it is to struggle, by becoming acutely aware of the foundational pieces, we deepen our practice. We make better choices. We pause to take in all the information before proceeding. We open ourselves to doing better work. By committing to doing the work correctly (we are beginners again, and so cannot rest on our skills – and even if we could, what would the apprentices think?!) we open ourselves to discovering what “correct” means here.
There both is and is not a discrete “I’ve finally made it” moment. Not one such moment, at any rate. Instead, we have a series of “I’ve made it here” moments. By embracing that beginner’s mindset, and by opening ourselves to struggle, we also get say “And I’m excited to see where I go next.” It’s like driving, in a way; we’ve gotten where we were going, and we have more destinations yet in front of us.
I didn’t learn to drive on my own. I had my parents and grandfather to teach me, and a lot of opportunities to safely practice. I didn’t learn to program on my own either – before I got my first programming job I had folks I could ask for help when I got stuck, and after I got my first programming job I had colleagues who were learning with me and helping me learn.
The mechanical parts of writing software become largely automatic with time. You’ll always need to periodically refer to documentation, but at some point your questions go from things like “How do I iterate over a collection” to “What’s the syntax for
reduce when I want a starting accumulator instead of just using the first value in the list?” – your questions become much more specific, much more directed, and backed by foundational knowledge.
As you gain fluency and automaticity, you’ll also find that the work becomes easier and (dare I say) less exhausting. You’ll have the cognitive space necessary to tackle progressively larger problems in progressively larger codebases. You’ll be able to orient yourself in new problems and new codebases more quickly. You’ll be able to do better work.
This fluidity, coupled with a beginner’s mindset and a hunger for learning, is a really potent combination. This sort of combination can carry you quite far in your career.