Andrew Harcourt
  • Personal
    • Posts
    • Life, the universe and everything
    • On the web
    • andrew.b.harcourt on Threads
    • andrew.b.harcourt on Instagram
    • Andrew Harcourt on Strava
    • Andrew Harcourt on Spotify
  • Photo albums
    • Out and about
    • 14th-28th January 2025 - Tour Down Under
    • 22nd September 2024 - Toohey Trail Run
    • 24th August 2024 - Beerwah
    • 11th-26th January 2024 - Tour Down Under
  • Software
    • Posts
    • Articles
    • Have me speak
    • Ask for the unreasonable… and then get out of the way
    • 'Good enough' software
    • Agility in business: what we can learn from the software industry
    • How to engage with the software industry
    • People are a distributed system
    • Messaging patterns for scalable, distributed systems
    • Inversion of control from first principles
    • Your domain model is too big for RAM (and other fallacies)
    • Back to basics: simple, elegant, beautiful code
    • How may I help?
    • Let's talk strategy
    • Coffee with Andrew
    • Project rescue
    • On the web
    • uglybugger on GitHub
    • Andrew Harcourt on YouTube
    • uglybugger on Twitter
    • uglybugger on SlideShare
    • Andrew Harcourt on LinkedIn

Road tripping

15 January 2025 07:00 AEST

Good morning, good morning, good morning, and welcome to QI the 2025 edition of the Tour Down Under. I’m looking forward to this trip, and intending to share much more of it this year.

Some photos will be on my Instagram account, and the bulk of the photos will be in my Tour Down Under 2025 gallery.

The Spotify playlist can be added to until the invitation link expires, but will continue to be available on my Spotify profile.

Most importantly, rides and other activities will be on my Strava profile :)


Tour Down Under 2025

10 January 2025 07:00 AEST

So I’m off to the Tour Down Under next week.

The TDU has been a yearly pilgrimage for many years. It’s long been one of my happiest places - almost a magical fairyland - and some of the absolute best days of my life have been at this event. Bike racing, good friends, club mates (and rivals), meeting random World Tour professionals in the street or at the cafe, fantastic food and a giant street party atmosphere… There’s even a canvas print from Norton Summit (Stage 4 of the 2018 TDU) on the wall in my apartment.

Norton Summit, Stage 4, Tour Down Under 2018

There are countless traditions regarding the TDU. The first ride (Adelaide CBD -> Greenhill Road -> Uraidla -> Hahndorf -> Stirling -> Crafers -> Adelaide CBD). A croque monsieur at the Adelaide Central Market. Mushroom salt. Roller Frenzy. Cheese sticks, cold meats and cheeses for breakfast. The Chateau. Casquettes. Norton Summit. Socks. Life in the Peloton. Bryton caps (don’t ask). Steak and shiraz. The best pub in Uraidla. Cheesecake. The worst pub in Uraidla. Blakeby’s Sweet Shop. Lying on beanbags watching Talking Tour. Adelaide Blanket. Haigh’s chocolates. The Mighty Black Stump. Nail & Gear hotstoppers. Charlesworth nuts. Snake Gully. Stopping at servo after servo for litres of Powerade. Mount Lofty. The Tour Village. Demo bikes. Hahndorf. Street crits. Coach Road. Car park climbs. Food trucks. Subaru bucket hats. Spotting “incognito” World Tour pros trying to sneak out of the village. The Adelaide Track League. The Parade at Norwood. Breakfast at the Flinders Street Project. Wheels in Motion.

As with most other aspects of life, this year it’s going to feel just a little bit different.

One of the differences is that this year, rather than flying, I’ll be road-tripping: just me in the hoonmobile with the cruise control on, the sunroof open, the obnoxious sound system turned up to eleven and a Canyon on the roof racks.

Yet another TDU tradition is the Spotify playlist. You can see previous years’ playlists on my Spotify profile. Traditionally, that’s been populated from 1) the previous year (prior to arriving in Adelaide); and 2) music playing in the Tour Village and start/finish areas throughout the event. This year, I’d like to crowdsource some additional suggestions as a way of virtually taking friends and family along with me. If you’re reading this post anywhere comments are supported, please leave a song/album suggestion in a comment - or just add to the Spotify playlist directly via this link. I’d really appreciate it if you’d consider taking the time to add even just one track. Troll me if you will, but please don’t trash anything that anyone else has added. Road tripping means that I’ll have two days of travel time each way, so there’s plenty of listening time.

I really would like to virtually take people along with me more than in previous years (see Happiness shared is happiness multiplied). I don’t know what I’ll be writing throughout but I do plan to journal more this year, and to also publish many more photos. You’ll be able to read whatever I write here plus on all the usual social channels, and see photos pretty much as they’re taken in my Tour Down Under 2025 gallery. Please come along on this part of the journey with me, my friends.


Happy new year!

1 January 2025 00:00 AEST

Happy new year, everyone.

I hope that 2025 is a much better year for many of us. Let’s do our best to make it so.

My yearly theme is Renaissance Man. What’s yours?


Read more…

If a process has a name, it's an entity

28 February 2020 06:41 AEST
Event choreography Process orchestration Event-driven architecture Software engineering Domain modelling AAA Single Responsibility Principle

There are many flavours of event-driven architecture. I tend to speak and write a lot about event choreography, as 1) it’s a pattern that allows for effective separation of concerns, and 2) it’s a more accessible introduction to event-driven architectures than things like event sourcing. (Although I do make noise about event sourcing, too.)

In particular, in-process event choreography is extremely useful as it allows different parts of the same codebase to take action without being directly coupled together, but still allows for all of the state changes to be committed within a single transaction. Similarly, for distributed systems, event choreography is a powerful pattern to deliver simple, scalable workflows across disparate parts of an organisation.

Choreography versus orchestration

It is, however, important to draw a distinction between choreography and orchestration. If the system that will perform the action makes the decision, it’s choreography. If the system that will perform the action gets told to do it by another system, it’s orchestration.

The key is which system decides that an action should be taken.

  • Choreography is when a system takes independent action of its own volution as a result of the action of another system.
  • Orchestration is when some kind of process manager instructs a system to take action, usually as a result of an action of another system.

So which should I use? How do I decide?

This brings us to the question of which we should use and when. A simple rule of thumb is if a business process has a name and some state, it’s an entity. When we speak in terms of rules, e.g. “When a customer signs up, send them a welcome email” then choreography is a good candidate. When we speak in terms of process names, e.g. “Your application process is at the ‘Pending approval’ stage” then it’s a good hint that we’re in orchestration territory.

How do we model an orchestrated process?

We’ve already established that an orchestrated process has both state (“Where is this process up to?”) and behaviour (i.e. state transitions). This sounds suspiciously like… a domain entity.

If we accept that our process is a domain entity, many things fall into place. For one, we can query its state, and we can instruct it to change state. It can also refuse to undergo an invalid state transition, e.g. a call to a LoanApplicationProcess.Approve(...) should probably fail if LoanApplicationProcess.CurrentState == LoanApplicationState.NotYetSubmitted.

Doesn’t process orchestration mean I need an enterprise service bus? Should I get one?

No matter what problem you have, an enterprise service bus can always find a way to make it worse.

Thinking purely in terms of domain-driven design, we already have all of the puzzle pieces we need to solve this problem: domain logic and state persistence. This sounds suspiciously like it woudld fit into the normal structure of our domain model. We presumably have a repository implementation of some sort, and a persistence layer.

When our process needs to respond to an external event, we can use a vanilla event handler to hydrate our process instance and dispatch the event to the process.

The only missing piece is when we have a process that is dependent on time, which can be solved quite easily with a metronome which hydrates every non-finished process entity and calls a .TimePasses(DateTimeOffset now) method on it.


The cat sat on the mat.

26 November 2019 07:39 AEST
Software engineering Domain modelling Event-driven architecture Event choreography AAA Single Responsibility Principle

… a facetious look at the nature of events.

Anything that happens, happens.
Anything that, in happening, causes something else to happen, causes something else to happen.
Anything that, in happening, causes itself to happen again, happens again.
It doesn’t necessarily do it in chronological order, though.

– Douglas Adams, Mostly Harmless

Principles of expressing events

  • Events are immutable facts about the past.
  • The system that undergoes the state change is responsible for publishing the event.
  • The system publishing the event is responsible for defining the structure of the event.

I’ll deal with each of these principles individually - and slightly out of order. Please forgive the poetic licence.

Principle: The system that undergoes the state change is responsible for publishing the event.

Whilst modesty is admirable in a human, in software it is confusing. The component that has undertaken the action or undergone the state change should be the one to publish an event saying so. Our software should shout about its own doings, and not expect the town crier to follow it around.

Our code should follow the Assert. Act. Announce. pattern. Specifically, it should assert its preconditions, perform precisely its appointed task (and nothing more) and then announce that that task has been performed.

If we have some code that looks like this:

var cat = CatFactory.SpawnOne();
var mat = MatFactory.WeaveOne();
cat.SitOn(mat);

then our Cat implementation could look something like this:

public class Cat
{
    // ...

    public void SitOn(Mat mat)
    {
        // Assert
        if (_remainingLives <= 0) throw new DeadCatException("Dead cats can't sit on things.");

        // Act
        _currentlySittingOn = mat;
        mat.BeSatUponBy(this);

        // Announce
        DomainEvents.Raise(new CatSatOnMatEvent(this, mat))
    }
}

Crucially, the Cat is the one that has undergone the state change so it is the one that emits the event. (Side note: the Mat might also change state by virtue of being sat upon, in which case it should emit its own event.)

Principle: The system publishing the event is responsible for defining the structure of the event.

… and for honouring that contract.

The system that underwent the state change is the one that knows what happened. It is therefore the best placed to define the structure of the event representing that state change. Crucially, the publishing system should not attempt to cater to downstream subscribers who might desire additional information.

Consider the following event:

public class CatSatOnMatEvent
{
    public Instant Timestamp {get; set; }
    public Guid CatId { get; set; }
    public Guid MatId { get; set; }
}

This structure is quite terse but describes exactly what happened and only what happened. This is a Good Thing.

What happens, though, when a downstream subscriber wants to know the cat’s name? We end up with something like this:

public class CatSatOnMatEvent
{
    public Instant Timestamp {get; set; }
    public Guid CatId { get; set; }
    public string CatName { get; set; } // not a good idea
    public Guid MatId { get; set; }
}

What could be so harmful about that? Let’s go one further and suggest that another downstream subscriber wants to know the colour of the mat upon which the cat sat:

public class CatSatOnMatEvent
{
    public Instant Timestamp {get; set; }
    public Guid CatId { get; set; }
    public string CatName { get; set; } // not a good idea
    public Guid MatId { get; set; }
    public Color MatColor { get; set; } // also not a good idea
}

All of a sudden, we discover that our publisher will be responsible for marshalling all sorts of additional information just in case a subscriber wants it. The first subscriber doesn’t care about the colour of the mat and the second doesn’t care about the name of the cat, yet the publisher ends up being obliged to collate both every time it publishes an event just in case a subscriber wants it. This gives the publisher potentially as many reasons to change as there are subscribers - exactly the opposite of what the Single Responsibility Principle advocates.

What the publishing system should be doing is including only the information 1) about which it is authoritative; and 2) necessary to convey the essence of what happened. The system that cares about the name of the cat can then call a service to retrieve the name of the cat; likewise for the system that cares about the colour of the mat.

The publishing system is responsible for honouring that event contract for as long as agreed with its downstream subscribers. For an in-process event a refactoring could be done in a single commit, but for a business event published to a Kafka stream it might need to honour the contract for weeks, months or even years. It is the responsibility of the publisher to honour this contract for as long as its SLA specifies. (Site note: contract tests and/or schema registries will come in useful here.)

Principle: Events are immutable facts about the past.

An event should describe a thing that happened. It must have actually happened at a specific time. Events are expressed in the simple past tense.

The cat sat on the mat.

This is a good event. It’s expressed in the simple past tense. It unequivocally happened. Anything that may have happened after this event does not change the correctness of this event.

The cat is on the mat.

This sentence is in the present tense.

We could validly fire this event infinite times per second provided that there were, indeed, an appropriate cat sitting upon an appropriate mat. It would not be helpful. It would be much more helpful if we were to announce (once) at the moment that the cat were to first sit on the mat that it had done so.

The cat was sitting on the mat.

This is in the past progressive tense. It’s in the past, true, but it describes something that was happening and continuing to happen. Provided that the statement was once true (i.e. that the cat, once upon a time, sat upon the mat), the statement will always continue to be true. While a true statement, it is not helpful.

The cat sits on the mat.

Does it? When? Is it there now? Does it just generally sit on the mat? Do all cats sit on all mats?

The cat will sit on the mat.

Are we sure? How sure? Are we sure that it’s going to sit on the mat at precisely the timestamp on the event? It is a cat, after all. What if it gets hungry? Or bored?

This event is neither immutable (it might or might not happen) nor about the past.

The cat would have sat on the mat.

… but it didn’t because cats are fickle. This is not a thing that happened, therefore it’s not a good candidate for an event.

The cat should sit on the mat in ten minutes.

This is a command, not an event. It’s a valid command but it’s not a fact about the past.

Some other considerations

Commands should not be dressed up as passive-aggressive events.

We want our event publishers to observe the Assert. Act. Announce. pattern. Specifically, the publisher of an event should actively not care about whether any downstream consumers take action as a result of the event.

When an upstream system requires a downstream system to take a specific action as a result of something that happened, it should send an explicit command (either synchronous or asynchronous) to that system rather than announcing an event and then waiting expectantly.

Dinner is served, cat!

This is a passive-agressive event. The publisher of the event is waiting expectantly for their cat to come and eat its dinner, without having expressed that expectation.

Cat was requested to eat dinner.

This is also a passive-aggressive event. It expects a specific action to be taken and it is likely that the publisher of the event is waiting for that action to be completed.

Cat! Come and eat your dinner!

This is a perfectly acceptable command; it’s just not an event. It is an imperative instruction for an entity (cat) to undertake an action (come and eat dinner). It is entirely reasonable to send such a command; just not to present it as an event.

Think about your events’ granularity.

It is useful to structure events according to business events that actually happened and that people would talk about in real terms. It is likely that downstream systems will take different actions based on different events and don’t want to process “catch-all” events that they then have to further filter.

For a more serious example, consider entity-named events (e.g. CustomerEvent) that describe something vaguely related to a customer and, worse, generic CustomerUpdated or event just CustomerUpdate “events” that neither describe what happened or even assert that something did, in fact, happen.

A downstream system will most likely take very different actions as a result of a CustomerCancelledAccountEvent (perhaps sending an apology letter) than a CustomerChangedEmailAddressEvent (sending an alert email to the old address), and a different action again as a result of a CustomerConvictedOfFraudEvent (perhaps suspending shipments to that customer). If all of those happenings are wrapped up in a single CustomerUpdated or CustomerEvent then 1) too much responsibility is pushed onto each subscriber; and 2) the event payload will bloat in order to accommodate all of the different information required for all the downstream subscribers.

Statements about the future are not events.

We see many examples of these kinds of anti-patterns in transaction-processing systems.

For example, future-dated transactions are inserted into a table in the same way as past-dated transactions (strike one: not about the past). Almost invariably they are then updated with an IsProcessed flag or similar when they are actually processed (strike two: not immutable).


Assert. Act. Announce.

14 November 2019 06:02 AEST
Software engineering Domain modelling Event-driven architecture Event choreography AAA Single Responsibility Principle

A friend and colleague, Steve Morris and I, have been attempting to propagate the naming of this pattern for quite some time and it’s about time I wrote about it. In the vein of the AAA pattern of unit testing, we’ve been promulgating the AAA of code responsibility: Assert. Act. Announce.

  1. Assert. Check your preconditions.
  2. Act. Do the thing. And just the thing. No more.
  3. Announce. Shout that the thing was done.

Consider the common case of a customer’s changing their subscription level to an online service. Let’s say that the simplified sequence looks something like:

  1. The customer changes their subscription level.
  2. The customer is sent a notification email.
  3. The customer’s billing schedule is adjusted.

We could model it something like this:

public class CustomerService : IAntiPattern
{
    IRepository<Customer> _customerRepository;
    IEmailSender _emailSender;
    IBillingService _billing;

    // ...

    public void ChangeSubscriptionLevel(Guid customerId, SubscriptionLevel subscriptionLevel)
    {
        var customer = _customerRepository.Get(customerId);
        customer.SubscriptionLevel = subscriptionLevel;
        _emailSender.SendSubscriptionChangedEmailTo(customer);
        _billing.ReschedulePaymentsFor(customer);
    }
}

There are several problems with this approach:

  • It’s slow. The customer has to wait until an email is generated and sent before they can be signed up.
  • It’s fragile. If the email server is down, the operation will fail.
  • To add a step to the process, we need to change existing code.
  • The code is resistant to change.
  • The CustomerService becomes a dumping ground for all things customer-related.
  • When we add behaviours to the CustomerService, our existing tests break.
  • Anything can put our Customer instance into an invalid state just by modifying its properties.

If we were to add to the sequence so that it now looks like this:

  1. The customer changes their subscription level.
  2. The customer is sent a notification email.
  3. The customer is sent a notification text message. (New!)
  4. The customer’s billing schedule is adjusted.

then a couple of things happen. The first is that we need to change our existing CustomerService to add behaviour. We’re going to need to change the ChangeSubscriptionLevel method, and we’re also going to need to change the constructor to include some kind of ITextMessageSender. That means that all of our existing unit tests will immediately fail to compile.

Think about what we’ve just done. We’ve not changed the correctness of our existing code yet our unit test are failing. In other words, we’re teaching ourselves the lesson that whenever we add functionality, existing tests break. This is exactly the opposite of what we want, which is that tests only break when we’ve broken the functionality that they specify.

Enter the AAA pattern: Assert. Act. Announce.

If, instead of our CustomerService, we just modelled a customer with their behaviours, what might be different?

public class Customer
{

    // ...

    public void ChangeSubscriptionLevel(SubscriptionLevel subscriptionLevel)
    {
        // Assert. Check preconditions.
        if (subscriptionLevel == SubscriptionLevel) throw new DomainException("The new subscription level must be different to the old one");

        // Act. Do the thing.
        SubscriptionLevel = subscriptionLevel;

        // Announce. Shout that the thing was done.
        DomainEvents.Raise(new CustomerChangedSubscriptionLevelEvent(this));
    }
}

By publishing the CustomerChangedSubscriptionLevelEvent we allow downstream behaviours to be decoupled from the original action. We get several benefits from this:

  • We can make the assumption that any time we are passed a domain entity, it is in a valid state. In other words, the customer entity can say no, and refuse a change that would put it into an invalid state.
  • The Customer class doesn’t have to change at all when we add a downstream behaviour.
  • The existing tests continue to compile without change.
  • The existing tests also continue to pass without change.

It’s worth noting that the Customer class in this case is not responsible for sending an email, sending a text or informing the billing department - and nor should they be. The Customer entity’s job is to represent a customer, not orchestrate a business process.

To bolt additional downstream behaviours onto the customer’s action, we use event handlers, e.g.

public namespace WhenACustomerChangesTheirSubscriptionLevel
{
    public class SendThemAConfirmationEmail : IHandleEvent<CustomerChangedSubscriptionLevelEvent>
    {
        IEmailSender _emailSender;

        // ...

        public void Handle(CustomerChangedSubscriptionLevelEvent e)
        {
            _emailSender.SendSubscriptionChangedEmailTo(e.Customer);
        }
    }
}

This isn’t a new pattern. Udi Dahan wrote about it in 2009 in his Domain Events – Salvation post, we’ve been using it for over a decade and the Observer pattern is an original GoF pattern. At the ThoughtWorks Event-Driven Architecture Summit in 2017, a number of us started to thrash out a bit more of an opinion about what “event-driven” actually means, and the various flavours of it. Martin Fowler’s article on What do you mean by “Event-Driven”? is one of the outputs of that summit. We’re generally calling pattern that we’re using in this case event notification or event choreography.

If we want multiple behaviours, we just add mulitple handler classes; the principle being that in order to add behaviours, we just add code. We don’t want to change existing code unless the existing behaviour of the system needs to change. We do need to understand which events should be handled synchronously versus which can be handled asynchronously but there are straightforward solutions to that problem.

The pattern to remember, though, is AAA: Assert. Act. Announce.


Read more…

Play

Cyclist. Runner. Hiker. Singer. Violinist. Budding skydiver. Photographer. Former semi-pro photographer. Ballroom dancer. Motorcyclist. Occasional sailor. Good with edged weapons. Red Frog. Legatee.

Work

It should go without saying that any opinions, beliefs and other statements made here are my own, and do not represent in any way the views of any employer either past or present. Let's be grown-ups about this, shall we?

I'm Head of IT & Engineering at Etax, Australia's largest privately-held tax agent. Other interesting places I've been before Etax include Octopus Deploy, ThoughtWorks, Readify, Zap BI, Realex Payments and TRL.

I'm a fan of high-quality code, domain-driven design, event-driven architecture, continuous delivery and, most importantly, shipping software that works and that solves people's problems.

I have a number of small open-source creations, including Nimbus, ConfigInjector and NotDeadYet, and am an occasional contributor to several more.

I'm a regular speaker and presenter at conferences and training events. My mother wrote COBOL on punch cards and I've been coding in one form or another since I was five years old.

Sportsball