5

Let's say that I have two bounded contexts, Billing and Shipping.

In Billing Bounded Context I have this:

class Account {
    private $id;
    private $address;
    private $zipCode;
    private $city;
    private $postbox;
}

And in the Shipping Bounded Context i have this:

class Recipient {
    private $id;
    private $address;
    private $zipCode;
    private $city;
    private $doorCode;
}

So now, the 2 models, as we all know relate to another a User in some other bounded context.

Should the Account and Recipient share the same id and this id would come from User Model.

Do I have to add a field in these models called $userId in addition to accountId and recipientId?

Thibssss13
  • 51
  • 2
  • I’m voting to close this question because as a design question rather than an implementation one, I think it would be better suited for the sister site https://softwareengineering.stackexchange.com/ - although do check their help pages for tips on how to write a question which will be well received there. – IMSoP Sep 18 '20 at 14:26
  • 1
    @IMSoP This question seems to be an implementation one, in my opinion. I mean, it's not about the DDD concept itself, but about implementing DDD principles in a real application. If I am wrong, please let me know. – Andrei Prigorshnev Sep 22 '20 at 09:08
  • @AndrewPrigorshnev I meant "design" in the sense of "deciding whether to do something", as opposed to "implementation" in the sense of "writing some code in a particular language or framework". Although tagged PHP, it feels to me like this is really about clarifying a principle of DDD itself, and I feel like that would fit better on SE.SE – IMSoP Sep 22 '20 at 09:24
  • @IMSoP I agree that tag PHP can be considered as redundant here. – Andrei Prigorshnev Sep 23 '20 at 07:09

2 Answers2

5

From the DDD perspective, you should add a field userId to Account and Recipient.

The reason is that Recipient, Account and User are entities. It means they should have their own identity. Even if your User always has only one Account, it doesn't mean that User is Account, so they cannot share the same id.

Additionally, it could be better to have the possibility of having several accounts for one user from the very beginning. Let's say a user decides to remove his account. In this case, I guess you shouldn't remove his past orders, so you shouldn't remove a User itself. You should remove a user's Account only.

If in the future, the same user decides to create a new Account, you could literally create a new one and have an old inactivated account and a new active account in your database.

However, I can imagine a design when you decide to use the same Id for these entities for some reason, even though it doesn't fit well with DDD principles. But if you decide to do so, it's better to use a clear name for the id field. Instead of just:

class Account {
    private $id;
    private $address;
}

you'd better have:

class Account {
    private $userId; // if it's userId we should express it explicitly in the name
    private $address;
}
  • Thank you for your answer. Another question is: Should the userId value object be in the User Context and be shared in others context or every bounded context should have their own VO's ? – Thibssss13 Sep 23 '20 at 11:04
  • @Thibssss13 Normally every bounded context should have its own VO. You shouldn't have direct references from the domain layer of one bounded context to the domain layer of another one. So you cannot declare VO or entity in one domain and just reuse it in another one. When entities and VO's is crossing boundaries of bounded contexts, you should use a context mapping. It's the best option in my opinion. But if you want to share some models you have an option. It is [shared kernel](https://stackoverflow.com/questions/42562820/ddd-shared-kernel-or-pure-event-driven-microservices). – Andrei Prigorshnev Sep 23 '20 at 12:39
  • @Thibssss13 and take into account that using value objects for identifiers is just an option. You can use `long` or something as well. – Andrei Prigorshnev Sep 23 '20 at 12:42
  • Hi, thanks to i make a lot of changes and now i feel like everything is in place. The only thing is want to use context mapping but i don't know how to implement that. Do you have any examples code, suggestions, articles, doc to help me? Thank you – Thibssss13 Oct 12 '20 at 15:19
  • @Thibssss13 [here](https://github.com/citerus/dddsample-core/blob/master/src/main/java/se/citerus/dddsample/infrastructure/routing/ExternalRoutingService.java) is an example of a service which gets data from another bounded context and maps it to the own domain model. Specifically, `toItinerary()` method is doing mapping there. It maps the external model `TransitPath` to the local model `Itinerary`. – Andrei Prigorshnev Oct 12 '20 at 16:35
0

Yes, referencing the user id from the User context as some external id in your other contexts (here in the Account and Recipient entities) is a valid approach.

You can even think if using some custom value object class that represents the user reference in your other contexts. With that you have strong typing for the reference to the user rather than simply using a string.

Andreas Hütter
  • 3,288
  • 1
  • 11
  • 19