Hey! Thanks for reading! Just a reminder that I wrote this some years ago, and may have much more complicated feelings about this topic than I did when I wrote it. Happy to elaborate, feel free to reach out to me! 😄
🎵 The song for this post is Hotter Than That, by Louis Armstrong & His Hot Five. 🎵
I saw this fantastic quote on a roundup of cross-platform GUI frameworks:
People will say “But there’s WxWidgets, but there’s GTK, but there’s Qt” as if someone is looking for ice cream and everyone is going “But there’s frozen shoe leather, but there’s frozen peas, but there’s an empty refrigerator”
I find this true about a lot of problem categories.
Sometimes I get sad that Desktop Software™ is long dead — personal computers are ridiculously powerful machines (and have been for over a decade!) and we're either just using the displays ("$3000 Facebook machine") or spend half the compute on Slack. More and more I'm meeting people who never used software that ran entirely on a machine that they were also allowed to program.
Someone left a comment I liked a while back: to own a computer but not know how to program it is like having access to a full pantry and kitchen and only eating microwave meals. Which, as someone who's only started cooking with my kitchen and pantry: no judgement! I offer it entirely as a "amazing possibilities open up" rather than "look at these rubes who don't know better."
Like all things that I miss, it's fine. There are good reasons for it. For things that don't matter much, getting mad that the world isn't shaped to my preferences is making the choice to be mad: I either don't understand why things are that way, or don't want to confront and accept it. And hey, the web-based world is also pretty great. Until we fully Clear Channel it, anyways.
Compile times, modularity, tangles
One of the lines in the linked article above is:
If C++ compile times wouldn’t be measured in hours, half of the the problems I have with the existing frameworks would probably go away.
I am… familiar with C++ compile times! My first gig was Flash Runtime at Adobe, and one of my projects was to investigate why our Linux builds were so slow. In the spirit of "cross-platform GUI frameworks… what a mess!" one could easily write a similar post about "cross-platform build tools." The primary platforms (Windows, OSX) were done with their first-party project files (Visual Studio or XCode), but Linux and many ancillary platforms (Blackberry's QNX, some Samsumg TVs) used CMake.
It turns out that the biggest source of compile-time hell for most C++ projects
#include directives. While C++20 finally had some sense of modules as a
language feature, for most of its 30+ year history, the only way to have
your project across multiple files was lexical inclusion via preprocessor as
inherited from C. For those who don't know: if you
#include "somefile.h", the
compiler has to find that file, open it, and read it, and injects its contents
where that directive was.
As a project gets larger,
#includes have their own
#includes, and you end up
creating a nasty web of these things, each, ostensibly, requiring touching the
filesystem, opening the file, reading the file, doing the appropriate thing in
memory, and closing the file. While compilers had tricks to skip parts of this,
when you repeat this hundreds of thousands of times, and you can see why build
times slow down. And if you have thousands of files in your compilation graph
that have multiple of these links, you can see how destructuring your program to
#include complexity is non-trivial. Especially if, as Flash did, you
have a matrix of supported platforms and products (Windows, Mac, Linux, TVs;
many of them having more than one of: plugins (NPAPI, ActiveX, Chrome Pepper),
Standalone Desktop player, embedded player for the Flash Authoring tool, Adobe
AIR desktop app runtime, and others).
(also: given my rants on people saying "simple" in programming contexts, this is a fantastic example of a "simple" solution that's fucking terrible: you can't think of a more straightforward modularity construct than "make the contents of that file visible here," and the most straightforward way of doing that is "include its contents here." But it turns out these simple straightforward constructs get bad, very quickly if your project grows to any real size. Never trust when someone says "simple.")
I was not expecting to run into this ghost when I read about speeding up mypy for production code systems, but it turns out the biggest issue was that Dropbox's Python codebases do a similar thing with Python's similarly "simple" importing mechanism. And not just Dropbox: Khan Academy spending literal months moving files around. Here's Instagram wishing Python had any invariants at all on its module loading.
The mypy article has a good name for this: "tangle." I urge you to be mindful of them: many languages make them very easy to build and you'll waste far too much of your life because of them. Ideally, if you know you're going to grow a product for any real amount of time or staff size, I might suggest not using a technology that nudges teams to make them. I often say "I don't hate Python, I just wish people would stop starting companies with it." But if you do, think as early as possible about dependencies. A little extra thought might save you hours every week for the project's lifetime.
Thanks for the read! Disagreed? Violent agreement!? Feel free to join my mailing list, drop me a line at , or leave a comment below! I'd love to hear from you 😄