dddsample一个可运行的实例

该实例是DDD书中cargo的可运行的实例.大家谈谈其设计

没人看过吗,告诉大家下载地址:
http://dddsample.sourceforge.net/

不错,是Spring+Hibernate架构,具体模型是DDD书中的cargo案例,这个代码是一个成型的结果。

有趣的是,我发现它的仓储CargoRepository 是在Service中实现,而不是在模型Cargo中,模型Cargo是主要业务方法。

这和JiveJdon3处理方式类似,不过我真希望在模型中能够和谐处理好CRUD的点子。

更准确的说是cargoRepository的实现是在application中.主要考虑到依赖于hibernate,但这个实现在领域中是不可见的.领域中只见到其接口.可以说DI/ioc帮助了DDD的实现

对的,你说的是repository实现。

我们在另外一个帖子讨论中(http://www.jdon.com/jivejdon/thread/35600.html),调用顺序是这样:
客户端--->服务 ---> repository
这是符合DDD定义的,基于服务的SOA就是那种全局唯一的入口,通过这个入口调用repository,而不是象infoQ里那样,将repository注射到Model中,因为Model中有自己的业务方法,这点从cargo这个模型代码看就很正常。

public TrackingId bookNewCargo(final UnLocode originUnLocode, final UnLocode destinationUnLocode) {
Validate.notNull(originUnLocode);
Validate.notNull(destinationUnLocode);

final TrackingId trackingId = cargoRepository.nextTrackingId();
final Location origin = locationRepository.find(originUnLocode);
final Location destination = locationRepository.find(destinationUnLocode);
Cargo cargo = new Cargo(trackingId, origin, destination);

cargoRepository.save(cargo);
logger.info("Registered new cargo with tracking id " + cargo.trackingId().idString());

return cargo.trackingId();
}

public List<Itinerary> requestPossibleRoutesForCargo(TrackingId trackingId) {
Validate.notNull(trackingId);

final Cargo cargo = cargoRepository.find(trackingId);
final RouteSpecification routeSpecification = RouteSpecification.forCargo(cargo, new Date());

return routingService.fetchRoutesForSpecification(routeSpecification);
}

>>>我这里再补充解释一下:90% 的系统的业务逻辑,都包含 crud

>>>>这是符合DDD定义的,基于服务的SOA就是那种全局唯一的入口,通过这个入口调用repository,而不是象infoQ里那样,将repository注射到Model中,因为Model中有自己的业务方法,这点从cargo这个模型代码看就很正常。

感觉最后还是成了贫血模型。

>感觉最后还是成了贫血模型
晕倒,cargo中那么业务方法(打开代码可以看到),还是贫血?那就让Evans和MartinF Fowler去掐架吧。



public Location lastKnownLocation() {
final HandlingEvent lastEvent = deliveryHistory().lastEvent();
if (lastEvent != null) {
return lastEvent.location();
} else {
return Location.UNKNOWN;
}
}

/**
* @return True if the cargo has arrived at its final destination.
*/

public boolean hasArrived() {
return destination.equals(lastKnownLocation());
}

/**
* Attach a new itinerary to this cargo.
*
* @param itinerary an itinerary. May not be null.
*/

public void attachItinerary(final Itinerary itinerary) {
Validate.notNull(itinerary);

// Decouple the old itinerary from this cargo
itinerary().setCargo(null);
// Couple this cargo and the new itinerary
this.itinerary = itinerary;
this.itinerary.setCargo(this);
}

[该贴被banq于2009-02-25 18:37修改过]

呵呵,banq有点上火了.
俗话说一行代码胜千言万语,这个例子确实是学习ddd的好例子,各位别错过了.

怎么区分业务方法与Service??
或者说业务方法需要依赖数据库操作的时候怎么来处理呢?
在领域对象与数据库操作间加一个中介者?

数据据操作由repository来完成.接口与实现分离