This happens more often than I’d care to admit. While programming, I’ll receive a flash of insight that maps cleanly onto a trite phrase I’d heard dozens of times before. Prefer composition to inheritance. The law of Demeter. Code is read a lot more than it is written. The pith is endless.
You’ll come across a problem and realize how doing it the easy way has bitten you in the ass. You’ll stop making the mistake of doing it the easy way, and start doing it the right way. I’ve found that with lessons like these, you almost always have to go the long way around, experiencing them firsthand before there can be a deep understanding.
A great example of one of these lessons is making small classes and small methods. Ben Orenstein gives advice to this effect in one of his posts. I remember defending to my Ruby-writing coworkers: maybe you could write Ruby that way, but Objective-C is just too complex and verbose to write with one-line methods. I was, of course, super wrong. Not only is it possible to write Objective-C in that style, it’s also joyful.
David Foster Wallace, in his now-classic commencement address for Kenyon College, said:
Because a huge percentage of the stuff that I tend to be automatically certain of is, it turns out, totally wrong and deluded. I have learned this the hard way, as I predict you graduates will, too.
There’s a delightfully meta component here: not only are the lessons hard to learn, but the lesson that the lessons are hard to learn is hard to learn.
There’s a somber component too: learning lessons the hard way sucks. Our knowledge is stuck in our brains, and can only come out in low-bandwidth forms, like prose, speech, or drawing.
When you finally have that bug that causes you to have the epiphany, all you end up with is a shitty platitude. You have no way to impart to anyone else what you’ve discovered. The lesson took time for you to learn, and once you’ve learned it, you wish you could give it to other people. If you’ve ever written a monad tutorial, I’m looking at you.
I’ve found only two ways to route around it. The first is to feel someone else’s suffering at the hands of one of these bugs and experience empathy.
The everpresent joke in computer science says there’s two hard problems: naming and cache invalidation. When I was starting out, I remember thinking “ha ha, there’s no way cache invalidation could be that hard”. Fast forward a few years, and while I’ve learned a few lessons of my own about bad caches, reading Code Climate’s incident report for a major issue made me understand on a far deeper level what it means for cache invalidation to be hard. Lesson learned, bon mot deployed.
The second approach to teaching hard ideas is to change the value function. Programmers take shortcuts and write code “the bad way” because it’s way easier. It feels as though the cost is lower than the hard way, because you can’t see the interest acquired by your technical debt. Instead of making the cost of shortcut higher, we can increase the value of the “right way”.
To make the hard way more appealing to your audience, the trick is finding the perfect example to illustrate it. Most readers will skim a new post when it comes out. They don’t stop and pick out each word you write. Code blocks break up the writing, and they provide somewhere for the readers eye to jump. Given that you’re only getting a small amount of the reader’s attention, you have to find an example that strikes the right note with the reader. The example decides if the post lands or not. It has to be relatable and short, so that you don’t lose the attention of the reader, but it has to be complex enough to not be trivial.
For example, I’m very proud of my post on the method object pattern, Graduation. This post makes it simple, obvious, and elegant to take a method and make a new class out of it. It readjusts the value function in the programmer. When the value of the good way increases, it takes far less activation energy to jump from the bad way to the good way. Put another way, the intensity of the lesson you have to learn is much lower before you’re happy to switch over.
Part of why I love Sandi Metz’s work is that she takes a simple problem, like inheritance, and thinks about it a lot, and finds the right words to make even the most novice programmer understand why to prefer composition to inheritance. I’d heard about this platitude plenty when I was just starting out, but Sandi’s talk was what really drove it home.
Ultimately, we can only do so much. It’s a shame that these methods have to be learned over and over, the slow way. The best we can do is grease that path for those that follow us.