Search code examples
domain-driven-designcqrsevent-sourcing

How/where to load value object that is entity in different BC in DDD and CQRS/ES based system


I have gone through this great tutorial: http://www.cqrs.nu/tutorial/cs/01-design and trying to do my app same way.

According to my previous questions I know, that what is entity in one BC can be represented as value object containing identifier of entity in other BC and optionally any other parameter. (I put those identifiers to Core BC.)

Now, let's say I have two BC: PlansEditor and Subscribing.

In PlansEditor, given there is Editor (person with role), when he creates Plan with some params like frequency and vip, then Plan is created.

In Subscribing, given there is Customer and some available Plans, when customer subscribes to a Plan, then Subscription is created.

Plans here could be just VO with frequency and VIP parameters, because Subscription needs just them (to protect invariants). But customer clicks to subscribe to a plan and request with id of plan is sent.

So I start my BC lifecycle with id of customer and id of plan he subscribed to. I need to load/create that Plan "value object" (which is really entity in PlansEditor BC) by given identifier somewhere.

Where and how should I acquire that Plan VO in Subscribing BC?

I thought in application layer through Event Repository - to be able to send SubscribeCustomerToPlanCommand(Customer, Plan) containing this value object. But Subscribing BC would then need to know that Plan as entity in PlansEditor exists in order to load it and translate it to Plan as VO, which is unacceptable - one BC would need other to function properly.

Or should I just get informations needed to create Plan VO from some read model and do that in application layer, is that convenient? Or how and where? :)


Solution

  • As far as I can tell Plan wouldn't be a VO in either contexts. It's not because one BC has the authority on an entity's life cycle that the entity becomes a VO in other contexts (it could).

    If the downstream context needs to stay aware of the lifecycle of an entity in a remote context then this entity should probably be modeled as an entity in the downstream context as well.

    For instance, I suppose that Plans can be deactivated at some point that and it wouldn't make sense to allow subscribing to these? That would be a good indicator that Plan is not a simple value in the Subscribing context.

    There are multiple strategies when it comes to BCs integration, but if you favor availability over consistency then messaging is most likely the better option. The upstream context would publish events on a messaging infrastructure and these would get consumed by the downstream context, allowing it to keep it's local copy of the entity state in sync.

    "BC would then need to know that Plan as entity in PlansEditor exists in order to load it and translate it to Plan as VO, which is unacceptable - one BC would need other to function properly"

    Any integration strategy will require some level of coupling, but that coupling should be abstracted away in an anti-corruption layer.