dddsample一个可运行的实例

09-02-14 mygol
该实例是DDD书中cargo的可运行的实例.大家谈谈其设计

1
mygol
2009-02-16 15:03
没人看过吗,告诉大家下载地址:

http://dddsample.sourceforge.net/

banq
2009-02-16 20:05
不错,是Spring+Hibernate架构,具体模型是DDD书中的cargo案例,这个代码是一个成型的结果。

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

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

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

banq
2009-02-18 08:45
对的,你说的是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);

}

zwjsoft
2009-02-25 15:03
>>>我这里再补充解释一下:90% 的系统的业务逻辑,都包含 crud

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

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

banq
2009-02-25 18:35
>感觉最后还是成了贫血模型

晕倒,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);
  }
<p>

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

mygol
2009-02-26 10:37
呵呵,banq有点上火了.

俗话说一行代码胜千言万语,这个例子确实是学习DDD的好例子,各位别错过了.

zwjsoft
2009-02-26 14:24
怎么区分业务方法与Service??

或者说业务方法需要依赖数据库操作的时候怎么来处理呢?

在领域对象与数据库操作间加一个中介者?

mygol
2009-02-26 17:31
数据据操作由repository来完成.接口与实现分离

猜你喜欢