In my service facade layer, I have a service class with a method/operation that accepts a DTO (data contract) object. AutoMapper is used to map this DTO into an instance of my domain object to apply any changes. The request is passed onto my domain service which does the actual work. Here's what the method might look like:
public EntityContract AddEntity(EntityContract requestContract)
{
var entity = Mapper.Map<EntityContract, Entity>(requestContract);
var updatedEntity = Service.AddEntity(entity);
var responseContract = Mapper.Map<Entity, EntityContract>(updatedEntity);
return responseContract;
}
The Service and Mapper properties are set using constructor injection with Unity as the IoC container.
In performing the operation, the domain service makes changes to the entity then uses a repository to persist the changes like:
public Entity AddEntity(Entity entity)
{
// Make changes to entity
Repository.Add(entity);
// Prepare return value
}
The Repository is also set using constructor injection.
The issue is that the data becomes immediately available to other clients once it has been persisted so I have to ensure that no invalid data is persisted. I've read the "blue book" of DDD (Evans) as well as Nilsson and am not clear what approach to validation I should take.
If my goal is to prevent the entity from entering an invalid state, should I validate entityContract in my service method to ensure all rules are satisfied before ever passing the request on to my domain service? I hesitate to do so because it seems like I'm breaking encapsulation having these rules defined in the service facade.
The reason we are using a thin facade layer delegating to domain services is that we are exposing course-grained interfaces in our API but support reuse via composition of the fine-grained domain services. Keeping in mind that multiple facade services may be calling the same domain service method, perhaps delegating these rules into the domain service would be better so we know every use is validated. Or should I validate in both places?
I could also put guards in the property setters that prevent unacceptable values from ever putting the entity into an invalid state. This would mean that AutoMapper would fail when trying to map an invalid value. However, it doesn't help when no value is mapped.
I still can't get past the thinking that these rules are part of the entity's behavior and determining if the object is valid should be encapsulated within the entity. Is this wrong?
So first I need to determine when and where I perform these validation checks. Then I need to figure out how to implement with DI so the dependencies are decoupled.
What suggestions can you provide?
I've read the "blue book" of DDD (Evans) as well as Nilsson and am not clear what approach to validation I should take.
Blue book approaches the problem from a different angle. I think that the term 'Validation' is not used because it is a dangerous overgeneralization. A better approach is to think about object invariants, not validation. Objects (not only in DDD) should enforce their internal invariants themselves. It is not UI or services or contracts or mappers or 'validation frameworks' or anything else that is external to the objects. Invariants are enforced internally. You may find these answers helpfull: 1, 2, 3, 4.
I could also put guards in the property setters that prevent unacceptable values from ever putting the entity into an invalid state. This would mean that AutoMapper would fail when trying to map an invalid value.
You probably should not care about AutoMapper failing or using AutoMapper at all. Domain objects should encapsulate and enforce their internal invariants and throw exception if the attempt to break it is made. It is very simple and you should not compromise the simplicity and expressiveness of your domain objects because of some infrastructural issues. The goal of DDD is not to satisfy AutoMapper's or any other framework's requirements. If the framework does not work with your domain objects don't use it.
You have two types of validation:
Object consistency: is the responsibility of entities. Entities should not allow you to set them to invalid state, dependencies should be enforced, values should be in range. you have to design classes' methods and properties and constructors not to allow invalid state.
Business roles validation: this type of validation requires server processing, like checking id availability, email uniqueness and the so. these types of validations should be processed in server as Validators or Specifications before persistence.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With