I am using strongly typed ids in my domain model, mostly following the guidance from Andrew Lock at:
https://andrewlock.net/using-strongly-typed-entity-ids-to-avoid-primitive-obsession-part-1/
These ids, e.g. ProductId, CustomerId, etc. are declared in the Domain Model.
My question is about exposing these to consumers of the Application layer. At the moment, an API controller could create a Command to send to the Application layer. These commands also needs to use Ids. My current implementation in the Command objects is use the primitive type, Guid, and then create a Strongly Typed Id when calling methods on the Domain Model.
However, it makes sense to extend the control offered by using strongly typed ids to communication between the API Controller and the Application Layer. But, I do not want my API Controllers to have a reference to the Domain Model (which is where the Strongly Typed Ids are declared at the moment).
How to go about this?
Declare a similar set of Strongly Typed Ids from the Application Layer. But this would still need a translation between the Application declaration and the Domain Model declaration before calling methods in the Domain.
Move the declaration of Ids into a 'public' module that both the API and Domain Model can reference. But this would mean some leakage of Domain Model dependencies to the API Controller dependencies and any change in my Domain Model approach may impact the API Controllers, which is not desirable.
The ask seems reasonable, but neither of the above solutions feel optimal. Any thoughts?
Having reviewed Vaughn Vernon's book "Implementing Domain-Driven Design":
I have followed the advice on page 580, which is basically "be pragmatic".
Specifically,
For Ids and any other value object that I consider pretty 'fixed' I have chosen to use a shared kernel that API, Application and Domain layers can use (i.e. option 2 from my question).
For other, potentially more complex, value objects that may contain additional business logic specific to the Domain and may be more volatile in response to business change, then I am using option 1 from my question and creating a slimmed down (DTO) version for exposing from the Application and performing mapping from those to the Domain Model versions.