The philosophy behind the things I create
The philosophy
I do not come from a traditional developer background. I come from a background where everything had to operate, and if it didn't, it needed to be fixed. Failure woke up people in the middle of the night and downtime cost money. This has molded my way of thinking about systems architecture greatly. The great motivator behind all of the things I've created is that I have a valid reason expecting something to do something differently. I've often found myself arguing with a product developer that while I appreciate your choice, I don't really see any point even trying to achieve that.
I was in the process of finding a ready-made radio playout software to fulfill the needs of a small-scale radio station that couldn't hire full-time audio engineers, not to talk about software architects. We tested some of the options, but quite quickly found out that they either didn't do what we expected or required more staff just to handle scheduling, or found systems that almost did what we wanted, but weren't stable enough for production use, or just simply couldn't do more than basic scheduling. I had some time alone with a calculator, and decided that the time we're wasting on trying to find a ready-made solution that could work, but perhaps couldn't grow with the station, we could as well use the time to build something from scratch. Liquidsoap scripting language was on the table right from the point where we decided to build something of our own.
The foundation for the product we needed was to build something that does not require human intervention at all. Most programs fulfill this requirement until anything unexpected happens. My goal was to come up with a program that would always work exactly as expected, even when failing. This meant that while the system could indeed be smart and do very clever things, I needed to deliberately make it dumb.
Smart systems try to predict what you want. Dumb systems do exactly what you tell them, every time. That's what's best in computers: give them clear instructions and they're happy to follow them. When your station goes silent at 3 AM because some "intelligent" algorithm made an assumption, you realize why predictability beats cleverness.
This philosophy shaped three core principles:
Fail forward, never fail silent
This may seem basic functionality, but in reality is something that is a core foundation for a working system: to fail in a predictable way. The system gets multiple sources to fail to, and each source has a priority. This is the basic fallback logic: source 2 goes down, source 1 is unavailable, try source 3 (and so on...). The best part is that the audience will not know you have just had a failing component. The worst that could happen is they hear a jingle.
State should be explicit, not inferred
Instead of trying to find out "where we left off", we track exactly where we are and where we're going. Playlist positions are written to disk. Episode history is logged with timestamps. When Liquidsoap restarts, it doesn't guess - it reads the state and continues from a known position (because we made it deliberately dumb). By having the state written to disk, we can also manipulate the state easily without having to build complex telnet integrations.
Make the simple case trivial, and the complex case possible
Most of the time, we're just playing the next track in a playlist. But when we need to go from music to podcasts, we're telling the system how to fail instead of making it panic and go "oh god oh god there's a podcast, quick, stop everything and PLAY". One of Liquidsoap's core components is the sense of availability, which translates to sense of failure. Forcing things to fail in a controlled manner is often easier than trying to come up with a complex logic to make things available in the most complex way known to mankind.
How we do this, is that we make the sources always switch to Liquidsoap's internal component `source.fail()`. But before that, we make the computer do what human operators used to do: fade, because no one wants to hear abrupt cuts ever. So in essence, what the listener hears is a beautiful fade out for the music track (if it runs long), and the podcast show will start exactly at the right time.
Why so complicated? Because I want to make the most of the philosophy behind Liquidsoap. Another strong concept in Liquidsoap is the sense of track sensitivity. Liquidsoap offers you the choice of making fallback operators track-sensitive, but who really wants to live in a binary world? By making all fallback operators track sensitive, we can be surgical about when to exactly be track sensitive and when not.
Being track insensitive in a track sensitive context bugged me for a long time. I knew I needed to sometimes be track insensitive, but for some sources at the same time, be track sensitive. I remember browsing through the API documentation one night when I couldn't sleep, and I stumbled upon the `source.fail()` operator. Then I realized this is exactly what I need, I just need a way to make things fail beautifully.