How I Became a Better Programmer

March 20, 2017

Several people at React Conf asked me for advice on becoming a better programmer. For some reason, people see me as a pretty advanced programmer worth listening to. I thought it would be worthwhile to write down my "mental model" for how I have approached programming over the years.

Some details about me: I'm 32 years old and have over 10 years of solid experience. It probably wasn't until the last few years until I really felt confident in what I was doing. Even now, though, I continually doubt myself. The point is that this feeling doesn't go away, so just try to ignore it, keep hacking, and keep building experience.

Let me be clear that these are only a few tips for improving your skills. Ultimately you need to figure out what works best for you. These are just things that I have found helpful.

  • Find people who inspire you, but don't idolize them.

    Over the years there have been many people that I looked up to and watched for new tech. I learned a lot by simply trusting they were right and digging into things they worked on. These people tend to be very productive, brilliant, and inspiring. Find them and let them inspire and teach you.

    However, make sure not to idolize them. It's easy to seem intimidating from a twitter feed, but if you look at how they work in real life, you'll see that they aren't that different. Hacks everywhere, etc. We're all just experimenting. Lastly, don't blindly trust them; if you disagree, engage them and learn from it. Some of my most productive conversations happened this way.

    My Emacs config is a mess. I don't know why my OCaml autocompletion is broken (it's been broken for over a month). I don't automate stuff and have to dig around in my shell history to find commands I need sometimes. I write the ugliest code at first. I stick things on the global object until I know what I'm doing. The most experienced programmer uses hacks all the time; the important part is that you're getting stuff done.

  • Don't devalue your work.

    Newer programmers tend to feel like their work isn't worth much because they are new. Or maybe you are an experienced programmer, but working in a new area that makes you uncomfortable. In my opinion, some of the best ideas come from newer programmers who see improvements to existing tech that those who have already-formed opinions don't see.

    Your work is worthwhile, no matter what. In the worst case, if your idea doesn't work out, the community will have learned better why that approach doesn't make sense. (A note to the community: it's up to us to execute on this and be welcoming to newcomers.)

  • Don't feel pressured to work all the time.

    With new tech coming out every day, it can feel like the world will move on without you if you take a night off. That's not true. In fact, you will do better work if you disengage a lot. Your perspective will be fresh, and I find myself subconsciously coming up with new ideas when I'm not working.

    The majority of the stuff being released every day is just a rehash of the same ideas. Truly revolutionary stuff only happens every few years. A good talk to watch on this subject is Hammock Driven Development.

  • Ignore fluff.

    One of the biggest ways you can objectively get better faster is by ignoring "fluff" that won't actually improve your skills very much. Another way to say this is "use your time wisely". You only have so many hours in the day and if you spend it on deeper things you will see a big difference over time.

    So what is "fluff"? It's up to you, but I can give you some examples of what I consider fluff: language syntax, library APIs, and configuring build tooling. Learning a new ES7 JS syntax won't make you a better programmer nearly as much as learning how compilers work, for example. Adopting a new library that implements the same idea but with a new API isn't that interesting. All of those things are important, of course, but I recommend spending more time learning deeper concepts that will reward you for years.

    Here's a question I like to ask: do you spend most of your time making your code look "nice"? If so, I recommend not focusing on it so much. Your code is going to change a lot over time anyway. It's better to focus hard on the core problems you're trying to solve and think hard about your layers of abstractions. After you've nailed all of that you can spend a little time polishing your code. (This also applies to the DRY principle. Don't worry about it so much. Feel free to duplicate.)

  • Dig into past research.

    If you're excited about an idea, it's super tempting to sit down an immediately get going. But you shouldn't do that until you've done some cursory research about how people have solved it before. Spending a few days researching the topic always completely changes how I am going to solve it.

    It's valuable to learn how to read academic papers. I don't know anything about denotational/operational/etc semantics so there are a lot of papers I can't read. But there are many that use code instead of math and aren't too hard to read. There is a huge amount of knowledge sitting in papers from the last 30 years. If you get good at extracting this, you'll be a thought-leader in no time.

    Prettier is a perfect example of this. I knew what I wanted but I had no idea how to implement it. After a little research I found this paper and after a few days I knew exactly what I needed to do. I had something basic working in a week. If I ignored previous research it would have taken a lot longer.

    If you're looking for papers, the Papers We Love GitHub repo is a great place to start.

  • Take on big projects. Get uncomfortable.

    There's nothing better than experience. Not everyone is in the position to experiment, but if you have time, try and take on some big projects. You don't even need to finish them. Just trying to tackle something like writing a compiler will teach you tons in the first few weeks.

    I honestly hate the feeling where I have no idea how to solve a complex problem. It's uncomfortable. I know I'll have to do a lot of research and learning before I'm even close to a solution. But I'm always a much better programmer afterwards.

    Start with learning a new language. It's the most effective way to force you out of your current habits and see things in a new light. For me, the best thing I did as a young programmer was learn Scheme. It's an extremely simple language and forces you to do everything in a functional style, and really learn the fundamentals of how code works. The few years I spent in Scheme are still paying off today; the way I see code is fundamentally changed. (I even named my company Shift Reset LLC after the shift/reset operators from Scheme.)

    Here's a list of a few things I would recommend doing. These are all things that had huge impacts on my programmer career. Most of them continue to pay off to this day in subtle ways and help me to deconstruct new ideas mentally. You don't need to do these to become a good programmer, and there are many other things you can learn to improve yourself, but these are what helped me.

    • Learn C - Just the basics, if you don't already. I think it's valuable to understand why everyone complains about it.
    • Write a compiler - Perhaps the best way to get uncomfortable and learn. Check out the super tiny compiler.
    • Learn macros - See Scheme, Lisp, or Clojure(Script). Macros will really change how you see code.
    • SICP - SICP is an old book that I think is still relevant today (some people disagree). It assumes very little programming knowledge and walks you all the way up to implementing a meta-circular evaluator and compiler. Another book I really enjoyed and goes a lot deeper in compilers is Lisp In Small Pieces.
    • Understand continuations - Continuations are a low-level control flow mechanism. Scheme is the only language to implement them, and while you will never use them in production, they will change how you think about control flow. I wrote a blog post trying to explain them.
    • If anything, just try a new language - Regardless of what you do, you really should explore other languages. I would recommend any of the following: Clojure, Rust, Elm, OCaml/Reason, Go, or Scheme. All of them have unique features and will force you to learn a new way of thinking.