写点什么

使用面向.NET 的 Naked Objects 进行快速应用程序开发

  • 2009-04-14
  • 本文字数:3622 字

    阅读完需:约 12 分钟

面向.NET 的Naked Objects 作为一个框架,提供了针对.NET 框架下裸对象架构模式的 一种实现。裸对象背后隐藏的基本概念是在编写一个业务应用程序时,开发者只需要编写领域对象以及封装在领域对象中的业务逻辑。而该框架就会将领域对象以丰 富的面向对象样式的用户界面形式暴露给用户,同时还会处理这些对象的持久化与管理,这通常通过一个ORM 实现。对于那些提出领域驱动设计的人,这一模式可能正是投其所好。除了消除编写用户界面层和数据访问层的需求,裸对象模式还有助于良好的对象建模——因为你可以瞬间将一个原型领域模型转换为一个能够为业务用户评估的应用程序。

很多人听及此的第一反应就是它无法在大规模的复杂业务应用程序下工作。然而在爱尔兰政府的一个员工人数超过1000 人的部门 DSFA ,使用的应用程序就是 Naked Objects 开发的,它能够支持每年价值数亿欧元的社会保障金管理。

历史

Naked Objects 框架最初脱胎于 Java 平台。最早的版本是用 Java 1.1 编写的。在软件开发的历史长河中,一个最伟大的偶然事件是我们发现它能够未经修改就能够以 J#语言运行在.NET 平台上。然而,当 Naked Objects 的后期版本迁移到 Java 1.5 后,它与.NET 的兼容性就消失了。让人大吃一惊的是在 2007 年 1 月,微软证实从.NET 3.5 之后将不再支持 J#。

为解决这一问题,面向.NET 的 Naked Objects 就作为框架的完整重现应运而生。它使用 C#进行编写,设计时完全利用了.NET 平台的功能,包括泛型和 LINQ。而面向.NET 的 Naked Objects 创建的通用用户界面则使用 WPF 编写。

Naked Objects 的工作原理

通用用户界面并不依赖于代码生成:它是动态创建的。在运行时,框架使用了反射技术将领域对象呈现在用户界面上。这一技术被称之为“内省”技术,它支 持开发人员快速地将域模型转换为可用的应用程序。下面的截图展示了一个对象的打开视图,该对象包含了几个关联对象的链接(每个图标表示一个域对象);用户 可以通过单击浏览这些关联对象:

(文中所有的截图和代码示例都节选自一个简单的费用处理程序,该程序是 Naked Objects下载示例中的一部分。)

当然,很多能以简单的CRUD 用户界面形式呈现领域对象模型的框架都提供了数据库的浏览或维护功能。Naked Objects 之所以获得更多关注,则是它能够生成完整功能的应用程序。默认情况下,任何公共方法对于用户而言都是可用的,形式则是通过在对象图标上弹出 菜单的动作,而方法名则以动作名进行重新格式:

如果方法具有参数方法签名,通常会创建一个对话框用于调用动作,如:

<span color="#0000ff">public</span> <span color="#2b91af">IExpenseItem</span> CopyAnExistingExpenseItem( <span color="#2b91af">IExpenseItem</span> otherItem)则呈现为:

Other Item 字段要求用户拖动或粘贴一个类型为 IExpenseItem(UI 字段会拒绝其他任何类型的对象)的现有对象。在字段的右边同样是一个下拉框指示器,它能够自动提供一个列表对象,其类型在其他标签上对用户是可见的,这样就能够避免不必要的标签转换。

如果 Expense Item 在屏幕或下拉列表中不存在,用户如何能够找到它?或者说,当他们没有另外一个对象作为开始对象时,用户该如何创建一个新的对象实例?这正是仓储模 式和工厂模式所要解决的,它们都是领域驱动设计的标准模式。在 Naked Objects 的术语中,仓储和工厂都是服务样本,服务本身就是最上等的领域对象。服务的使用有三种方式。

第一种方式,服务提供主菜单,并呈现在屏幕顶端。通常这些菜单提供业务活动起点的动作,例如创建一个新的客户,或者查找一个现有客户。第二种方式,可以将服务注入到其他需要服务的领域对象中,这遵循了依赖注入(DI)模式。Naked Objects 以透明的方式管理服务的注入,你只需要为所需服务类型提供一个可设置的属性,而不需要像许多依赖注入框架所要求的那样在外部进行配置。

使用服务的第三种方式按照我们的术语规定就是“赠予动作”。如果服务具有一个公共方法:

复制代码
<span color="#0000ff">public</span> <span color="#0000ff">virtual</span> <span color="#2b91af">IList</span> <<span color="#2b91af">RecordedAction</span>>
allRecordedActions(<span color="#2b91af">IRecordedActionContext</span> context)

那么它就会自动作为一个用户动作被“赠予”给实现了IRecordedActionContext的任何对象,你所选择的动作所执行的对象会自动填充对话框的第一个字段。(该动作表现为“Recorded Actions”子菜单,如第一张截图所示——并成为提供该动作的服务名)。

Naked Objects 最强大的功能是为你提供了一种实现多继承的方法(至少从用户的角度来讲是如此)。它的某些概念与 mix-ins 或者.NET 扩展方法的概念相仿,虽然在实现上略有不同。

实现业务规则

你该如何实现业务规则呢?有两个选择。其一是使用特性,它可以应用到类、属性、方法或参数。例如:

  • 默认情况下,框架会要求用户能够在保存一个对象之前完成所有字段,并且能够在执行动作之前,在对话框中提供所有字段。你可以使用 [Optionally()] 特性重写该行为。
  • [MaxLength()],``[Mask()][RegEx()]允许你为输入字符串指定约束以及 / 或者对他们进行格式规范。
  • 如果因为编程的原因,你必须将属性或方法定义为public,但又不应暴露给用户,则可以使用[Hidden]。各种条件都可以应用到该特性上。
  • 默认情况下,类、属性和动作的名称都会被使用,在用户界面上可以对其名称进行合理的格式规范。我们认为这是一个好的实践。然而,如果你需要一个代码不会使用的 label(例如它包含了符号或标点),则可以使用[Named()]。(注意这是一种完全独立的机制,它为所有 label 提供了国际化支持)。

第二种选择更为灵活,可以根据下面所展示的约定采用编程方式:

复制代码
<span color="#0000ff">public virtual void</span> CopyFrom(<span color="#2b91af">IExpenseItem</span> otherItem) {...}
<span color="#0000ff">public virtual string</span> ValidateCopyFrom(<span color="#2b91af">IExpenseItem</span> otherItem) {...}

在本例中,CopyFrom方法会作为一个用户动作被框架所呈现;框架同时能够识别ValidateCopyFrom方法,作为验证动作参数的逻辑:如果方法返回一个非空字符串,则对话框的“OK”按钮就会从灰色转为可用,字符串消息则作为工具提示显示给用户。相似的,DisableCopyFrom可以使得动作不可用,譬如当一项主张已经被持久化。(注意,框架具有一套完全独立的基于用户角色管理许可的机制)。还有其它一些约定,例如指定默认值或者为参数指定选项(下拉列表)。

POCOs

这些编码约定增加了可选的行为。你必须遵守三种简单的编码约定。有两种是应用在属性上的,如下所示:

复制代码
<span color="#0000ff">public virtual</span> Employee Claimant {
<span color="#0000ff">get</span> {
Resolve(employee);
<span color="#0000ff">return</span> employee;
}
<span color="#0000ff">set</span> {
employee = <span color="#0000ff">value</span>;
ObjectChanged();
}
}

Resolve()调用确保对象已经被加载到内存中,而ObjectChanged()则会通知框架属性值已经改变。两者都是为了更新对象的视图,以及确保改变被持久化。(注意框架会为你自动化处理持久化:你不需要为加载、保存和更新对象编写任何方法)。

第三个要求是你编程创建的任何对象都必须通知框架。你不能这样写:

<span color="#0000ff">Employee</span> employee = new Employee();而需要这样:

<span color="#0000ff">Employee</span> employee = Container.NewTransientInstance< <span color="#2b91af">Employee</span>>();这些调用并不是 Naked Objects 框架要求的,而只是将其委托给定义在IDomainObjectContainer中的方法。如果你为你的对象类型提供了一个属性,框架就会将其注入到容器中,该容器在运行时为你实现这些功能。作为一种快捷方式,你可以选择让域对象继承自AbstractDomainObject,它可以代替你为每种情形生成这几行代码。

但是必须声明的重点是继承是可选的:Naked Objects 是一个基于 POCO(Plain Old CLR Object,普通旧式 CLR 对象)的方式。除了通常意义上 POCO 所具有的优势外,它还意味着你可以选择使用相同的域对象,并将其运行在更加广泛的架构中:编写必要的用户界面和其他层。你所需要做的就是为容器提供这三类调用的存根代码。(如果你希望使用面向方面编程,你可以从域代码中去除Resolve()ObjectChanged()newTransientInstance()调用,但是我们不希望将 Naked Objects 与具体的 AOP 实现紧密耦合。)

Naked Objects 引人入胜之处是你可以只使用它就能够支持开发过程中的领域驱动设计:Naked Objects 不会强迫你必须要实现整个系统。还有一个好消息是你可以只使用 Naked Objects 的表达式编辑器,它可以免费下载


给InfoQ 中文站投稿或者参与内容翻译工作,请邮件至 editors@cn.infoq.com 。也欢迎大家加入到 InfoQ 中文站用户讨论组中与我们的编辑和其他读者朋友交流。

2009-04-14 06:493637
用户头像

发布了 109 篇内容, 共 41.5 次阅读, 收获喜欢 14 次。

关注

评论

发布
暂无评论
发现更多内容

原创 | TDD工具集:JUnit、AssertJ和Mockito (二十七)运行测试-在构建工具中运行测试

编程道与术

Java 编程 TDD 单元测试 JUnit

架构师训练营第 1 期-week10

习习

性能测试界“网红”云性能测试服务,了解一下?

华为云开发者联盟

CloudTest 沙箱实验 云性能测试

《迅雷链精品课》第七课:以太坊数据存储分析

迅雷链

区块链

为什么程序员不做外包

Java架构师迁哥

马士兵最新2020涵盖P5—P8Java全栈架构师学习路线,跟着老师学我已拿P7Offer!

Java架构追梦

Java 学习 架构 面试 马士兵

双指针算法和位运算&离散化和区间合并

落曦

原创 | 使用JPA实现DDD持久化-只要O,忘记R & Maven配置

编程道与术

Java hibernate 编程 mybatis jpa

都是“算法”惹的祸,字节三面处处坑,我的offer要凉了?

Java~~~

字节跳动 面试 编程语言 算法和数据结构

视频作品播放量低:自媒体作者如何走出新手村

石头IT视角

申通快递 双11 云原生应用实践

阿里巴巴云原生

阿里云 Kubernetes 运维 云原生 监控

基于DAYU的实时作业开发,分分钟搭建企业个性化推荐平台

华为云开发者联盟

华为 算法 数据 dayu

纷享销客罗旭:拐点下的中国SaaS

ToB行业头条

SaaS

容器化时代到来!跳转机分配问题终于“有救”了

华为云开发者联盟

容器 镜像 网络

我是面试官,我来分享一波面经!看看我的内心OS

比伯

Java 编程 架构 面试 技术宅

如何用CSS实现图像替换链接文本显示并保证链接可点击

陈北

CSS小技巧

程序员面试的时候突然遇到答不上的问题怎么办?

Java架构师迁哥

打工人、打工魂、高效MES助力打工者都是人上人

Marilyn

敏捷开发 快速开发 MES系统

理解三值逻辑与NULL,你离SQL高手更近了一步

华为云开发者联盟

sql null 逻辑

英特尔与南京溧水经济技术开发区共同成立智能交通研究院

E科讯

原创 | 使用JPA实现DDD持久化-数据库连接配置:persistence.xml

编程道与术

Java hibernate 编程 mybatis jpa

三分钟带你搞懂分布式链路追踪系统原理

Java架构师迁哥

LeetCode题解:169. 多数元素,分治,JavaScript,详细注释

Lee Chen

算法 大前端 LeetCode

云原生应用Go语言:你还在考虑的时候,别人已经应用实践

华为云开发者联盟

微服务 云技术 Go 语言

什么是堡垒机?为什么需要堡垒机?

xcbeyond

运维

接口请求(get、post、head等)详解

测试人生路

HTTP

大厂都是怎么用Java8代替SimpleDateFormat?

Java架构师迁哥

有奖话题 | 如果程序员和产品经理都会凡尔赛文学,将如何对话?

YourBatman

话题讨论 凡尔赛文学

架构师训练营 1 期 -- 第十周总结

曾彪彪

极客大学架构师训练营

《华为数据之道》读书笔记:第 3章 差异化的企业数据分类管理框架

方志

数据中台 数据仓库 数据治理 元数据

Alibaba最新《Java架构核心宝典》限时开放下载,互联网主流技术详解总结,提升技术能力的必备宝典!

Java架构之路

Java 程序员 架构 面试 编程语言

使用面向.NET的Naked Objects进行快速应用程序开发_.NET_Richard Pawson_InfoQ精选文章