Connascence of Timing

Connascence of timing is our 2nd level of dynamic connascence and our 7th level of connascence in general. Things are getting pretty serious right about now and we’re at the point that we don’t want to be ignoring any connascence we find at this level.

Connascence of timing refers to when multiple components must agree on the timing of particular executions. We’re talking dynamic connascence here, so once again it’s something we can only observe and reason about in relation to runtime objects rather than compile time classes.

You can get connascence of timing when one component presumes to know how long a different component’s operation is going to take- you’ll usually see this expressed as Thread.sleep() or something similar. Anyone that’s ever used Selenium for UI testing knows how dangerous this can be. There’s also the case where we’re using distributed systems with eventual consistency that can have an impact with connascence of timing if we’re not careful.

Let’s see a real life example of how this might come about and what issues it could cause.

We’ve got connascence of timing here, as the transfer station presumes to know that after registering a dinosaur for transfer, there’s a 25 second delay before the registration goes through and the dinosaur can be shipped. And this might be true- currently. What happens if the process takes a bit longer than expected? The dinosaur won’t be shipped successfully and we’ll have to try again. What if the registry doesn’t have to check the no fly list any more, because we’re actually shipping them by cargo container on a ship? The process may only take 3 seconds in that case, but the transfer station will still be waiting for 25 seconds for no reason.

What can we do about this? One technique is to use retries with exponential back-off periods, so trying after 1 second, 2 seconds, 4 seconds, etc. until it succeeds. This still gives us connascence of timing relating to what we set our eventual complete timeout to be, but it’s less strong.

Alternatively, we could completely ignore the timing of the call and use callbacks/promises/observables/subscriptions instead- which are all a similar pattern of asynchronous processing with no timing requirements. Entire books have been written about each of these techniques, so we’ll just pick a simple one to demonstrate how it removes connascence of timing from our transfer station.

We’ve created a Callback interface with a single invoke() method, which we’re going to use to remove the connascence of timing between our two components. TransferRegistry now takes a Callback as part of it’s registerForTransfer() method, and will call the invoke() method on that callback when it’s finished registering. Our transfer station wraps the logic it was performing originally in a lambda and passes it through as that Callback. The transfer station is now no longer reliant on the registry completing in a certain amount of time- the callback will be handled as soon as the registry is complete.

This does have the side-effect of returning out of the transfer method straight away rather than 25 seconds later like before. I like to see this as a benefit- but if that’s something that’s required we could use exponential back-off in a retry mechanic instead, to at least reduce the connascence of timing to something that is more sensible.

Connascence of timing is another one of those that you want to get rid of as soon as possible, as it can lead to a world of hurt when timings change- networks get faster, slower, execution takes longer or has more to do. And you can’t tell if everything is still going to work until you run it.

 

Author: Sean O'Toole

I like development and I like dinosaurs. Here we are.

Leave a Reply

Your email address will not be published. Required fields are marked *