Category: Software

I had a weird week back in October, and it all started when I posted this GitHub issue.

What happened?

The .NET team built a feature called Hot Reload for .NET 6, which would allow for code to be changed while an application is running. It was planned as a feature for all of .NET from the start:

Our goal is to provide a consistent dev inner loop experience in .NET Core across all platforms, architectures, and workloads.

A preview version of the feature landed in April 2021 and by October it was pretty much done. I used Hot Reload throughout the preview period and loved it. Then at the last minute, Microsoft announced that the feature would be locked to Visual Studio; to say I felt disappointed would be an understatement. I posted on GitHub asking for more information, and I soon found out that many, many others felt the same way.

There was a huge community uproar, I was quoted in multiple news articles, and Microsoft eventually backed down. It was a happy ending, but I was still left with a bitter taste in my mouth.

OK, so what?

To many people, it’s not obvious why this was such a big deal. I think there are 2 main reasons:

  1. Quick feedback isn’t a niche feature; it’s an essential element of any creative activity.
  2. Limiting Hot Reload to Visual Studio would exacerbate .NET’s existing weaknesses.

I’ve rambled about 1 before, so I’ll focus on 2 here.

.NET’s at a bit of a disadvantage when it comes to cross-platform development, in both perception and reality. The tooling situation outside of Visual Studio (or Rider) often leaves much to be desired, and newcomers often get a poor first impression from the OmniSharp tooling in VS Code. Hot Reload in dotnet watch is a big step forward for .NET outside of Visual Studio; it’s a feature I can point to and say “yes, .NET has good tooling no matter where you use it.”

That’s the crux of the matter; removing Hot Reload from dotnet watch would harm .NET in an area it needs to do much better in. The .NET team understands this, but the change was imposed on them by senior Developer Division leadership against strong internal opposition. This suggests that senior leadership does not understand .NET (bad) or prioritizes Visual Studio over the long-term health of .NET (worse).

I like working in .NET, and the .NET team is doing a world-beating job of pushing the ecosystem forward from its stodgy enterprise-first origins. It’s unsettling that senior Developer Division leadership was willing to throw so much away to sell a few Visual Studio licenses.

It’s been a while since my last update. I wrapped up my sabbatical, did a whole bunch of interviewing, and have since been working on some interesting spreadsheet-related problems at a new job.

Oh, and there’s been a global pandemic on, it’s been weird. Anyway, I kept busy over the last year and a bit:

Switched to Windows

I switched to Windows full time, after a lifetime of Macs for personal use and a decade of Windows for professional use.

This was an experiment in intentionally shaping my own interests; I knew that if I used Windows at home I’d be more interested in the minutia of making good Windows applications.

It worked; I’m just over a year in, and I’ve learned a lot. I still miss a lot of things about macOS but I’m mostly happy on Windows. The Surface devices are really neat pieces of hardware.

ReiTunes

I built my own music player. This was the culmination of something I’ve been thinking about for years; I listen to a lot of long-form music and existing music services don’t serve that niche well. iTunes is progressively less interested in catering to users who bring their own music, and the Windows client has many irritating bugs.

So I decided to build my own music library system with an offline-first native client; how hard could it be? Well, 500+ commits later…

Robin Sloan’s post about “home-cooked” code has been making the rounds, and for good reason. It’s about highly personalized programs; when you build something purely for yourself or a small audience, it’s more like home cooking than industrial production. I really love the analogy, and it’s inspired me to write about one of my own “home-cooked” tools: wat.

The Problem

I spend a lot of my day in a terminal, and command line interfaces have notoriously poor discoverability. It’s easy to remember the handful of commands+flags you use on a regular basis; it’s much harder to remember the ones you only use a couple times a year. So, like many people, I used to spend a lot of time digging through man pages when 1) I know what I want to accomplish 2) I can’t remember the exact CLI syntax to make it happen.

Unfortunately, man pages usually aren’t designed for this. The average man page is more like a lengthy novel than Cliff’s Notes; it’s thorough+exhaustive documentation when I just want a quick reference.

There are a few excellent projects that provide succinct documentation for *nix commands: tldr and cht.sh are my favourites. But they don’t provide good facilities for adding personalized documentation of my own; that’s where wat comes in.

What Wat Does

wat started out as a simple wrapper around tldr and cht.sh. The two provide similar content, but they do so in different ways; tldr is installed locally, cht.sh is usually accessed through a dead-simple web interface: curl cht.sh/command. The first iteration of wat was just a simple fish function that would call tldr if it’s installed, and otherwise fall back on cht.sh.

These days, wat is written in Python and it’s a tiny bit more sophisticated: it also displays custom Markdown notes which are synced across all my machines using Git.

Say I want to get some information about a video file, but I can’t remember the exact ffprobe syntax. I just type wat ffprobe in my terminal:

This returns a handy tldr/cht.sh summary and it renders the contents of ~/notes/ffprobe.md if it exists. In this case, it looks like I got annoyed enough by ffprobe to write down a note for the -hide_banner flag.

I’ve been maintaining command line notes for a long time, in various tools that just happened to be at hand: OneNote, Notes.app, Markdown in a repo… but wat lets me organize that information better, and view it inline with excellent community-provided documentation.

Immediate Feedback in Programming

Bret Victor's Inventing on Principle

Bret Victor’s talk Inventing on Principle (video, transcript) changed the way I think about computing in 2019. Inventing on Principle is partly about Bret’s guiding principle:

Creators need an immediate connection to what they create. And what I mean by that is when you’re making something, if you make a change, or you make a decision, you need to see the effect of that immediately.”

The Edit-Compile-Run Cycle

Although Bret doesn’t use the term, programmers are deeply familiar with his principle. We’ve all worked with toolchains that introduce significant delay before you can “see” the results of a change, and we know they’re painful. Everyone wants a short edit-compile-run cycle.

But until IoP, I’d assumed that slow cycles wouldn’t materially change the output – you’d eventually get to the same place. This was wrong. I also didn’t appreciate the very small time scales involved; a 5 second delay used to seem trivial to me, but it’s still meaningfully different from a response time measured in milliseconds.

Through some very impressive custom tools, Bret shows how immediate feedback enables exploration, which then gives birth to ideas which would otherwise never see the light of day. This was an epiphany for me. Since IoP I’ve constantly been looking for better ways to code, and re-evaluating my existing processes for shorter feedback cycles. The results:

Rust

My typical Rust development workflow goes something like this:

  1. Write a small function that does roughly what I want
  2. Write a small unit test inline to exercise the function (even if it’s a private function)
  3. Iterate using cargo test until the function is correct
  4. Later, “productionize” the tests if necessary

Rust’s native support for inline unit tests helps a lot here, and the excellent type system catches a lot of issues before I even run cargo test. On the other hand, Rust’s compiler is notoriously slow and that extends to IDE tooling that depends on the Rust Language Server. I’m looking forward to Cranelift for faster debug builds.

headshot

Cities & Code

Top Categories

View all categories