I have a question about DDD. I'm building a application to learn DDD and I have a question about layering. I have an application that works like this:
UI layer calls => Application Layer -> Domain Layer -> Database
Here is a small example of how the code looks:
//****************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
...
}
开发者_运维百科 }
I've seem to put most of my business rules in services rather than the models and I'm not sure if this is correct? Also, i'm not completely sure if I have the laying correct? Do I have the right pieces in the correct place? Also should my models leave my domain model? In general I'm I doing this correct according DDD?
Thanks!
When you ask
Should my models leave my domain model?
I would say that if at all possible you should work to avoid shuffling data back and forth between different sets of objects in one program. Doing that would result in you going through a lot of tedium writing a lot of boring and error-prone code, you will have a redundant set of DTO objects that have to mirror your domain objects, also you get less mileage out of the methods you write because they only operate on either the DTOs or domain objects. All in all it is very painful and doesn't accomplish much. I try to have one set of domain objects that is passed around throughout the application.
(That doesn't mean there aren't cases where you really have a need to move data between different sets of objects, like when building an anti-corruption layer. Just don't go looking for trouble if it's not absolutely necessary.)
As for
IShoppingCart shoppingCart = repository.GetShoppingCartByUserName(username);
//Do shopping cart logic like calculating taxes and stuff
//I would put these in services but not sure?
one of the goals of Domain-Driven Design is to try to separate business logic from infrastructure code. Whatever you can figure out how to calculate using only the domain objects is better off going into the domain model, where you can write tests for it that do not involve the database. I would want to have the service pull an aggregate of domain objects, then have the business logic calculations happen in the domain objects, then have the service save the state changes that the calculations brought about in the domain objects.
DDD works best when services (application layer) expose only commands on domain objects, not the objects themselves.
In you example I would create a service method like Purchase(strng productName, int quantity) which internally would get a ShoppingCart from Repository (don't have to use interface here) get a Product (by its name) from Repository and call cart.AddProduct(product, quantity)
not, the business logic of adding products to cart, calculating total amount, total weight or other business stuff is encapsulated in the mode.
You should have one thin layer between domain objects and services to manipulate with domain objects (recommended by Eric Evans). This object name is usually ending on “Manager”. For example PurchaseManager or similar. All logic that connect different domain objects (user, purchase, address …) is in this object.
- Service call Manager.GetSomething()
- Manager get data from different repositories, do business logic and return result
- Manger Return Result but never return domain objects itself ! If you have domain object called User you should stick with naming convention you invent and map User to UserDataContract or similar. Don’t expose domain objects. It is extra work but you should not couple your domain model with UI.
- Many times domain object has methods to do some business logic
Regarding your question:
"I've seem to put most of my business rules in services rather than the models and I'm not sure if this is correct?"
If a business rule, does not access other resources (database, services, domain objects), you can have the rule in the domain object itself. If it does access other resources then you should put them in domain services.
精彩评论