最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

domain driven design - DDD: Where to trigger creation of Aggregate root that need existing referenced Data - Stack Overflow

programmeradmin4浏览0评论

I am currently building an online course platform where you can create courses and assign them to users as mandatory trainings (creation of training and assigning them doesnt have to be done by the same person). In this project I am trying out DDD principles and Hexagonal Architecture and came up with the following 2 bounded contexts but maybe they should be the same BC? Also the project is a (modular) monolith with one database

Trainingmanagement: This BC is for creating the courses, adding description, content and and some test questions. Also the training can be published which makes it available for assigning it to users and seeing it on the UI in the trainings catalog area.

Trainingassignment: This BC is for assigning the courses created in the previous BC to user and set a Deadline.

Obviously the training assignment aggregate references the training from BC1 by ID and thus it should reference an existing training. So my question is where should the creation of the assignment be triggered?

Option 1: Just create it inside BC2 and pass the referenced training to the service creating the assignment. But with this approach I would need to call the BC1 from BC2 to make sure the training exists or is activated (because the course can be in offline/unpublished mode).

Option 2: Inside BC1 I could have an assignTraining method on the training aggregate which triggers a Domain Event "TrainingAssigned" that is captured by BC2 and based on the event details the training assignment is created. This way it is assured that only existing and published courses can be used to assign trainings to users.

Option 3: Since the project is a monolith and using one database, I could access the trainings database table directly from BC2 and get the information. This is similar to option 1 but instead of calling BC1 via ports or adapters I just access the database table directly in the infrastructure layer. I like option 1 more than this one because I can use interfaces and the data access is only done by one BC. I ever choose to change the database table I would need to remember that BC2 is also using the table directly...

Option 4: Events inside BC1 could be captured by BC2 to have local copies of relevant data. For example whenever a training is published in BC1, BC2 could create an entry in a new database table and get the available trainings from there. With this approach I would have less coupling between the BCs but duplicated data and for every training in BC1 I would have an "Available Training for assignment" in BC2.

Option 5: Maybe they both are just one BC and then I wouldn't need to worry about coupling because inside the command service I could just check whether a training exists or not. Or I could more easily go with option 2 and the Training Aggregate creates directly the Training Assignment Aggregate.

I am not sure which option is best or maybe there are better options than the ones I was thinking of.

I am currently building an online course platform where you can create courses and assign them to users as mandatory trainings (creation of training and assigning them doesnt have to be done by the same person). In this project I am trying out DDD principles and Hexagonal Architecture and came up with the following 2 bounded contexts but maybe they should be the same BC? Also the project is a (modular) monolith with one database

Trainingmanagement: This BC is for creating the courses, adding description, content and and some test questions. Also the training can be published which makes it available for assigning it to users and seeing it on the UI in the trainings catalog area.

Trainingassignment: This BC is for assigning the courses created in the previous BC to user and set a Deadline.

Obviously the training assignment aggregate references the training from BC1 by ID and thus it should reference an existing training. So my question is where should the creation of the assignment be triggered?

Option 1: Just create it inside BC2 and pass the referenced training to the service creating the assignment. But with this approach I would need to call the BC1 from BC2 to make sure the training exists or is activated (because the course can be in offline/unpublished mode).

Option 2: Inside BC1 I could have an assignTraining method on the training aggregate which triggers a Domain Event "TrainingAssigned" that is captured by BC2 and based on the event details the training assignment is created. This way it is assured that only existing and published courses can be used to assign trainings to users.

Option 3: Since the project is a monolith and using one database, I could access the trainings database table directly from BC2 and get the information. This is similar to option 1 but instead of calling BC1 via ports or adapters I just access the database table directly in the infrastructure layer. I like option 1 more than this one because I can use interfaces and the data access is only done by one BC. I ever choose to change the database table I would need to remember that BC2 is also using the table directly...

Option 4: Events inside BC1 could be captured by BC2 to have local copies of relevant data. For example whenever a training is published in BC1, BC2 could create an entry in a new database table and get the available trainings from there. With this approach I would have less coupling between the BCs but duplicated data and for every training in BC1 I would have an "Available Training for assignment" in BC2.

Option 5: Maybe they both are just one BC and then I wouldn't need to worry about coupling because inside the command service I could just check whether a training exists or not. Or I could more easily go with option 2 and the Training Aggregate creates directly the Training Assignment Aggregate.

I am not sure which option is best or maybe there are better options than the ones I was thinking of.

Share Improve this question edited Mar 24 at 19:17 hadamard asked Mar 24 at 14:10 hadamardhadamard 4436 silver badges18 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 0

Option 1: Just create it inside BC2 and pass the referenced training to the service creating the assignment. But with this approach I would need to call the BC1 from BC2 to make sure the training exists or is activated (because the course can be in offline/unpublished mode).

I think this answer is closest, but still misses the mark: what I think you want in most cases is for BC2 to have a locally cached copy of the reference data that it needs to do its work.


In Eric Evan's DDD book, he uses as a primary example a "Cargo shipping" application. Cargo is moved between ports, and those ports have UN/LOCODE designators.

So we have a problem analogous to yours: BC2 is the cargo shipping application, which depends in part on reference data published by BC1 (UNECE).

How does that work? Well, the "current" issue of location data is published a couple times a year; and when you are ready to update the data in your cargo shipping app you download a copy and import it into whatever form of storage you decided was most appropriate for that data in your context.

Note that to use the data, you don't need to know anything at all about their internal processes, or what "events" are significant, or anything like that -- you just need to know the schema used when they publish, and some mechanism for knowing when a new issue is available.


Now, do you need that kind of distance when the publishers and subscribers are on the same payroll? Maybe! certainly, the trade offs are different (especially if there is a limited audience for the published data). And any time you introduce caching, you're also introducing cache invalidation (which is one of the Two Hard Problems).


Should the test questions also be stored as a local copy?

Aren't they also reference data? Information that we want to be available even when the other service is offline for maintenance, or whatever? And that information is still tied in to the same publishing cadence?


That all said, one important thing that you should acknowledge in your design is that you really aren't sure where the data should be; THEREFORE... you should try to arrange your code such that most of the system can be ignorant of the details of where it comes from (so that when change comes, you can make that change with minimum fuss).

See Information Hiding (Parnas, 1971).

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论