On Domain Events, English, and ubiquitous language

I attended a Python meetup last week, hosted by JobRad. The main presentation was a showcase of an "Event System", or how they used messages to share customer data between their ERP (Enterprise Resource Planning, the big database of their processes, inventory, and all other business activities) and their CRM (Customer Relationship Management, the main piece of software required by customer support with sales orders and support tickets).

I liked the presentation a lot, which isn't surprising given I spent the last five years head down in Domain Driven Design (DDD), message-driven architecture, and event-sourcing. Due to the audience variety — it was a general Python meetup after all, not a specialised one — the hosts gave us a good walkthrough with hints of advanced topics (especially domain model evolution and versioning). As a sidenote, I will be talking about "Event Sourcing in production" at EuroPython 2024 in July.

Eventually the presentation showed a few actual domain events they use in production. They had German names (ed. JobRad is a German company). The rationale shared with us is that those are the business terms as they are used by the stakeholders. They are directly taken from the ubiquitous language: said otherwise, they did not try to cater to their more international engineering team but sticked to the business processes.

After an initial surprise, I must say I find this approach bold yet totally rational. Let me explain.

JobRad is bigger than just Germany, at the very least Austria is already running, and I understood they were targetting other countries in the near future. In addition, their software engineering department grew quickly in the last couple of years and English is now apparently the primary working language for software folks. One could think the best approach would be to harmonise the codebase over English names throughout, from the code symbols to the developer documentation. Making virtually every term understandable by every single programmer (let's assume English is a requirement for that job), and hence expressing the business processes and intents in a common language.

(Un-)Fortunately, there is another shared language: the ubiquitous language. Nobody had to approximate translations for its terms. It is a gift by the stakeholders packed with history and meaning. Every term we come up with, as developers of the system, is bound to be an approximation. It is the (mental) model we make of the concepts we were told to work with, we interviewed people about, or simply read definitions somewhere. An abstraction is by definition less precise than the object it represents.
An additional piece of information was given during the Q&A: the most important events are deeply related to the German tax system. They are not generalised tax events but really encode the legal process followed by the company.

Whatever the language these messages use, let's not forget that the transport mechanism is an event bus. Want an English version of the messages? Place a consumer that translates the concepts and forwards them onward. It's cheap enough to set up. In my experience, the maintenance headache comes from fitting new requirements and the natural evolution of one's understanding onto the codified concepts, not from a 1-1 mapping of a pre-existing concept.

In the spirit of DDD, let's agree to accept that the code we write is more than machine instructions. The evangelists told us to live by the ubiquitous language, and I think they had a good reason to.

On the Fediverse…

I advertised this post on Mastodon