Failure, fairness and friends: development and video games
Photo credit: Igor Karimov on Unsplash
If you play video games, you may be aware of the Dark Souls series, or the genre of ‘Soulslike’ games. These games have common characteristics: they are third person action adventure games, usually (but not always) set in a fantasy world, where you fight an implacably hostile environment and enemies, including bosses who often tower above you. They have complex, obscure stories that you discover piece by piece, you level up by gathering resources (souls, or runes or something else) from the enemies you kill, and you lose those resources when you get killed - but you can regain them if you fight your way back to the place you died without getting killed. And they’re hard. Very hard.
i enjoy these games (with a few exceptions - ahem Sekiro ahem). Even though they are intense and frustrating, they are very rewarding when you manage to overcome challenges and get to the end. Moreover, they feel fair: when you die to a boss for the fifteenth time, you know that it was because you made a mistake: you dodged slightly too late, or you waited slightly too long to heal, or you pushed your luck a bit too far.
I enjoy these games so much that they have entered my mental vocabulary, and I sometimes find my inner monologue labelling some of the other challenges I face - particularly those in technology - as Dark-Souls-hard. I found this recently when I was working my way through the book The Elements of Computing Systems, which I wrote about a few weeks ago. One of the projects in this book is to write a program which translates bytecode into assembly language. When my brain was full of registers and pointers and addresses, I thought this is Dark-Souls-hard, and was thankful, once again, that I have never had to earn my living coding at this level of abstraction.
However, when I reflected, I realised that the development of all computer systems, at all levels of abstraction, is Dark-Souls-hard. This is not an attempt to lionise all of the people with whom I share a profession: rather, it is simply to recognise that systems development has some features which resemble the world of these tough video games:
Everything is out to get you: last week, I wrote about all the unexpected ways that users will use your system. That’s just one example of the hostile, unyielding environment into which your system will be thrust upon first release. You can guarantee that, if it’s possible to enter incorrect data into a field, someone will enter it. If it’s possible to send bad messages to an API, they will be sent. If it’s possible for an infrastructure component to fail, it will fail. Your system needs to anticipate and cope with all of these failure modes. It is sometimes said that genius is 10% inspiration and 90% perspiration; systems development often feels like 10% feature creation and 90% error handling.
Failure is an ever present lesson: even if you anticipate all of the errors that you think of, you will encounter failures that you didn’t expect. Many of them will be failures that you created. If you can write more than ten lines of code without making a mistake, then you are a better programmer than I am: last week, I wrote three lines of code that all referenced the same Python dictionary. As I found when I tried to run the code, I had managed to use slightly different variations of the variable name in all three lines. Running new code is like stepping into a new area in a Dark Souls game: one step, fail; overcome failure, second step, fail; overcome failure, third step, fail. And so on.
Fairness cuts both ways: just like Dark Souls, systems development is fair. If your system breaks, it is because you created the conditions for it to break. This is true whether the breakage is caused by bugs (you didn’t test enough), attacks (you didn’t build strong enough defences) or disasters (you didn’t create sufficient resilience). It’s also true whether you built the system, bought it or inherited it: it’s yours now. But, just as you’re responsible for breakages, you’re also responsible for success. Despite the hostile environment, despite the ever present prospect of failure, it is possible to build systems that are resilient, reliable and secure - and that do the things that we want them to do.
There are some other comparisons we could make: we could talk about the thrill of achievement, or about scary bosses, or about antagonistic players who invade your games. However, I think we should end by reflecting on the ways in which players of these tough games help each other: they can leave messages in the environment (just like comments in code); they create active online communities (just like Open Source communities and developer forums); and they can even show up to work alongside each other (just like pair programming).
Systems development may be Dark-Souls-hard, but we don’t have to face it alone.