Sometime last year, I came across Julie Zhou's article on Junior Designers vs Senior Designers. I love it - she does a fantastic job of highlighting the thought process behind different levels of a role. And with the understanding I've gathered in my blossoming career, today I'd like to do the same for developers.
I've had the privilege of working with exceptionally talented and thoughtful professionals since the start of my career. This might have intimidated me at first, but I quickly came to view them as mentors - a source of growth and exciting challenge. Much of my current skillset is influenced by them, but also quality time set aside in my day-to-day that's dedicated to deliberate practice. As I reach a point in my career where I'm steadily being assigned more senior-level tasks, I can't help but look back at my thought processes when I first started off and compare them to today's.
The tapestry of foundational knowledge for senior developers seem to be without a hole. The greater your understanding of how things come together or why something works the way it does, the greater your chances of building an optimal solution. In one of my first React projects, I wasn't sure how to get a component to update based off of a variable changing in another same-level component. I spent more time than I should have going down a rabbit hole of custom hooks,
useRef, and ended up with a hacky fix with useState. Looking back, it was clear that if I truly understood the component lifecycle and the reasoning behind some common React hooks, I would have known useEffect was built for the very purpose that I was attempting to solve for and I would have been done in just a few lines of code. If my fundamentals were clearer, I would have caught that earlier. Solid foundations are what contributes to razor sharp troubleshooting skills too...which leads me to my next point.
I find that when junior devs encounter a bug, they'll attempt to through every bit of knowledge they have in that arena until something sticks (and by sticks I mean until they have a different error). Seniors approach a bug more heuristically, taking the majority of the time to understand what the problem even is before jumping to a solution. They'll ponder on what the missing puzzle piece is. Once that information gap is realized, the understanding naturally leads them to possible solutions they can retrieve from their tight-knit tapestry of previous troubleshooting scenarios.
A common beginners versus experts trope is the famous Picasso quote: "Learn the rules like a pro, so you can break them like an artist". Oftentimes when you're starting out, you're constantly seeking affirmation if the code you've produced checks off all the boxes. After some time, once you've gained the ability to make that judgement call yourself, you can bring that judgement into the process of coding itself. You know where it's ok to cut corners to postpone a requirement to version 2 because you know how version 1 will meet the expectations of stakeholders in the most important ways. This also ties into the laziness factor. There is a difference between being "efficiently lazy" in creating a speedier process to improve a future need versus being lazy as a conclusion of not understanding what cutting that corner will cost the team.
You might be wondering how this differs from my point on troubleshooting. When I say troubleshooting, I mean that there is a clear error to be unblocked or bug to be fixed. When I refer to understanding a problem, this could mean a project requirement, like build a modal that pops up when you click on button X.
My Operating Systems professor in college once told our class, "if you understand the problem, but you don't know how to solve it, you don't understand the problem." This stuck with me. If I ever came to a point when trying to make something work where it seemed every direction was a dead end, it was a sign for me to step back and refine my approach. Refining my approach always meant going back to my understanding of the problem. It can be tempting for many junior developers to begin coding as soon as they have a quick, abstract grasp of what the problem is asking and then figure out edge cases along the way. Senior folks have mastered understanding what a problem is going to entail, and with speed.
A lovely example of this is when a project I was on involved building a text input with autocomplete ability. Upon seeing this requirement I was unsure of where to even begin. My teammate on the other hand, was able to build it in a few hours. Curious as to how, I asked him to walk me through his thought process:
- I need this text input to autocomplete...where else has there been an autocomplete in the company's products? Ah, yes the landing page of product XYZ.
- Dissect that autocomplete feature that's already in production. Open up the Network tab on Chrome DevTools and reload the page. What resources is it requesting? Looks like it's using resource ABC.
- Use sourcegraph (a tool to universally search through all code in the company) to find instances of components using those resources.
- Dissect those instances to see how they've built autocomplete.
While it might take a junior a few steps back into contemplating the problem once they've already dove deep into coding, seniors usually stick with the problem and then start once they fully grasp the scope. This helps them to build more reliable foundations with flexibility in mind, like what data should pass through which components as they have an idea of what else might come up if the direction changes.
This ties in with point #4. Chances are, if you understand the problem better you're better equipped to know how long something will take to get done. This is helpful in kickoff meetings for a new project, pointing tickets in sprint planning, or even just any conversation with a stakeholder who's not an engineer. As the builder, heads obviously turn to you when a Product Manager asks, "So how long do we think this project will take?" or "Is end of June a viable target?" I'd always watch my fellow developers who were far senior to me with a look of mesmerization as they gave an answer consisting of the perfect balance between giving exact dates but leaving room for unexpected delays or dependencies. This is a skill that cannot really be "practiced" in a sense of an online course. It's something that comes with more development experience as well as time in the industry.
This is a jab at the commonly argued differences between studying computer science in an academic sense and applying software engineering in industry. Much of what happens before or after you push your code is not quite discussed in college because you rarely work in environments where what you're developing is directly going to affect someone else's branch - considering you're usually working alone. Let's think about the pipeline. Senior developers have a strong grasp on steps like linting, testing and building. When you're thrown into a new project as a junior developer who's only ever worked on python assignments that require you to build a function for some outdated mathematical function, it can be frustrating to troubleshoot your way through a pipeline failure.
Some of the points I've discussed here are ones I'm still practicing. Many are in your control, like picking up a new skill. But things like robust problem solving ability and confidence in scope understanding need time to develop. This is exactly why experiences like internships, freelancing and volunteering are invaluable assets to sharpen your judgement. Strive to put yourself in situations that challenge you with people that inspire you.
I know all too well this process of growth can feel maddening, like taking 2 steps forward and 3 steps back. Writer Alice Walker penned the discomfort of growth beautifully:
"Some periods of our growth are so confusing that we don’t even recognize that growth is happening. We may feel hostile or angry or weepy and hysterical, or we may feel depressed. It would never occur to us, unless we stumbled on a book or a person who explained to us, that we were in fact in the process of change, of actually becoming larger than we were before. Whenever we grow, we tend to feel it, as a young seed must feel the weight and inertia of the earth as it seeks to break out of its shell on its way to becoming a plant. Often the feeling is anything but pleasant. But what is most unpleasant is the not knowing what is happening. Those long periods when something inside ourselves seems to be waiting, holding its breath, unsure about what the next step should be... for it is in those periods that we realize that we are being prepared for the next phase of our life and that, in all probability, a new level of the personality is about to be revealed."
For all the junior developers out there: May the pressure to perform be lifted. I hope this article will help you to see there are key areas you can productively focus your energy. As for the rest, time will tell.
Shoutout to ShutMeLoud for the hilarious gif on the cover. Be sure to check out the video for the full clip.