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.

 

Connascence of Execution

We’re starting our journey into dynamic connascence now, which is a bit trickier than static connascence. Dynamic connascence causes problems that you can’t necessarily see from the source code, as they require knowledge of how the program behaves whilst running. You can think of it as connascence that affects objects instead of connascence that affects classes.

Anyway, I hope you enjoyed the post on connascence of position, because connascence of execution is the dynamic equivalent. Connascence of execution refers to when multiple components must agree on the order of execution of code.

There are two main kinds of connascence of execution- sequential and adjacent. Sequential refers to when something must be done in a given order (Such as setting a recipient on an email before sending it), and adjacent refers to when something must be done without any intervening steps.

Let’s have a look at something that must be done in a given order:

Alright, everything looks fine so far- we have an enclosure that requires things to be done in the specific order in order to safely lock up a dinosaur. And we have a handler that agrees on this order and knows the right way to lock an enclosure.

If this was to ever change- say for a door needing to be locked before it could be primed, then both the enclosure and the handler would have to agree on the new order of execution, and both be changed at the same time to ensure correctness. And as connascence of execution is dynamic- we can only infer the behaviour from what happens at runtime, so it’s not as easy to track down and fix if we get something wrong.

To combat this, we need a way to transform our connascence of execution down to a lower level- preferably connascence of name. Let’s look at how we might do this:

Our DinosaurEnclosure now only exposes the correct action that can be taken next- like a state machine. A completely unlocked enclosure can only be locked, which returns a locked enclosure that can only be primed, which returns a primed enclosure that can only be electrified, which returns a safe enclosure that cannot be modified.

This has removed our connascence of execution, as it is no longer possible to execute the methods in the wrong order- the names of the classes and methods returned guarantee that, giving us connascence of name instead.

As connascence of execution is a dynamic connascence, it’s probably not a good idea to ever leave it alone where possible- they’re a lot harder to reason about from source code and tend to be a lot harder to fix if they go unchecked.

 

Connascence of Position

We’re at the end of our journey into the static levels of connascence, with connascence of position as the last stop. Connascence of position refers to when multiple components must agree on the order of values.

The most obvious example of connascence of position are method arguments- these must appear in the same position in the caller as they do in the declaration, or things are going to break. There’s also the order of items in a data structure such as an array, and having multiple components relying on this being the same. We’re going to look at method arguments in detail, as there are a number of ways to mitigate connascence of position when talking about the order of arguments.

Take the following classes:

We have connascence of position between these classes around the order of the arguments passed in to the method- we send an alert by passing in the recipient, the sender, and the message. We have to make sure that we pass those arguments in that exact order, otherwise our message isn’t going to get where it’s supposed to go, which could be disastrous.

We can already see that the alert in our test is being sent incorrectly, but that’s ok. We’ll just run our tests, the issues will be found and a helpful error message printed to the console, and we can proceed to fix the problems.

That’s the output of our alertConfirmationContainsRecipient() test. You might have noticed that the error message is incorrect- the test for the recipient shouldn’t expect the value to be generic.person@soontobe.eaten, it should expect it to be john.hammond@ingen.com.

The issue is that also we have connascence of position within our test class- with the JUnit library we are using for our tests. This is because JUnit methods such as assertEquals() expect the parameters to be passed in a certain way- the expected value followed by the actual value. We passed them in wrong, so when something fails we end up with a confusing and incorrect error message.

We can solve connascence of position in a number of ways, which we’ll examine below.

Probably the most elegant way of solving this particular connascence of position issue is using named parameters- instead of relying on passing parameters in the same order in the call as the declaration, we can give each of the passed parameters a label that matches the declaration, and reduce our connascence of position down to connascence of name.

That would be great if we were writing code in Ruby or C#… or Python, or Ada, or a whole bunch of other languages. Our code is in Java, so we’re not quite so lucky. I suppose we could attempt to mimic the behaviour of named parameters by passing in a Map, with the keys as the names and the values as what we want to pass.

That’s not really as elegant as I was hoping. We’ve made our parameters a Map<String, Object> so we can pass different types in to our method even though we don’t need to currently. Unfortunately this gets rid of any type safety we get, which is a feature I quite like from Java. It’s less explicit in what arguments you can pass too, so we lose those compile time checks as well. There’s also a whole bunch of extra boilerplate we need in both the caller and the declared method, which isn’t brilliant either. What else can we do?

Well- it doesn’t solve the issue of extra boilerplate (not by a long shot), but there’s something we can do with type safety and explicit arguments. There’s a technique we can use called Tiny Types. Instead of passing in basic data types like String, Integer, Double, etc., we can wrap these up in objects representing domain concepts for each of the parameters- like Recipient, Sender, and Message.

Ok yeah that is a lot of boilerplate actually- but it has managed to reduce our connascence of position down to connascence of type. Try to pass the wrong type in and you’ll get an error rather than your message going to the wrong place or getting lost all together.

Tiny types can be really useful when you’re trying to express an actual domain concept that has behaviour- such as maybe recipient having to contain an @ sign, or message only being a certain number of characters. However, it’s probably overkill to use this technique as purely a method to remove connascence of position when your primitives won’t benefit in other ways by being promoted to full-blown domain objects.

Alternatively, we can use the Parameter Object and Builder patterns to reduce our connascence down to connascence of type. We’ll have a look at what the Parameter Object looks like first, but we won’t stop there:

Not really that helpful- we’ve added a layer of indirection but we’ve still got connascence of position, it’s just somewhere else now. This is where the Builder pattern comes in.

There we go- connascence of position has been removed and replaced with connascence of type. We can now send an alert without needing to know the order of the parameters to be passed. We have opened up other issues in the code though- for example, the way we’ve used the Builder pattern currently allows us to create an AlertRequest in an invalid state, which is far from desirable. If we’d used the pattern as intended, any required arguments would be part of the builder constructor… which would give us connascence of position again. Alternatively, we could throw an InvalidStateException when calling build() without first setting the required parameters.

You’ll also notice that we’ve replaced calling the JUnit library directly with calling a different library instead- AssertJ. This library uses fluent method chaining (A technique we’ve not looked at) to ensure connascence of position isn’t an issue.

Anyway, we’ll leave it to the audience to decide which technique to use and when it’s appropriate to use it. As always, there are tradeoffs to consider when changing any code- just do one that you’re comfortable with.