2008-05-12
let's placeBid
这个例子很老啦,在之前的Domain Model的争论中被广泛引用(参见:http://www.javaeye.com/topic/11712)。我再来炒炒冷饭。
这个Domain可以简化为这样:
现在我们要添加一个行为叫placeBid。于是我们可以写出如下的贫血代码:
这样的代码有什么问题吗?我觉得在没有更多的需求,系统规模不大的情况下,无法拿出有力的证据证明这样做的缺陷。那么我们再来看看如何用经典的Hibernate做法来做领域模型(参见robbin的第二种模型):
在那篇老帖子(我知道,n年前了)中,七彩狼提出了一个问题,就是:
第三类DomainLogic,也就是需要依赖到复杂查询的Logic
那需要这样的逻辑的是什么?远在天边,近在眼前。currentMaxBid哪来的?不还是从DAO中取出来的嘛。我Item包含了自己的bids,它居然没有办法知道maxBid是什么,还需要从外边用参数传进来。这是不合理的,但是却是不得已的。Hibernate的经典解决方案制约我们必须把这样的查询逻辑放在Domain的使用者那一边中调用DAO来完成。如果改用(http://www.javaeye.com/topic/191261)我说的RichSet,就可以轻松解决:
max在缺省情况下的实现是遍历列表。在Hibernate增强之后就变成了SQL查询。类似于bids.add在缺省情况是列表操作,Hibernate存储的时候变成了SQL的INSERT。
我的观点是,所谓的大批量操作不属于Domain Logic是由于Hibernate造成的限制。实际情况中,Domain中应该有一个叫Repository的对象。它封装了一个List。
作为领域对象的ItemRepository,它是不关心items是从哪里来的。它就认为这个items是domain中的所有的item。于是,addItem的item没名字不重复的校验就可以自然的放在ItemRepository上。
在Domain中,所有的Item列表,都应该经过ItemRepository包装。从而保证Item的名字唯一性。
这个Domain可以简化为这样:
public class Item {
private Set<Bid> bids = new HashSet<Bid>();
}
public class Bid {
private User bidder;
private int amount;
}
现在我们要添加一个行为叫placeBid。于是我们可以写出如下的贫血代码:
Bid currentMaxBid = itemDAO.getMaxBid(itemId);
Item item = itemDAO.findById(itemId, true);
if (currentMaxBid != null && bidAmount <= currentMaxBid.getAmount()) {
throw new BizException("Bid too low.");
}
Bid newBid = new Bid(this, bidder, bidAmount);
item.getBids().add(bid);
itemDao.save(item);
这样的代码有什么问题吗?我觉得在没有更多的需求,系统规模不大的情况下,无法拿出有力的证据证明这样做的缺陷。那么我们再来看看如何用经典的Hibernate做法来做领域模型(参见robbin的第二种模型):
public class Item {
public Bid placeBid(User bidder, int bidAmount, Bid currentMaxBid) {
if (currentMaxBid != null && bidAmount <= currentMaxBid.getAmount()) {
throw new BizException("Bid too low.");
}
Bid newBid = new Bid(this, bidder, bidAmount);
bids.add(newBid);
return newBid;
}
}
在那篇老帖子(我知道,n年前了)中,七彩狼提出了一个问题,就是:
引用
第三类DomainLogic,也就是需要依赖到复杂查询的Logic
那需要这样的逻辑的是什么?远在天边,近在眼前。currentMaxBid哪来的?不还是从DAO中取出来的嘛。我Item包含了自己的bids,它居然没有办法知道maxBid是什么,还需要从外边用参数传进来。这是不合理的,但是却是不得已的。Hibernate的经典解决方案制约我们必须把这样的查询逻辑放在Domain的使用者那一边中调用DAO来完成。如果改用(http://www.javaeye.com/topic/191261)我说的RichSet,就可以轻松解决:
public class Item {
private RichSet<Bid> bids = new DefaultRichSet<Bid>();
public Bid placeBid(User bidder, int bidAmount) {
Bid currentMaxBid = bids.max("amount");
if (currentMaxBid != null && bidAmount <= currentMaxBid.getAmount()) {
throw new BizException("Bid too low.");
}
Bid newBid = new Bid(this, bidder, bidAmount);
bids.add(newBid);
return newBid;
}
}
max在缺省情况下的实现是遍历列表。在Hibernate增强之后就变成了SQL查询。类似于bids.add在缺省情况是列表操作,Hibernate存储的时候变成了SQL的INSERT。
我的观点是,所谓的大批量操作不属于Domain Logic是由于Hibernate造成的限制。实际情况中,Domain中应该有一个叫Repository的对象。它封装了一个List。
public class ItemRepository {
private RichList<Item> items
public ItemRepository(RichList<Item> items) {
this.items = items;
}
}
作为领域对象的ItemRepository,它是不关心items是从哪里来的。它就认为这个items是domain中的所有的item。于是,addItem的item没名字不重复的校验就可以自然的放在ItemRepository上。
public class ItemRepository {
public void addItem(String name) {
if (items.find("name").eq(name).size() > 0) {
throw new BizException("name duplicated");
}
Item item = new Item(name);
items.add(item);
return item;
}
}
在Domain中,所有的Item列表,都应该经过ItemRepository包装。从而保证Item的名字唯一性。
评论
partech
2008-05-19
yimlin 写道
这样一个好贴怎么没有顶起来!
Repository存在是必要的!domain model本身是有状态的,由于生命周期的关系,一些model的生命周期依附于另一些model.
据此,我们把Domain Model分级:一级对象,二级对象甚至三级对象,其中三级对象依附于二级对象,二级对象依附于一级对象.
二级和三级对象可以利用RichSet访问并处理一些逻辑,但一级对象就必须通过Repository来控制!
Repository存在是必要的!domain model本身是有状态的,由于生命周期的关系,一些model的生命周期依附于另一些model.
据此,我们把Domain Model分级:一级对象,二级对象甚至三级对象,其中三级对象依附于二级对象,二级对象依附于一级对象.
二级和三级对象可以利用RichSet访问并处理一些逻辑,但一级对象就必须通过Repository来控制!
Repository同DAO有区别么?
看了半天也没看出RichSet有多少实质的好处。查找对象往往是会跨越多个对象关系的,这种东东实在看不出有多少实用价值。
要找到最近的bid需要那么费劲么?
public class Item {
private Bid currentMaxBid;
private Set<Bid> bids = new HashSet<Bid>();
}
yimlin
2008-05-17
这样一个好贴怎么没有顶起来!
Repository存在是必要的!
domain model本身是有状态的,由于生命周期的关系,一些model的生命周期依附于另一些model.
据此,我们把Domain Model分级:一级对象,二级对象甚至三级对象,其中三级对象依附于二级对象,二级对象依附于一级对象.
二级和三级对象可以利用RichSet访问并处理一些逻辑,但一级对象就必须通过Repository来控制!
Repository存在是必要的!
domain model本身是有状态的,由于生命周期的关系,一些model的生命周期依附于另一些model.
据此,我们把Domain Model分级:一级对象,二级对象甚至三级对象,其中三级对象依附于二级对象,二级对象依附于一级对象.
二级和三级对象可以利用RichSet访问并处理一些逻辑,但一级对象就必须通过Repository来控制!
发表评论
提醒: 该博客已发表在公共论坛,博客所有留言会成为论坛回贴,留言请注意遵守论坛发贴规则
- 浏览: 81557 次
- 性别:

- 来自: 北京

- 详细资料
搜索本博客
我的相册
step2
共 6 张
共 6 张
最近加入圈子
最新评论
-
汉语编程,有搞头
就E语言算巴 没用过也没计划用 CHTML不错哈哈
-- by lwwin -
关于estimation的闲言碎语
1. BA是Business Analyst的缩写,就是写story的人.2. ...
-- by taowen -
关于estimation的闲言碎语
请教:1.BA是什么意思?Business Analyzer?2.“好的esti ...
-- by movingboy -
计划经济体制的CMM,市场 ...
有创意,有启发性。顶!!
-- by estest -
贫血的Domain Model
看了这么久的领域模型,争论的真是没完没了。 难道就不能跳开这个领域模型或者还领域 ...
-- by hunter001201






评论排行榜