我在刚接触ABP的时候一直有一个疑问——有了应用服务,为什么还需要领域服务呢?
领域服务和应用服务对比
领域服务 | 应用服务 | |
---|---|---|
返回值 | Entity | DTO |
被表现层调用 | 不可以(非强制) | 可以 |
在ABP里面不是强制要使用领域服务的,但使用领域服务是个比较好的实践。
什么时候使用领域服务?
- 处理的是业务,而非场景(use-case)
- 要对Entity的状态修改加限制
举例
栗子 电商的商品扣除库存
假设我们写在应用层
定义以下应用服务:
可能会造成的问题:public interface IStockApplication { ... bool Reduce(ProductDto product, int qty); } public interface IOrderApplication { ... void Submit(OrderDto order); }
- 扣库存这个业务就会暴露给表现层,造成表现层可能出现直接调用的情况,这是应该避免的。
- 开发Submit方法的技术人员不知道IStockApplication.Reduce,而是直接操作Product实体
解决问题:
将Product实体的Stock属性设置为只读,定义领域服务
public class Product
{
...
//库存
public int Stock{get; protected set;}
//保留库存
public int RetainStock{get;set;}
internal bool Reduce(int qty)
{
//检查库存
if(RetainStock > Stock-qty)
return false;
Stock-=qty;
}
}
public interface IStockDoman
{
...
bool Reduce(ProductDto product, int qty);
}
public class StockDoman:IStockDoman
{
...
bool Reduce(Product product, int qty)
{
...
product.Reduce(qty);
...
return true;
}
}
public interface IOrderApplication
{
...
void Submit(OrderDto order);
}
这样就有效的避免了上述问题