I often run into this decision making scenario of where to call a Domain (or Application Service) when building my Domain Models. Maybe the confusion is in identifying whether this is a Domain service or an Application service itself. I would love to see what others think. I'll try my best to explain this with a simple scenario, and pose additional examples that I run into.
Imagine an Address Domain Model. It has the following items:
Now I have a constructor defined like so:
Address(string addressLine1, string addressLine2, string city, string stateProvinceCode, string countryCode, string zipCode)
I need to ensure that the State Province code being passed matches a state province in the Country. If I had a database of cities, I would also like to match the City as well as the ZIP code.
In scenarios like these, how do I best solve this? Here are my options:
- I keep the constructor super simple, there should be no reason why someone can't stuff whatever data they want to build the Address Object. I then create a method called Validate() in the Domain model which accepts an IAddressValidator which knows how to validate the data.
The implementation of IAddressValidator can be implementation specific.
Alternatively, I introduce the IAddressValidator as a part of the constructor. The problem with this approach is that now everyone wanting to use the Address domain (no matter for whatever rudimentary reasons) now has to worry about building the IAddressValidator implementation.
Do not have IAddressValidator/Validate in the Domain at all. Assume that the Domain will be populated by an Application Service, say AddressService which does the job of validating all of the data and then populating the address model which can later be persisted to the database. This also means that if someone doesn't call the Address Service to do the validations, they risk saving invalid data in the Address.
Likewise, I have a lot of similar scenarios where I feel like I don't know where the best place to validate incoming data is.
An example where a user answers survey questions. Each Question has potential answer options that need to be validated before the answer is added to a survey. Does this validation belong at the domain level i.e. should I do SaveAnswer(Answer answer, IAnswerValidator validator)? Or at Service level using IAnswerValidator to first validate the answer and then simply call SaveAnswer(Answer answer) in the domain assuming that all validation will be done by service layer?
E-Commerce Scenario, when an Item is added to cart and we also need to validate if inventory exists. Should we pass the inventory checker interface to the domain like so: AddItem(CartItem item, IInventoryChecker checker)? Or should we do it at a service level and leave the domain with a simple AddItem(CartItem item) method.