As an avid gamer, I love the structured challenges and feedback loops that video games provide. Especially when there are clear goals, but a lot of flexibility how to achieve them. Can we make practicing programming more engaging by combining it with gaming?
I love programming. Enough to make it my career and dedicate most of my free time to it. Writing code is like a multidimensional puzzle to me. A problem must be analyzed and understood, so that a solution for it can be designed. The design must fit specific requirements and constraints, and often trade-offs have to be made. The same is true when finally implementing the design, where technical and organizational concerns need to be considered. Each of the three steps provides its own challenge, and almost limitless opportunity for learning and improvement.
For me, getting better at programming has a lot to do with practice. I can read a book or an article, but only when I implement its lessons myself will I actually internalize them. When I try to learn something completely new, for example a new programming language, this is simple. Books and courses provide examples, and I often have small ideas that are easy enough to try out in an afternoon. After doing this for years, I have also built up a lot of transferable experience that makes this process easier. Learning the first functional programming language was much harder than learning the third...
What I struggle with is practicing advanced conceptsthat go beyond simple examples. Domain-driven design (DDD) for example. The calculator I would write to try out Haskell is not complex enough to teach me anything about DDD. What I normally do in such a case is start a new side project. But there are two problems with this approach.
First, it is highly inefficient. I am a bit of a perfectionist, and so I would typically spend the first few hours of each project setting everything up. GitHub, continuous integration, automatic deployments. (I'm really good at configuring GitHub Actions now.) And most projects require at least some boilerplate to get to the interesting parts. Things I have done many times already in other projects, such as authentication, application layouts, or a command-line interface. The more challenging the topics I want to learn are, the more difficult it is to set up a project to practice them. If I look ahead at a few very interesting techniques used in enterprise application architecture that I'd love to try out, I have no idea how to spin up an environment to do that. These lessons require multiple services and a high traffic volume to simulate the problems they are designed to solve. This is beyond a simple to-do app that I can create myself on a weekend...
Second, always starting a new project undermines my confidence and motivation. How many projects did I already start and never finish? I could probably archive two-thirds of my GitHub repositories, because they will never see another commit from me. For the longest time I wondered why I would never finish a project, and always start a new one when there were still so many unfinished ones. It made me feel insecure, especially when I saw the amazing projects others around me continued to release. Until I realized that I was not interested in the project, but in the practice. I started these projects to learn a particular topic, and once I was satisfied with my learning, there was no need to continue with the project.
While this explanation helped make sense of my behavior, it did not help with my motivation. It is harder than ever for me to start a new project now, because I know that I will never finish it. Because I don't want to. My interest is in learning a particular topic, not building, releasing, and then maintaining yet another Twitter clone.
As much as I love programming, I have struggled to enjoy a lot of it recently. I want to work on interesting problems, design solutions, and practice my craft. But I don't want to build a portfolio, and I don't want to create more responsibilities for myself by publishing open source projects that I created to learn something.
When I am not working on a side project and some code, I am most likely playing video games. My favorite genres are racing simulations, city builders, and strategy games, with the occasional shooter and survival game. What they all have in common are open ended challenges with many possible solutions and fast feedback loops. In a racing game, there is an infinite amount of lines you can take around the track, but each lap time you set is feedback whether this lap was faster or slower than the previous one. City builders are sandboxes with unlimited possibility, and countless different systems to optimize. And competitive strategy games such as Starcraft tell the sometimes brutal truth about your ability and skill compared to the opponent's.
What excites me about games is what I am missing when practicing programming. Video games provide a challenge, a set of rules, and a feedback loop.
The challenge keeps me engaged. I want to achieve better lap times, build bigger and better cities, and destroy my friends in friendly competition with more style and skill. I try it once, gather data, and now I want to do it again with an improved strategy in mind.
I particularly like games that allow me do tackle these challenges in a variety of ways. Cities: Skylines is an enormous sandbox, and I can choose to build a green, environmentally friendly city, or to extract as much resources from the ground as possible for maximum profit. I can set up public transport and policies to encourage citizens to use it, or I can build massive six lane roads throughout the city. The challenge is the same every time, but my approach to solving it differs. This makes it possible to play a game many times, and retry the same challenge over and over again without it becoming boring.
The same would benefit me greatly in programming. Tackling the same problem again and again would allow me to compare the strength and weaknesses of different designs. Learn from my mistakes, improve and optimize, and throw everything away to redo it again. Progressing towards the best solution would build muscle memory that would benefit me when faced with a similar problem in the future.
I have a theory why facing the same challenge in games over and over again is not as boring as it sounds. (Although–sometimes–it can be.) In my opinion, this is due to the two other components of games: game mechanics and feedback.
Rules and game mechanics restrict the problem space. This can be a challenge in itself, limiting the amount of possible designs for a solutions. But the limited problem space also makes it easier to approach a challenge and experiment. Starting a game of Starcraft with 50 minerals makes it pretty obvious what to do first: gather more minerals. A game like Flappy Bird with only a single mechanic removes the need to learn complex input schemes, and instead allows players to learn and perfect the execution of that one mechanic.
I wish I had the same guidance when trying to learn domain-driven design. A clearly defined problem, and a sandbox with a limited problem space. Someone telling me to achieve this goal, using these tools. Without knowing DDD already, it is impossible for me to design a problem in such a way that DDD is a good solution for it. This has been the source of much frustration for me in the past, because what I wanted to learn was not the best technology choice for the projects I started. I was trying to force a square block through a round hole.
The final piece of the puzzle are feedback loops. Video games are exceptional at providing fast feedback to the actions of a player. In Starcraft, it takes me 20 minutes on average to learn if a strategy was good or bad. That's how long my games usually take. In racing, I can get that number down to a minute, or however long it takes me to do a full lap around a circuit.
The feedback provided by games is not only fast, it is also actionable. It tells players how well they are doing, allowing them to adjust their approach. In racing, lap times are hard, objective benchmarks, and drivers can react to them to increase their performance. In seconds to minutes, players can try a behavior, observe its output, and adjust their approach for better results. This is highly motivating and engaging.
When I try to learn a new programming skill, I usually don't have such a tight feedback loop. Most often there are no objective benchmarks for how well I am doing. Does my new design perform better than the last? I do not work on projects long enough to learn about the maintenance costs of my design decisions. And as the only user of my small app, I cannot generate the necessary traffic to really answer this question. Simulating traffic is not the skill I'm here to learn...
The last few days I have been thinking deeply about these two things. On one hand the desire to practice my craft, and the problems I face when I try to do so. Losing motivation, and being slowed down by setting up an environment that allows me to practice a specific skill. And on the other hand the video games I like, purpose built to teach their game mechanics and guide players on their path to mastery. I am wondering what it would look like to take the lessons learned in game design, and applying them to programming. Could we make practice more engaging?
To be fair–this is not a new idea. Gamification of learning has been around for a while, and there is even some prior art out there that does this with programming. Screeps is an ambitious project to build a MMO real-time strategy game for programmers. CodeCombat is a role-playing game that teaches coding. And Zachtronics–through their games TIS-100 and Shenzhen I/O–managed to bring programming challenges inspired by assembly to a broad player base. (Both of which I can highly recommend to the interested reader!)
I am tempted to take this on as a new challenge. Design a game that I would like to play myself, with mechanics that rely on programming to solve them. A game that is engaging and challenging, so that players can practice the advanced techniques in which they are interested. The more I learn about game design, the more fascinated I am by the wisdom and experience that has been acquired across 30 years of building video games. There has to be a way to bring this to programming...
It has become abundantly clear to me that this is a project too big to do alone. That it requires a diverse community and collaboration to design and build an engaging and inspiring virtual world. So as I start to write about my ideas and vision, please get in touch if this is in any way interesting to you. In this early stage, any form of interest and encouragement is greatly appreciated...