Naked Objects 增加对 Java 1.5、Injection、Hibernate 的支持

  • Geoffrey Wiseman
  • 张海龙

2007 年 11 月 21 日

话题:Java架构语言 & 开发

Naked Objects 是一种架构模式,也是一个以领域对象为中心角色的应用开发框架。Naked Object 应用中的领域对象是用户界面的核心,同时也是开发活动的焦点。Naked Objects 最近发布了 3.0 版,它支持 Java 1.5、注入(injection)、一个可选 UI、Hibernate 对象存储、集成安全和认担动作(Contributed Actions)。其间他们与爱尔兰社会和家庭事务部门一道进行的努力,为使用 Naked Objects 提供了一个有价值的学习案例。

InfoQ 借机与 Naked Objects 集团的共同创办人、Naked Objects 模式的创造者 Richard Pawson 进行了沟通。

Naked Objects 模式鼓励开发者关注于设计带有数据和行为的富领域模型,而它则自动提供一个展现层和一个瘦控制层。

Naked objects 源于对下面这一个有效循环的认识:

如果你决心设计有完善行为的领域对象,那么为用户展现领域对象的直观视图和存取方法,就是用户界面要做的全部——而这些都可以由反射机制来自动完成。如果你把用户界面设计成领域对象的直接反映,那么用户界面将强迫,同时也帮助你完善领域对象的行为。

这种着眼于领域模型的方法与领域驱动设计有着相似之处: 

我想他们是非常互补的。现在大家称为 DDD(领域驱动设计,即 Domain-Driven Design)的理念驱使我在 90 年代后期开始构想 Naked Objects,我们在 Naked Objects 中应用了这些模式。

首先,我真认为所有坚信 DDD 思想的人都应该使用 Naked Objects,因为它让 DDD 的好处更加具体和明显,它也让 DDD 的过程更容易满足业务。多年的经验让我发现,讨论 UML 图表不能吸引商业赞助人,这也是人们为什么通过屏幕线框图来设计系统的原因(一个很不好的主意)——因为它很容易吸引人们对屏幕布局进行讨论。用 Naked Objects 构建你的领域模型原型会更容易满足业务要求,因为业务实际上关注的就是领域模型本身。

其次,我相信 Naked Objects 和 DDD 会互相促进,因为它避免了在手工开发上层的展现层和控制层时,抵消掉领域模型的力量的问题,我最近的 Blog就是关于这一主题的。

就 Naked Objects 是如何帮助你探索领域展开来谈:

随着我们越来越多地使用 Naked Objects,我们学到的一个普遍性质就是,UI 会强迫你将一些否则可能会忽略的东西放入领域模型。模型也因此更全面地表现了现实——模型绝不会不恰当或不优雅。Naked Objects 的方法还为业务本身澄清了概念。我最喜欢的例子就是“预付款”和“后付款”,这在最初的标书里就有描述,通俗讲它的意义就是:一个还没有付款,而另一个已经完成付款。

但我们要问的问题是:预付款是怎么来的?得到的答案是那是用户的权益(如最后他们可以获得养老金)。实际上,我们可以把“预付款”改成“权益金(Entitlement)”,而“后付款”就对应变成“支付款项(Payment)”。权益金是预先计算的(可以回溯调整),当权益金到期时,就用“支付款项”去清偿“权益金”。

当然,Naked Objects 不可能适合所有的应用,Richard 特别警告那些面向消费者的应用:

使用 Naked Objects 开发交付的应用只适合于内部用户,而不是公共访问型应用。 我们从来没有声明过生成的用户界面很“直观”——实际上,研究说明不存在什么直观的用户界面,只有熟悉的用户界面——其中肯定会存在学习曲线的问题,但我们交付界面的目标总是把用户“看做问题解决者,而不仅仅是流程跟随者”。

Naked Objects 3.0

Naked Objects 3.0 支持直接在领域类中添加 Java1.5 标注来实现声明式的数据验证和字段排序,向领域模型注入共享的服务,HTML 和富客户端界面(还会有更多,如 Eclipse RCP、命令行和 AJAX),集成 Hibernate 以支持领域模型的存储,一个内建的安全模型(它能在数据库、简单文件或 LDAP 中进行存储和管理),认担动作。Naked Objects 3.0 还改用了 Apache 许可。

认担动作(contributed actions )允许服务将动作贡献到领域模型,并成为用户界面的一部分。不过这样做的风险是错误地鼓励了开发者将行为从领域类转移到服务层:

我们最近为一位大客户完成了一个短期项目,当时客户声称项目已经按照 SOA 的规则进行了架构设计(但没有实现),他们把所有的行为都放在了服务层。于是我们使用 Naked object 非常快速地为他们的模型构建了一个原型,原型中定义了完全贫血的实体,并让服务承担所有的动作。我们绝对不推荐这样进行设计,但当时的问题是要么在他们已完成部分上继续工作,要么就不做。不过,结果我们得以通过这样的设计向他们说明他们对服务的观念是很贫乏的,而且极度不协调。当然,我们也说明了如果他们当初尽量将行为放进领域对象,结果会更加好。

我们的观点是,仅当需要在不同对象间实现同一个行为而又无法使用继承时,才使用认担动作。这是绕过单一继承限制的一个有效途径。认担动作很像 AOP,只不过它是发生在运行时,而不是编译时。

也可以结合使用 AOP 和 Naked Objects,Naked Objects 的 Blog 上已经演示过。从 GPL 许可换成 Apache 许可是为了回应用户的要求:

不幸的是,有相当多的人不愿意与 GPL 产品打交道,同样,在保证与 Naked Objects 使用的各种开源库的许可兼容的问题上,GPL 给我们带来了一些麻烦。

关于 Naked Objects 接受程度的问题:

我们发布 Naked Object 3.0 获得了良好的反响(第一周就有超千次下载)——我们认为这是 Naked Objects 第一个比较完善的实现。我们的新版本发布通知邮件列表里 有几百人进行了登记。但是抛开 DSFA 项目这个意外惊喜不谈,我不得不承认它毕竟还是一个刚刚成长起来的技术,大多数人仍然会将它作为一个原型工具,而不是一个完整的部署平台。我们期待在接下来的几个月里,它会获得实质的成长。

我强烈感受到其它许多技术正越来越接近 Naked Object 的理念(Ruby on Rails、Spring ROO 等),我们朝我们看到的这些趋势的理想终点笔直前进。因此,Naked Objects 相比主流开发而言,常被视为太激进(或者叫做固执)。或许这样说没错,但我们已经见识过它的力量,因此我们决不会回头。

Richard Pawson 在他的 Blog 上详细对比了 Naked Object 和Ruby on Rails 以及 Grails

Naked Objects 和爱尔兰社会及家庭事务部

爱尔兰社会及家庭事务部(DSFA)是 Naked Objects 最著名的样板。DSFA 与 Naked Objects 的第一个试验项目是 2002 年启动的,在 2004 年再次与 Naked Objects 集团续约,到 2007 年 9 月该应用已经“持续被超过 700 用户使用”。而且:

2007 年 5 月,DSFA 宣布一个新的四年计划,进一步扩展新的架构,开发一系列全新的应用,同时将更多遗留的系统移植到新的平台上来。希望可以在项目期间通过 Naked Objects 将用户数提高到数千。

然 Richard Pawson 不愿对进行中的架构扩展进行评论,但他保证将会有更多新东西。下一步会有:

可选自动生成用户界面、一个全新的自动化测试框架、开发工具,但我可不想提前公布。

对 DSFA 项目的案例研究得出了这些优点:敏捷性、原型化和重用。 

就代码重用主题来讲:

这么说有两个原因:第一个很简单,那就是 Naked Objects 鼓励好的对象建模(行为丰富的实体,大量的多态),而对象建模就是为了更好的重用;第二个原因就是在 Naked Objects 环境里 ,当你在应用间重用领域对象时,不必担心 UI 的问题。在传统架构中,如果你想重用,如重用一个“Customer”对象,你要么必须编写新的视图和控制器,要么重用前一个应用中的视图和控制器,结果却发现这些视图和控制器并不仅仅与“Customer”对象相关联,不得不大动干戈。

这里面还有一个政治因素。以我的经验看来,如果你想让一个房间内所有的利益相关方都对 Customer 对象有一个共同的定义,只有一个结果,不可能——他们不可能被说服,因为他们每一个人都有不一样的需求。但是,如果你能展示些什么让他们知道你正在做他们每个人想要的,那就简单了。Naked Objects 项目的成功之处就在于可以向不同的利益相关方展示(不仅仅是告诉他们)同一个业务对象模型是如何满足他们各自的需要,而传统的 UML 建模就做不到这一点的。

查看英文原文Naked Objects adds Java 1.5, Injection, Hibernate
Java架构语言 & 开发