Domain driven design 存储库引发事件和注入依赖项

Domain driven design 存储库引发事件和注入依赖项,domain-driven-design,ddd-repositories,Domain Driven Design,Ddd Repositories,请查看以下存储库。对于DDD规则,存储库可以注入一些依赖项并引发事件吗?我读到存储库通常属于基础设施,不应该做这样的事情。你认为这种方法怎么样? 也许最好在域服务中包装存储库调用,并在其中执行事件源和依赖注入?: public class JpaOrderRepository implements OrderRepository{ @Inject Private RebatePolicyFactory rebatePolicyFactory; @Inject Private Injecto

请查看以下存储库。对于DDD规则,存储库可以注入一些依赖项并引发事件吗?我读到存储库通常属于基础设施,不应该做这样的事情。你认为这种方法怎么样? 也许最好在域服务中包装存储库调用,并在其中执行事件源和依赖注入?:

public class JpaOrderRepository implements OrderRepository{

@Inject 
Private RebatePolicyFactory rebatePolicyFactory;
@Inject 
Private InjectorHelper injector;
@Inject 
DomainEventPublisher eventPublisher;

public  void persist(Order order) {
 super.persist(order);
 eventPublisher.publish(new OrderCreatedEvent(order.getEntityId())); // !! **Events**
}

Public  Order load(OderId orderId) {
 Order order = super.load(orderId);
 injector.injectDependencies(order);
 order.setRebatePolicy(rebatePolicyFactory.createRebatePolicy()); // !! **Dependencies**
 return order;
}


}

存储库中获取的代码是DDD模式,它表示您需要一个行为类似于集合的抽象来封装更改数据的操作。在更改数据之前,应仅使用存储库加载数据

比如:

public class AnApplicationService
{
    public void addItemToOrder(orderId, item)
    {
        Order order = repo.load = (orderId);
        order.AddItem(item); // You could publish the event inside AddItem if you prefered
        repo.persist(order);
        eventPublisher.publish(new ItemAddedToOrderEvent(orderId));
    }
}
如果您需要检索订单,因为您想向用户显示有关订单的信息,但不需要修改订单,那么不应该使用存储库模式。你需要用别的东西

public class AnApplicationService
{
    public ReadOnlyOrder GetOrder(orderId)
    {
        ReadOnlyOrder order = finder.findReadOnlyOrderById(orderId);
        /* You could put those 3 lines inside your finder.findReadOnlyOrderById implementation if you prefer */
        injector.injectDependencies(order);
        order.setRebatePolicy(rebatePolicyFactory.createRebatePolicy());
        return order;
    }
}
否则,我认为您没有处理足够的抽象。在核心中,您需要所有存储库、finder和eventPublisher的接口

public interface IOrderRepository
{
     void persist(Order order);
     Order load(OrderId orderId);
}
public interface IFinder
{
     ReadOnlyOrder findReadOnlyOrderById(OrderId orderId);
}
public interface IEventPublisher
{
     void publish(IEvent event);
}
现在,在您的基础设施中,您可以创建扩展这些接口的具体类。您可以自由地使这些依赖项以DI方式获取依赖项,并让它们发布事件。但代码的其他地方应该使用接口,而不是这些具体的实现。类似地,您的repo应该被注入一个IEventPublisher和一个IRebatePolicySetter,以便它依赖于抽象,而不是实现

public interface IRebatePolicySetter
{
     void setPolicyOnOrder(Order order);
}

public class RebatePolicySetter implements IRebatePolicySetter
{
     @Inject 
     Private RebatePolicyFactory rebatePolicyFactory;
     @Inject 
     Private InjectorHelper injector;

     void setPolicyOnOrder(Order order)
     {
          injector.injectDependencies(order);
          order.setRebatePolicy(rebatePolicyFactory.createRebatePolicy());
     }
}

public class JpaOrderRepository implements OrderRepository, IOrderRepository
{
    @Inject 
    Private IRebatePolicySetter rebatePolicySetter;
    @Inject
    IEventPublisher eventPublisher;

    public  void persist(Order order)
    {
         super.persist(order);
         eventPublisher.publish(new OrderCreatedEvent(order.getEntityId())); // This is ok in my book, as long as eventPublisher is an interface.
    }

    Public  Order load(OderId orderId)
    {
        Order order = super.load(orderId);
        rebatePolicySetter.setPolicyOnOrder(order);
        return order;
    }
}
话虽如此,在基础架构代码中,您可以拥有任意多的依赖项。你可能不应该,尽量限制他们,这就是我在这里做的。但是,如果repo需要这些东西来执行其工作,那么在repo中注入依赖项是可以的。不过,您不希望您的业务逻辑依赖于事物,所以您应该让它们使用接口

但请记住

注意:您的persist方法似乎只执行创建添加。如果您也使用它进行更新,您的OrderCreatedEvent不是很混乱吗


注2:为什么再就业政策来自工厂?订单折扣政策的信息不应该来自持久层吗?

存储库属于域层,其实现属于基础架构层。我觉得这个不错。但通常不建议将依赖项注入模型。是的,接口属于域,实现属于基础结构。不建议使用DI,那么事件源呢?我认为您在这里脱离了DDD的整个要点。您的问题中有一个实现,但没有要求。您试图解决的业务问题是什么?我听说存储库的实现不属于这个领域,因为它通常与基础架构相耦合。问题是:在某些方面(属于基础设施的内容)设置依赖项或生成域事件可以吗?根据洋葱/六角形结构,它是允许的。