When two program elements exhibit temporal coupling, there’s a more or less implicit order in which they must be called. The archetypical example is any form of an initialize method that must be called to ensure that the object or data structure is in a valid state. Consider:
ComplexObject complex = new ComplexObject(); complexObject.initialize(10.7, "complex", 0); complexObject.doSomething();
If the call to initialize is omitted, subsequent method calls will fail more or less spectacularly. While an initializer is a relative harmless example, some APIs may come with far from obvious temporal dependencies.
Temporal coupling can make legacy code very hard to touch, because it will impose a certain execution order, and if combined with long methods and conditional logic, it can really make large blocks of code very difficult to change, or test for that matter.
In a way, temporal coupling is an aspect of state, as it adds a time dimension to its buildup. So, in order to reach state S, you would need operations o1, o2, …, on to happen in a certain order.