by Leon Rosenshein

Ubiquitous Language

I like bounded contexts. More generally, I like both bounds and contexts. Together they're really good at defining scope, both "in scope" and "out of scope". Knowing what you're talking about goes a long way to reducing cognitive load. If it's in scope you think about it. If it's out then you don't need to worry about it.

But that's only part of the battle. Even when you know what's in scope and everyone is in agreement on the scope, you still need to use the same language to discuss things. And you need to use the same language everywhere. Because when it comes to the Venn diagram of what everyone knows, what you know, and what your customers know, the overlap can be surprisingly small.

Ubiquitous language comes from the Domain Driven Design world. And language in this case isn't English vs German vs Spanish, or even C++ vs Go vs Python. It's about terminology. It's about naming. And naming is hard. It's one of the really hard problems in programming. DDD's solution is to ask the expert in the field (the Domain Expert) and use that language. And use it everywhere. In the user docs. In the design docs. In the code. Especially in the code. Because the developers are not the domain experts, and the developers need to be able to communicate with the users and domain experts. If you're already using the same terms for the same things then there's no translation needed and no additional cognitive load. On the other hand, if you're not using the same term, every time you have a conversation the terms need to be translated. In real time. With loss of accuracy. And additional cognitive load.

In the batch processing world we deal with jobs a lot. Customers want to run jobs. They want to start them. They want to know if they're finished. They want to know what the errors were. But what exactly is a job? To Kubernetes it's a structure/API. To Amazon it's a feature in the console. To ML model developers it's a bunch of GPUs running tensorflow on a dataset. To others it's a directed acyclic graph (DAG) of tasks. So what's a "job"? So what's a job? We all need to agree at all times or we're setting ourselves up for problems later.

We decided a job is DAG of tasks (task definition is another part of the ubiquitous language). It could be a simple DAG of one thing, it could be a DAG of N things that need to happen together, or it could be a complicated DAG. In general customers don't need to care. The model they use lets them do everything they want regardless of the complexity of the DAG. As developers we don't care because it's all a DAG and we can treat it as such. And we all agree to ignore Amazon's and Kubernete's definitions. Because they just get in the way and add ambiguity. If we (the developers) need to care about those definitions we wall them off carefully behind facades so that they don't interfere with our ubiquitous language.

And of course, every domain/bounded context can (should?) have its own ubiquitous language. And the interfaces/translators need to be clear. But at least inside a domain/scope/context you have a language that's shared ubiquitously.

So next time you need to abstract something, think about the language you use, because language matters.