我正在阅读Hibernate in Action,作者建议将业务逻辑转移到我们的域模型中(p.306)。例如,在本书提供的示例中,我们有三个名为Item
,Bid
和User
的实体,作者建议在placeBid(User bidder, BigDecimal amount)
方法中添加Item
方法{1}}上课。
考虑到通常我们有一个独特的业务逻辑层(例如Spring中的Manager
或Service
类),其中包括控制事务等,这真的是一个很好的建议吗?是不是最好不要向我们的实体添加业务逻辑方法?
提前致谢。
答案 0 :(得分:14)
如上所述
我们有一个独特的业务逻辑层(通常称为服务层)
域驱动设计(DDD)声明您应该将业务逻辑放在域模型中。而且,相信我,这真的很棒。正如POJO在行动书中所说的关于服务层
之前
@Service
public class BidServiceImpl implements BidService {
@Autowired
private ItemRepository itemRepository;
public void placeBid(Integer itemId, User bidder, BigDecimal amount) {
Item item = itemRepository.getById(itemId);
if(amount.compareTo(new BigDecimal("0.00")) <= 0)
throw new IllegalStateException("Amount must be greater than zero");
if(!bidder.isEnabled())
throw new IllegalStateException("Disabled bidder");
item.getBidList().add(new Bid(bidder, amount));
}
}
<强>后强>
@Service
public class BidServiceImpl implements BidService {
@Autowired
private ItemRepository itemRepository;
public void placeBid(Integer itemId, User bidder, BigDecimal amount) {
// itemRepository will retrieve a managed Item instance
Item item = itemRepository.getById(itemId);
item.placeBid(bidder, amount);
}
}
您的域逻辑显示如下
@Entity
public class Item implements Serializable {
private List<Bid> bidList = new ArrayList<Bid>();
@OneToMany(cascade=CascadeType.ALL)
public List<Bid> getBidList() {
return this.bidList;
}
public void placeBid(User bidder, BigDecimal amount) {
if(amount.compareTo(new BigDecimal("0.00")) <= 0)
throw new IllegalStateException("Amount must be greater than zero");
if(!bidder.isEnabled())
throw new IllegalStateException("Disabled bidder");
/**
* By using Automatic Dirty Checking
*
* Hibernate will save our Bid
*/
item.getBidList().add(new Bid(bidder, amount));
}
}
使用Domain-Driven-Design时,您的业务逻辑生活在正确的位置。但是,有时,在服务层内定义业务逻辑可能是个好主意。请参阅here原因
答案 1 :(得分:9)
最引用的文章之一是:
马丁福勒的“贫血领域模型”。 非常值得一读:http://martinfowler.com/bliki/AnemicDomainModel.html
一般要点是,如果您的域模型纯粹是没有行为的数据,那么您就失去了OO设计的许多好处。
或引用:
“一般而言,您在服务中发现的行为越多,您就越有可能剥夺自己对域模型的好处。如果您的所有逻辑都在服务中,那么您就会使自己失明。” / p>
答案 2 :(得分:0)
我个人喜欢贫血模型 - 数据是数据,代码是代码;但也有例外。
归结为'密度':如果你有大量的服务与一些域对象交互;将一些通用业务逻辑放在您的域模型中是有意义的,因此它成为服务的一部分。如果您有一些与许多域对象交互的服务,那么优先于贫域模型而不是胖域模型。
我发现如果我在多个上下文中使用我的域对象(例如,我在客户端和服务端使用相同的域对象),那么业务逻辑通常会妨碍 - 因为它必须适用于所有情况。