Optimistic locking is the process by which we block a client from changing an object that was changed by someone else during this client’s edits. The process is common: user A and B both load the same resource and start work. User B submits their work first. When user A submits their work it’s rejected because the underlying object has changed while they were editing it. We call this optimistic locking because we assume it isn’t going to happen very often and the user is optimistic that they won’t have wasted their edits.
Usually we implement this with a number (or timestamp — same thing) on the object. We get a request to change an object so we load it by ID and check it’s version number. If it’s different from the version number on the submitted object we know that the submitted object is out of date and we can’t accept the changes.
Of course, we don’t need to load the whole object just to find out that we’re going to reject the changes — an optimistic locking exception. For efficiency, we could query for the object using a compound key — the ID and Version Number together – if we don’t find an object to update we reject the changes. We could even simply issue the DB update (if we’re using a DB), using the compound ID+version key in the where clause and note if a change was made, offering a rejection response if nothing was updated. Efficient it may be, but really it’s 100% equivalent to load and check (actually, it’s better to use the direct update, rather than load and check, unless you want to risk the underlying data changing between the load and the check).
But, given the optimisation above I noticed that, effectively, the object’s identity changes on every update. An object with optimistic locking is an object who’s identity is encoded in the sum of its attributes, and if a single byte changes then so does its identity.
This is deep. We often assume that an object’s identity is tied to its ID, but here we’re deliberately subverting the id to ensure that a user is fully informed before they take an action. In so doing, we’re forcing an object’s identity to change, when we should be changing only the value of its attributes.