What Advent of Code taught me about real world software engineering.
Tags: adventofcode
Published: 2021-12-14 00:01:14

[Advent of Code (AoC)](https://adventofcode.com/) is an advent calendar of coding puzzles. It has been running since 2015 and I myself have been taking part since 2018. The puzzles are great fun and I'm always astonished by the creativity and energy of the community. I believe there is a lot to learn from these puzzles, with transferable skills that can be applied to real world software engineering. I thought I'd share a few thoughts on some of these real world lessons here.

---

* Tests are awesome.

AoC is a great way to get more familiar with automated testing. Generally each puzzle contains a small example (or two) which I use as a test case, before running my code against my personalized puzzle input. This test-first approach gives me confidence that my solution works, and helps me to debug as I go along. What's more, once I've completed the puzzle I can add a test case for my final solution, which helps me ensure correctness as I tidy & refactor my code. When refactoring I can see how well I've tested against behaviours and remove any tight coupling to implementation. 

In real world software engineering good testing is vital. Tests codify behaviours and correctness and provide confidence to refactor. AoC provides a great source to practice and develop this skill.

* Premature optimization is a waste & danger.

Each AoC puzzle is split into two parts, and you only get access to part 2 after completing part 1. Generally part 2 is some kind of extensions/twist on part 1 however it is hard to guess exactly what will be needed for part 2. This uncertainty of requirements gives me an excellent opportunity to exercise development best-practices such as [YAGNI (You aren't gonna need it)](https://en.wikipedia.org/wiki/You_aren%27t_gonna_need_it) & [KISS (keep it simple, stupid)](https://en.wikipedia.org/wiki/KISS_principle). In general I find trying to guess at what part 2 will be before finishing part 1 to be a waste of time. I prefer to write a very simple solution for part 1, using minimal abstractions. That way when I get to part 2 I don't have to spend effort undoing my guesswork from part 1.

In real software engineering avoiding premature optimization and incorrect abstractions is extremely useful. It will save you time and make for simpler, more maintainable code. AoC is a great way to observe & question your choice of abstractions and notice premature optimizations you created.

* Practice makes perfect, be patient.

This is the 4th advent I've taken part in AoC. While some of the puzzles still cause me to scratch my head, especially the ones later in the month, I'm really able to notice progress and see how I've developed as an engineer. Often puzzles that would have taken me hours when I started now take 20 minutes. I find myself naturally reaching for better data structures & algorithms and making use of best practices such as test driven development & good abstractions. The annual nature of an advent calendar means there is plenty of time to develop yourself between iterations and a degree of long term vision is created. Reflection on your strengths & weaknesses and patience to gradually & continuously develop your skills is critical for any software engineer in the real world. I enjoy using AoC as an opportunity to reflect and take notice of changes since last year. 

* Read code as well as write code.

There is an extremely active community of people taking part in AoC. I enjoy finding example solutions & ample discussion on reddit or twitter, written in virtually any programming language and to every taste. Different participants take different approaches, so it is possible to read a great variety of solutions: from code golf, to verbose and documented, to deeply visualized, to the most performant algorithms. I find there is a wealth of knowledge to gain from reading some of these solutions, and indeed in reading others code in a more general software engineering setting. AoC provides a great opportunity for me to read other peoples code, compare and consider tradeoffs, and develop my own taste for good solutions. Being well read in this way is very helpful for a real world software engineer, where code review and consideration of tradeoffs & alternative approaches happens on a daily basis.

* Data structures & algorithms are important, sometimes.

When I first participated in AoC I was a recent university Physics graduate, so was very familiar with vectors & matrices, but less so with other data structures such as hash maps, trees & graphs. One side-effect of this was that I would almost always try to solve my AoC puzzles using lists/arrays. This often led to overly complex and under-performant solutions. Usually this would work fine for the simpler part 1 of a puzzle, but then would hit a performance bottle neck in part 2 ("now simulate for 10 billion iterations..."). AoC gives me a good opportunity to consider the performance characteristics of my code, and optimize this when necessary. In general I try to maintain a test suite for all the puzzles, and keep solution run time to below a fixed target, such as 1s per day. When my solution runs fast enough, as defined by my target, I will avoid chasing milliseconds, however if my solution is too slow I will make an effort to research a better approach and optimize my code. This kind of metrics based performance optimization, and only when needed, is extremely important in real software engineering.
 
* The choice of programming language isn't that important.

A lot of energy is spent between developers discussing programming languages, with everyone insisting that their favorite is the best and all others are greatly inferior. However, AoC really can be solved well in almost any language. Visiting the solutions megathread on reddit you will find all kinds of excellent solutions, using a diverse set of languages and patterns. It's quite clear to me that in most cases the particular programming language used isn't particularly important. Many use AoC as an opportunity to learn a new language, and that can be great, but I find I can gain just as much by deepening & sharpening my knowledge in a language I already know (Python or GO for me). While I don't learn a new language, I can deepen my knowledge of idioms, the standard libraries, new features and best practices. In my experience choice of programming language matters relatively little in real world software engineering contexts, while a deep & complete understanding of your day to day tools in relatively critical.

---

In summary I think the AoC puzzles are great fun, but also an excellent way to work on your real world software engineering skills. Going beyond just learning a new programming language, you can learn more general and I think more useful lessons, such as automated testing, considered abstractions and optimizations, how to better read and review code and to reflect on and continuously develop your knowledge.