以下旨在充分利用事件记录模式和存储库模式的方法有什么缺点(例如在可测试性方面)?
每个持久化对象都暴露了save()和delete()方法,但没有静态方法来加载自身,或者加载类似对象的列表:从上层加载是通过直接调用存储库来完成的,以避免静态方法持久对象。
“save()”和“delete()”方法只是外观,它们被委托(delegate)给存储库。
这种方法真的需要考虑可测试性吗?即使使用纯 Active Record 方法:是否存在数据库逻辑仅代表整个业务逻辑的一小部分的信息系统,并且模拟数据库访问会很有趣?
编辑:这种方法需要持久对象从实现“save()”和“delete()”的AbstractPersistentObject继承,并且它会阻止业务继承,但我读到最好避免业务继承,并用组合代替它,所以它可能是一个优点,而不是一个缺点......?
编辑2:也许这篇文章会更好地解释我正在尝试解决的问题:http://moleseyhill.com/blog/2009/07/13/active-record-verses-repository/
最佳答案
有两件事引起了一些担忧。第一个是这句话(强调我的):
[...] are there information systems where database logic represents only a small part of the whole business logic, and where it would be interesting to mock the database access?
您是否将业务逻辑放入数据库中?如果是这样:不要这样做,它会使模拟您的数据库非常变得困难。您必须将所有业务逻辑从数据库复制(并维护!)到您的模拟,否则您的测试毫无用处。
但是您如何知道模拟是否正确实现了业务逻辑?您可以为模拟编写单元测试,或者重用数据库的单元测试(您确实有它们,对吧?),但这是我不惜一切代价尝试避免的方法!让我再说一遍:永远不要(必须)为你的模拟编写单元测试。如果您发现自己处于这种情况,请退后几步并检查您的设计,因为有些地方非常错误。
将业务逻辑放入数据库只会在模型和数据库之间产生不必要的耦合,并使测试层变得非常复杂。关注点分离是这里的关键:模型仅关注业务逻辑,数据库仅关注持久性,没有其他。
这让我想到了下一个问题:为什么在域模型上需要与持久性相关的 save()
和 delete()
方法? 持久性不属于域模型。
我知道,您说过这些方法将委托(delegate)给存储库,因此域模型(希望)不包含实际的持久性逻辑。但它如何知道应该委托(delegate)给哪个存储库?
如果您在 save()
方法中调用服务定位器,则无法将实体保存到多个存储库。您还向调用者隐藏了对存储库的依赖关系,我认为这是一件坏事。
要解决这些问题,您可以将存储库实例传递给 save()
方法,如下所示:
public class Foo extends AbstractPersistentObject {
public void saveTo(IFooRepository repository) {
repository.save(this);
}
}
但是这样的方法意味着调用者已经有一个存储库实例,因此他不妨直接在存储库上调用 save()
方法。域模型上的任何持久性方法都将过时。
也许我把你的问题过于简单化了。你想达到什么目的?您只需要 entity.save()
语法,还是想解决更大的问题?
关于design-patterns - Active Record 模式、Repository 模式和可测试性(java 中),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5677518/