Domain Driven Design (DDD) defines a number of concepts and patterns that help designing software effectively, in-line with the business requirements. Axon separates infrastructural concerns from the domain logic, which in combination with DDD best practices, keeps complexity to a minimum.
A business operates within a domain and that’s what we’re trying to design and model with DDD. We can derive more concrete definitions of a ‘Domain’ in the context of DDD:
- A concept that lives in a ‘problem space’.
- The subject area to which the user applies a program.
- A sphere of knowledge, influence, or activity.
Domains can be very complex and different areas within a domain might have different expertise. For example, in the Domain of Banking, there is a clear difference between consumer banking, corporate banking and wealth management.
Typically, we can split complex domain into subdomains, where each subdomain corresponds to different part of the business. Identifying subdomains requires understanding of the business, mostly its organizational structure and areas of expertise.
There are numerous techniques to discover a domain. Event Storming is a particularly interesting one. It is a workshop format for quickly exploring complex business domains.
The result of this strategic process of exploring and decomposing complex domain is a set of smaller subdomains that should be categorized by importance:
- Core (sub)domain - most important part of your domain - the money maker - key differentiator for the business
- Supporting - related to what the business does but not a differentiator. These can be implemented in-house or outsourced.
- Generic - not specific to the business and are ideally implemented using off-the-shelf software
A model is: “A system of abstractions that describes selected aspects of a domain and can be used to solve problems related to that domain;”
In other words, a model captures what's important and helpful in solving a specific problem within our domain. We can derive more concrete definitions of a ‘Domain Model’ in the context of DDD:
- A concept that lives in a ‘solution space’.
- A software programing model which is applied to a specific domain (problem area)
Domain Model should define the vocabulary and should act as a communication tool for everyone involved (business and IT) deriving a Ubiquitous Language. This language needs to be rigorous, since software doesn't cope well with ambiguity.
Axon & Domain Model
Axon offers mature programming model (AxonFramework) for crafting tactical building blocks of a Domain Model:
- Aggregate root
- Value object
- Domain event
An Aggregate is an entity or group of entities that is always kept in a consistent state (within a single ACID transaction). The Aggregate Root is the entity within the aggregate that is responsible for maintaining this consistent state. This makes the aggregate a prime building block for implementing a domain model in Axon based applications.
Complex business logic often requires more than what an Aggregate with only an Aggregate Root can provide. In that case, it is important that the complexity is spread over a number of Entities (aggregate member) within the aggregate. Axon provides support for event sourcing complex aggregate structures like these out of the box, with the ability to handle messages on the Entity level.
A Value Object is an immutable type that is distinguishable only by the state of its properties. Value Objects represent concepts in our Ubiquitous Language, and so they should always tell a story about the problem we are solving. For example `CustomerName` is a value object holding two `String` properties: `firstName` and `lastName`. Axon is encouraging us to use Value Objects in a way we think fit.
In Axon, Aggregates accept business commands, which usually results in producing an event related to the business domain – the Domain Event.
In CQRS based applications, Aggregate is very explicitly presented in the Command Model, as that is where change is initiated. However, Query Models / Projections are also built up of Aggregates. Generally, however, aggregates in Query Models are much more straightforward, as state invariants are generally less strict in those models.
Axon explicitly separates the business logic from configuration of the infrastructure in which this logic needs to operate. AxonServer is such an infrastructural component of Axon, and takes care of storing and routing events and other types of messages (commands and queries) in an optimal and reliable way. This separation makes Axon very flexible and configurable (with alternative components available for RDBMS, NoSQL, AMQP, Kafka, etc). More importantly, it allows you to focus on getting the domain logic implementation right, without distraction from infrastructural concerns.
A context is "The setting in which a word or statement appears that determines its meaning".
In other words, the same domain concept may have a different meaning to different people.
Consider, for example, the concept of a Flight. For a passenger, a Flight is the period between departure of an aircraft until the arrival at your destination. The Ground Crew, however, cares about the arrival of a Flight at the Gate, the number of meals, pillows, etc to get on board, and they're done when the flight leaves the gate. For them, departure time is a deadline, not the starting point.
A goal is to develop a Ubiquitous Language as our domain (subdomain) model within an explicitly Bounded Context.
Therefore, there are a number of rules for Models and Contexts:
- Explicitly define the context within which a model applies.
- Explicitly set boundaries in terms of team organization, usage within specific parts of the application, and physical manifestations such as code bases and database schemas.
- Keep the model strictly consistent within these bounds, but don’t be distracted or confused by issues outside.
- Ideally, keep one subdomain model per one Bounded Context.
Axon & Bounded Context
Axon deals with Bounded Contexts in a few different ways. From the Framework perspective, by separating business logic from configuration this allows logic to focus on the relevant aspect of the context itself, using configuration of serializers, upcasters, etc, to explicitly define how messages and interactions are shared beyond the boundaries of the context of the application itself.
AxonServer explicitly supports bounded contexts, by allowing different (groups of) applications, to connect to different contexts within AxonServer. Unless specifically indicated otherwise, contexts are strictly separated and information is not shared between them.
You can read more about bounded context, click here.
A bounded context never lives entirely on its own. Information from different contexts will eventually be synchronized. It is useful to model this interaction explicitly. Domain Driven Design names a few relationships between contexts, which drive the way they interact:
- partnership (two contexts/teams combine efforts to build interaction)
- customer-supplier (two contexts in upstream/downstream relationship - upstream can succeed independently of downstream contexts)
- conformist (two contexts in upstream/downstream relationship - upstream has no motivation to provide to downstream, and downstream context does not put effort in translation)
- shared kernel (explicitly, sharing a part of the model)
- separate ways (cut them loose)
- anti-corruption layer (the downstream context builds a layer to prevent upstream design to 'leak' into their own models, by transforming interactions)
Axon & Context Mapping
In Axon based application, the context defines the boundary in which Events carry value. Some events may be valuable only in the context in which they are published, while others may be valuable even outside. The broader the scope in which an event (or any message, in that respect) is published, the more components end up coupling to the sender. Axon is a flexible platform that lets us choose any of the context mappings we find fit for our organization.
Effective design with DDD and Axon
Axon originated in an attempt to find a solution to the ever increasing accidental complexity. Applying concepts from Domain Driven Design will help to a very large degree, enabling us to design our domain model effectively (in-line with the requirements).
While Axon is opinionated on how the interaction with a domain model should take place, it tries to avoid any restrictions on the modelling freedom that one has. Even when your opinion differs from that of Axon, there are enough hooks, configuration options and triggers to change certain aspects of Axon's behavior.
Sign up for email notifications
by submitting you agree to receive occasional emails