You ever see one of the old spy movies where the agent puts a tattletale, like a hair, across a door frame to know if the room is entered while they are out?
Recently I had to write a tactical piece of code that was to run for about a month. It was designed to spin off a separate thread and periodically create a heartbeat message to keep a device alive until the next version of the device no longer required that heartbeat. It was a couple of pages of code, written to be rolled out ASAP. It was kept as simple as possible to avoid the risks introduced by complexity. That said, it wasn’t done in a haphazard way. The development was test driven and there was thorough test coverage. Testing the heartbeat code was being invoked off in it’s own thread did prove a challenge with the complexity adverse implementation.
Had the code been a full on strategic solution with a normal life span I know exactly what approach I’d have taken. The separate thread would have depended on a delegate to send the heartbeats and in testing I’d set the delegate to a Spy instance that I could work with in the tests. The introduction of delegation and dependency injection, was just too much of an over design, particularly when driven solely by testing needs.
So, instead of a full on spy, I went with just a little tattletale. I passed an optional tattletale reference into the thread calling the heartbeat. If the tattletale was present, the heartbeat code changed it’s value as a signal (it was an Optional<Semaphore> to be exact). In testing the tattletale was passed in and monitored for change. Under normal operation no tattletale was passed in. Really it was still the spy pattern, just done in a very low tech way, with minimal design impact.