How is ApplicationEvent different from DomainEvent? - domain-driven-design

In the DDD Sample, Cargo Tracking application, there are "ApplicationEvents" and DomainEvents.
ApplicationEvents examples: "cargoHasArrived", "cargoWasMishandled"
DomainEvent example: "HandlingEvent.LOAD", "HandlingEvent.RECEIVE", "HandlingEvent.UNLOAD",etc.
How are application and domain events supposed to be different semantically and what are some guidelines you use to determine if it goes in ApplicationEvent or DomainEvent?

Application Events are characteristic to the specific Use Case/User Story. They model application (not domain) behavior.
Technically Domain Events are the same. Difference is on the mental level - Domain Events model facts that takes place in domain model.
https://code.google.com/p/ddd-cqrs-sample/wiki/DomainDrivenDesignBusinessDeveloperMentalModel

Related

Is this leaking domain knowledge to service layer?

Currently, my service layer handles loading aggregate roots that are responsible to react to some domain events. This involves calling the persistence layer to filter and load the responsible aggregate roots using some domain knowledge (who should/when to react). Is this considered domain knowledge leakage and how to prevent it?
Thank you!
my service layer handles loading aggregate roots that are responsible to react to some domain events. This involves calling the persistence layer to filter and load the responsible aggregate roots using some domain knowledge (who should/when to react).
If you are willing to substitute "application layer" for "service layer", I think you'll find that's a pretty good match for the patterns that Eric Evans describes in the original Domain Driven Design book.
This layer is kept thin. It does not contain business rules or knowledge, but only coordinates tasks and delegates work to collaborations of domain objects in the next layer down. It does not have state reflecting the business situation, but it can have state that reflects the progress of a task for the user or the program.
The sample cargo shipping application (a collaboration between Eric Evans and Citerus) exhibits patterns that I see fairly often when discussing designs with other DDD practitioners. The code I think you are talking about is here: https://github.com/citerus/dddsample-core/blob/master/src/main/java/se/citerus/dddsample/application/impl/BookingServiceImpl.java
public void assignCargoToRoute(final Itinerary itinerary, final TrackingId trackingId) {
final Cargo cargo = cargoRepository.find(trackingId);
if (cargo == null) {
throw new IllegalArgumentException("Can't assign itinerary to non-existing cargo " + trackingId);
}
cargo.assignToRoute(itinerary);
cargoRepository.store(cargo);
logger.info("Assigned cargo " + trackingId + " to new route");
}
In this case, Itinerary and TrackingId are value objects - the definitions are in the domain layer, but these instances are actually constructed in the web/presentation layer, and passed to the application logic that is responsible for coordination.
I am wondering how to go about loading/filtering the responsible aggregate roots without leaking domain knowledge to service layer? For example, filtering aggregate roots using some business knowledge about who/when should a domain event be handled.
The heuristic I use is that we want to separate calculation/logic from information retrieval. So if identifying the right aggregate to load depends on the form data submitted by the user, a tax table, and the conversation the CEO had at the airport last week, then we'd prefer a design like
aggregateId = computeTheAggregateId(formData, taxTable, ceo.conversation())
aggregate = repository.get(aggregateId)
aggregate.doSomethingCool(formData)
Does computeTheAggregateId belong in application or in domain? In the abstract, it's not obvious that it matters very much. The right answer might depend on how often it changes, or what code changes at the same time.
Ultimately: this is a pattern language - if the pattern doesn't "work" in the context you are in, then you are expected to have the good judgment not to use it.

How granular should a domain event be?

I am wondering how granular should a domain event be?
For example I have something simple, like changing the firstName, the secondName and the email address on a profile page. Should I have 3 different domain events or just a single one?
By coarse grained domain events when I add a new feature, I have to create a new version of the event, so I have to add a new event type, or store event versions in the event storage. By fine grained domain events I don't have these problems, but I have too many small classes. What do you think, what is the best practice in this case?
What's the problem with many classes? Really, why so many devs are afraid of having too many classes? You define as many classes as needed.
A domain event signals that the domain changed in a certain way. It should contain all the relevant information and it should be taken into consideration the fact that an event is also a DTO. You want clear events but it's up to the developer to decide how granular or generic an event is.
Size is not a concern, however if your event 'weights' 1 MB maybe you have a problem. And the number of classes is not a domain event design criteria.
I can agree with MikeSW's answer, but applying SRP during the modeling, you can end up with small classes, which is not a problem at all.
According to Greg Young the domain events should always express something that the user does from a business perspective. For example if the user has 2 reasons to change her phone number PhoneNumberChanged, and this information can be important from a business perspective, then we should create 2 event types PhoneNumberMigrated, PhoneNumberCorrected to store technically the same data. This clearly violates DRY, but that is not a problem, because SRP can override DRY in these cases as it does by sharing aggregates and their properties (most frequently the aggregate id) between multiple bounded contexts.
In my example:
I have something simple, like changing the firstName, the
secondName and the email address on a profile page.
We should ask the following: why would the user want that, has it any importance from the perspective of our business?
her account was stolen (security, not business issue)
she moved to another email address
she got married
she hated her previous name
she gave the account to somebody else on purpose
etc...
Well, if we have dating agency services then logging divorces can have probably a business importance. So if this information is really important, then we should put that it into the domain model, and create an UserProbablyDivorced event. If none of them are important, then we can simple say, that she just wanted to change her profile page, we don't care why, so I think in that case both UserProfileChanged or UserSecondNameChanged events can be acceptable.
The domain events can be in 1:1 and in 1:n relation with the commands. By 1:1 relation they name is usually the same as of the commands, but in a past tense. For example ChangeUserProfile -> UserProfileChanged. By 1:n relation we usually split up the behavior which the command represents into a series of smaller domain events.
So to summarize, it is the domain developer's decision how granular the domain events should be, but it should by clearly influenced from a business perspective and not just from a modeling a data schema perspective. But I think this is evident, because we are modeling business and not just data structure.

How to be with huge Domain classes in DDD?

When you are developing an architecture in OO/DDD style and modeling some domain entity e.g. Order entity you are putting whole logic related to order into Order entity.
But when the application becomes more complicated, Order entity collects more and more logic and this class becomes really huge.
Comparing with anemic model, yes its obviously an anti-pattern, but all that huge logic is separated in different services.
Is it ok to deal with huge domain entities or i understand something wrong?
When you are trying to create rich domain models, focus entities on identity and lifecyle, and thus try to avoid them becoming bloated with either properties or behavior.
Domain services potentially are a place to put behavior, but I tend to see a lot of domain service methods with behavior that would be better assigned to value objects, so I wouldn't start refactoring by moving the behavior to domain services. Domain services tend to work best as straightforward facades/adaptors in front of connections to things outside of the current domain model (i.e. masking infrastructure concerns).
You can also put behavior in Application services, but ask yourself whether that behavior belongs outside of the domain model or not. As a general rule, try to focus application services more on orchestration-style tasks that cross entities, domain services, repositories.
When you encounter a bloated entity then the first thing to do is look for sets of cohesive set of entity properties and related behavior, and make these implicit concepts explicit by extracting them into value objects. The entity can then delegate its behavior to these value objects.
Since we all tend to be more comfortable with entities, try to be more biased towards value objects so that you get the benefits of immutability, encapsulation and composability that value objects provide - moving you towards a more supple design.
Value objects enable you to incorporate a more functional style (eg. side-effect-free functions) into your domain model and thus free up your entities from having to deal with the complexity of adding complicated behavior to the burden of managing identity and lifecycle. See the pattern summaries for entities and value objects in Eric Evan's http://domainlanguage.com/ddd/patterns/ and the Blue Book for more details.
When you are developing an architecture in OO/DDD style and modeling
some domain entity e.g. Order entity you are putting whole logic
related to order into Order entity. But when the application becomes
more complicated, Order entity collects more and more logic and this
class becomes really huge.
Classes that have a tendency to become huge, are often the classes with overlapping responsibilities. Order is a typical example of a class that could have multiple responsibilities and that could play different roles in your application.
Given the context the Order appears in, it might be an Entity with mutable state (i.e. if you're managing Order's commercial condition, during a negotiation phase) but if you're application is managing logistics, an Order might play a different role: and an immutable Value Object might be the best implementation in the logistic context.
Comparing with anemic model, yes its
obviously an anti-pattern, but all that huge logic is separated in
different services.
...and separation is a good thing. :-)
I have got a feeling that the original model is probably data-centric and data serving different purposes (order creation, payment, order fulfillment, order delivery) is piled up in the same container (the Order class). Can't really say it from here, but it's a very frequent pattern. Not all of this data is useful for the same purpose at the same time.
Often, a bloated class like the one you're describing is a smell of a missing separation between Bounded Contexts, and/or an incomplete Aggregate separation within the same bounded context. I'd have a look to:
things that change together;
things that change for the same reason;
information needed to fulfill behavior;
and try to re-define aggregate boundaries accordingly. And also to:
different purposes for the application;
different stakeholders;
different implicit models/languages;
when it comes to discover the involved contexts.
In a large application you might have more than one model, thus leading to more than a single representation of a single domain concept, at least for concepts that are playing many roles.
This is complementary to Paul's approach.
It's fine to use services in DDD. You will commonly see services at the Domain, Application or Infrastructure layers.
Eric uses these guidelines in his book for spotting when to use services:
The operation relates to a domain concept that is not a natural part of an ENTITY or VALUE OBJECT.
The interface is defined in terms of other elements in the domain model
The operation is stateless

DDD: inter-domain referencing design issue?

What are DDD recommendations for inter-domain referencing design?
Should I try to connect them as "Matryoshka" (put one into another) or it is better to create upper-level "inter-domain" business service?
P.S. Crossing this smooth water, I was unable to find anything useful to read in the Internet, and have started thinking that for this kind of things exist better term than "inter-domain referencing"... Am I right?
DETAILS:
I have two models/business services.
Semantically first domain (A) is CRM with sell/maintenance process for our goods, second domain (B) is "design" data of our goods. We have two view points on our goods: from seller perspective and from engineer perspective.
Actually each model is effective ORM (Object-Relational Mapping) tool to the same database.
There are some inter-domain activities e.g. validations (e.g. sometimes we can sell things to smb. only if some engineering rules are valid).
From developer's point of view I have two clear possibilities (reference B in A or create new cross reference domain/service C ). But from designer perspective I am lost in understanding what kind of Business Service I have when I compose business logic from two different domains.
As far as I know, DDD has no strict rules for 'inter-domain' referencing. At the end of the day your domain model will have to reference basic Java or .NET classes. Or it may reference specialized date/time or graph library (aka 'Generic Domain').
On the other hand DDD has a concept of Bounded Context. And it has quite a few patterns that can be applied when you work at the boundaries of the system. For example 'Anticorruption Layer' can be used to isolate you from legacy system. Other integration styles can be used depending on how much control you have over external code, team capabilities etc.
So there is probably no need to introduce artificial glue layer if you just dealing with two subdomains in one Bounded Context. Might also be worth reading Part 4 of DDD book (Strategic Design).
UPDATE:
Based on the information you provided, it looks like you only have one Bounded Context. You don't seem to have 'linguistic clashes' where the same word have two different meanings. Bounded Context integration patterns are most likely not applicable to your situation. Your Sales domain can reference Products domain directly. If you think of Products domain being more low-level and Sales being high level you can use Dependency Inversion Principle. Define an interface like ProductCompatiblityValidator in Sales and implement it in Products domain. And then inject the actual implementation at the application layer. This way you will not have a direct reference from Sales to Products.
In addition to what Dmitry has already said...
I think of any code that crosses bounded contexts as application layer code. I would have that application layer code reference domain types from both contexts (and their repositories) but not have two domains reference each other. I think it's OK to have business logic in an application layer if it specifically crosses domain boundaries and is unit-testable.
If you really have a hierarchy, then it would be OK to have the the more concrete subdomain reference the more abstract domain. However, I would be careful if this causes you to need to have domain objects reference repositories of any type. Pulling objects out of of a repository is rarely a true domain concept. Referencing repositories is best done in an application layer that sits a layer above the domain model.
Of course this is all as much art as science. I'd try modeling a thin slice of your application a couple different ways and see what friction you run into with each approach.

Does it make sense to only transfer some data to the UI when thinking DDD?

Say I have a model Exam. There will be a collection of Question objects containing questions and answers, and a collection of what each student have answered.
I think it is ok for the application layer to give the presentation layer only the bits it need to create the UI. In other words when students are answering questions, the application layer does not present the other students to the presentation layer.
Same idea when the data goes back to the application layer. Questions cannot change, so we send only the students answer back to be attached to the domain model.
IMHO this is according to E. Evans description of the application layer: Defines the jobs the software is supposed to do and directs the expressive domain objects to work out problems.
Yes, it does make sense. Not only that, in most scenarios this should be the go-to architecture, in my opinion. The thing is DDD is great in managing complexity while keeping consistency within aggregates and bounded context - the things that occur when something gets changed. And there shouldn't be any change while reading (displaying) the data, so you get no help from DDD on this part. Moreover, if you use your domain object for providing data to your UI layer, you end up tailoring domain for user interface instead of business domain, and these are different contexts.
Actually there are entire architectures basing on that facts, CQRS being one of them. CQRS has this great idea of keeping two sets of data stores - one tailored to domain model, the other explicitly prepared for reading the data to present on UI (for example).
You might also be interested in this blog post on the repository pattern by Szymon Pobiega - it also follows the idea of separating the write (domain) and read (queries) side.

Resources