DDD entity shared between two apps - domain-driven-design

Say I have an object that for the most part has necessary attributes, etc for two different apps because both apps have the need to use them. It's possible that 10% of the attributes won't' be used in one app. Is it better to share that object (and aggregate/bounded context as a shared kernel?) or duplicate the attributes and data that is stored? One app is for end users/activities and the other app is for the management of the users/activities.

We recently developed an application that involved several modules using a lot of common entities. When we developed them, we moved these common entities to a project called common-domain and then had all the dependent modules use it. It turned out to be a disaster.
While we initially found several attributes to be common, we found out that how we designed them for certain modules conflicted in how they were used for the others. Altering the entities in the common-domain to fit the needs of one module sometimes broke how they worked for the other modules. We did not use a test-driven approach and it made finding the resulting bugs tedious.
Learning from that mistake, we should have recognized and identified the bounded contexts and identified the entities and their associated attributes per bounded context. The "common" entity should have been defined per bounded context along with any attribures that are needed for that context. Some attributes will definitely be common but since they are separate bounded contexts, they have to be declared per entity per bounded context.
I'll go a little bit further to mention where an item can be shared. Each entity in a bounded context has its own repository. It is possible that the "common" entities share the same underlying database table. It is the responsibility of each BC's entity repository to retrieve the relevant columns in order to return the appropriate entity instance.

An entity is typically not shared between BCs. You may have another BC in play. You should have one BC that is the system of record for the entity. All other BCs should be downstream from it and contain only the identity and relevant bits of data. Typically one would employ an event-driven architecture to notify dependent systems of any relevant changes to the state of the entity in question.
It may also be that you are trying to split a single BC. Perhaps focus on the BC side of things as opposed to the technical/application side.
Hope that helps :)

Related

DDD reusable models

I have a few microservices that reuse similar models i.e.
RepairService
InventoryService
AuctionService
An Item (Cars, Bikes, etc) can be found in each of these services and each time I add new properties or a new item type, I then end up duplicating these models in 3 places
I thought about putting these models in a fourth library "ItemService" but since these models have different methods in each service, then InventoryService would be able to repair items, etc
But what if my "ItemService" only contained interfaces for these models (Just the state not the methods) which the other services then implement, so you could find ICar in the ItemService, package it into RepairService which then implements it and adds methods to repair a car.
I can't seem to find anywhere on the internet about having domain entities implement interfaces, so I'm not 100 percent sure
Cheers
In a previous project we ended up creating a separate library with all the common stuff used by different microservices. I think it is similar situation with what you describe here. The difference seems to be we used only plain beans for the models (not recommended when you do DDD, I know).
Taking this difference into account, what about using a Decorator?
This means you define the common properties/behavior in a common library, and them decorate them with the needed responsibilities in each service you use?
And I would not worry about having domain entities implement interfaces, if you think it is useful, just do it. I cannot think of any disadvantage.
I have a bit of a write-up around the same concept.
The point is that the various bounded contexts do something different on the same thing so even though there would be a unique identifier for a specific instance of, say, Car you would have different implementations of that class in the various bounded contexts. In many, if not most, cases you would probably have a class with a more relevant name in each particular BC.
Only a single one of the bounded contexts would, however, be the system of record for the entry.

Where put a common value object between two bounded contexts?

i'm trying to apply the domain driven design in a little project
i want to separate the authentication of rest of the users logic,
i'm using a value object for the id (userID) in the beginning i have the userID in the same level(package) of the users but I realize when i separate bounded context for authentication and user, they share a common value object for the userID, so my question is where supose that i have to put the common or share value objects? is correct if i created a packages called commons?
It is recommended to not share models between bounded contexts, however, you can share IDs and even simple Value objects (like Money).
The general rule is that you may share anything that is immutable or that changes very infrequently and IDs rarely change structure (here immutability refers to the source code and value immutability).
Packages called "common" usually refers to reusable concepts that you use in your projects, so that you don't have to code them in every project. There it's usual to put base abstract objects and interfaces, for entities, value objects, etc.
But it's not your case about userId. What you are saying is to put userId in a "shared kernel" model. It is an option, but usually it is not recommended.
From my point of view:
The auth BC has the concepts id,login,password,role,etc.
The user BC has concepts like name,surname,address,age,etc, but it also has to have the id, that it gets from auth BC.
From what I know, you have 2 options:
(1) Authentication BC shares "id" concept explicitly, i.e. it has a shared kernel. So "id" concept would belong to user BC model too.
(2) Authentication BC is a generic BC. So you have to integrate the user BC with the auth BC to get the id from it.
First of all, I personally see this as an context mapping question at code level, where you are effectively looking to have a shared kernel between multiple bounded contexts.
This depends on the business really. You typically need to consider the following questions:
How do different teams responsible for each bounded context collaborate with each other? If it's 1 team maintaining all the related bounded contexts, it might be OK, but it's multiple teams have different objectives, it leads to the next point.
How do you plan to maintain this shared kernel over time? In general, this shared kernel will need to change to adapt to business changes.
For more detailed arguments, there are plenty of resources out there about context mapping, such as Vaughn Vernon's book "Implementing Domain Driven Design".

Translator between bounded contexts in DDD (and some other questions)

I've been reading Eric Evans' DDD: Tackling Complexity in the Heart of the Software and in the section in context maps, Evans cited an example of 2 bounded contexts (Booking context and Network Traversal Service) using a translator to integrate them.
If I understand correctly, when we create a model, we put everything into bounded contexts creating conceptual boundaries for the domain. My questions are:
If everything should be in a bounded context, where should the translator be located? In Evans' sample diagram, the translator is outside (in between) both bounded contexts.
Say we have a single team working on a ERP. Should the ERP be put in several bounded contexts or a single one only. Based on Evans' sample, the bounded contexts were devised so that multiple teams could work on their own model. But since this is a single team, wouldn't they benefit on a single model so integration wouldn't be an issue? Or did I understand this wrong?
In question 2's case, if multiple bounded contexts, what if in implementation, we need a class from Accounting to be used in Payroll? I don't think we need a translator here but I'm not sure how to share the required class. Will just referencing the needed class from another bounded context be fine?
And lastly, how is a module in DDD related to a bounded context?
In an Infrastructure layer (outside the Domain), it's a technical detail.
A bounded context(BC) emerges from the Domain, that's why we identify them and not defining them. Once identified, if there are many BCs and there are developers available then the workload can be split so that the app can be developed faster. A single model is not advisable, you want a single domain model per BC and also a simplified read model for querying (CQRS).
I don't know but for me Payroll is part of Accounting, there aren't really 2 BC. Account is a BC, however other BC might need a Payroll but that definition is specific to the BC. And probably the definition is just really some data (a read model). Payroll behaviour should stay in Accounting. So you need to have clearly defined what each BC understands by "Payroll". Usually you'll have a domain service who will use concepts from both BC and which will use the 'translator'.
It isn't. A module just groups things together from a technical point of view. A BC is pretty virtual, you might choose to have a project or a module corresponding to one BC but that's your decision how to organize things.
If everything should be in a bounded context, where should the translator be located? In Evans' sample diagram, the translator is
outside (in between) both bounded contexts.
I think this question has no sense. Each BC is a boundary in wich a domain model exist, and the boundary is determined by the UL, each BC has its own UL. If you just create one model, you don't need translation. Instead of spliting a big model into several smaller ones, you are joining them.
Say we have a single team working on a ERP. Should the ERP be put in several bounded contexts or a single one only. Based on Evans'
sample, the bounded contexts were devised so that multiple teams could
work on their own model. But since this is a single team, wouldn't
they benefit on a single model so integration wouldn't be an issue? Or
did I understand this wrong?
I think you understood wrong. You split a single model into several BCs according to the UL, not to the available teams. Then if you don't have enough teams for the number of BCs created, a team will have to develop more than one BC. By the way, the opposite is not desirable, i.e., a BC shouldn't be developped by more than one team.
In question 2's case, if multiple bounded contexts, what if in implementation, we need a class from Accounting to be used in Payroll?
I don't think we need a translator here but I'm not sure how to share
the required class. Will just referencing the needed class from
another bounded context be fine?
You shouldn't reference a domain object of another BC. That BC should protect its domain model, that's the application layer for. The application layer expose DTOs, plain objects, it shouldn't expose the domain model to the outside world. What you are asking for is a shared kernel (a model shared by other BC).
And lastly, how is a module in DDD related to a bounded context?
A module is just a java package, useful for keeping together things that a related to each other. So you split the source code of a BC in modules. Do it according to the UL, not to technical aspects. For instance, a module for each aggregate, not a module for entities, another one for repositories, etc.

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

Breaking up Entities into smaller Entities in DDD?

Does it make sense to make subsets of an Entity if you consider their usage in the application differently? IE. I take my entity and define a new entity with only some of the attributes of the first. Now I have 2 Entities that overlap but are used differently but ultimately persist in same datatable. These Entities will be accessed through different repositories...
I am only starting to learn about DDD myself, so if I am wrong please comment and let me know. Here are my thoughts though:
If the entity is going to be accessed through a different repository, I think it deserves its own class. Additionally, the bits that overlap now may not overlap in the future, and if you use a shared base class, you will probably be more likely to try adapting things at that point, which will dirty up your domain.
If the two classes are part of separate sub-domains, they probably should be separate. My thoughts are based around parts of an example I remember hearing in Rob Connery's interview on Hanselminutes. A product has several properties that are important to consumers (pricing, description, etc), and several properties that are important to warehouse personnel (location in the warehouse, weight, dimensions, etc). The implication to me in that episode was that the two products should be defined separately in the domain, instead of being defined once and shared.
If by "usage in the application" you mean you'll display different parts in different views, then I'd suggest you use a presentation pattern like Fowler describes in his Presentation Model (or if your developing a WPF app you can use the more WPF-specialized version called Model-View-ViewModel (MVVM)).
But if you by "usage" mean that you'll use different attributes of the entity in different sub-domains or part of your domain, then I agree with Chris; You'd probably be better off breaking them into different entities. The reason being that in your domain model you should reflect how the entity is used in that specific (sub)domain. And if you're using different parts of the entity under different circumstances, they probably have different meanings in these settings which again should be reflected in the naming of the entities. And if it were me, I'd probably make one repository for each of the entities. Having a 1:1 mapping between entities and repositories seems to make sense in most cases as far as I've experienced. But then again; just like Chris, Rob Conery and 90% of the developers trying to do DDD; I'm fairly new to the DDD-game and so my experiences might be overruled by someone more experienced :)

Resources