On Suffering

Ivan Appel
7 min readJan 28, 2025

--

It took me about twenty years of tinkering with Python to attain what Zen Buddhists call enlightenment. I’m not saying it will necessarily have the same effect on you, nor was it the only spiritual technique I practised during that period of my life, but it certainly played a part.

For the majority of those twenty years, it was Python 2.x, which was a great language that I still miss dearly.

The philosophy of Python 2.x was rather simple. Essentially, it was “for a thousand-line program, we’re the best tool available; for a million-line program, look elsewhere.”

Also, Python 2.x was actually fantastic for writing thousand-line programs. Mind you, when you have a powerful standard library and an even more powerful repository of third-party packages, and local traditions allow you to say stuff = [{'blabla': 42}] rather than public class StuffDecoratorVisitorFactory implements StuffVisitorDecoratorProvider, there was a lot you could get done in a thousand lines of code. You could make a CLI utility, or you could make a REST webservice, or you could make an ad-hoc data scraper and analyser, all in a thousand lines of Python. In Java or C#, it was significantly harder to do (I’d tell you a pom.xml joke here, but they’re all just too long…), and C++ wasn’t better.

One might say (in a condescending tone, obviously) that “this is a small piece of software that doesn’t have many functions.” To which I’d reply, “This is a sufficient piece of software that doesn’t need those functions.”

Look, if a problem you have at hand can be solved by a five-page script you’ve jotted down in an afternoon, there’s nothing wrong with that per se. There’s no technical necessity to inflate it into a “proper” multi-week or a multi-month project. There might be an organisational necessity, but that’s a story for another day.

Now, let’s talk about million-line programs. A million-line program isn’t something you write from the beginning to the end in one very long sitting. A million-line program is an outcome of a multi-year, multi-person process with evolving requirements and evolving teams, new features grafted without proper structural changes, old features abandoned without proper sendoff, and old mistakes mixed with later reengineering, and all kinds of amazing weird stuff you can find in a big, well-established project.

Python 2.x wasn’t particularly well-suited to be the primary language for a project of such scale. First of all, it was fairly slow. This isn’t really a problem while code performance is negligible (e.g. if a program spends 90% of its’ running time downloading data over the Internet, then squeezing the remaining 10% won’t really get you anywhere), but it begins to hurt as you accrete a lot of complex business logic.

Second of all, it was single-threaded, which meant you couldn’t easily get around slowness by throwing more hardware at it.

Most of all, Python 2.x was dynamically typed. That’s why the preferred paradigm for code maintenance was “write it once, write it well, never touch it again”… Don’t get me wrong, this is a great way to write software if you have the skills, discipline, and willpower to pull it out. When a module has a precise meaning and a clean interface, and its implementation perfectly fits its purpose, and it’s the final version because there’s simply no need to change it ever again… It’s just beautiful.

But let’s be real. It only takes one enthusiastic junior coder and one impatient PM eager to see his feature shipped, and that’s it. Wonderland is over, fairies are sold into sex slavery, unicorns are ground into meatballs, and you’re left with refactoring this bucket of spaghetti bolognese back into some semblance of structure.

And any non-trivial refactoring of a complex dynamically-typed codebase was, well, not trivial, even with top-notch IDE support that we didn’t have back in the days. In Python 2.x, there were quite a handful of ways to cut corners and make “well-thought-out shortcuts” ( getattr() / setattr(), global variables, duck typing, dicts as domain objects, tuples as domain objects, you name it) that were pretty handy at a thousand-line scale, but at a million-line scale, each of such “well-thought-out shortcuts” eventually became a “well-placed landmine.” You could’ve put a strict ban on all that, which would make life less adventurous, but then you were essentially writing Java, except you were too hip to admit it.

So the common understanding on the street was that by the time your Python project has grown to a six-digit LoC scale, you’re supposed to be gradually migrating it to something like Java, C++, or C#.

That’s why if, circa 2010, someone asked me what kind of programming language would I imagine to be the most popular in the world in 10–15 years, I’d think about something akin to D/Kotlin/Swift/Nim. So, neither Java nor C++, but a new language that takes all the good stuff from both of those, leaves all the legacy mistakes behind, spices it up with a bit of Haskell and a bit of Erlang, and makes a fresh start.

Fast forward to 2025, and the most popular programming language in the world is Python 3.x…

That’s how I attained Satori of what exactly Zen Buddhists mean when they speak about suffering.

In the West, we commonly see suffering as something imposed on us from the outside. The world is full of evil people who do terrible things and make your life awful. Also, the world is full of random shit that happens and makes your life awful. Also, the world is full of nice things you can’t have, which makes your life awful. And then there are variations and combinations, but pretty much everything can be traced back to these three categories.

Therefore, if we as a society and we as humankind manage to eliminate (or at least neutralise) random shit, and we manage to eliminate the evil people, and we make the nice things available for everyone, then it’d be Heaven on Earth.

Whereas Buddha teaches that many people suffer “simply” because suffering is an innate feature of human nature, even though the word “simply” is woefully inapplicable here.

Let me elaborate. Some people suffer because of the circumstances they find themselves in, and denying that to push all the blame back on their “lack of mindful enlightenment” would be overwhelmingly stupid, stupidly cruel, and cruelly arrogant. Like, when you go to sleep in a peaceful village and wake up in the middle of a warzone, and mindfulness spirituality gurus on Instagram preach that “you can find a positive side in everything that happens to you,” and you feel positive about still being alive, but that’s pretty much it, really, and Lord Jesus Christ seriously considers to do The Second Coming thing solely to tell those Instagram gurus that if they use their mouths less for talking and more for oral sex that’d be better for literally everyone, and I digress.

With that disclaimer written down. Many people “just” suffer despite having no rational narrative or redeeming reasons to attach to that.

Like, many people just eat junk food. Not because they can’t afford proper nutrition. Not because they’re looking forward to having a stroke shortly after a heart attack. Not even because it tastes better than healthy food. They just eat junk food.

Many people just keep living in dodgy neighbourhoods, even though they can move out at any time. Many people just keep doing shitty jobs for years, and many people just stay in toxic relationships for decades.

Many people just do shite for no reason. This is a tricky thing to wrap your head around when you’re a liberal/atheist/humanist type of person, or a libertarian/spiritual/humanist type of person, or anywhere around that vicinity when it comes to believing in people being rational and reasonable. Look, I told you it took me twenty years in the opening paragraph of this essay, so I know first-hand how hard it is.

I think, in part, it was hard because I was trained as an engineer. As engineers, we’re constantly dealing with sacrifices, tradeoffs, and compromises. That’s why when we see a dubious solution, we’re often too quick to assume that it must’ve been a product of one. So, it must have some redeeming advantages, even if you don’t see them immediately. Like, it’s difficult to maintain; therefore, it must be reliable. Or, it’s hard to understand, and therefore, it must be fast. Or, it’s slow; therefore, it must be easy to develop.

That isn’t always true. Sometimes, an idea is simply bad across the board.

Some people just use inadequate platforms for their software systems.

Some people just write functions that span hundreds or thousands of lines of code.

Some people just write functions with ten-twenty-fifty arguments.

Some people just keep maintaining a dozen of heavily interconnected microservices instead of bundling them all together into a single tidy REST endpoint.

Some people just keep maintaining a bunch of heavily interconnected spreadsheets and bash scripts instead of bundling them all together into a single tidy REST endpoint.

Some people just remain enamoured with somewhat typed programming languages, even though they combine the flexibility of Java from circa 2010 with the reliability of JavaScript from circa 2010.

Some people just produce copious unit tests that don’t really test anything.

Some people just copy-paste swaths of code and then painstakingly keep them in sync.

But it’s not all dark and grim. The Third Noble Truth that Buddha teaches us is that there’s cessation of suffering, which can be attained by the right attitude and the proper practice.

I hope it’ll take me less than twenty years to write a follow-up essay.

--

--

Ivan Appel
Ivan Appel

Written by Ivan Appel

Writer of code, developer of stories, drinker of coffee, runner of marathons, dreamer of the better world

No responses yet