Let's assume we are developing an e-commerce store and are just implementing the shipping feature.
If the order has just been created, shipping should be rejected because the customer has not paid.
If the order has already shipped, it should return the existing shipment or reject the duplicate request rather than create another one.
The shiporder command remains the same, but its correct interpretation changes over time.
This brings us to a situation where the command alone is therefore insufficient to determine the correct behavior. The system must also know something about what happened before.
Let's start with the most basic implementation; Our very first model contains only an identifier:
The object cannot answer because it tells us only which order we are discussing. It does not tell us whether the order was paid, canceled, shipped, or delivered.
The smallest useful improvement is to retain the order’s current condition.\ Let's improve our model a bit by adding a status field so that our basic system can distinguish several stages.
The status field records the order’s current stage. It does not enforce the rules for reaching that stage.
id names the order. Change it, and you are talking about a different order. It does not change what shiporder may do.
status sits next to it, as if it were the same kind of value. It is not. It bears a role the field does not show. Change created to paid, and the system is allowed to ship. Change it to shipped, and the same command must stop.
Both fields are strings, but our business rules give them different responsibilities. The status should influence whether shipping is allowed; our current code does not check it.
Both fields actually store data, but one of them has a different responsibility.
Let's call that role state, for now. That is the role that changes how the system acts next.
Changing the customername from Alice to Alice Russel does not necessarily affect whether the order may be shipped. However, changing the status from created to shipped does.
Change status from created to shipped, and shipping does care. That field is still doing the other job. That is still state.
The status changes the set of valid future operations. That makes it a behavioral state.
But... Although it is useful, the boundaries of this distinction are not so rigid.
