Lots of object models primarily track application state. For example, OkHttp’s Http2Connection.kt has state for whether a ping’s reply is outstanding:

private var awaitingPong = false

This is set to true each time a ping is sent and then false again when its reply is received.

I’ve recently started to prefer models that primarily track facts instead. For example:

private var pingsSent = 0L private var pongsReceived = 0L

The pingsSent is incremented when a ping is sent and pongsReceived is incremented when its reply is received. The state is a function of the two fields:

fun awaitingPong() = (pingsSent > pongsReceived)

Tracking facts is more code so I shouldn’t prefer it! But I do:

There’s no lock shared between the thread writing pings and the thread reading their replies.

When a reply is late the code can now report how many successes we saw before the failure.

It affords more focus in tests.

I like event-driven architectures for microservices. It’s awesome how that strategy scales down to a single class.