2010-04-16 12 views
5

Tengo una pregunta sobre DDD. Estoy compilando una aplicación para aprender DDD y tengo una pregunta sobre capas. Tengo una aplicación que funciona así:Definición de capas de aplicación en Domain-Driven-Design

llamadas capa de interfaz de usuario => Capa de aplicación -> Capa de Dominio -> base de datos

Aquí está un pequeño ejemplo de cómo se ve el código:

//****************UI LAYER************************ 
//Uses Ioc to get the service from the factory. 
//This factory would be in the MyApp.Infrastructure.dll 
IImplementationFactory factory = new ImplementationFactory(); 

//Interface and implementation for Shopping Cart service would be in MyApp.ApplicationLayer.dll 
    IShoppingCartService service = factory.GetImplementationFactory<IShoppingCartService>(); 

    //This is the UI layer, 
    //Calling into Application Layer 
    //to get the shopping cart for a user. 

    //Interface for IShoppingCart would be in MyApp.ApplicationLayer.dll 
    //and implementation for IShoppingCart would be in MyApp.Model. 
    IShoppingCart shoppingCart = service.GetShoppingCartByUserName(userName); 

    //Show shopping cart information. 
    //For example, items bought, price, taxes..etc 
    ... 

    //Pressed Purchase button, so even for when 
    //button is pressed. 
    //Uses Ioc to get the service from the factory again. 
    IImplementationFactory factory = new ImplementationFactory(); 
    IShoppingCartService service = factory.GetImplementationFactory<IShoppingCartService>(); 
    service.Purchase(shoppingCart); 


    //**********************Application Layer********************** 
    public class ShoppingCartService : IShoppingCartService 
    { 
     public IShoppingCart GetShoppingCartByUserName(string userName) 
     { 
      //Uses Ioc to get the service from the factory. 
      //This factory would be in the MyApp.Infrastructure.dll 
      IImplementationFactory factory = new ImplementationFactory(); 

      //Interface for repository would be in MyApp.Infrastructure.dll 
      //but implementation would by in MyApp.Model.dll 
      IShoppingCartRepository repository = factory.GetImplementationFactory<IShoppingCartRepository>(); 

      IShoppingCart shoppingCart = repository.GetShoppingCartByUserName(username); 
      //Do shopping cart logic like calculating taxes and stuff 
      //I would put these in services but not sure? 
      ... 

      return shoppingCart; 
     } 

     public void Purchase(IShoppingCart shoppingCart) 
     { 
      //Do Purchase logic and calling out to repository 
      ... 
     } 
    } 

Parece que he puesto la mayoría de mis reglas comerciales en los servicios en lugar de los modelos y no estoy seguro de si esto es correcto. Además, no estoy completamente seguro si tengo la colocación correcta? ¿Tengo las piezas correctas en el lugar correcto? ¿También deberían mis modelos dejar mi modelo de dominio? En general, ¿estoy haciendo esto correctamente según DDD?

Gracias!

+0

me queda bien !!! –

Respuesta

2

DDD funciona mejor cuando los servicios (capa de aplicación) exponen solo los comandos en objetos de dominio, no los objetos mismos.

En ti ejemplo, me gustaría crear un método de servicio como de Compra (Strng productName, cantidad int), que internamente se obtener una ShoppingCart del repositorio (no tiene que utilizar el interfaz aquí) obtener un producto (por su nombre) del Repositorio y call cart.AddProduct (producto, cantidad)

no, la lógica comercial de agregar productos al carro, calcular la cantidad total, el peso total u otras cosas de negocios se encapsula en el modo.

+0

Gracias por su respuesta. ¿Entonces los servicios deberían ser estáticos y vivir en la capa de aplicación? Pensé que los servicios deberían implementar una interfaz porque hace que sea más fácil de probar. Además, ¿quién es responsable de llamar a la lógica empresarial como calcular el importe total? ¿El repositorio hace eso? –

+1

Si llama a AddProduct en un carro, este carrito es responsable de mantener su propia consistencia por lo que debe actualizar cualquier información que deba actualizarse (como la cantidad total). Sí, es bueno implementar la interfaz en los servicios, pero dado que DDD dice que no se debe colocar la lógica comercial en los servicios, son candidatos pobres para las pruebas. Pero las interfaces son útiles cuando se hace programación orientada a aspectos. Solía ​​interceptar la invocación de mis servicios y, en un aviso de AOP, comencé/confirmaba la transacción en la base de datos, registraba cualquier excepción y así sucesivamente. –

3

Cuando se le pregunta

En caso de mis modelos de dejar mi modelo de dominio?

Yo diría que, si es posible, debe trabajar para evitar mezclar datos entre diferentes conjuntos de objetos en un programa. Si lo hace, tendrá que pasar por un tedio escribiendo un código aburrido y propenso a errores, tendrá un conjunto redundante de objetos DTO que tendrán que reflejar los objetos de su dominio, también obtendrá menos rendimiento de los métodos que escriba porque solo operan en DTO u objetos de dominio. En general, es muy doloroso y no logra mucho. Intento tener un conjunto de objetos de dominio que se pasan a través de la aplicación.

(Eso no significa que no haya casos en los que realmente tenga que mover datos entre diferentes conjuntos de objetos, como cuando se construye una capa anticorrupción. Simplemente no busque problemas si no es así absolutamente necesario.)

en cuanto a

IShoppingCart shoppingCart = repository.GetShoppingCartByUserName(username); 
//Do shopping cart logic like calculating taxes and stuff 
//I would put these in services but not sure? 

uno de los objetivos de Driven Design-dominio es tratar de lógica de negocio separada de código de infraestructura. Lo que sea que pueda averiguar cómo calcular usando solo los objetos de dominio, es mejor entrar al modelo de dominio, donde puede escribir pruebas que no involucren la base de datos. Me gustaría que el servicio extrajera un agregado de objetos de dominio, luego hiciera que los cálculos de lógica de negocios ocurrieran en los objetos de dominio, y luego el servicio guardara los cambios de estado que los cálculos generaban en los objetos de dominio.

1

Debe tener una capa delgada entre objetos de dominio y servicios para manipular con objetos de dominio (recomendado por Eric Evans). Este nombre de objeto generalmente termina en "Administrador". Por ejemplo, PurchaseManager o similar. Toda la lógica que conecta diferentes objetos de dominio (usuario, compra, dirección ...) está en este objeto.

  • Servicio de llamada Manager.GetSomething()
  • Director de obtener datos de diferentes repositorios, hacer la lógica de negocio y el resultado
  • Manger devolver resultado volver pero nunca devolver los objetos de dominio de sí mismo! Si tiene un objeto de dominio llamado Usuario, debe seguir con la convención de nomenclatura, invente y asigne Usuario a UserDataContract o similar. No exponer objetos de dominio. Es un trabajo extra, pero no debe acoplar su modelo de dominio con la IU.
  • Muchas veces dominio objeto tiene métodos para hacer algo de lógica de negocio
+2

¿Podría ser específico acerca de dónde proviene la recomendación de Eric Evans de la que hace referencia? No recuerdo nada como esto en su libro (es posible que me haya perdido algo, obviamente). –

+0

Encontré esto como una referencia en uno de mis documentos (no tengo libro en este momento): Existen operaciones de dominio importantes que no pueden encontrar un hogar natural en un objeto Entity o Value. Dado que nuestro paradigma de modelado es objetos, debemos tratar de encajarlos en objetos. Algunas veces forzamos esas operaciones en un objeto apropiado, deslizándonos gradualmente hacia la programación de procedimientos. Terminamos con objetos que levantan nombres que terminan en "Administrador". No tienen ningún estado propio ni significado en el dominio más allá de la operación que albergan. –

+2

si no me equivoco, Evans está describiendo un * anti-patrón * en esa sección, no lo recomienda. Reconoce que hay * ocasionalmente * operaciones que no se ajustan a los objetos de dominio, en cuyo caso es apropiado poner esas operaciones en un servicio, pero recomendamos encarecidamente que tratemos de evitar eso y nos esforcemos por poner la lógica en nuestro modelo de dominio. –

0

cuanto a su pregunta:

"He parece que poner la mayor parte de mis reglas de negocio en los servicios en lugar de los modelos y No estoy seguro de si esto es correcto? "

Si una regla empresarial no accede a otros recursos (base de datos, servicios, objetos de dominio), puede tener la regla en el propio objeto de dominio. Si accede a otros recursos, debe ponerlos en servicios de dominio.

Cuestiones relacionadas