Many have learned programming to the point where they understand if and for and function calls, and can make the computer do what they want. Few know how to structure code so that it is easy to work with, over time and at large scale. How can you learn to structure code well? For a start, I suggest a book, an essay, a collection of functions and a talk, in this order.

Grok simplicity

Grokking Simplicity by Eric Normand teaches all the things I wish every programmer knew, but few do (at least judging from all the code I've seen so far). Other sources, such as The Pragmatic Programmer, Refactoring or TDD try to teach these, too, but they don't hit the heart of the matter. Instead they focus on lagging metrics like ‘easy to change’, heuristics like function length and proxies like testability. Grokking Simplicity hits the heart of the matter.

It is almost 600 pages long, but those are not the heavy pages of Skiena's Algorithm Design Manual. Rather, they are light pages with many pictures and repeated examples. And the more advanced you are, the faster you can move. It's not the kind of book where you skip one exercise and lose track.

Finally, you can start applying what you learn from this book in any existing codebase. No rewrite from scratch required. If you start wondering how, as you make your way into the book, I suggest reading the last chapter. It will tell you.

Learn to grow a language

Growing a language is a skill that I consider very important and which is taught in Grokking Simplicity. But in my experience, two or three more things are required to make it stick: Read Programming Bottom-Up by Paul Graham and, to see many concrete examples, explore the Clojure standard library. If you have time, watch or read enough of Growing a Language by Guy Steele (YouTube) to get the point. (If you have even more time, I recommend you watch or read it all.) I'm lazy to argue why these are the things to read/explore/watch. They are short enough to speak for themselves, I hope. But I'll leave you with a thought from Growing a Language, which might otherwise be overlooked:

I had to take time to think through how to phrase each thought. And there was this choice for each new word: is it worth the work to define it, or should I just stick with the words I have? Should I do the work of defining a new word such as mirror, or should I just say “looking glass” each time I want to speak of one? (As an example, I was tempted more than once to state the “ly” rule for making new words that change what verbs mean, but in the end I chose to cast all such words to one side and make do. And I came that close to defining the word without, but each time, for better or for worse, I found some other way to phrase my thought.)

I learned in my youth […] that it is better to choose short words when I can. […] I should try to make my thoughts clear; if they are clear and right, then other persons can judge my work as it ought to be judged.

[…] Short words work well, if I choose them well.

Notes