From the dawn of the age of computing, humans have been telling computers to do things. That has never been the problem. A stack of punch cards can instruct a computer just fine.
The problem is, and always has been the human comprehension of these programs. Because until recently all computer programs had to be written by humans, it was imperative that humans be able to understand and modify programs, the vast majority of which contained complexity large enough to overwhelm our puny human brains.
And so was born the discipline of computer science, a branch of mathematics that deals with evolving languages not so that we can better instruct computers but so that we can better understand our programs.
All the schools of thought in this field are essentially tasked with reducing this complexity to the point where we can safely and faithfully express our intent. So whether it’s Lisp, Functional Programming, Object Oriented programming or any other school of language design, type systems and so on, all of them are given this one task and the way they do this is by building abstractions.
An abstraction is a simplification of a concept that provides us the essentials of it while losing some of the detail. What detail you choose to lose and what essence you choose to capture is the fundamental tradeoff in any abstraction. The map, as they say, is not the territory, but even so armed with these maps we have been able to build, maintain and grow systems of staggering complexity.
Those abstractions are hard at work. Hard at work everywhere except, it would appear, in your programs.
This is a short file and even then one can easily get lost in it. You know you have a utils folder with 3000 LoC files, minimum. 90% of you are writing programs as a series of instructions to be followed with nary a thought given to the transfer of meaning to the next person that reads the code. This is not programming.
In order to understand this program, I have to boot up the computer in my head and process each of these instructions. Some of these are instructions to the language interpreter, in this case Ruby, to do things like open files and what not. Some of these are instructions to the framework, in this case Rails, to do things like rendering a partial, and some of these are instructions to your business logic to do some business-y thing. Three layers of abstraction, all mixed up like a lovely serving of bhel.
Or as Westerners would call it, spaghetti, which is a leaky abstraction because spaghetti is made up of only one thing — but I digress.
In order to understand the above program, I need to not only parse and execute the code like a computer, I also need to jump layers of abstraction. My feeble human brain can not keep up.
Instead, consider this.
This is programming. What does render
do? It replaces the mailwall, it replaces the paywall and it return the doc as HTML. Now if you want to know how the mailwall is replaced, you read that function. It’s a simple call to the replace
function with some parameters. If you really want to know how replace
works you can now boot up a tiny computer and see what it does. Each function only deals with one level of abstraction and the program starts to be readable because of this.
You can push this beyond the limit as well….
… if it be to your taste. 98 lines of bhel-puri condensed to 28 lines of Bailey’s Irish Cream. Three different flavours mixed together in one smooth-ass mouthful. You can get high on this shit if you’re not careful.
Why do your programs not read like this?
There are three reasons.
The first reason is that, truth be told, you don’t know better. Neither have you been so dissatisfied with the scheme of things that you left everything to solve this problem. You’re so busy shopping offers, running away from the ubiquitous mess, never having enough authority to actually fix things, in stand-ups morning and night, under pressure to deliver the next feature and the next and the next that you never took the time to really ask - where do the problems in my code come from? What, after all, is programming?
Well, now you know. So you don’t have that excuse any more.
The second reason is that you don’t read good code.
One of my startups collapsed under technical debt. Ironically, the business was fine and growing, but the stress of working on the codebase resulted in extreme fatigue, short tempers and eventually blown fuses.
So I took a three month study leave and I studied this problem as deeply as I could. And one day I was coding and the Internet went down. Without access to StackOverflow, I was forced to open up the gems and read the code to understand how to make them do what I wanted.
And what I saw there blew my mind. I learned so much from reading good code that I would now routinely disconnect from the Internet while coding so I was forced to read through the code I was using.
Turn off your StackOverflow and copilot. Please.
The third reason is that you don’t write tests. I see you roll your eyes and say oh God there he goes again but it’s true. The biggest predictor of good code is the ability to refactor audaciously, fearlessly, with confidence. The kind of confidence garment merchants from Ghaziabad develop in Pattaya. And if you can’t do this you will always end up with poorly factored and hard to read code.
This is a good time to show you how the tests evolved along with the code.
Before →
After →
Do you see the abstractions we built at the end of the spec file? We made our own matchers so the tests would read at one level of abstraction. This is an act that is perhaps too audacious for you to have even considered earlier.
The real reason your code doesn’t read like this is because you don’t demand it. You wake and sleep under the cover of the warm blanket of security provided by the abstractions that surround you, and yet you wet that selfsame blanket with every single line of code you write. Blind you are to the intellectual achievements of those who designed and built the systems you work on.
Respect the abstractions. Your code will love you for it.
</article>
This is a free post because it’s targeted at junior devs. Even so, there’s great value in getting a paid sub. Every fortnight I’ll send you an article which will hypnotise you into being a better programmer and manager. Thanks for reading and do share if you liked the article.
Keep reading with a 7-day free trial
Subscribe to The Engineering Organisation to keep reading this post and get 7 days of free access to the full post archives.