2022; year in review

Date 2023-01-03

Another year, another "year in review" blogpost.

Highlights

Health

My mental health has improved a lot this year. I have spent a lot of time and energy learning to communicate more effectively, both inward and outward.

One big insight I had this year is that I had tried to use more time in a day by unhealthily sacrificing sleep. I tried out sleeping without alarm clocks. This forced me to not over-commit my time and go to bed in time to get up before my first appointments. If you are the kind of person who doesn't remember the last time they've woken up well-rested, let this be a prompt to try it out.

This will sound silly, but I have practiced resting. Resting does not come easy to me. Doing nothing, on purpose, was very frustrating, but also certainly a good exercise.

Work & Leadership

Work has become even more interesting this year. Last year I had a technical leadership role, in which I grew a team from 3 to 9 engineers. This year I took on a CTO role. I managed managers and got to grow teams of teams with dozens of extremely intelligent people. The project did not end up working out for various reasons, but learnt a lot in this experience.

A picture of me giving a leadership talk

Excitement and disappointment

For as long as I can remember, I have been easily disappointed and have over-corrected for avoiding disappointment. This year I gained a big insight into this problem.

The reason I say "over-corrected" is because my reasoning went as follows: "I feel disappointment, what am I doing wrong? Well, being excited is necessary to be disappointed, so I just have to not be excited about anything!" It's easy to judge me when I write down the thought process this way, but this is just the distilled essence of years of trying to deal with this issue.

I'm convinced that this disappointment problem is much of why I care about making software that works. If you use 50 pieces of software in a day, and they all work 99% of the time, you'll be disappointed by software about every other day.

The great insight came from this exchange on twitter:

The exchange on twitter that gave me an insight about disappointment

I'm assuming the comment was meant to be tongue-in-cheek, but it made me realise that what disappointed me about my phone responding slowly is not actually the slow phone. What disappointed me is synchronously waiting for five seconds while expecting the process to be instant.

So I changed some things in my life:

  1. I try to keep myself out of synchronous processes.
  2. I focus on throughput of "things going on" rather than latency.
  3. I use self-management to keep track of all the "things going on".

Synchronous processes prevent me from doing 2. or 3. in the short term. This way I can relieve myself of disappointment while not having to get rid of excitement at all.

My software projects are an example of how this works.

  1. I let CI do all the big builds.
  2. I have multiple projects in the backlog at any time. When I inevitably get stuck with one, I can get back to it when inspiration strikes.
  3. I keep track of all the projects in Smos.

Software & Writing

I wrote a great deal of software in 2022 and am really happy with the results. I've only blogged about things as I've made them, so there were fewer blog posts this year, but more condensed ones. Here is a short overview of what's been made. You might just find some cool new things to try!

Smos

There have been no fewer than 11 releases of Smos in 2022.

A screenshot of the changelog index on the Smos docs site

I spent quite some time speeding up the release process. The biggest improvement came from talking to Gabriella Gonzalez who gave me an insight about how one can get rid of the staging environment. This way we were able to reduce and optimise the release checklist to make it possible to release a new version of smos in minutes instead of days.

Nowadays, Smos has a completely local automated testing strategy, including forward and backward compatibility testing and a comprehensive release checklist.

Social Dance Today

I spent a lot of time on Social Dance Today again this year. Last year, the site had around 1000 upcoming parties every month. In 2022, that grew to around 4500 every month, 2000 per week, and almost 250 per day!

We can even see that there were more than 500 new year's celebrations on the site!

An graph of the parties per day on Social Dance Today

Usage also exploded. Where we had 500 monthly-active users in 2021, that metric grew to over 3000 monthly-active users in 2022 at some point. This was mostly because our excellent SEO got Google to send quite a bit of traffic our way.

An active users graph for Social Dance Today

Technically speaking, this has been a very interesting project as well. We've had some really cool bugs.

For example, when I made this visualisation of all parties we know about, something looked suspicious:

A world map of the cool bug in Social Dance Today

Why were there so many parties on a line through Turkey?! Hint: The line goes through "Null Island". It turns out that some part of the code incorrectly set the latitude to equal the longitude. This line is exactly the line where latitude equals longitude. I would not have found this without the map-based visualisation, so I'm happy we made it!

Another bug is one with which I'm still struggling. There is a space leak in the server somewhere, so the CPU usage (from garbage collecting more and more data) goes up steadily over time and eventually locks up the server. At the moment I'm just rebooting the server every few days while I look for the space leak.

A graph of the CPU utilisation of the Social Dance Today server

We also added some great new features this year:

  • We made it possible for Organisers to automatically schedule recurring parties.
  • We translated the site into four more languages: Spanish, French, German, and Dutch.
  • We added dance style filters, so you can see Bachata parties in Z├╝rich specifically.
  • We added advanced search, so you can perform and share custom searches.
  • We added ical integration, so users can have their favourite organisers' new parties show up in their calendars automatically.
  • We sped up the page loads by about half, with fancy page pre-loading, lazy image loading, and search caches.
Sydtest

I started Sydtest in 2021, but in 2022 it got new features, some of which I'm guessing are actually entirely novel.

  • Webdriver-based testing, with nix support: You can now write robust selenium tests in sydtest, including golden screenshot tests. We also figured out the nix integration for you, so you can just hook into the digging that we've done on that front.

  • Flakiness stopgap combinators: with the flaky combinator, you can unblock your team when you notice a flaky test without having to remove it.

  • Automatic flakiness diagnostics: Sydtest will now automatically try to diagnose whether a given failing test is flaky, so you can see whether the test fails consistently.

  • Global deterministic randomness: To maintain reproducibility, Sydtest now also sets the global pseudo-randomness seed deterministically.

A piece of sydtest code to show off flakiness tools
Really safe money

After all too many discussions with coworkers and other techies about floating-point numbers and how to perform computations related to money, I decided I would write a reference implementation for safe computations involving amounts of money. The name safe-money was taken, and that library is not really as safe as I wanted it to be, so I wrote really-safe-money. I announced the library shortly after that, in the rewrite of my blogpost on how to deal with money in software.

And of course, a really safe library requires a really good test suite. The test suite runs more than 700 tests, for a total of more than 1.6 million test runs that all run in under a second.

A sydtest summary of really-safe-money tests
Feedback

At some point during the summer, I got fed up with how difficult it was to set up a feedback loop for non-Haskell projects, without stack. A few days later I had a working prototype of a feedback loop manager. A few months later I announced the project and now I use it every day.

An example view of me using feedback to prototype dekking
Dekking

I had been frustrated with the state of Haskell's test coverage tool HPC for years. It was buggy, confusing, and so hard to integrate with that I've never actually succeeded in doing so. This year I spent a few weeks seeing if I could make something that I could actually use. Not so long after that, I announced Dekking; A next-generation Haskell coverage tool.

A coverage report index for Smos

It has a simplified user interface, more robust integration with Nix builds, and fewer bugs of course (or different ones, at least). It was also the first project where I felt the need to use Tagref because of how many comments I was writing.

Bevel

Early on in the year, almost right after the new year's celebrations in fact, I started up a new project to replace my usage of Atuin.

It is essentially the same idea; "Command history in an Sqlite database with nice querying", but written in Haskell, well tested, and easy to integrate with NixOS.

An example invocation of bevel

It was also the first project in which I deliberately wrote some part in C because it needs to be fast. So now the part of bevel that hooks into your shell to save the commands is written in C.

Declops

At some point during the year, I had quite a lot of trouble with upgrading NixOps during a NixOS upgrade. In my signature arrogance, I thought "surely this can't be that difficult, let me try to write my own!" and came up with Declops.

A Declops feature comparison table

I ended up pausing the project when I realised how big it would have to become in order for it to be what I wanted it to be. I realised I don't have the time or funding to take this project on any time soon.

If anyone wants to fund this effort or collaborate, feel free to get in touch!

ICal

Over the past few years, I've gotten numerous reports from Smos users that smos-calendar-import had failed to import a given .ics file. This was always an issue with parsing the .ics file. It turns out that the problematic .ics files were invalid ICal according to the ICal spec. Indeed, Google, Apple, Microsoft, and Fastmail all regularly spit out invalid .ics files. When these fail to parse, Smos gets the blame of course.

So I set out to see if I could make an ICal library that was sufficiently flexible. It needed to be correct, able to be both strict and lenient with invalid ical, and well-tested. In the process, I would learn about many of the ways in which dealing with calendars, timezones, and recurrence is so difficult.

At this point, my ical library already powers both Social Dance Today and smos-calendar-import.

An ICal event for a party on Social Dance Today

Dance

Dance classes

We continued teaching Salsa at Rhythmia. Our classes grew to over five couples per class on most weeks and let us travel to festivals with our students.

A picture of Sandra and I teaching our class

I was fortunate enough to travel to Berlin, London, Paris, and Croatia to dance.

A group picture of our group of dancers in Berlin
Zouk

As I started feeling more comfortable with Bachata, people kept recommending me to learn Zouk and Kizomba. Eventually I gave in and tried out Zouk. It is intense! I look forward to learning more in 2023.

Acrobatics

I started partner acrobatics in 2021 and have continued to love it all through 2022. My acro partner and I have managed to perform some new skills together, like a standing hand-to-hand and a baby-handstand.

A picture of Lena and I doing a standing hand-to-hand
A picture of Lena and I goofing around in training together
A picture of Lena and I doing a baby handstand

German

In order to show good will during my upcoming residence permit application, I scheduled a German B1 exam in December. At that point I figured I should probably learn German in order to pass the exam, so I started studying.

There are no cases in Dutch (anymore), so learning a language with cases was a particularly challenging task. The first big hurdle was the rectangle of hell:

German definite articles table

The ridiculousness of these cases is really well exemplified by the 144 possessive pronouns:

German posessive pronouncs table

The tenses were doable they are similar to the Dutch ones, and the vocabulary too, with the exception of some false friends.

The exam went a lot better than I expected, mostly because it was so much easier to prepare for than university exams. The preparation materials showed the exact structure of the exam with practice exam, as well as everything you might need to know to pass it, including all the vocabulary! In the end I still have no idea whether I passed the exam because it turns out that TELC takes up to 8 weeks to correct exams.

Building a new workstation

Once I realised that 2017 was five years ago, and not three, I started ordering new computer parts under the guidance of my buddy Jorik who knows more about hardware than I ever hope to.

Building a computer, part 1

We built quite the beefy machine. It has a 32-thread Ryzen 9 5950x CPU that's cooled with 8 fans, an NVIDIA GeForce RTX 3070 Gpu, and a 2 TB SSD that I haven't managed to fill yet.

We also built a little NAS system with four 8TB server HDDs, two of which are for redundancy.

My NAS system

Two of the drives have already failed (at the same time!) and been replaced without any data loss, so I will go ahead and call that mission success for my backups!

Miscellaneous activities

Presented without comment

Skiing
Graffiti Workshop
A high bird in actrobatics
Acrobatics with Despina
Colouring my beard
Colouring my beard
A plank hold on the table
A movie reference at the chocolate museum

Focus for 2023

I plan to continue 2022's theme of doing whatever seems interesting at the time. I hope to continue doing the hobbies that I love, stay in good health, and find more interesting work to do.

Previous
A dancing space leak

Know a technical team that could use strong technical leadership?

Hire me
Next
Announcing Dekking: Next generation code coverage reports for Haskell