Facts and Events
Organizations use software to help them achieve their business goals. In essence, this statement is indeed a dynamic principle, for it marks one particular path into the future as the preferred one: the path in which the organization gets closer to achieving the goals that it pursuits.
In other words, what organizations do in terms of operations to achieve their goals happens on the timestream. The same timestream wherein human beings live our lives. In terms of the Domain-based methodologies that we have been discussing in this blog, for example here and here, this means that the Domain is also time-based by nature.
It is very common to name Facts the atoms of change in the timestream. Facts are the tool we people rely on to tell stories about what happens: what there was before changed because some Fact occurred in a particular moment. To explain what happens in a comprehensible way, Facts tell stories in a language that we can understand.
When I buy groceries, book a room in a hotel, or tweet a picture, I am doing actions that change the amount of money I have, the items I own, the places I sleep, my persona in social networks, etc.
The same rules apply to organizations. They handle and communicate change in multiple ways: memos, reports, accounting books, spreadsheets, etc. All these supports tell stories to make comprehensible some raw Facts. The details of these Facts are continuously gathered, stored, and processed by software applications. And so, to make this possible, people in charge of software applications had to explore the Domain where those Facts belong and to represent them in the code.
In the long history of software applications, software designers have adopted different approaches to depicting changes that happen in the outside world in their code. The most popular approach even today is the transaction-based representation: purchase orders, work orders, shipping orders, etc. are the common vehicle to bring whatever changed in the real world into the code, although Facts are not explicitly managed. In this representation, Orders start, go through stages, and finally reach their final end. All these stages are very often represented as different Status values.
Another representation that has become popular this decade is event-based representation. In this representation, the atomic nature of Facts is key and is respected throughout the Codomain. The representation of Facts in this kind of Codomain is called Event.
Let’s see how the timestream shows up in both representations.
Domains placed in the timestream
If we picture an arrow with time in the X-axis and paint transactions as segments above this axis with lengths that try to depict how long it takes for those transactions to be fulfilled, we’ll notice that Facts within those transactions do not happen randomly but follow the business logic.
For example, a Client submits an Order, the Items are gathered, packed, shipped, delivered, and the Customer is billed. As you may see, all facts are expressed in the past tense, which is what makes Event-based Codomains feel so natural. Anyway, in Transaction-based Codomains, these facts are seen as changes that happen to one same Transaction (the segment in the picture) and so they are handled as Statuses that Orders go through during their history.
Let’s illustrate this with a picture:
Of course, this is a simplified version of it. Every Fact in the timestream may trigger the execution of other actions that, once completed, will pop up in the picture as new Facts. These Facts are correlated with the Transaction, for they happened because the transaction had happened first, but do not necessarily belong to its main flow. For example, a new Order to the Supplier might be sent after the inventory of some of the Items in the Client’s Order reached a minimum stock threshold. The Client has nothing to do with that Purchase Order to the Supplier, but there is a cause-and-effect relationship here.
Causality is a topic I am planning to explore in future posts. Let’s ignore it for now.
The absence of any action can also be a trigger for new Transactions to start. For example, social networks track the activity of their Users and often send notifications to them when they had not signed in to the network for a given period.
Now, observing the segments and the Facts they hold inside, it is noticeable that the knowledge they enclose is quite different. In the example above about a Client submitting a purchase order, we have Items, Prices and Discounts, stock in warehouses, transportation and delivery of physical objects, and Invoices. There is plenty of knowledge involved in stocks handling and it has nothing to do with Invoicing. As containers of knowledge, Stock handling and Invoicing define two separate Domains.
Let’s show the Domains in the picture above explicitly:
All these Domains would require to be mapped into the Codomain then.
Global and local contexts in the Codomain
In the canonical Domain-driven Design methodology, the components that teams define to structure the Codomain are called Bounded Contexts. This name always sounded a bit awkward to me, like “a round circle” does, so I eventually got used to saying just “context“. Whatever the name, the key point here, and what defines what Bounded Contexts are, is the fact that they are limited by a boundary of meaning.
It is because some words change their meaning across contexts that those boundaries become noticed. For example, a Client can be someone who buys our Items in the Sales Bounded Context or someone who is our debtor in the Accounting Bounded Context. Within each of those Contexts, a Client means one thing or the other, but not both. This is because within the Accounting Bounded Context the code knows nothing about Sales.
Bounded Context boundaries are defined by the tight coherence in meaning the elements within share. That is the role the boundaries play in the Codomain.
And yet, there are exceptions to this rule. People who buy shoes, post a picture or a text on social media, or watch a movie, are represented in the Codomain as Users. Software applications can also run actions on other software applications, so they are represented as Users too.
Now, there is no such thing as a User in the Domain. First of all, Users bring an element of identity and an element of clearance to the whole collection of services, modules, or components that give structure to the Codomain. This is true even when the identity is “anonymous” and the clearance is “can do nothing“.
But Users do not stay contained in the infrastructure layer. They are linked to those actors, human or not, that buy shoes, watch movies, or send automated notifications to other people’s cell phones. So Users are part of all the Bounded Contexts, for there is no Bounded Context without identity and clearance.
This double role that Users bring is the same throughout the Codomain. Otherwise, we would see the execution flow across Bounded Contexts interrupted by continuous signing in operations. This does not happen because the element of Identity, and quite often the element of clearance too, is unique. So, Users belong to one Context within the Codomain that is effectively unbounded.
Users belong to the Global Context.
Certainly, the majority of Contexts are Bounded. You might even decide that all Contexts are bounded by definition and so that there is no room for a Global Context in your Codomain. Does this decision collide with the fact that Users meaning (again, identity and clearance) does not change across Bounded Contexts?
This appalling conflict is the topic of our next post. Make sure you are here to read it.
Back to the timestream
Once you realize that Facts appear in a sorted manner in the timestream and that Events are the representation of Facts in the Codomain, event-based representations feel pretty natural. Indeed, far more natural than the transaction-based representations.
In a certain sense, software designs that model business transactions are relics from older times, when transactions were handled in desks and were mainly supported on paper. Those times are gone now. Should not our models move on too?
Picture copyright note: cover of the Marvel Comics magazine The Fantastic Four (Volume 1) issue 337, published on February 1990. Art cover by Walter Simonson.