Stop the Clock

My watch has this neat feature where it automatically keeps the time and date synchronised via a radio signal. For the most part it works flawlessly, and I haven’t had to worry about setting the time in all the years I’ve had it, even when I accidentally starve it of sunlight to charge and its battery dies. A short walk outside and it’s back up and running in no time, back to the correct time again.

But one morning recently I noticed it had started to run about two minutes fast, and in trying to manually set the time I learnt a valuable lesson that I think is informative far beyond just my watch.

I pulled out the instructions manual and found the section on manually setting the time. Pull out the dial on the side to change mode, and then press a little button to advance forward by one minute—there is no button to rewind a minute. It’s a twelve-hour watch, I need to advance by … seven-hundred and eighteen minutes. Mercifully, you can just hold down the button to continue advancing.

After several minutes of the hands whizzing around it went past noon, and I notice the little day-of-month indicator panel. Oh yeah, it is a twenty-four hour watch. Okay that’s … one-thousand four-hundred and thirty-eight minutes. The hands continue whizzing by. No wait, once I go forward a day then the day-of-month indicator will be wrong. I need to go forward an entire month? There’s no month indicator. But that’s … a lot of minutes.

The hands continue whizzing by as I think, but I haven’t even advanced a single day yet. Wait wait wait, I can’t advance a month because not every month has the same number of days. There’s no 31st of November. So, a whole year then? Still the hands continue to whiz by but the finish line is getting further and further away.

By this point it’s clear to me that this isn’t the correct way to adjust the watch backwards two minutes. I have probably been going for ten minutes already and goal has blown out from twelve hours to a whole year, but now I can’t stop my brain from going down the rabbit hole thinking about whether this will ever even work. I can’t do a year because there are leap years every four years. Except they aren’t every four years because they don’t happen every hundred years but they do happen every four-hundred years. How many minutes are there in four-hundred years?

Enough! Stop wasting time, there has to be another way.

I check the manual again but this time to follow the instructions to synchronise with the radio signal, and after a few more minutes of the hands whizzing around I’m back where I started, two minutes fast and about fifteen minutes of my life gone.

I pull the dial out again and then pause to think. There is another button, but it doesn’t do anything in this mode. I can’t see anything else on the watch besides the dial and the forwards button. I start to wonder if maybe the dial has another setting for a backwards mode, when I notice that the hands are paused. It’s been paused the whole time. I’ve been thinking for a minute, and now my watch is only one minute fast. If I just wait one more minute, it’ll be right.

So in the end, after fifteen minutes spent madly rushing forwards with no plan, with the finish line only getting further and further away the more I chase it, I achieved absolutely nothing and had to reset and start over again. What was really needed was to pause, understand the situation properly, wait for the right moment, and then the solution was trivial.

Read Stop the Clock

A Different Kind of Delivery

In my day job I’m a software development consultant, which means I work in a delivery team and spend a great deal of time working closely with my product owner to build great software. Outside of my day job, I was recently part of a big project completely unrelated to software and was on the other side of the fence, as the (co-) product owner working with a rather different type of delivery team.

It has been a huge learning experience for me, not just getting the product owner’s perspective but also observing how delivery teams work in other industries. In this post I’ll share some of the most important lessons which I think we can carry across to software development.

Read A Different Kind of Delivery

Battles and Wars

In software there are battles and there are wars. The battles are the day-to-day—dealing with tech debt, buggy code, flakey build systems, inadequate testing, unreliable stakeholders, vague and changing requirements, overbearing processes, the usual stuff. The wars are the bigger picture—hitting a deadline, delivering a big project, developing strong relationships, shipping product.

There is an infinite stream of battles. Regardless of whether you win, lose or surrender, there will always be more battles to fill your day-to-day. Battles come and go all the time, and they’re always changing. Wars, on the other hand, play out over a much longer timeframe—it takes time for the tides of war to change, and you can’t always choose the wars you fight in.

Read Battles and Wars

100 Days of Blogging

100 days ago, on 16th January, I started a public blogging streak on Twitter. At that point, it had been 232 days since my last post and I was suffering from writer’s block. My goal was not to post every day or even every week, but just to force myself to make some progress towards a post each day by thinking of a topic, bashing out a few points in a Twitter thread, drafting or actually (eventually) posting.

This isn’t my first attempt at an activity streak. I’ve previously written about my 199 Days of Git, and late last year I attempted 100 days of meditation publicly on Twitter to mixed success. In the end, I posted to Twitter on 70 of the 100 days and added 12 posts (including this one) to my blog. Now that it’s come to an end, it’s time to reflect on the experience, so here are my top five lessons learnt.

Read 100 Days of Blogging

Code Review

I’ve seen a lot of questions recently about code review, so I thought I would write about my experiences working across a few development teams. But first, it’s important to remember that code review is but one small part of a good development process. It’s hard to give advice in general about code review without considering the whole process.

For example, some people argue that code review is a waste of time because by the time you review code, it’s already too late to change the design. The author and reviewer will argue for a bit, but by the sunk-cost fallacy the author will only commit to minor changes and move on. Some complain that code review mostly devolves into petty bike-shedding over code style and formatting. Some complain that waiting for review becomes a huge bottleneck in the development process.

Read Code Review

When Two Rights Make a Wrong

A few years ago I came across this awesome post, How I hacked hundreds of companies through their helpdesk, which describes a neat hack on a whole bunch of companies. I encourage you to read the full post because it’s a fascinating read, but I’ll summarise the gist of it here.

Some work apps, the most common example being Slack, allow you to register and sign in with any email address on your employer’s domain, e.g. anything@company.com. This is a convenience that allows your employees to self-service register without allowing just anybody in. This sounds safe enough to a lot of companies, because they figure they only give out these email addresses to current employees.

Read When Two Rights Make a Wrong

Lessons from the AFL

The footy is back on again, and I was thinking about what lessons we can take from team sports, like the AFL, and apply to team environments at work, like a typical software development team. So in no particular order, here are ten lessons I think that we in software development could learn from AFL teams.

Read Lessons from the AFL

The Perils of Premature Planning

A few years ago I was consulting with a service delivery team. They had some manual processes for on-boarding new customers that took two weeks and they were trying to drive this time down. They knew all the tasks that were involved, and they used a spreadsheet to plan it all out.

They were trying to switch from this waterfall-ish process to something more agile, which of course started with adopting an Enterprise-grade Agile tool like Azure Devops. They had 4 on-boarding jobs in the pipeline, so they created a backlog and filled it up with eight weeks’ worth of work.

Read The Perils of Premature Planning

Scheduling a Weekly Lunch-and-Learn

Early last year, before COVID, I joined an initiative in my squad at work to boost employee engagement. There were four of us in the group and we were each tasked with running a series of events for the members of our squad. I volunteered to organise a monthly lunch-and-learn session at the office, where each month a member of our squad would present on a topic of their choosing during our lunch break.

We already had these going on an ad-hoc basis sporadically throughout the year, usually individually organised by the speaker, but I wanted to make this a regular event at the office. Unfortunately lockdown struck before we could run the first session, and so we had to change plans. With everybody working from home employee engagement felt more important than ever, so we quickly pivoted to online sessions and we decided to temporarily up the frequency from monthly to weekly, at least for as long as momentum could carry us.

Since then we’ve continued to run these weekly, having just passed 40 sessions, and having missed only a handful of weeks due to holidays or clashes with all-hands. Here’s my top 10 tips for you to try this at your work.

Read Scheduling a Weekly Lunch-and-Learn

Object-capability Model

The object-capability model is a really interesting model of programming that I don’t think is well taught and certainly not well practiced, nor even encouraged by most modern programming languages.

Think about the concrete actions that your application can take: making a web request, reading/writing to the filesystem, communicating with another process like a database, printing to the console, etc. We call these “capabilities”, and without them a program is basically useless.

Read Object-capability Model

Top-down vs Bottom-up

I like to look at the world around me in layers of hierarchy, and there are two lenses that I apply when thinking about how these layers come together.

The first lens, “top-down”, looks at the world by starting at the top, something high-level or abstract, and then working down to the lower layers. The second lens, “bottom-up”, is the opposite—starting with something low-level or concrete and working up. This sounds pretty vague, but you can apply these two lenses to pretty much everything, so let’s explore by looking at a few examples.

Read Top-down vs Bottom-up

Triggers and Causes

In the tech world, the common wisdom is that when things go wrong we have blameless post-mortems. The idea here is that preventing the triggering event from occurring is only part of the solution. The other part, often the bigger part, is mitigating other factors which cause the event to have such a large impact. Sometimes it’s not possible to prevent all triggering events, and we can improve our resilience and reliability more effectively by mitigating common contributing factors to outages.

We ask questions like, “Can we detect the triggering event sooner?” “Can we speed up our response process?” “Can we limit the number of people impacted, or the degree to which they are impacted?” “Can we automate an error-prone manual process?” “Can we allow a system to self-correct?”

Read Triggers and Causes

Redefining Success

There’s an expression in tech that I think is often misunderstood and then used to justify bad behaviour—“fail fast, fail early”. The idea behind it is that if an idea is going to fail, it’s better if it fails early, before you reach the point of the sunk-cost fallacy.

This sounds sensible, and encourages people to build a Pilot rather than a Season 1, which I think is generally a good thing. But I have two major concerns with this expression.

Read Redefining Success

Framing Solutions in Terms of the Problem

I was working on a Scrum project where the user stories always ended up being too big to fit into a sprint, and we were constantly half-finishing stories and carrying them over to the next sprint. Our team agreed we needed to split the stories up, but we couldn’t agree how.

The team proposed we split stories into front-end and back-end components. This is a common way of splitting up work, because it’s obvious, it’s easy to do, and it’s easy to then assign the smaller stories to those with the right skills. I proposed instead we use vertical story slicing, where you slice stories into thin, end-to-end slices, and each slice is fully integrated and useful to a user. Vertical story slicing could be a post in its own right, and I won’t go into a full discussion of its merits here.

Read Framing Solutions in Terms of the Problem

Minimum Viewable Program

The term MVP, Minimum Viable Product, gets thrown around a lot in our industry. Some people say MVPs are too small and customer expectations are higher than ever, and propose instead the Minimum Awesome Product. Others say MVPs are too big and bloated and still cost too much.

To help people agree on the size and scope of an MVP, I propose the following simple analogy: Is your MVP a Season 1, or a Pilot? And to match, an alternative expansion of MVP: Minimum Viewable Program.

Read Minimum Viewable Program

DIY Page Analytics

This site is hosted on GitHub Pages. Because I’d like to have a rough idea of which of my posts are receiving the most engagement and which sites are driving the most traffic, and since GitHub Pages doesn’t provide me with this by default, I decided to add some page view analytics to my site. I’m not particularly keen on privacy-invasive services like Google Analytics, which collect far more information than I need and share it with 3rd-parties, so I decided to build my own minimalist service. Also, it just seemed like a fun yak-shaving exercise, and everything else on this page is hand-made.

In this post we’ll walk through how to build a very basic page analytics service using Azure Functions and Table Storage, which you can host yourself for a few cents per year—my last twelve invoices reached a grand total of 49 cents.

Read DIY Page Analytics

Goldilocks Routines

I hate the lock on my front door. It’s pretty standard. Unlock with a key from the outside, lock by turning the knob on the inside. Open from the inside and the door stays locked. Seems pretty simple, so what’s not to like? If I was capable of following the routine perfectly, it wouldn’t be so bad. When I get home I unlock the door, step inside, turn the knob to lock the door, and put my keys down on my desk. When I leave home I grab my keys from my desk, open the door, step outside, and the door stays locked behind me.

The problem is that I don’t always follow the routine perfectly. I can be a forgetful person, and I don’t want to lock myself out by leaving the house having forgotten my keys. I know that if I’m leaving for work I’ll never forget to take my bag, so sometimes when I get home I put my keys in my bag instead of on my desk. But at the same time, I don’t want to train myself to think “I will never forget my keys because they’re always in my bag”, because sometimes I leave the house without my bag, if it’s not for work. This means that every time I leave the house, I do the dance where I step outside, keep the door propped open with my foot, and then double-check my bag or pockets for my keys.

Read Goldilocks Routines

Good Intentions

We make a lot of decisions in software development. Compared to other fields of engineering, the process of building software relative to designing it is very rapid, shrinking the time between decisions and also typically shrinking the time spent on decisions. Modern agile software development methodology only exacerbates this problem. “Move fast and break things”.

On top of this, software systems will often stay under active development for decades, growing to be unfathomably large and complex. In complex systems decisions in one area often have implications in other seemingly unrelated areas, making us hesitant to make quick decisions.

Read Good Intentions

Meeting Companion

Building a Real-Time Chatroom with SignalR and React

In this post we’re going to build a real-time web application with SignalR and React that lets you create chatrooms and send noises to each other, perfect as a meeting companion when you don’t want everybody coming off mute. If you follow along, you’ll be able to build and deploy your very own copy of Meeting Companion and run it completely free on Microsoft Azure. All of the code is available in my GitHub repository. This is a slightly simplified version of another webapp I built, Soundroom, which can also be found in my GitHub repository.

Read Meeting Companion

Make it Work, Make it Right, Make it Fast

This is an expression originally used to describe a process for writing code. Make it work—get something, anything, running as quickly as possible. Make it right—get the program to do what you want it to. Make it fast—get the program to do what you want it to fast enough for your needs. What’s important here is the order. If you do these in the wrong order, you’re gonna have a bad time. The easiest time to make code compile and run is when there’s barely any of it and it doesn’t really matter what it does. It’s really hard to fix bugs in tightly optimised code, because it’s likely a lot more complicated than it was before you optimised it.

Read Make it Work, Make it Right, Make it Fast

People and Purpose

Whenever I interview for a job at a company, there’s one question that I make sure to ask every single person I can.

What’s the one thing you would miss the most if you left $COMPANY_NAME?

When I interviewed at Readify, everybody said it was the people. Not in the “these people are my best friends” sense, although that may very well be the case, but more importantly in the “this is the smartest, most passionate, most supportive, most inspiring bunch of people I’ve ever worked with” sense. Seeing a handful of Readifarians present at DDD Brisbane in 2017 is what attracted me to Readify in the first place, so I had a strong feeling this was going to be a common answer when I was asking the question.

Read People and Purpose

Take a Step Back

In my time so far working in software development, as a developer and as a product manager, I’ve made and seen a lot of mistakes. I spent some time recently reflecting on some of the biggest mistakes, the ones that ultimately cost the most time or money, that caused the most frustration and heartache, and tried to devise some lessons learnt. In the end I realised that the vast majority of mistakes were actually variants of the same core mistake, and that one main lesson applied to all of them.

In this post I will discuss this mistake, some examples of where it comes up in software development, some thoughts on why it keeps happening, and some tips on how to avoid it.

Read Take a Step Back

Impostor Syndrome

What do a junior and a senior developer have in common? They both constantly feel like they have absolutely no idea what they’re doing. What’s the difference between a junior and a senior developer? The senior developer knows that this is completely normal. One of the things about programming is that if you’re doing something you’ve done before, you’re usually doing it wrong. And by this I mean that if you’re trying to solve a problem you’ve solved before, you should just reuse the solution from last time.

We’re lucky in the world of software that we can do this, but one of the consequences of this is that most software development is almost by definition something that has never been done before, at least by you. If you work in software, you’d better get used to this feeling. It’s easy to look at all the people around you at work or in the community and the great work that they do and think they must know what they’re doing. “These people are real developers, I’m just an impostor. One day they’ll all realise I am completely out of my depth and I’ll be fired.” This feeling is so common that it has a name—impostor syndrome.

Read Impostor Syndrome

Computer Science as Exploration

What is computer science really about? In the present day, despite being such a relatively young and immature field, computer science employs millions of people all over the world, it produces the technologies that run our lives, and it is responsible for countless billions or trillions of dollars of value. Even going into the near-term future, the software that has been built over the last few decades will continue to affect the daily lives of people for generations to come.

But to me, that’s just commercial success. At the end of the day, or perhaps better to say at the end of the millenium, will anybody really care? If we made contact with an alien race, would we brag about our ability to share cat photos with millions of strangers, or even our ability to build billion dollar companies? There must be some deeper meaning to this all. I can feel it. When I’m programming or problem solving, I feel like I’m exploring. But what am I exploring?

Read Computer Science as Exploration

Accidental Agility

Today marks the 18th anniversary of the final day of the meeting at Snowbird which ultimately lead to the creation of the agile software development manifesto. If it were a person, it’d be at the legal drinking age (here in Australia). And it has a lot to celebrate, it’s come a long way in that time. What started as scribblings on a blackboard in a meeting of seventeen programmers has since grown to take the business world by storm. Some would even say it’s grown out of control (some of the original authors, no less).

In this post, I want to rediscover the essence of agility by looking at an example of an industry that exhibits the principles outlined in the original manifesto, despite not even being aware of it. This essentially means that they have independently discovered the ideas of agile development, but because they missed the surrounding hype, they’ve managed to avoid a lot of the unnecessary baggage that tends to follow “Agile” in practice. My goal is to make people refocus on what is really important and valuable about agile software development, and see past the noise that has built up around it.

Read Accidental Agility

Find a Purpose

My Journey, Part 2

I continued building tiny, incomplete games with Game Maker for a couple of years, never really making anything substantial but still learning a lot. And while I was enjoying the act of making games, and I certainly enjoyed playing games, I didn’t really enjoy playing my games. Partly because they weren’t very good, but also because I knew how they worked, how to beat them, and I didn’t get the same feeling of discovery that I got playing other games. And as the enjoyment of playing the games diminished, so too did the enjoyment of making them. I wasn’t sure whether I should be programming for the sake of programming, or programming for the outcome.

At the same time, I was spending a great deal of time playing an online game, which will remain nameless. The client for playing this game had an IRC chat window below the main game window, which I would use to chat with my friends while playing. One of my friends was also a programmer, and he knew how to make IRC bots. If I recall correctly, his bot simply helped administer the channel—it would grant certain users permissions when they joined, kick people out when they broke the rules, it could even run a little trivia game. It didn’t do anything terribly exciting, but I could see the potential.

Read Find a Purpose

The First Great Epiphany

My Journey, Part 1

My first exposure to programming was some time around the turn of the century with a program called Game Maker, which as the name suggests, was built for making games. Game Maker actually supported a decent amount of graphical programming by dragging-and-dropping icons around the screen to describe the behaviour of different objects in the game, but as soon as I learnt that there was another way to do it that had more features, I wanted to learn that.

The tutorial for the scripting language in Game Maker at the time walked you through programming a little game similar to Space Invaders, where you controlled a space ship at the bottom of the screen and the goal was to shoot the enemy ships approaching from the top of the screen. I followed the instructions closely, typing in all the code it supplied to define the behaviour for moving and shooting, including a cooldown for the gun so that you wouldn’t just fire off a shot every game tick. And then they gave you an exercise, to add a second weapon to the ship that was triggered from a separate key and that had its own cooldown. And I was stumped.

Read The First Great Epiphany

Multiple Git Profiles

If like me, you need to make Git commits from multiple email addresses on the same machine (say, from your personal and your work address), here’s a handy trick that will help make sure you make every commit with the right address.

Start by creating a directory for each profile, named after the profile. In my case, I have D:/git/home and D:/git/work. Move all your Git repositories into the directory corresponding to the profile that you want to use when making commits to that repository. At the root of your profile directories, create a .gitconfig file with the following content.

Read Multiple Git Profiles

Programming by Wishful Thinking

This is a technique that I discovered several years ago while teaching an introductory programming course, and I was extremely pleased to find out that although it had already been discovered, I had given it the same name. Programming by wishful thinking is a style of top-down program design that helps you improve the structure of your code, isolate the hairy parts from the simple parts, think more clearly about data flow, and work faster. I find it particularly helpful for novice programmers who feel intimidated when starting a new project and aren’t sure how to get started, but I still practise it regularly as well.

Read Programming by Wishful Thinking

Diagnostics Anonymous

When working with large systems, especially with software, inevitably something will go wrong and you’ll be stuck trying to diagnose it. My years of developing software have given me a lot of practice diagnosing errors or unintended behaviour in software systems (usually in my own code), and over time I’ve built up a systematic process that I run through to speed up the process. In writing this post, I came to realise that my process actually has quite a lot in common with 12-step programs, so I’ve tweaked the format a little to make the content a little more interesting.

Read Diagnostics Anonymous

Imitating Classes

In this post, we are going to explore how you might imitate classes in a language that doesn’t have them, to get a better feel for how various object-oriented language features actually work. We will use JavaScript, but ban ourselves from using

  • the class keyword (obviously),
  • the new keyword (we will construct all of our own objects),
  • the this keyword,
  • prototypal inheritance (we will build our own inheritance mechanism).

Read Imitating Classes

The Freedom of Restrictions

One of my great joys when designing things is when I discover that I can lift a restriction and make something both simpler and more powerful at the same time. This can happen at all levels, from something like changing a function signature to make it more generic, right up to unifying high level system components. The more generic something is, the more situations you can use it in, and the more value it can provide.

Read The Freedom of Restrictions

What’s in a Language?

What’s the purpose of a programming language?

A programming language is an interface between humans and computers, that allows us to program computers to perform some task. The purpose of the task is usually to solve some particular problem that the human has. Most languages are Turing complete, which essentially means that they are mostly all equivalent. So what’s the point of creating a new programming language if it’s equivalent to ones that already exist? Turing completeness means that languages are equivalent in terms of the programs they are able to express, but it says nothing about the journey of getting to the finished program.

Read What’s in a Language?

199 Days of Git

Reflections on Git streaking

May 20, 2016. My Git streak comes to an abrupt end on 199 days. Today, GitHub disabled the commit streak feature and left me stranded one day short of a milestone. It feels a little frustrating to get so close and then have it taken away, but in the end the overwhelming feeling is actually one of relief.

I’m a chronic procrastinator and a prolific sidetracker—I’ve always had trouble following through on things after the initial whirl of enthusiastic development dies down. More often than not, it’s not so much that I get bored of the project I’m working, it’s that I get distracted by something else more exciting. I’ve tried lots of different approaches to improve this, but haven’t had much success.

Read 199 Days of Git

Trust Nobody, Not Even Yourself

Trust the programmer

This phrase is part of the C philosophy, and has influenced the design of many programming languages. In general C usage, this is best observed by the use of pointer casts—a mechanism by which the programmer can bypass the type system, trading compile-time type safety for flexibility and potentially incurring fatal crashes at run-time. The phrase needs little explanation—the programmer knows what they’re doing, don’t get in their way.

Read Trust Nobody, Not Even Yourself

Why Static Isn’t Real Sharing

The static keyword has origins as far back as C, and has carried across to C++, Java and C#, among others—although its meaning has changed a bit along the way. In C# and Java, one of the common uses is for class-level sharing of members. Static members don’t belong to any instance, and can only be accessed directly from the class or from another definition in the same class.

And this is all well and good for sharing within a class, but the problem is that it doesn’t play well with inheritance, because static members cannot be overridden. And inheritance is another common method of achieving code sharing. Consider the following snippet, which shows how one might hope to override static members in C#.

Read Why Static Isn’t Real Sharing

Intuition of Church Encoding

After first being introduced to the concept of Church numerals in Structure and Interpretation of Computer Programs, I decided to learn more about them and the more general topic, Church encoding. For those who don’t know, Church encoding defines a way to represent common data types and structures in the Lambda calculus using only functions, since functions are the only terms available.

I eventually stumbled upon a pretty neat intuition for how Church encodings work, which enables you to create encodings for arbitrary data types very easily. But first, a little on how I got there…

Read Intuition of Church Encoding

Pre-processing Imports in Python

Inspired by David Beazley’s talk on various hacks that can be made to Python’s import system, I whipped up the following script for running a preprocessor over a file at import-time. In most cases, I would say this is far from a good idea, but it might be useful for creating small domain-specific languages, or defining new literals, or something like that.

Read Pre-processing Imports in Python

Multiple Dispatch in Python

I recently read Functional Programming in Python which mentions a library which adds multiple dispatch to Python. One of my biggest hobbies is creating things from scratch, as it really helps me get a better understanding of how they work, so I thought I’d see if I couldn’t figure out how to do it myself.

Read Multiple Dispatch in Python

Programming Languages for Beginners

What’s the best/easiest programming language to learn for a beginner? I see this question asked all the time. Usually asked by people who want to get into programming, or maybe they’ve just finished learning the basics in their first language and are thinking about where to go next. It’s an innocent enough question and usually asked with good intentions, but it still bugs me every time I see it.

Read Programming Languages for Beginners