Between Art and Algorithms

January 14, 2024 5 minute read

I was more of a humanities person in high school. Didn’t do great in math and informatics, loved history and philosophy. So most people were surprised when I decided to pursue programming, and afterwards stunned when I managed to make a decent career out of it.

“You were never a science guy”, they’d tell me.

I’m still not. And that’s when I tell them my long and boring lecture about how programming is as much of an art as it is a science.

To many people logic and art are the two distant ends of the creativity line where you have to pick one or the other. To me, they are both sides of a circle and they lead to the same spot of absolute craftsmanship. The greatest engineering marvels are a work of art, and the best paintings and poems have more logic than you’d imagine.

Programming and writing, are two sides of the same coin.

Voice

When I start reading a new book it takes me a while to get used to the author’s voice. No two people’s thoughts ever flow the same way and the first pages always feel like an effort until I get used to it and my eyes start flowing through the lines.

I feel the same way when I’m browsing an unfamiliar codebase. It will take me a few days to get used to the conventions, the folder structure, and the logical flow.

Much like writers, programmers establish their own voice with time. They adopt practices from different schools of thought - some gravitate to OOP, others prefer a functional style, and some write procedural code regardless of the language.

I once heard a colleague say that someone was writing Java in a Go codebase referring to another engineer who wasn’t able to change his writing style.

That’s why linting and formatting tools are so useful in programming. They remove the “voice” of the programmers, making them follow a specific way of writing that we can all get used to and not waste time figuring out someone’s naming or structural preferences.

And that’s why I’ll never follow a style guide when I’m writing prose.

The First Draft

The first implementation of any program you make is your first draft, and much like in writing, the first one is never good. It’s proof. You write it as a testimony to yourself that the idea in your mind is achievable by a human being.

You don’t fret over performance, the same way you put aside all the commas and grammar when you’re writing a story for the first time. You’re telling it to yourself.

But editing and doing second, third, fourth, and sometimes even fifth drafts is acceptable only in writing. Too many programmers leave their work half-done and ship their first draft to production.

Not only is this hurting their work, for they will have to come back, extend, and maintain their mess of creation, but it’s hurting their abilities as engineers. Real writing happens in the edits when you’re sweating over every word. Great engineers are born in the refactoring process, when they’re structuring their work, shaping it like sculptors.

But most importantly, if you ship your first draft, you’re missing out on the satisfaction of looking at your work, thinking “Man, I wrote that…”

Subjectivity

One event I’ll never forget is the hour-long lecture my high-school literature teacher gave me on an essay about a poem. She threw a barrage of witty jokes at me in front of everyone because I dared to express my own thoughts and didn’t follow the analysis structure in the textbook.

I had committed a cardinal sin but I couldn’t understand why.

This mirrors my experience submitting my first PR for code review a decade ago. Why are you doing this? This doesn’t make sense. What have you done here? Do you not see the potential problems this can cause? The senior engineer in the team wasn’t one to spare criticism.

But… it works - was the only thing I kept repeating. Both in high school and at my first job.

It didn’t matter that it worked, I did it in a way that didn’t match the standards everyone used or the patterns they were all aware of.

It wasn’t “clean”.

But what is “clean” anyway? It’s a five-letter word that every engineer fills with their own preferences. To some, it means testable, to others readable, to another group it means you’ve followed the idiomatic practices of the language, and there are the Uncle Bob purists who demand you stick to the guidelines in the book.

And no matter what you do you can’t satisfy all of them. Some maybe, but not all.

The term clean is filled with subjectivity, the same way an author’s way of writing can be nigh unbearable for some readers and breathtaking for others. It’s all in the eye of the reader (or reviewer).

There are abstract evergreen rules that we agree to follow. We know active voice is better than passive voice, and that showing is better than telling. In programming, we agree to keep things simple and avoid duplication.

But even they can be subjective, and anything beyond them even more so.

The Reader

The programmer is an author who is writing for a very picky reader in the face of the compiler. On top of that, the language I have at my disposal has a limited vocabulary compared to the one I can use when I’m writing a story.

And on top of that, if you get one thing wrong, the compiler will disregard it altogether and send you a cryptic message often painted in red that will make you question your choice of career. Few human readers do that.

The compiler is a savage critic and being on the receiving end of its negative feedback can be very disheartening.

That’s why the jump from a statically typed to a dynamic language feels like switching from Shakespearean prose to a chat with a friend. The rules are far simpler, the writing process is quicker and you receive less negative criticism. But with time you appreciate the complexity of a more verbose writing style where you make everything known and the reader doesn’t have to consult with an appendix every few pages.

Borrow From Both Worlds

It helps if you look at yourself as a writer when you’re having trouble with an implementation. You just haven’t found the right expression to convey your idea to the compiler.

Being an engineer helps too.

When I’m creatively blocked I don’t shelf a story for weeks, waiting for the muse. I do what an engineer does.

I go for a walk, I start from the end, I change perspectives, I tell the story to my wife, I get a good night’s sleep, and somehow things always fall into place.

Tao of Node

Learn how to build better Node.js applications. A collection of best practices about architecture, tooling, performance and testing.