3

In all DDD books I read so far, they say a bounded context can have its own implementation architecture, which suggests a single architecture per bounded context.

In my journey of DDD and also CQRS, I found in a bounded context, certain domain concepts are suitable for a rich domain model so I will have aggregate roots, value objects and entities for those. But besides those, I have quite a number of things that are simple but closely related to those domain concepts.

For example, in my application, users can add others as users, can create a chat group by adding many users, can add posts, etc. So I have aggregate roots for user, chat group, post. But there are things like blocking another user, mark a user as important, mark a chat group as important. These are mostly settings involving a user-user relationship or a user-chatgroup relationship. It is awkward model these things as aggregates. Each different setting is not much related to others, so group all user-user settings into a big aggregate is also weird.

Right now, it is easier for me to have two implement architecture inside a bounded context: 1) DDD for those complex concepts 2) transaction script for those simple stuff. Is this acceptable?


Besides above-mentioned thought, I also considered splitting them into multiple bounded contexts. But I am worried about how to combine data in two bounded contexts into one in querying phase. In the case of a user querying another user, he wishes to see all things related to that user. In terms of restful api, the user wishes to see:

{
    "userId": 12, //from ddd
    "Name": "Somebody", //from ddd 
    "IsFriend": true, //from ddd
    "IsImportant": true, //from transaction script
    "Blocked": false //from transaction script
}

But since DDD usually suggests each bounded context should have its own database and it is better not to share a database. I can make compromises to share databases only for the purpose of querying (not writing), but I am still not sure if there might be problems I cannot foresee right now.

I'd like to hear opinions and suggestions. Thanks in advance.

2

It is awkward model these things as aggregates

Why ? Since you're using CQRS, these aggregates would only be used on the write side. It would be awkward if you had to load all these little aggregates in memory each time a screen is displayed, but with CQRS you can have ad-hoc queries that will get all needed data in one go from the database.

The problem with mixing DDD and non-DDD approaches in the same Bounded Context is IMO consistency and future proofness. As soon as you find an invariant overlapping one aggregate and a transaction script, you'll have to transfer all the objects you're using in the transaction script over to the DDD realm which can be a significant rewrite.

Another option could be to create a separate Bounded Context - PersonalRelationships or something. But only you and your domain experts can tell if

  • This functional area is something that is likely to change independently from the rest

  • It would be worth the extra overhead in terms of separate database, maybe separate code repositories, builds and deployment process.

  • You're ready to accept that everything will happen in an eventually consistent way. For instance, a User that is removed from the system will not immediately be removed from the list of important users of another user. Also, if the chat system is in another BC, there will be a small delay until a user that you blocked can't chat with you. That sort of thing.

2

Hm, I'd say that it is absolutely plausible to model the user-user relationships as a property of a user. So if you queried the current user, you would have:

{
    userid: ...,
    otherAttributes: ...,
    blockedUsers: [userid1, userid2],
    importantUsers: [userId3, userid4]
}

Outside of the user context it would not make much sense, so it would perfectly fit in your user aggregate. User-chatroom relationships are equivalent.

  • But I have many things similar to this in users: blocked users, important users, flagged users. There is even a feature that lets a user assign an alias to another user which is also a user-user relationship. These lists can potentially be very long for an active user. It is sub-optimal to keep them all inside the user aggregate. Think about when a user clicks a button to block another user, it will trigger a full load of all these lists in the repository. – foresightyj Mar 6 '16 at 0:06

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.