Temporal coupling

Temporal coupling is the need to execute some code, before executing another code. We say that the two (or more) calls are temporally coupled.

How do you decouple a system temporally?

To do it, more principles have to be at work:

Overarching them is another goal:

At any given moment, only the methods which make sense to be called, should be able to be called.

This goal is within reach when using ISP. Let's recall, as described in use the type-system of the language, that interfaces are also types, and that an object can implement multiple types (interfaces).

Given this, we can create a state machine in terms of types (different interfaces for the most part). Each interface stands for a state of the state machine, and each method of the interface for a possible transition from that state to a new state (the return type of each method).

From outside, it all looks like we'd have completely different classes, one for each state (interface), but this is not true. Thanks to polymorphism, in all these methods we can return the pointer to the current object this.

What we end up with is a single class and many interfaces, and methods doing their job but returning this, as a new type. Because the returned type is always a seggregated interface, from the outside you can only call methods which make sense, not all methods of the class.

In practice, if you use an IDE, the auto-completion tells you what are the next available methods, given the current state of the object, making code writing a breeze: you don't need to know how the system works, but instead you are exposed to parts of it as you type.

Each of the methods will require parameters needed to accomplish the transition from one state to the next.

Caveats

Modelling your objects like state machines can become very expensive. For this reason, I advise to do it only in the domain model of your application, where it brings the most advantages: your domain is the most unique part of your application, and so guiding (via auto-complete) even the most novice in your team about how the domain works brings the most value in terms of robustness and explorability of the code.