I originally compiled these thoughts as an email response to my mentee at Emergent Works, but I thought other people might benefit from it, so I've turned it into a public blog post.
There are an abundance of coding exercise platforms on the internet. Most of them will try to convince you that by completing their exercises, you'll be ready for a career in software. There's truth to that assertion, but it comes with important qualifiers.
Coding exercises will help you practice specific skill sets. They will also provide you with a tight feedback loop. At the outset, you'll improve those specific skills rapidly because of their narrow scope and quick feedback mechanism.
However, a fruitful career in software requires mastery of more than syntax, semantics, computer science riddles, and aptitude tests. To be a very successful software professional, you must also learn to make responsible business decisions, adapt to new technologies and domains quickly, and you must develop judgment about when to use old, boring solutions instead of cutting-edge trends. These skills are harder to teach in coding exercises, and come from hands-on practical experience.
There's a chicken-and-egg problem here. How can you get hands-on practical experience without some fundamental training? How can you understand what the fundamental training is trying to teach you without the broader context that comes from experience?
The answer is to practice both types of learning in tandem, and accept that you will initially struggle in both areas. The struggle is important, because as you struggle with your coding exercises, you may find wisdom from project-based work, reading books about software craftmanship, or asking experienced coworkers and mentors for help. And as you take on more responsibilities and challenges in your career, you will begin to recognize the application of many of your early coding exercises.
I conceptualize coding exercises in three buckets:
Syntax and semantics
Some coding exercises are designed specifically to teach you the syntax of programming languages. You'll find them on website like:
These kinds of exercises have the most rapidly diminishing returns of all. When people learn natural languages, their goal is to be able to have conversations without a dictionary or reference material.
But when it comes to programming languages: the most proficient programmers frequently use reference material to enhance their ability in real time.
It is good to start with these exercises to get used to a new syntax. They also provide you with code samples that illustrate the art of the possible. But be wary about trying to memorize and internalize the exercises as you might do with a vocabulary assignment in a natural language class.
Your time is better spent learning a few key commands to become capable of writing a workign program, and then looking up reference material when your vocabulary fails you. This is a virtuous cycle because you will only spend time learning the syntax and semantics directly useful to your work, and you will learn those things well. As you do more and more professional work, your aptitude for picking up languages and quickly reading through reference material will improve.
Abstract problem solving
There are a variety of "classic" logic/mathematics/computer programming problems in the world. Many people are exposed to these problems through formal education. For people without that exposure, curating a list of the "fundamentals" is challenging. The secret is: there is no canonical list. Computer science is a young field. Software engineering is even younger. Both fields are beholden to trends in education. If you pick a random episode of Computer Science: Just the Useful Bits, you're guaranteed to hear Noah Gibbs remark about how different his CS education was than any of his guests. And if you compare different guests, you'll see widely divergent perspectives on what the "fundamentals" are.
Putting aside my nitpicking about the idea of "fundamental" computer science, it's true that many software professionals have a shared academic background. Becoming familiar with that background will help you in your career as you talk to people. Perception matters, and being able to communicate within a shared set of assumptions can improve peoples' perception of you.
There are coding exercise websites that curate these kind of fundamental computer science challenges and provide you with quick feedback on your solutions. You'll find that on website like:
The value of these exercises is that you can develop a familiarity with common computer science ideas, and use the exercises to practice your syntax and semantics in a given programming language. That's a compelling case, in my opinion, to spend only a little time in the first category of exercises, and move on to these exercises as soon as you can. You will get more out of these challenges, and there is more here to learn.
Still, the balance between abstract knowledge and practical experience is shifted a little too closely to the former. There is another, more balanced category of exercises.
Gatekeeping aptitude tests
Software hiring is broken. It's broken because companies like Facebook, Apple, Amazon, Netflix, and Google (FAANG) experience unique hiring challenges that most companies don't. To address those challenges, they create interview processes that are extremely skewed towards false negatives, as opposed to false positives.
To put it another way: they would rather turn down 100 amazing employees before hiring even 1 mediocre one.
I don't have any evidence as to whether or not this achieves their goals. I won't speculate. I will say that the overwhelming majority of companies have attempted to follow their lead, and that is harming the industry. It means that hiring processes are inefficiently turning down perfectly good candidates for all the wrong reasons. They reap few if any of the benefits of this high threshold that FAANG companies can afford to maintain, and they continue to shut out qualified and competent candidates along lines that reflect inequality in our society (racial discrimination, housing discrimination, immigration discrimination, education discrimination).
A cornerstone of this exclusionary process is a type of exercises I call gatekeeping aptitude tests. In the same way that SAT tests measure income, not aptitude, these kinds of exercises really only measure how many of these types of exercises you have seen before. These gatekeeping tests weaponize computer science knowledge against people who would like to contribute to the shared community of software knowledge.
Anecdotally, I've noticed fewer and fewer of these tests in hiring processes over the past year or two. I have noticed more people speaking out against them. Perhaps I'm in an echo chamber, but I am somewhat hopeful that the software industry will collectively decide to forgo them as part of the hiring process.
But for the moment, getting adept at these kinds of exercises is a contributing factor towards success in software interviews. Moreover, since these specific sets of exercises are tied to business goals and money, there is a more robust industry centered around creating good resources for them. These exercises also contribute towards the goals laid out for syntax and semantics exercises, and abstract problem solving exercises. They require you to use programming languages to complete, and they are usually modelled after classic computer science problems. This means that by practicing these gatekeeping exercises, you will improve your working knowledge of a programming language syntax, you will be exposed to a common set of computing related challenges, and you will become more adept at navigating the broken software hiring ecosystem.
If you only do one type of exercise, make it this one. If you do some syntax exercises, I recommend quickly jumping to abstract problem solving, and I recommend jumping quickly again to this set of challenges once you have seen a few of the classic examples of computer science challenges.
To get started with these exercises as a complete beginner, I recommend you:
- Read Cracking the Coding Interview to get context and useful tips on how to approach these challenges. In many ways, this book is one of the reasons for the broken state of software hiring. But if you want to participate in that process, it may help to understand how we got where we are today.
- Join LeetCode and work through interesting courses, paths, and problem sets that line up with your interests.
- Alternatively, join HackerRank. HackerRank provides a similar set of features as LeetCode, but I personally prefer LeetCode's interface, grading system, and resources.
Other ways to get better
I think once you spend time with the aforementioned exercises, you will experience diminishing returns on your progress. Which leaves the question: "what next?"
Here are some things that have worked for me beyond coding exercises:
- If you're just getting started, you may want to begin with very heavily guided tutorials. The challenge is finding cheap or free tutorials. I subscribe to blogs like CSS-Tricks and follow along with any how-to articles that catch my interest. If you have the means to pay for a course, I really like Level Up Tutorials, Frontend Masters, and Wes Bos. Those resources are pretty frontend/full-stack heavy. But they should give you a benchmark for the kind of tutorial I think is best.
- ProjectLearn.io will help you connect the dots with what type of tools you want to learn and what type of projects you want to work on. It has an advantage in that most of its resources are free, or more affordable that tutorials. But it requires a touch more experience since it is more self-guided.
- Once you find yourself comfortable in tutorials and demo projects, I think there is a strong case for dense, deep-dive books. As an intermediate software professional, I have learned a lot from books like Rebuilding Rails and Mastering Software Technique by Noah Gibbs. I found these resources by listening to podcasts like Rails with Jason and ShopTalk Show.
- Building projects for myself and freelancing. It is not a prerequisite to being successful in software to do work outside of your working hours. But if it inspires you and gets you think and actively work on your skills in an enjoyable way, I think personal projects that solve your own problems, or freelance projects that provide side income are a great way to learn. You get quick feedback like coding exercises because you can ask yourself "is this making my life better?" or ask your client "does this meet your requirements?" and get an evaluation of your work. With that evaluation, you will learn and improve.
Software is an extremely powerful tool in our world, but it is not magic. There is no special "kind" of person who is uniquely good at producing and working with software. You can improve your skills at software like any other skill you can practice. Good luck, I can't wait to see what stuff you build.