DDD – Is Validation Application Logic or Domain Logic?

domain-driven-design

Suppose that we are modelling a form using DDD; the form may have certain kind of business rules associated with it – perhaps you will need to specify an income if you are not a student, and you are required to list your children if you indicate that you are married. And if you specified a country, then it should have a valid country.

Does this kind of validation lives in the domain or application layer? Some other issues I was considering:

  • Certain frameworks, such as Laravel, provides validation rules that can validate input before a request hits the controller. Does it break DDD if validation is done at that level?

  • For cases like determining whether the country is valid, usually I will just query a database table of all the countries in the world. However, in DDD, this is likely (from my understanding) to be done on the domain layer. Is the domain layer allowed to access the DB, or must I use a non-SQL search to determine a valid country?

  • Is it necessary to validate the input both at the application, and domain layer?

Best Answer

Does this kind of validation lives in the domain or application layer?

Application. The magic search term you want is anti corruption layer

Typically, the message received by your application will be some flavor of DTO. Your anti corruption layer will typically create value types that the domain will recognize. The actual command dispatched to the domain model will be expressed in terms of validated value types.

Example: a DepositMoney command would likely include an amount, and a currency type. The DTO representation would probably express the amount as an integer, and the currency code as a string. The anti corruption layer would convert the DTO into a Deposit value type, which would include a validated Amount (which must be non negative) and a validated CurrencyCode (which must be one of the supported codes in the domain).

Having successfully parsed the command into types the domain model understands, the command is executed in the domain, which may still reject the command on the grounds that it would violate the business invariant (the account doesn't exist yet, the account is blocked, this particular account isn't allowed to use that currency? etc).

In other words, the business validation is going to happen in the domain model, after the anti corruption layer validates the inputs.

The implementation of the validation rules will normally live either in the constructor of the value type, or within the factory method used to construct the value type. Basically, you restrict the construction of the objects so that they are guaranteed to be valid, isolating the logic in one place, and invoking it at the process boundaries.