I'm struggling with a basic issue. The project is in C#, but the issue is general.
I'm following the always valid object principle. As one example I have a product entity that has a mandatory property "ProductCategory". The allowed product categories are user defined and therefore persisted (in a database).
For type safety and better reading I defined Value Objects for various properties to encapsulate the business rules for those types. So there is a ProductCategory class. When creating a ProductCategory instance a factory method checks for example the max length of the string that is passed to the factory before creating the instance. This ensures that each instance of ProdcutCategory is valid.
Simple parameter checks like length are easy and straight forward. My question is where to implement the validation check against the possible values that are persisted. A repository for the allowed values hides the persistence technology and has a method Exists or IsValid.
Option 1) calling the repository from the application layer before calling the factory.
Here the domain layer has no dependency on the repository/infrastructure layer as many advocate. But the factory can't ensure a valid object anymore. It depends on the application layer that the business rule is implemented. Also each command that needs a ProductCategory has to check the repository, which violates DRY.
Option 2) calling the repository from the value object factory
Since factories are part of the domain layer the layer must have access to the repository, which introduces extra coupling. The benefit is that the business validity of ProductCategory is ensured by the object itself and can't be circumvented.
Is there another solution to this dilemma or are there any specific criteria that encourage one or the other option? Would it be OK, if the factory is programmed against an interface of the repository that is saved in the domain layer and only implemented by the repository in the infrastructure layer? I have tried to understand the different approaches, but in this case I feel lost.