所以,我注意到我绝对倾向于模式化我的Spring/Hibernate堆栈对象,如下所示:
这里的问题是Foos没有任何真正的逻辑.例如,如果每次Foo到期时都需要发送电子邮件,则不会调用Foo.expire().有一个对FooService.expireFoo(fooId)的调用.这有以下几种原因:
因此,出于这些原因,我的Spring域对象往往是带有一些验证逻辑的美化结构.也许这没关系.也许Web服务可以作为程序代码.也许随着新功能的编写,创建以新方式处理相同旧对象的新服务是可以接受的.
但是我想摆脱这种设计,我想知道其他Spring使用的是什么呢?你是否用装载时编织等花哨的技巧来对抗它(我觉得不舒服)?你有其他的伎俩吗?你认为程序是好的吗?
pto*_*mli 12
您可以使用AOP将Spring注入您的Hibernate实例化实例中.你也可以使用拦截器让Hibernate做同样的事情.
见http://www.jblewitt.com/blog/?p=129
关于"让Foo在事务上做几个事情很烦人",我希望你的服务实现能够知道/关心事务,如果你现在在你的域模型中使用服务接口,那现在应该是不完全的很烦人.
我怀疑决定何时应该保存域模型取决于它是什么以及你正在做什么.
FWIW我倾向于产生同样的贫血结构,但我已经到了那里,现在我知道可以以更明智的方式做到这一点.
听起来您的应用程序是围绕过程编码原则设计的.仅这一点就会阻碍你尝试做的任何面向对象的编程.
Foo可能没有它控制的行为.如果您的业务逻辑很小,那么不使用域模型模式也是可以接受的.一个事务处理脚本模式有时也很有道理.
当逻辑开始增长时,问题就出现了.将事务脚本重构为域模型并不是最简单的事情,但它肯定不是最困难的事情.如果你有很多关于Foo的逻辑,我建议你转向Domain Model模式.封装的好处使得它很容易理解发生了什么以及谁参与了什么.
如果你想拥有Foo.Expire(),请在你的Foo类中创建一个事件,例如OnExpiration.连接foo.OnExpiration += FooService.ExpireFoo(foo.Id)对象创建,可能通过工厂使用的工厂FooRepository.
真的先考虑一下.这是非常可能的,一切都已经在正确的地方...现在.
祝好运!
我认为有一个简单的重构模式可以解决您的问题。
这将帮助您朝着更丰富的领域模型发展。它还保留了单一职责原则,因为所有依赖于数据库的代码都保留在 FooService 实现中,并帮助您将业务逻辑从 FooService 迁移到 Foo。如果您想将后端切换到另一个数据库或内存或模拟(用于测试),除了 FooService 层之外,您不需要更改任何内容。
^ 我假设 FooService 执行的 DB 调用太慢,无法从 ORM 执行,例如选择与给定 Foo 共享属性 X 的最新 Foo。这就是我见过的大多数工作的方式。
例子
代替:
class Controller{
public Response getBestStudentForSchool( Request req ){
Student bestStudent = StudentService.findBestPupilForSchool( req.getParam( "schlId" ).asInt() );
...
}
}
Run Code Online (Sandbox Code Playgroud)
你会朝着这样的方向前进:
class Controller{
public Response getBestStudentForSchool( Request req ){
School school = repo.get( School.class, req.getParam( "schlId" ).asInt() );
Student bestStudent = school.getBestStudent();
...
}
}
Run Code Online (Sandbox Code Playgroud)
我希望你会同意,这似乎更丰富了。现在您正在进行另一个数据库调用,但是如果您在会话中缓存 School ,则损失可以忽略不计。恐怕任何真正的 OOP 模型都比您使用的贫血模型效率低,但是通过代码清晰度减少错误应该是值得的。一如既往,YMMV。
| 归档时间: |
|
| 查看次数: |
4813 次 |
| 最近记录: |