resueltos online modelo modelado introduccion herencia entre ejercicios dominio domain diferencia diagrama clases analisis language-agnostic domain-driven-design ddd-repositories

language-agnostic - online - modelo de dominio introduccion



Al trabajar con modelos de dominio y clases de POCO, ¿a dónde van las consultas? (5)

Soy nuevo en los modelos de dominio, POCO y DDD, por lo que todavía estoy tratando de entender algunas ideas.

Una de las cosas que no pude entender todavía es cómo mantener mis modelos de dominio simples y agnósticos en cuanto al almacenamiento, pero aún así poder realizar algunas consultas sobre sus datos de manera enriquecedora.

Por ejemplo, supongamos que tengo un Pedido de entidad que tiene una colección de Elementos de Ordem. Quiero obtener el artículo más barato, por cualquier razón, o tal vez una lista de artículos de pedido que no están actualmente en stock. Lo que no quiero hacer es recuperar todos los artículos de pedido del almacenamiento y filtrarlos más tarde (demasiado caros), así que quiero terminar teniendo una consulta db del tipo "SELECCIONAR ... DONDE ITEM.INSTOCK = FALSE" de alguna manera. No quiero tener esa consulta SQL en mi entidad, o cualquier variación de si eso me atara a una plataforma específica, como las consultas de NHibernate en Linq2SQL. ¿Cuál es la solución común en ese caso?


Según entiendo este estilo de diseño, encapsularía la consulta en un método de un objeto OrderItemRepository (o quizás más adecuado OrderRepository), cuya responsabilidad es hablar con el DB por un lado, y devolver objetos OrderItem del otro lado. El repositorio oculta detalles de la base de datos de los consumidores de instancias de OrderItem.


En la capa de servicio.


Las entidades son las "unidades" de un dominio. Los repositorios y servicios hacen referencia a ellos , no al revés. Piénselo de esta manera: ¿lleva el DMV en su bolsillo?

OrderItem no es una raíz agregada; no debería ser accesible a través de un repositorio. Su identidad es local a una Order , lo que significa que una Order siempre estará en el alcance cuando se habla de OrderItem s.

La dificultad de encontrar un hogar para las consultas me lleva a pensar en los servicios. En este caso, representarían algo acerca de una Order que es difícil que una Order misma conozca.

Declara la intención en el proyecto de dominio:

public interface ICheapestItemService { OrderItem GetCheapestItem(Order order); } public interface IInventoryService { IEnumerable<OrderItem> GetOutOfStockItems(Order order); }

Declarar la implementación en el proyecto de datos:

public class CheapestItemService : ICheapestItemService { private IQueryable<OrderItem> _orderItems; public CheapestItemService(IQueryable<OrderItem> orderItems) { _orderItems = orderItems; } public OrderItem GetCheapestItem(Order order) { var itemsByPrice = from item in _orderItems where item.Order == order orderby item.Price select item; return itemsByPrice.FirstOrDefault(); } } public class InventoryService : IInventoryService { private IQueryable<OrderItem> _orderItems; public InventoryService(IQueryable<OrderItem> orderItems) { _orderItems = orderItems; } public IEnumerable<OrderItem> GetOutOfStockItems(Order order) { return _orderItems.Where(item => item.Order == order && !item.InStock); } }

Este ejemplo funciona con cualquier proveedor de LINQ. Alternativamente, el proyecto de datos podría usar ISession e ICriteria de ICriteria para hacer el trabajo sucio.


Los objetos de dominio deben ser independientes del almacenamiento, debe usar el patrón Repostiory o DAO para conservar los objetos. De esa manera está imponiendo la separación de las preocupaciones, el objeto en sí mismo no debería saber cómo se almacena.

Idealmente, sería una buena idea poner construcción de consultas dentro del repositorio, aunque usaría un ORM allí.

Aquí está la definición de Martin Fowler del patrón de repositorio.


Yo diría que no tiene sentido hablar de "una Orden que contiene solo los artículos de pedido que no están en stock". Una "Orden" (supongo) representa la lista completa de lo que haya ordenado el cliente; Si está filtrando esa lista, ya no está tratando con un Pedido per se, se trata de una lista filtrada de Artículos de pedido.

Creo que la pregunta es si realmente quieres tratar los pedidos como una raíz agregada , o si también quieres extraer listas arbitrarias de artículos de pedido de tu capa de acceso a datos.

Has dicho que filtrar elementos después de que hayan vuelto de la base de datos sería demasiado caro, pero a menos que promedies cientos o miles de artículos de pedido para cada pedido (o hay algo más especialmente intenso en el trato con muchos artículos de pedido), puedes tratar de optimizar prematuramente y hacer las cosas más difíciles de lo que deben ser. Creo que si puede dejar Order como raíz y filtro agregados en la lógica de su dominio, su modelo será más limpio para trabajar.

Si realmente no es el caso y necesita filtrar en la base de datos, entonces puede considerar tener un repositorio de artículo de pedido por separado que proporcione consultas como "darme todos los artículos de pedido para este pedido que no están en stock". Luego los devolverá como IList<OrderItem> (o IEnumerable<OrderItem> ), ya que no son un Pedido completo, sino más bien una colección filtrada de Artículos de pedido.