I have a question regarding Domain Driven Design. In the User Account/Profile bounded context of my application, there is a User Entity with account information(id, username, password, email, salt, etc) and profile information(fullname, avatar, birthday, gender, etc). I also have another bounded context for Job Positions/Applications, in which each Job Position has an Employer User and each Job Application has an Applicant User.
The question is, should the Employer/Applicant User in Job bounded context be the same User Entity I use for user account bounded context? Or should I design different User type entities for Employer and Applicant?
As you see, only information such as id, fullname, email and avatar from the account bounded context is relevant in the job bounded context. If the Employer/Applicant is the same User Entity from Account/User Profile, it will load a lot more useless data(dont need to know user password for an employer/applicant). But if I create different entity classes for them, it will make data persistence more tricky as changes made in different entities classes can change the same data in the same database table.
What do you think? Should I use one User Entity for all, or different User Entities for different bounded contexts/aggregates? If the latter is desirable, how can I do with data/entity persistence?
Anything that shows domain concepts, relationships, rules, and so on. Since a bounded context is a boundary for a model, it could include concepts from multiple subdomains. Or a single subdomain could be modelled as multiple bounded contexts.
A bounded context is simply the boundary within a domain where a particular domain model applies. Looking at the previous diagram, we can group functionality according to whether various functions will share a single domain model. Bounded contexts are not necessarily isolated from one another.
In general, the functionality in a microservice should not span more than one bounded context. By definition, a bounded context marks the boundary of a particular domain model.
To identify bounded contexts, you can use a DDD pattern called the Context Mapping pattern. With Context Mapping, you identify the various contexts in the application and their boundaries. It's common to have a different context and boundary for each small subsystem, for instance.
It is old question and you probably solved this dilema somehow, but I will try to answer it.
You wrote:
"only information such as id, fullname, email and avatar from the account bounded context is relevant in the job bounded context"
Are they really relevant to Job BC? With Entities (and even more: with Aggregates) you are modelling processes, not data. In which process or use case of Job BC do you need fullname? Is there a requirement in the domain that persons with specific first or last name shouldn't be employed? I assume not. By saying so you probably had in mind, that you had had to display some screens where fullname of a person had been displayed. But screens are not processes, they are just reports. You shouldn't drive your model by reports/screens/UI, but by processes that exist in specific domain.
Ok, but how to do that? Obviously you still need to generate some reports/screens. Don't you? The answer is: you need CQRS (https://martinfowler.com/bliki/CQRS.html). Command stack is just your model of processes reached by Aggregates etc. So your building blocks will be persisted by some ORM. And data model for them will be driven by how they (the building blocks) look like. Use some ORM here that can easily persist even complex Aggregate, for example Hibernate.
Then you have to build up Query stack. I see two ways to achieve it and they depend if you have both BC in the same DB schema or not.
When both BCs are on the same schema, just use some database views that will construct data for your reports/screens. Use some really fast and flexible for complex queries ORM here like MyBatis or Spring JDBC (or even plain JDBC if you like to struggle with JDBC anger ;) ). Don't use Hibernate here if you are not forced to, because you will find that it is good to be as close to SQL as possible in this stack. Data query abstractions will force you to struggle with used framework/ORM to achieve complex joins of data model that is driven by Aggregates and theirs processes, not screens. Another reason is that in ordinary business application there are several orders of magnitude more readings than writes to DB, speaking in CQRS, there are more Query stack usages than Command stack usages, so you need something fast here.
When BCs are on different schemas you need to build the Reporting Database (https://martinfowler.com/bliki/ReportingDatabase.html) which will "merge" both schemas. Then you can do views on merged schema and the problem simplifies to above one.
Please notice that Reporting Database gives you another scaling possibility: this database is read only, so it can be easily replicated among several servers, your Query stack services can be multiplied and hidden behind some Load Balancer.
Ok, but what with email address property? You probably have a use case in your domain that Employer or Applicant should be notified about some action/process done on domain. I think Domain Service (or Domain Event handler) handling this use case should ask other BC's service for email of this particular user (or broadcast Domain Event that will be handled somewhere). Or even better - it should delegate this work to some Notification Service in yet another BC. And this Notification Service will ask Account BC's service for email address.
In my opinion Bounded Context (along with Ubiquitous Language) is the most important idea of DDD. This is really powerful tool to avoid Big Ball of Mud during modelling. And it is really not easy to determine Bounded Context in real domains :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With