Ubiquitous Language and Value Objects in Domain-Driven Design
Driving design with natural abstractions. Natural abstractions are how we describe complex concepts. Natural abstractions are simple concepts that we use to explain complicated concepts.
Ubiquitous Language is a common language between businesses and software developers. A model can be anything the people involved with the domain agree on. The Ubiquitous Language is another way to represent a model. The Ubiquitous Language is a shared language developed by domain experts and software developers. Domain-Driven Design models the ubiquitous Language per Bounded Context. Ubiquitous Language reflects the structure of the model. The systems that the model suggests should show up in the Software. We use these abstractions in day-to-day conversations with stakeholders and programmers.
The language we share to communicate ideas about a system is the concept we need to map within the code. Everything starts at the level of a rule or a need that someone has. That’s why the definition of User Stories has to be as abstract and near to the Language of the business as possible.
The first to identify is an easy way to expose or share valuable concepts for those needing the solution. In describing any need, many concepts might be necessary to the user. By looking at how the condition refers to actions and names, we can grab most of the abstractions we need at least to start experimenting.
User Stories follow specific characteristics that make them reusable. For instance, When defining a User Stories is preferable to use a declarative style over the imperative one. The imperative style is too concrete and specific, reducing flexibility and expression. Making user stories declarative suggests an abstract language to describe the problem. After extracting some of the concepts embedded within a rule, we can start deciding how to put this concept in place in code. There are two types of artifacts during development. One part is primary data, and the other part is behavior. I will use a different name to refer to the same thing here. I will come from behavior `actions` and data `state .`Both items need to be separated. Yet, we need to find a way to make them work together. Here is where the usage of some of the concepts from Domain-Driven Design comes in handy.
The Imperative shell orchestrates the relationships between those interfaces while maintaining the state. Think is a glue layer between HTTP and any business domain. The imperative shell is a layer that surrounds the functional core and is the bulk of the application. The functional core defines the minimal and essential algorithms of a system. The imperative shell provides `interfaces` to interact with the impure external world and our pure internal one. We can use value Objects to represent raw business data. To know what a value object is, we need to ask, `is the data more important than the behavior?` if yes, then we are dealing with a value object.
Data can be represented in code in several ways. Value Objects are the most valuable pattern when implementing a domain model in code. Since data represents the state, there are implications of having global access to our application’s state. That’s why we want to restrict the updates to the data at the application level. We can enforce this notion by transporting pieces of information within the system as Value Objects. The advantage of this approach is that we can enforce an immutable state across the system’s internal parts.
Immutability prevents side effects, thus protecting from *direct access*. Immutability also promotes stability by avoiding side effects. Encapsulation restricts direct access to object internals. Thus by reducing side effects, encapsulation is enforced in a software system. Design your program as a core of independent functional pieces in this style. The available details take values and return values — the glue layer between any application’s core domain and interactions from users or other systems. The Imperative shell orchestrates the relationships between those interfaces while maintaining the state. The Imperative shell help connects with the external implementation details of the system.
[¹]: Domain-Driven Design: Tackling Complexity in the Heart of Software