Mesdames et messieurs: voici la tentative d’aujourd’hui de passer Γ  un petit-dΓ©jeuner plus minimaliste: deux grands cafΓ©s au lait.

Ladies and gentlemen: presenting today’s attempt to move to a more minimalist breakfast: two large cappuccinos.

A cappuccino in a black coffee mug, placed on a matching saucer with a spoon beside it, sits on a wooden table outdoors alongside an iPad.

Just listening to Ben Thompson’s and Andrew Sharp’s hot takes on baseball on the latest episode of Sharp Tech. My suggestion to Ben would be to try watching a game of test cricket some day. Sounds to me like they share many of the same attributes that Ben likes about baseball. πŸ˜„

Reddit’s decision to allow only Google to index their site will probably mean I’ll be seeing them far less often than I do β€” which is almost never anyway, and generally from the results of a search. So I’m recording this screenshot, which I call “Reddit in the results”, for posterity.

A screenshot of an Ecosia search result for the query 'postgresql unsigned integer values', with links to Stack Overflow, Reddit, and PostgreSQL docs in the results

Edit: Turns out Ecosia sources some of their index from Google, so these Reddit links will likely remain in my searches. I guess that makes this post unnecessary. I’m going to keep it up though, for posterity of my unnecessary effort to post for posterity. πŸ˜„

Why did I eat the breakfast I did today? I told myself I wasn’t going to, as it tended to make me nauseous sometimes. Well, an hour later and here we are: mild nausea. πŸ€¦β€β™‚οΈ

Need to work on that self control thing people talk about. The aroma of baked goods at the cafe was the thing that got me today, though. Maybe I should start wearing a nose clip.

πŸ”— Never Tweet Your Heroes

I wonder if M.G. Siegler had anyone in mind when he wrote this.

Go Feature Request: A 'Rest' Operator for Literals

Here’s a feature request for Go: shamelessly copying JavaScript and adding support for the “rest” operator in literals. Go does have a rest operator, but it only works in function calls. I was writing a unit test today and I was thinking to myself that it would be nice to use this operator in both slice and struct literals as well.

This could be useful for making copies of values without modifying the originals. Imagine the following bit of code:

type Vector struct { X, Y, Z int }
oldInts := []int{3, 4}
oldVec := Vector{X: 1}

newInts := append([]int{1, 2}, oldInts...)
newVec := oldVec
newVec.Y = 2
newVec.Z = 3

Now imagine how it would look if rest operators in literals were supported:

type Vector struct { X, Y, Z int }
oldInts := []int{3, 4}
oldVec := Vector{X: 1}

newInts := []int{1, 2, oldInts...}
newVec := Vector{Y: 2, Z: 3, oldVec...}

I hope you’ll agree that it looks a bit neater than the former. Certainly it looks more pleasing to my eyes. True, this is a contrived example, but the code I’m writing for real is not too far off from this.

On the other hand, Go does prefer clarity over brevity; and I have seen some JavaScript codebases which use these “rest” operators to an absurd level, making the code terribly hard to read. But I think the Go user-base is pretty good at moderating themselves, and just because it could result in unreadable code, doesn’t make it a forgone conclusion. Just look at Go’s use of type parameters.

Anyway, if the Go team is looking for things to do, here’s one.

I hear Robb and John are looking for a new term for the bringer of snacks for Ruminate. Allow me to throw my suggestion into the ring. It might be difficult to get at first, but trust me, it’ll make sense after saying it a few times.

Okay.

You ready?

Better strap in: it’s going to get a little mind-blowy around here.

Okay, here it is:

It’s snack-plier.

Get it? Snack…plier. The snacks supplier. What does a snack-plier do? They supply snacks. They are the snack supply person. Their whole purpose in their endeavour is to ensure the supply of snacks to those that are requiring snacks.

There it is: snack-plier. Yeah, I told you it’d be good. πŸ˜‰

(Okay, I think I’ve embarrassed myself enough today. πŸ˜‚)

Was talking to a fellow colleague today and he mentioned that he’s recently started a blog on Bear Blog. He was reluctant to share the URL to it though, which I can understand. I’m not in the habit of sharing mine with people I know.

Anyway, if J. C. happens to stumble upon this blog, hey! πŸ‘‹

A Follow-Up To Mockless Unit Testing

I’m sure everyone’s dying to hear how the mockless unit tests are going. It’s been almost two months since we started this service, and we’re smack bang in the middle of brownfield iterative development: adding new features to existing ones, fixing bugs, etc. So it seems like now is a good time to reflect on whether this approach is working or not.

And so far, it’s been going quite well. The amount of code we have to modify when refactoring or changing existing behaviour is dramatically smaller than before. Previously, when a service introduces a new method call, every single test for that service needed to be changed to handle the new mock assertions. Now, in most circumstances, it’s only one or maybe two tests that need to change. This has made maintenance so much easier, and although I’m not sure it mades us any faster, it just feels faster. Probably because there’s less faffing around unrelated tests that broke due to the updated mocks.

I didn’t think of it at the time, but it also made code reviews easer too. The old way meant longer, noisier PRs which β€” and I know this is a quality of mine that I need to work at β€” I usually ignore (I know, I know, I really shouldn’t). With the reviews being smaller, I’m much more likely to keep atop of them, and I attribute this to the way in which the tests are being written.

Code hygiene plays a role here. I got into the habit of adding test helpers to each package I work on. Much like the package is responsible for fulfilling the contract it has with its dependants, so too is it responsible for providing testing facilities for those dependants. I found this to be a great approach. It simplified the level of setup each dependant package needed to do in their tests, reducing the amount of copy and pasted code and, thus, containing the “blast radius” of logic changes. It’s not perfect β€” there are a few tests where setup and teardown were simply copied-and-pasted from other tests β€” but it is better.

We didn’t quite get rid of all the mocking though. Tests that exercise the database and message bus do so by calling out to these servers running in Docker, but this service also had to make calls to another worker. Since we didn’t have a test service available to us, we just implemented this using old-school test mocks. The use of the package test helpers did help here: instead of having each test declare the expected calls on this mock, the helper just made “maybe” calls to each of the service methods, and provided a way to assert what calls were recorded.

Of course, much like everything, there are trade-offs. The tests run much slower now, thanks to the database setup and teardown, and we had to lock them down to run on a single thread. It’s not much of an issue now, but we could probably mitigate this with using random database names, rather than have all the test run against the same one. Something that would be less easy to solve are the tests around the message bus, which do need to wait for messages to be received and handled. There might be a way to simplify this too, but since the tests are verifying the entire message exchange, it’d probably be a little more involved.

Another trade-off is that it does feel like you’re repeating yourself. We have tests that check that items are written to the database correctly for the database provider, the service layer, and the handler layer. Since we’re writing tests that operate over multiple layers at a time, this was somewhat expected, but I didn’t expect it to be as annoying as I found it to be. Might be that a compromise is to write the handler tests to use mocks rather than call down to the service layer. Those tests really only validate whether the hander converts the request and response to the models correctly, so best to isolate it there, and leave the tests asserting whether the business rules are correct to the server layer.

So if I were to do this again, that’ll be the only thing I change. But, on the whole, it’s been really refreshing writing unit tests like this. And this is not just my own opinion; I asked my colleague, who’s has told me how difficult it’s been maintaining tests with mocks, and he agrees that this new way has been an improvement. I’d like to see if it’s possible doing this for all other services going forward.

Every so often, Goland gets into a weird state where it completely forgets about symbols from a certain package. It’s not every package, and the build might run perfectly fine. Yet when you try to do any code completion from this package, it says it cannot find symbols. It’s very strange.

Clearing the cache and restarting seems to be the only way to resolve this. I’m about to do this for the second time today.

It’s going to be a lovely day today. Perfect day to just sit in an office and do work. πŸ§‘β€πŸ’»

Networking is hard. This remark applies to every form of networking you can think of.

This day in work spam: anyone care for some “world knowledge information”? 😏

A screenshot of an email spam, from joe.jonas, subject RE: External Camera Screen, sent on 19th July 2024. Message follows: Dear, Our External Camera Screen marked report is the latest data. Please let me know so you can check the information. Best, World Knowledge Information

Preparing the second room for a couple of house guests that’ll be coming next week. 🦜

A room contains a large empty metal cage, a rowing exercise machine, a small table with electronic equipment, all set on a brown mat and a protective floor covering.

They get a little funny around mirrors so I’d had to cover the wardrobe with newspaper. Hope it holds.

A room is set up with newspaper taped in front of half of the sliding-doors of a wardrobe with full-sized integrated mirrors. A large birdcage is positioned on the right side.

Continuing my exploration in Go GUI toolkits. Golang Weekly linked to one called Fyne, which I tried out this morning. Looks very promising. Missing a couple of things, but a lot is there and I really like how the API works. Managed to build a somewhat functional Boop clone as an experiment.

A screenshot of the Boop-clone which shows a toolbar with a single button, and a text field with some example text. A screenshot of the Boop-clone which shows a list of actions overlayed over the text field. The two actions are Quote and Dequote, and the entry above the actions show the input 'qu'

πŸ”— Major Windows BSOD issue hits banks, airlines, and TV broadcasters

Oof! I feel bad for all those Window sys-admins who’s weekend has just been ruined.

Maybe the key to a happy career in software engineering is: keep the number of systems you have admin access to as low as you can. πŸ˜›

Had a go at recreating the last song Anders Enger Jensen wrote for 8 Bit Keys, since it’s one that I like quite a bit. Here’s a YouTube link to the original. This one was done in Logic Pro, and has a little more of the typical synth leads than the more brassy sound Anders Enger Jensen used.

This week’s earworm: Warsaw in the Sun, by Tangerine Dream. 🎡

Album cover of the Tangerine Dream Zeitgeist Concert, at the Royal Albert Hall London 2010

πŸ“Ί Everybody’s Free (to Make Websites)

One word: this!

Edit: Kev Quirk shared a link to the post by Sarah Joy, who wrote the narration for this video.