The Last Responsible Moment (LRM) is a lean development principle defined as:
“A strategy of not making a premature decision but instead delaying commitment and keeping important and irreversible decisions open until the cost of not making a decision becomes greater than the cost of making a decision.”
Let ti be the specific point in time for a concrete design decision Di. The LRM principle tells us that ti should be deferred as much as possible. One of the reasons is to avoid making decisions based on assumptions, so that we should decide when we have optimal information about the requirements and there is a reduced risk that our decisions will need to be changed.
During the incremental software development process we will implement a set of concrete design decisions D1 … Dn, in which D1 … Di-1 are the decisions implemented before Di, and Di+1 … Dn are the decisions made after Di. This order of decisions is not arbitrary and will follow some design rationale.
But of course these design decisions are not independent of each other. Thus, among the decisions D1 … Di-1 there will be some of them that depend on Di. For example, if each design decision Dj is encapsulated in a class Cj, we must know at least the interfaces of the other classes being used by Cj.
Before the Last Responsible Moment
This means that for each design decision Di there must be a point in time, before ti, in which we define an abstraction for Di. This abstraction allows the implementation of all design decisions that depend on Di but must be made before it. If Di is represented as a class, the abstraction would be its interface, and it should be defined at a time tAi < ti.
This definition of abstractions before implementations is exactly the result of Test-Driven Development (TDD). When we write unit tests for a class we are defining its interface, both at the syntactic and the semantic levels. By the time all unit tests are written for class Ci we have reached tAi, but we are still before ti, the last responsible moment in which we will decide how to implement Ci.
After the Last Responsible Moment
No matter how long we were able to defer a concrete design decision Di, there will probably be a moment in which it will need to be changed. The last responsible moment is the first time we provide an implementation for an abstraction, but certainly this does not mean that there is any guarantee that this implementation will never be modified.
For every design decision Di there may be a time tCi > ti in which its implementation is changed. We do not want this change to affect the modules that depend on Di, and this can only be done by preserving the interface. Therefore, the importance of abstractions is twofold: they allow concrete design decisions to be deferred until the LRM, and they also allow these design decisions to be changed after the LRM.
In order to adopt the Last Responsible Moment principle it is essential to focus on the definition of abstractions representing the diverse design decisions. These abstractions serve as the placeholders that will allow the concrete implementation details to be deferred as much as possible. Moreover, good abstractions are essential to support maintainability and allow these design decisions to be easily changed.