Recently a former student and dear friend asked me this question: I feel that I am switching back-n-forth between a few different things at my job, and that there isn't a lot of focus. I worry that I only have a basic level of knowledge on each thing and am not able to get to the next level on any of them. What can I do to make sure that my skills don't stagnate?
I thought long and hard about this question. I thought back to my younger career and the things I did back then. I thought about answers some other senior developers gave. I even test drove a couple of answers with the junior developers I currently work with. I settled on a list of four things:
- drill down
- refactoring
- building for developers
- evaluate your progress
Next, I will go into more detail and specifics on each one. Come along!!!
Drill Down
If you really want to get good at something, you want to go deep, not wide. Don't go chasing after every tutorial that's on discount. Don't learn CS algorithms just because that's what people are talking about on twitter. Don't chase all the latest buzz words if they are not relevant to your day-to-day work.
Don't get me wrong, it is valuable to know a variety of different skills, but it's not enough. If you want to get to the next level, you must go deeper. And nothing will give you a more immersive experience than your 9 to 5 job. Well, in most cases. If not, maybe re-evaluate your options.
What does drill down mean? It means you want to drill down to specific skills in your repertoire and really get a deep understanding of the subject and really refine the skill. Get obsessive about it. Like when you hear a song you really like and you get obsessed about it, and you play it on repeat in the car, and you memorize the lyrics, and you sing along with the recording in the car, and you listen to the other songs on that album, and you obsess about that artist, and you listen to their other album, and another album, and you obsess about another song that's not an original, and you find the original artist that recorded that song, and you listen to different versions of that song, and you memorize that song, and you learn to play that song on your harmonica or whatever instrument you play. You know what's really insane? You find this new song you are really obsessed about and then you find that another favorite artist you used to obsess about also recorded a version of that song. You listen to it and it's so good and so much feelings are bubbling up and you are experiencing this euphoria and you are wondering whether you are hallucinating???!!! 'Know 'I'm sayin'?
That's what I mean by drill down.
Okay, how do you find a target for a drill down? Look for things that
- You feel vague or uncertain about.
- Has come up multiple times.
- You are interested in learning more about.
- Is relevant to your work.
How do you actually drill down? Apply all of the learning skills you already know, but just in a much more focused way, directly at your target:
- Research and read articles online.
- Ask plenty of "why" and other questions.
- Research some more.
- Perform toy experiments to get answers for yourself.
- Ask experts in the field - go find them in Slack communities and IRC rooms.
- Ask your mentors.
Refactoring
Refactoring means changing the design of the code without changing its functionality. It is really important in software development because software gets more and more complex over time at a rapid rate. This happens because software developers are constantly adding to it - that's what you get paid to do every day! As the complexity goes over certain thresholds, things get untenable unless structural changes are made.
It's like the structure within a company. Take a startup, for example. If you are a solo-entrepreneur, all you have to worry about is yourself and there is zero communication overhead. Once you have a co-founder, you have to work on communication. That means taking care and planning to meet regularly, and to be courteous of each other's needs and desires. When you scale up the company to say 5 or 10 people, it's yet a different ball game. You'll start needing to have company meetings and processes and standards in place, and think about further growth and how to expand the team. It's more different yet when there's 50 people, you may need an HR department. Even more so when there's 500 people; 5000 people, 10,000 people, etc. As the company grows to each level, new structural changes need to be keep it running smoothly. Without the needed structural changes at each stage, the company's operations will bog down.
The same happens with code. A code base that has only 100 lines, vs 1000, vs 10,000, vs 100,000, vs 1,000,000 lines. At each level, different structures are needed to keep the codebase running smoothly. By running smoothly, that means the developers are able to maintain the code and add new features efficiently. Refactoring is the work that provides those needed structural changes as codebases go through these growing pains. But it is too often the case, in too many companies, that a codebase does not receive the structural changes it needs. To put it another way, too many codebases in the industry are overdue for refactorings, and as a result, their developer productivity spirals downward over time. This is an opportunity for you.
Refactoring is difficult. Few developers are very good at it. Why? When you refactor code, you are really redesigning the code, and that requires two abilities:
- The design chops (skill) to come up with an improved design.
- The ability to get the codebase from here to there.
Both of the above abilities are difficult to attain. But that's not a reason to give up. Au contraire, it should motivate you to get good at it. Because once you attain them, you would be one of the few.
How do you get good at refactoring? Well, by doing it, of course. Look for refactoring opportunities, big and small. If you are a refactoring novice, start out with the small ones, and then gradually move your way up. Uncle Bob's boy scott rule is: always leave the campground cleaner than you found it. Apply it to your work.
When you are tackling larger refactors that involve making changes to multiple files or components, it may be more difficult to see the forest from the trees, and you may sometimes pin yourself into a corner in the middle of a large refactoring move. This is okay. Failure is an option. Do it on an experimental branch. Throw it away if it doesn't work out. Sometimes you may have to have several tries in order to come to an improved solution.
If you are at a fork of the road and you are unsure which approach to take - which approach would yield a better design at the end - there is a simple way to know: try them both. Try them both, then decide. The reason it was hard to decide is because of uncertainty. Now that you've done it both ways, you can evaluate the pros and cons of each approach based on the final result of each. Yes, this does means you are going to throw away some work, but this is how you gain the design chops you need to be a next-level refactorer - or err...maybe "software architect"? How does that sound?
Over time, as you get more experience this way, you'll be better able to imagine what the outcome would be in your head if you chose one approach vs another. Now you might think: "If that's the case, I'll just get my senior architect to decide for me." Yes, but then you won't get the experience of seeing the result of both approaches. And, even senior architects still sometimes have to do it through trial and error too. So, look at the extra added work as tuition for getting to the next level.
Building For Developers
Experienced developers are more "meta" than juniors. Rather than only building software for users, they also build software for developers, who in turn build software for users.
Why would you do this? To make developers more productive. In case you didn't catch it, this is the purpose of refactoring as well. In fact, many artifacts built for developers came as a result of refactoring. For example:
- a reusable UI component
- a reusable utility module
You can also build things apart from the core software itself. For example:
- a module (ex: npm module, a gem, an egg, a jar, a crate)
- a plugin to a framework (ex: redux thunk, express body parser)
- a CLI tool (ex: npm, eslint)
- a project template (ex: HTML5 Boilerplate)
- a CLI tool that generates a project template (ex: create-react-app)
- a web-based tool (ex: online CSS gradient generator)
- a desktop tool (ex: Postman)
When you gain the ability to build and design software for developers, you are helping your entire team become more productive, not just yourself. Also, you'll get a different perspective on what being productive means: working smarter, not working more.
Evaluating Yourself
Finally, I want to give you some ways for evaluating your learning progress. If your goal is to level up, how would you evaluate whether or not you are actually leveling up? Here are a couple of ideas:
- Every time you have an ah-ha moment - as in, something in your brain just clicked into place - you just understood something new - write it down. At the end of each week, count the number of ah-ha moments you had.
- Every 2 month or so, look back at some code you worked on 2 months ago or longer. Do you have new perspectives/ideas on how to improve that code?
That's it! Take everything I say with a grain of salt. Good luck on your journey! May the force be with you.