Every now and then when I’m out walking my dog I nerd snipe myself and start thinking of interesting little programming challenges to toy around with. This post explores using Ktor to build a tiny reverse proxy that forwards Snowplow events and pushes notifications over WebSockets so a debug UI can react in real time. Background The app I work on uses Snowplow for event tracking. When you send…
In this post I explore Swift’s @propertyWrapper s and parameter packs to implement a common behaviour. I ran into some code that captured work in a closure and ensured it was only invoked once. The pattern for this one-shot closure looked like this: class Example { private var delayedWork : (() -> Void )? func functionThatQueuesWork () { delayedWork = { print ( "some work" ) } } func…
I spend a lot of time thinking about developer experience at all levels, from what makes a helpful error message deep in a framework to how we make people’s dev environments easy to spin up. In this post I’ll walk through how a local development tool I wrote evolved over 4.5 years and what that taught me about designing developer facing tools. This isn’t a post about Docker, SwiftUI or Compose.…
When I’m solving problems I rarely move in a straight line. I tend to circle the goal, trying a handful of bad or awkward ideas before something clicks. With experience those loops get shorter, but they never really go away. This post is about one of those loops: a small problem in some of our KSP generated code. I’ll walk through a few iterations of the solution and end with a much simpler…
Kotlin’s let is a great tool for writing expressive code, but I’ve noticed it can introduce subtle fragility when used the wrong way - especially alongside certain compiler features. Let’s start with a question - should this code compile? Types class Example { val title : String ? = null } data class Id ( val value : String ) Usage val example = Example () example . title ?. let { Id ( example .…
It’s often a red flag if we see duplicated code and we generally try to reduce it as much as possible. When we control all the code, we can massage structures to make this task easier but we don’t always have this flexibility. This post explores how to remove duplication when two functions share logic but act on unrelated types with no shared interface - using Kotlin and Swift as examples. Let’s…
Most of us are familiar with YAGNI (“You Aren’t Gonna Need It”), that old developer mantra reminding us not to add code or functionality until it’s truly needed. But if we have a mantra for not adding unnecessary code, it seems only fitting we have one for removing code that’s outlived its usefulness. That’s where my internal monologue often kicks in: DYSNI - Do Ya Still Need It? Ruthless…
I don’t use a rebase flow on every project, but when I do, here are the habits that help keep things smooth. The Basic Command I use this formulation of the git rebase command (1) The commit where we branched from | | (2) The branch we want to rebase on top of | | | | (3) The flag to keep merge bubbles | | | .------. .-------------. .-------------. git rebase old_base --onto new_base…
Great developer experience isn’t always about polished UIs sometimes it’s as simple as surfacing the right problem at the right time. One small feature I added to our tech estate that always makes me smile when I use it is a horrible global pop up . Here’s what lead me to build it. The Problem I work on a mobile app team that owns parts of the backend estate. We often need spin up multiple web…
I predominantly work in Swift and Kotlin, both of which support default arguments. As with any feature it’s worth being careful as overuse can lead to unexpected design trade-offs. A common pattern I keep seeing in various codebases I work on is that data transfer objects are being defined using default arguments in their constructors. I think this leads to a few issues that I’ll explore in this…
Crafting regular expressions is fun - when you nail the incantation you feel like a wizard but as time passes, that once elegant spell can start to look like the output of an Enigma machine. My approach when needing to figure out what an old regex was doing was to paste it into whatever the top search result for “Explain regular expression” was. Something that I’ve been doing for a while but…
When a CI job fails, the first thing you usually do is scroll through a wall of logs trying to spot the error. It’s tedious, slow, and often the exact same dance on every project. You could bolt on scripts to comment on PRs or ping Slack, but then you’re duplicating logic across repos and languages and spreading around more auth tokens than you’d like. What if instead, your build just emitted…
There’s something oddly satisfying about seeing a piece of physical hardware with its little flashy light brrring along executing some Swift code I wrote to serve requests over the internet. The hardware is a tiny Raspberry Pi and the app was custom made purely to help my brother out who lives 200 miles away and doesn’t have a mac so software sharing options are complicated. A blocker After…
Retain cycles are often a pain to track down and here’s an example of a less obvious one we had recently. The problem Here’s a simplified reproduction of the issue class Example { var task : Task < Void , Never > ? init () { task = Task { [ weak self ] in guard let self else { return } repeat { performSomeWork () } while ! Task . isCancelled } } func performSomeWork () { } deinit { print (…
I’ve been using Kotlin Symbol Processing (KSP) for a few years so I thought I’d reflect on how I like to work with it to stay productive. First things First Let’s start by recognising if you are new to KSP it is hard to get up to speed, it’s not impossible but it will require some graft to really get stuck in. Many of the blog posts I read when I was starting were very good at helping you get…
SwiftTesting’s parameterised tests are really great. I’ve been finding that I often want to give each example a nice name that shows in the test navigator as the default String(describing:) approach doesn’t always hit the mark. Let’s take the contrived example of testing an enum initialiser that allows the enum to be constructed with a case insensitive string. Attempt 1 As a first stab we might go…
I’m always fascinated when people build complex things, not so much by the final artifact but by the journey they travelled to get to the end result. Projects are very rarely plotted with a straight line from problem statement to final solution but when all you see is the final product it’s easy to discount the work that went into its creation with all the interesting choices and solutions to…
TL;DR Try creating a cli executable in your project that exposes common project tasks that are written in the project’s core language. This allows better contribution and less single points of failure with pockets of knowledge in the team. Scene setting Over time projects accumulate helper scripts to perform various admin tasks. I’ve historically tried to avoid bash as much as possible for these…
I work in a team with many colleagues where we are responsible for several code bases. Often if someone has an issue with running a project you end up either assuming you’ll have the same environment and forget to ask or spend time probing for details about the person’s system. I think this is an ideal case for putting a small script in your project that will collect information that will be…
I had a case recently where I wanted to migrate an Objective-C class to Swift but as it was a large class. I wanted to go one method at a time to allow easier reviewing and to keep my sanity, whilst having each step still pass all unit tests. I quickly hit issues where it seemed like I would have to bite the bullet and just do it as a single large commit. Helpfully I saw a proposal to allow you to…