What Event Sourcing is not
hugopicado.com
hugopicado.com
Consider for instance an API to create and account. Now let's say we want ability to update address. One approach would be an API that changes the address by updating the account but the customer never asked to update the account. The customer wants to change the address. How about we give them the API with change of address request/semantics? This way, no matter what happens, the API and the events remain in sync and you don't expose internal data storage semantics to customers that have no interest in them.
I think this can be easily misunderstood to describe an unnecessarily strict view of how event sourcing can work. To use the most common example, a bidding system, someone might see the state as the record of accepted offers, bids, and sales, and the events as recording changes to that state. That would be one way to design the system. However, that means events can only be issued after state changes are decided. That means after synchronization and business logic have been applied. Suppose a user submits a bid that is rejected by the system because it does not meet the rules, comes after bidding is closed, or because the system rejecting the bid does not recognize the item id. That bid does not get recorded as an event and cannot be replayed, so if it was rejected in error, the erroneous action is not recorded and can never be reconstructed. This kind of event-based system amounts to little more than capturing a database commit log. Actions taken by users and peripheral parts of the system are obscured, leaving a very subjective account of what happened.
If you enlarge the concept of state to include more of the distributed state of the application, then this description can yield a larger and potentially more useful set of events. The user submitted a bid — that's an event. The system rejected the bid — that's an event. The system closed bidding — that's an event. Then you can replay bugs. Was the bid incorrectly rejected as invalid? Did the system close bidding prematurely? If I fix a bug in a system and replay events to it, does it do the same thing or something different? You can also discover performance problems. If a bid event is relayed through the system before it is processed, you might see that the difference in timestamps between the bid being placed and the bid being rejected is higher than expected.
A simple example of this trap is when an event is used as a passive-aggressive command. This happens when the source system expects the recipient to carry out an action, and ought to use a command message to show that intention, but styles the message as an event instead.
I think this is another part that can be misunderstood, or perhaps I disagree with it altogether. Commands can be significant events that are helpful for event sourcing. Ask yourself, if you exclude them from the event log, are you still able to reconstruct what happened to the degree necessary for debugging? Capturing commands as events might allow replay with only a subset of the system running, which can be helpful. Also, computers are more precise than humans. If I tell my girlfriend, "There is someone at the front door," there may or may not be an implied request. There is no reason to design computer systems with that kind of ambiguity, so there is no need to create a separate category of "commands." "System A has scheduled task 23 to execute next on executor Z" is an event that we can program executor Z to respond to in a certain way. The behavior can be specified and tested.
Commands have their own problems. I have seen too many systems that report spurious errors because a programmer did not want to report "success" unless a "command" was carried out. "Command" evokes a human relationship that applies to a small subset of interactions between computer systems. When you change the shipping address on an Amazon order, your browser does not say, "Change the shipping address on the damned order!" It says, "The buyer requested to change the shipping address on the order." Now, that kind of message is sometimes modeled as a "command" by sloppy programmers, but really it reports a fact, an event. The browser does not take a position on what the right action to be taken is; that is the responsibility of the server. If you call it a "command" then the server should respond with a 4xx client error or a 5xx server error if it receives the request a nanosecond after the order shipped, when in reality neither the client nor the server did anything wrong. The client correctly reported a fact, and the server responded correctly as well. To call it a command is to imagine the browser client deciding on a state change and attempting to command the change on its own authority, which would be an absurd division of responsibility. The browser client merely reports the intentions of the user.
Commands also make systems hard to understand as they evolve, because the "command" issued by a system often stays the same while the correct action taken by the recipient system changes over time. Eventually what the "command" asks the recipient to do can bear little resemblance to what the recipient actually does. The code (and the state of the system) is supposed to be designed to make sense to humans, so the system issuing the command should be changed to make the command accurate, but that rarely happens, and it shouldn't be necessary in the first place. The message issued by the first system should not be modeled in a way that encroaches on the responsibilities of the recipient system.