有些东西一直困扰着我的DDD读数。从我所看到的情况来看,似乎我的系统中每个给定的聚合根类型只有一个存储库实例。
例如,考虑以下想象的情况作为更深层域模型的抽象:
当以“标准风格”编码时,我会认为我系统中的每个Owner
都有自己的汽车集合,因此会有相同数量的Car
集合(应该我称之为存储库?),因为有Owner
个。但是,如前所述,似乎在DDD中我应该只在整个系统中有一个 CarRepository
(我已经看过将它们作为静态类访问的示例),以及要做一些简单的操作,例如将汽车添加到Owner
,我应该使用域服务,对于简单的情况,这似乎不太适合API。
我是否正确只在我的系统中实例化一个CarRepository
(Singleton),或者我错过了什么?我想争取像
public void an_owner_has_cars() throws Exception {
Owner owner = new Owner(new OwnerId(1));
CarId carId = new CarId(1);
Car car = new Car(carId);
owner.addCar(car);
Assert.assertEquals(car, owner.getCarOf(carId));
}
但如果没有将存储库注入Owner
,这似乎是不可能的,这似乎是一种被禁止的东西。
答案 0 :(得分:2)
存储库不代表属于另一个实体的集合。我们的想法是它代表整个实体集合。
因此,在您的示例中,Car
是一个实体,可能是一个聚合。所以你的模型在概念层面上是可以的,但你需要在Car
和Owner
之间分开紧密耦合,因为Owner
绝对是AR,在你当前的模型中,删除它会意味着所有属于它的汽车也应该被删除。
你可能会追求的是:
public class Owner {
private IEnumerable<OwnedCar> cars;
}
public class OwnedCar {
public Guid CarId { get; set; }
}
或者,作为VO的替代方案:
public class Owner {
private IEnumerable<Guid> carsOwned;
}
因此,一个AR不应该引用另一个AR实例。
另一点是你可能不想将存储库注入实体,因为这可能表明存在一些设计缺陷(有些代码味道)。
让拥有的汽车进入所有者将是OwnerRepository
的工作,因为它是同一聚合的一部分。由于它是一个值对象,因此不会有OwnedCarRepository
。
答案 1 :(得分:1)
100%肯定,除非您在不使用任何依赖性不当机制的遗留系统中工作,否则您不必创建单个CarRepository。
如果您发现需要向所有者注入CarRepository以检索属于特定所有者的汽车,也许这是一个提示,您应该重新建模关系,如:
public class Owner {
}
public class Car {
private Owner owner;
}
使用CareRepository实现目标:
public interface CarRepository {
List<Car> findBy(String onwer);
}
只是一个推测,静态部分可能引用DomainEvents,如:
public class Owner {
public long quantityOfCarsOwned() {
return DomainEvents.raise(new SumCarsEvent(this));//static
}
}
public class SumCarsEventHandler {
private CarRepository carRepository;//inject this, SumCarsEventHandler should be a statless bean managed by container like spring
public long handle(SumCarsEvent event) {
return carRepository.countBy(event.getOwner());
}
}
在非常简单的情况下,我认为这太复杂了。