从POEAA一书中,Martin介绍了工作单位的概念。如果您想拥有自动提交系统,那么它运行得非常好,在这个系统中,您的域模型使用“工作单元”来标记自己为新的、脏的、删除的或干净的。然后只需调用UnitofWork.commit(),模型的所有更改都将被保存。下面是一个具有以下方法的域模型类:
public abstract class DomainModel{
protected void markNew(){
UnitOfWork.getCurrent().registerNew(this);
}
protected void markDirty(){
UnitOfWork.getCurrent().registerDirty(this);
}
protected void markRemoved(){
UnitOfWork.getCurrent().registerRemoved(this);
}
protected void markClean(){
UnitOfWork.getCurrent().registerClean(this);
}
} 使用此实现,您可以通过业务逻辑方法将域模型标记为任意保存状态:
public class Message extends DomainModel{
public void updateContent(User user, string content){
// This method update message content if the the message posted time is not longer than 24 hrs, and the user has permission to update messate content.
if(!canUpdateContent(user) && timeExpired()) throw new IllegalOperationException("An error occurred, cannot update content.");
this.content = content;
markDirty();
}
}乍一看,它看起来非常棒,因为您不必手动调用存储库/数据映射程序上的插入、保存和删除方法。然而,我认为这种方法有两个问题:
你怎么看?Martin中描述的最初的工作单元模式是否违反了良好的OO设计原则?如果是的话,你认为这是反模式吗?
发布于 2015-10-16 21:35:17
准确地说,没有人“马丁·福勒执行工作股”。在这本书中,他区分了将修改后的对象注册为UoW的两种类型。
Caller注册,其中只有调用对象知道UoW,并且必须将(被调用的)域对象标记为脏。据我所知,这里没有反模式或不良做法。
对象注册,其中域对象向UoW注册自己。这里还有两种选择:
要使这一计划发挥作用,工作单位要么需要传递给对象,要么需要在一个众所周知的地方。传递工作单元是乏味的,但在某种类型的会话对象中传递它通常是没有问题的。
代码示例使用的是UnitOfWork.GetCurrent(),它更接近后一种选项,而且由于紧密耦合的隐式依赖(Service样式),目前被公认为反模式。
但是,如果选择了第一个选项,即将UoW传递给域对象,让我们假设一个工作抽象单元,这会是一种糟糕的实践吗?从依赖性管理的角度来看,显然不是。
现在仍然是坚持无知的一面。我们能不能说一个对象可以向另一个对象发出信号--它刚刚被编辑/创建/删除--它是持久性感知的?有很大争议。相比之下,如果我们查看最近的领域对象实现,例如在事件源中的实现,我们可以看到聚合可以负责保存自己未提交的更改的列表。,这或多或少是相同的想法。这是否违反了坚持无知?我不这样认为。
:Fowler选择了具体的代码来说明许多UoW的可能性之一,这显然被认为是一种糟糕的实践,但对于您指出的问题#1,而不是真正的问题#2,情况就更糟了。而且这并不会取消他所写的其他实现的资格,也不会取消他所写的整个UoW模式,它的更改跟踪机制大部分时间都隐藏在第三方库魔术(读: ORM)中,而不是像书中的例子那样硬编码。
发布于 2015-10-15 06:32:15
从DDD的角度来看,这是你不应该做的事情。
DDD包含以下规则:
应用程序服务应该只修改每个事务的一个聚合。
如果您遵循这条规则,那么在应用程序服务操作期间,可以清楚地看到哪些聚合发生了变化。然后,需要将该聚合传递给存储库,以便保存到DB:
repository.update(theAggregate);不需要打其他电话。这与你所描述的模式的增益相去甚远。
另一方面,您描述的模式将依赖关系从域引入到持久性机制(取决于设计过程中的实际依赖或概念依赖)。--这是您应该避免的事情,因为它大大增加了模型的复杂性(不仅在内部,对于客户也是如此)。
因此,您不应该将此表单中的模式与DDD一起使用。
DDD外
话虽如此,我认为这种模式是解决某个问题的许多解决方案之一。这个解决方案有优点也有缺点,你在问题中会描述其中的一些。在某些情况下,这种模式可能是最好的选择,所以
不,这不是反模式,
发布于 2015-10-14 07:55:54
我不认为模型不应该依赖于UoW。它更像是一个依赖于UoW的存储库,而存储库又将依赖于模型。
如果您的存储库只依赖于抽象的UoW,那么了解持久性技术的唯一谜团就是具体的UoW。
我倾向于允许模型依赖的唯一类是模型的其他部分:域服务、工厂等。
https://stackoverflow.com/questions/33119379
复制相似问题