Llevo 8 años adaptando el diseño basado en dominios e incluso después de todos estos años, todavía hay una cosa que me ha estado molestando. Es verificar un registro único en el almacenamiento de datos contra un objeto de dominio.
En septiembre de 2013, Martin Fowler mencionó el principio TellDon'tAsk , que, si es posible, debería aplicarse a todos los objetos de dominio, que luego deberían devolver un mensaje, cómo fue la operación (en el diseño orientado a objetos, esto se hace principalmente a través de excepciones, cuando la operación no tuvo éxito).
Mis proyectos generalmente se dividen en muchas partes, donde dos de ellos son Dominio (que contiene reglas comerciales y nada más, el dominio es completamente ignorante de persistencia) y Servicios. Servicios que conocen la capa de repositorio utilizada para datos CRUD.
Debido a que la singularidad de un atributo que pertenece a un objeto es una regla de dominio / negocio, el módulo de dominio debería ser largo, por lo que la regla es exactamente donde se supone que debe estar.
Para poder verificar la unicidad de un registro, debe consultar el conjunto de datos actual, generalmente una base de datos, para averiguar si Name
ya existe otro registro con un digamos .
Teniendo en cuenta que la capa de dominio ignora la persistencia y no tiene idea de cómo recuperar los datos, sino solo cómo realizar operaciones en ellos, realmente no puede tocar los repositorios en sí.
El diseño que he estado adaptando se ve así:
class ProductRepository
{
// throws Repository.RecordNotFoundException
public Product GetBySKU(string sku);
}
class ProductCrudService
{
private ProductRepository pr;
public ProductCrudService(ProductRepository repository)
{
pr = repository;
}
public void SaveProduct(Domain.Product product)
{
try {
pr.GetBySKU(product.SKU);
throw Service.ProductWithSKUAlreadyExistsException("msg");
} catch (Repository.RecordNotFoundException e) {
// suppress/log exception
}
pr.MarkFresh(product);
pr.ProcessChanges();
}
}
Esto lleva a que los servicios definan reglas de dominio en lugar de la capa de dominio en sí y que las reglas estén dispersas en varias secciones de su código.
Mencioné el principio de TellDon'tAsk, porque como puedes ver claramente, el servicio ofrece una acción (guarda Product
o arroja una excepción), pero dentro del método estás operando objetos usando un enfoque de procedimiento.
La solución obvia es crear una Domain.ProductCollection
clase con un Add(Domain.Product)
método que arroje ProductWithSKUAlreadyExistsException
, pero le falta mucho rendimiento, porque necesitaría obtener todos los Productos del almacenamiento de datos para averiguar en código, si un Producto ya tiene el mismo SKU como el Producto que intentas agregar.
¿Cómo resuelven este problema específico? Esto no es realmente un problema per se, he tenido la capa de servicio que representa ciertas reglas de dominio durante años. La capa de servicio por lo general también sirve para operaciones de dominio más complejas, simplemente me pregunto si ha encontrado una solución mejor y más centralizada durante su carrera.