Software you can love: miroir Ô mon beau miroir ❤️

A few years ago, I was really into Raspberry Pis. I think they are amazing pieces of hardware to own if you love tinkering and learning new stuff. By stuff, I mean: software, embedded systems, kernel development, self-hosting, networks, clusters, robotics, and more. I still own quite a few. Raspberry Pis are a great educational tool, they only require swapping out a single SD card to boot up into some new project and there are hundreds of projects out there using Raspberry Pis. Enough about raspberry pis, I’m not here to sell you one.

I’ve started writing this post on December 2024 and it got a little bit out of hand so I decided to split it into two blog posts parts. The first one is a rant about my view on software quality as a whole. It’s more of a broader discussion about the “why” I chose to write MagicMirror in Rust. The second part is dedicated to diving into technical details of the design choices I made when building the app. Feel free to jump to any section !

The state of software quality

One of those fun projects using Raspberry Pi is https://magicmirror.builders/. One afternoon coming back from work, I found a broken window thrown outside, but the mirror attached to it was still in good condition. I immediately thought of building my little magic mirror. One weekend and a few screws later, I put a badly built magic mirror frame on a wall in my bedroom. I still can’t figure out why my wife let me put such a piece of crap on the wall. I guess she took pity on me when she saw how excited I was. But that’s neither here nor there…

Back to our little magic mirror. I installed the magic mirror software on a Raspberry Pi 3 A, which comes with a Broadcom BCM2837B0, Cortex-A53 running at 1.4 GHz, and 512MB of RAM. I used the official magic mirror project. The project is written in JS and uses Electron to render the widgets to the screen. Electron, yes, you know where this is going…

At the time, I just wanted something working that looked cool. I set up the config and chose the widgets I was interested in and threw that together. A few weeks went by, and the magic mirror kept falling apart. It was either frozen, the widget fetching stuck in an infinite loop, the RSS feed didn’t update, or one of two hundred other weird issues that just kept nagging at me. So I looked around one afternoon and found the senses-mirror project. It looked a little bit better than the magic mirror, had a lot of built-in widgets, and I liked the idea of having an app on my phone to set up and control the magic mirror. My experience modifying the MM config.js was really bad, and a mobile app could help with that. The obvious catch was that senses-smartmirror was also written as an Electron app in vue.js

So now I have a piece of wood hanging to my wall that sometimes worked but often didn’t. It sometimes completely froze the RPi, and I needed to manually restart it once a month. The site recommended using a Raspberry Pi 4, but I thought that the Raspberry Pi 3 A with a processor that is 700 times faster than the Apollo guidance computer that we used to send a rocket to outer space was enough… Silly me.

Small note: The RPi3 also has 128,000 times more RAM than the Apollo guidance computer. I thought it could at least render a black screen with some white text that refreshes every 2 hours. But I guess that’s not how modern software people view software performance these days …

Now that’s why I am writing this article. I am here to bring you some bad news:the state of software as a whole has been on a decline other than a few rare spots.

Yes, I know this sounds like a doomsday guy kind of sentence, but please hear me out (also stop reading here if you don’t want to; I am not going to force you to continue reading; we are all adults here). I’ll try to break down what I mean by a declining state.

I think we can all agree that a very small number of applications are ACTUALLY usable. Meaning never crash, always work the way you want, are rock-solid stable, and their performance is great. The vast majority of software is filled with bugs, consumes way too many resources, and is underutilizing the hardware so much that it’s borderline criminal.

One hilarious display of modern software being quite bad is the tweet from Rerun’s CTO comparing their software to the Microsoft team’s improved version of Microsoft team. Now can you explain to me how in the world an app that shows some blocks of static text runs orders of magnitudes slower than a 3D cloud point visualizer graphics on the same piece of hardware?

One (of the many) reasons for this demise in software quality was pinpointed by Casey Muratori in an interview with Richard Feldman. I’ll paraphrase it a bit, but the gist of his thought is the following: Programmers forgot that their primary job is to program a computer, ie program a piece of hardware to do a certain job! That’s it!

Programming an actual piece of “raw” hardware is quite hard, so software engineers did what they do best: Simplify doing this job through abstraction! The abstractions help developers build on top of existing pieces of software so they can do their job quickly. Then we ran this cycle for decades, pushing these abstractions more and more. Now somewhere along the way, developers lost the ability to understand the underlying piece of hardware and what it is capable of. What you gained or lost developers before them had to tradeoff when building the abstraction were completely erased from common knowledge. Nobody seems to care anymore about the theoretical limits of the software they are writing. We all heard phrases like “ Don’t “reinvent the wheel”” or “Don’t fix what isn’t broken”. These phrases became “common wisdom” in software engineering. Next time someone tells you one of these (usually some manager) as if he had some deep wisdom to cast upon you, please tell him to explain to you how that wheel ACTUALLY works. Or how would he rebuild the same wheel from scratch? He’ll probably babble some nonsense and tell you to write him a Jira ticket.

Some industries over-optimized on this notion of never understanding the underlying systems and call it: “developer experience”. I am talking about the web of course. In multiple interactions with frontend engineers where the subject of building electron apps came up, I was shocked to hear that they qualify it as ‘amazing’ or ‘great’, and that they don’t see any issue about shipping a 500 Mb single page app that renders text or that includes an entire chromium engine for funsies.

Another horrible consequence of this “don’t have to worry about low-level details” attitude is that we (as devs) are all programmed to think about solving problems in an artificially constrained space. We usually make tradeoffs against some predefined set of technologies and software without thinking of pushing beyond these arbitrary limits. We rarely ask questions about actual hardware limits, about the overhead for OS, about building sites without React, about training ML models without PyTorch… I can go on and on forever.

Now that I have painted a gloomy, bleak dev world, I’ll stop here and say that I am seeing a push against this way of thinking everywhere! Moore’s law has come to an end (at least the linear scaling of computing), and software engineers are starting to question these preconceived notions and peel off unnecessary abstractions that are slowing them down.

Some examples of this push back: the return of statically typed compiled languages (Go, Rust, Zig, Odin…), blazing fast written-from-scratch IDEs like Zed, the push for unikernels, shared user/kernel space ring buffers like iouring… All examples of this trend to make “software great again”.