When writing code, there are many specific principles that aim to make your code more maintainable: DRY, the single responsibility principle, the Law of Demeter, the open/closed principle, etc. These are great principles to follow, but it can be difficult to keep all of them in your head at once. I’ve found it’s often easier to keep a few broader ideas in mind.
Change Your Perspective
As I’m writing code, I try to constantly review it from the perspective of a new developer joining the project. I imagine what it would be like to read this code for the first time.
Would I understand the overall flow? Have I used terms in a way that is consistent with the rest of the project? If I had to search for this thing without knowing what it is called, would I be able to find it quickly?
At Atomic Object, we often do pair programming, which is a great way to immediately get answers to these questions from someone who is not you.
One of the best ways to ensure that your code is maintainable by someone else (or your future self) is to make it self-documenting. I don’t mean that you should add comments all over the place. Comments should be reserved for the rare bits of code that are influenced by factors beyond the code itself (for example, a customer requirement or a bit of historical context). But rather, put serious thought into the naming of everything. After all,
There are only two hard things in computer science: cache invalidation and naming things.
— Phil Karlton
Have you ever seen an obfuscated code contest? Yes, it is possible to write code that does something useful and yet is completely unreadable itself. Those contests are just for fun, of course, but it can be easy to slip into bad formatting habits (or apathy toward it altogether). Code that is pleasing to look at also tends to be easier to scan quickly.
Compilers are actually pretty good at parsing and optimizing code, while humans are not. Take pity on the puny humans, and write code for them first, with the machine as only a secondary concern.
Prefer clarity over cleverness. Readability counts for far more than small optimizations. Brian Kernighan said it best:
Everyone knows that debugging is twice as hard as writing a program in the first place. So if you’re as clever as you can be when you write it, how will you ever debug it?
Avoid Special Cases
Few things will wreck your code faster than special cases. These are the things that take your nicely constructed machine and poke holes in a few of its tubes. It might seem easier in the short term to just slap some duct tape on it and try to ignore it, but if you don’t fix the root issue, it’s just going to spring a leak again later on down the road.
This might look like a quick-and-dirty fix to get something working in time for a release. It might look like reusing a component for something it definitely wasn’t designed to do. It’s those things that mostly work but have a few nasty jagged edges.
It can be tempting to simply use something that gets you most of the way there, but it takes discipline to refactor that thing so it gets you all of the way there. It’s worth it!