Relatively new to Domain Driven Design i decided to try it out in an saas app currently under development/refactoring. I've refactored the identity part out to it's own context (class library in .net) and came up with the following Domain models:
- Organization. Is an Entity and Aggregate Root (all users in the system should be part of an organization) and Users can only by added through the Organization AR.
- User. Is an Entity referenced (List of User) by Organization (the user that is part of an Organization.
So one of the most important constraints is that a User should always be part of an Organization. At this point there aren't many business rules so the Domain Entities are realy simple at this point. I have multiple designs but cannot figure out what design is best in terms of encapsulation/performance (i know, don't optimize prematurely).
- Organization implements Users as child entities (object reference). In this way Users can only be added through the Organization AR giving full encapsulation. This design also makes it explicit that Users in this context should always be deleted when an Organization is deleted. Exactly what needs to be done. But now when i want to add a User i have to load the whole Organization AR (keeping invariants) including all Users within the Organization so i can check if a User doesn't exists already within the Organization. I don't see any problems with this approach but for large Organizations that can have hundreds of Users this can be resource intensive. Another approach within this design to ensure uniqueness is to update a read model (UniqueUser) when a User is added to an Organization. When the API tries to re-register a User than in the AfterLoginEnsureOrganization UseCase the User is first validated by the UniqueUser readmodel repository.
- Organization and User are both AR (User referencing Organization by OrganizationId) and the UseCase implements the constraints leaving us with no encapsulation whatsoever. Currently i'm the only developer for this app so no biggie but how to prevent other developers from adding orphan users by misusing the IUserRepository and not the specific UseCase.
I'm not sure where to make the trade-off between encapsulation, complexity and performance.