Domain driven project. How do I work with user objects in different bounded contexts?

I have a question about Driven Driven Design. In the restricted context of my user / profile account, there is a User Object with account information (id, username, password, email, salt, etc.) and profile information (full name, avatar, birthday, gender etc.). I also have another bounded context for Job Positions / Applications where every job position has an employer user and every job application has an applicant user.

The question is, should the Employer User / Applicant in the Job Restricted Use Context be the same User Entity I use for the Restricted User Account Context? Or should I create different user type objects for the Employer and the Applicant?

As you can see, in the bounded context of a job, only information such as id, fullname, email, and avatar from the bounded context is important. If the employer / Applicant is the same User from the account / User Profile, it will download much more useless data (no need to know the user password for the employer / applicant). But if I create different entity classes for them, it makes the data complexity more complex, since changes made to different entity classes can change the same data in the same database table.

What do you think? Should I use one custom object for all or different custom objects for different bounded contexts / aggregates? If the latter is desired, how can I do this with data / entity persistence?

+3


source to share


1 answer


This is an old question and you've probably solved this dilemma somehow, but I'll try to answer it.

You wrote:

"only information such as id, fullname, email and avatar from the account bounded context is relevant in the task bounded context"

Are they really Job BC? With objects (and even more: with aggregates), you model processes , not data. In which Job BC process or use case do you need a full name? Does the domain have a requirement that persons with a specific first or last name should not be used? I guess not. By saying this, you probably meant that you had to display some screens that displayed the person's full name. But screens are not processes , they are just reports . You don't have to manage your model with reports / screens / user interface, but processes that exist in a specific domain.

Ok, but how do you do it? Obviously, you still need to create multiple reports / screens. Is not it? Answer: you need CQRS ( https://martinfowler.com/bliki/CQRS.html ). The command stack is just your process model, reached by aggregates, etc. This way your building blocks will be persisted by some ORMs. And the data model for them will be determined by how they look (building blocks). Use some ORMs here that can easily port even a complex aggregate like Hibernate.

Then you need to create a request stack. I see two ways to achieve this, and it depends if you have both BCs in the same DB schema or not.



When both BCs are on the same schema, just use multiple database views that will build data for your reports / screens. Use some very fast and flexible for complex ORM queries here, like MyBatis or Spring JDBC (or even plain JDBC if you like fighting the JDBC rage;)). Don't use Hibernate here unless you are 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 the infrastructure / ORM in use to achieve complex data model unions that are driven by Aggregates and their processes, not screens. Another reason is that in a typical business application there are several orders of magnitude more reads than writing to the DB, talking in CQRS,there are more use cases for the query stack than for the command stack, so you need something fast here.

When the BCs are on different schemas, you need to create a reporting database ( https://martinfowler.com/bliki/ReportingDatabase.html ) that "merges" both schemas. Then you can make views on the combined diagram and the problem is simplified to one.

Note that the reporting database gives you another scalability option: this database is read-only, so it can be easily replicated across multiple servers, your query stack services can be replicated and hidden behind some kind of load balancer.

Ok, but what about using the email address property? You probably have a precedent in your domain that an employer or applicant needs to be notified of some of the activities / processes being performed in the domain. I think the Domain Service (or domain event handler) handling this use case should ask another BC service for that specific user's email (or broadcast a domain event to be handled somewhere). Or better yet, it must delegate this work to some kind of notification service in another BC. And this notification service will ask the BC BC service for the email address.

In my opinion, bounded context (along with ubiquitous language) is the most important DDD idea. It is a really powerful tool to avoid a big ball of dirt while modeling. And it's really not easy to define bounded context in real domains :)

+2


source







All Articles