[转]JSR#168 Portlet 说明

十一月 30, 2004

JSR#168 Portlet 说明

全文 (1)-(7) 由 jini (99% jakarta) 所撰写
版权归属于 (c)softleader taiwan ( http://www.softleader.com.tw )
如需转载请信告知 jini@bbs.openfind.com.tw

ch1 序言

许多大型企业的网站, 渐渐采用了 portal server 作为开发的基础. 至于什么是 portal 呢, 中文翻译为 “门户网站”。 有人可能想.. 天杀的.. 门户网站不是就像 yahoo, pchome, yam 等等。不过, 我们现在讨论的 portal server, 不是那么地简单, 基本上 yahoo, pchome, yam 那些只能称为搜索引擎的门户网站。

如果你从来�]有用过 portal server 或是似懂非懂.. 大家可以连结到 MyNetscapeMyYahoo 去 注册一个帐号。因为 MyNetscape 的样式比较好看, 所以我接下来就以 MyNetscape 为介绍的范例。

如果你第一次接触到 portal,你会惊讶的发现… 哇.. 为何一个网站里面充满了这么多小窗口. 我们称这些小窗口叫做 “portlet”,而且每个小窗口都存在着独立的信息与内容,可以放到最大化,缩小,还原,关闭等等。当你登陆之后,可以选择及调整自己 portlet 的配置,也可以设置自己喜爱的风格与样式,更可以设置每个 portlet 的资料配置。这种以客户为上帝的系统,就是我们将要介绍的 portal。

ch2 Portal 的组成

Portal 的组成可以分为三部份 (1) Portal Server (2) Portlet Container (3) Portlet

1) Portal Server 的定义是

一个 Portal(门户网站)就是指一个 Web-based 的系统,通常都会提供个人化设置、单一登陆、以及由各种不同来源或不同网站取得各式各样的信息,并且将这些信息放在网页之中组合而成的呈现平台,门户网站会有精巧的个人化设置去提供定制的网页,当不同等级的使用者来浏览该页面将获得不同的信息内容。

2) Portlet Container 的定义是

portlet container 是提供 portlets 执行的环境,包含了许多 portlets 并且管理他们的生命周期,他也会永远保存着 portlets 的喜好设置,一个 portlet container 接收到来自 portal 的请求后,接着将这个请求传递给存在 container 的 portlet 执行。portlet container 没有义务去组合 portlets 产生的信息�热荩�这个工作必须��portal 来处理。portal 和 portlet container 可以放在一起视为同一个系统的组件,或者分开成为两个独立的组件。

3) Portlet 的定义是

一个 Portlet 是以 Java 技术为技术的 Web 组件,由 Portlet Container 所管理,专门处理客户的 request 以及产生各种动态的信息内容。Portlets 为可插式 ( pluggable ) 的客户界面组件,提供呈现层成为一个信息系统。这些由 portlet 产生的内容也被称为片段 (fragment),而片段是具有一些规则的Markup( HTML、XHTML、WML ),而且可以和其他的片段组合而成一个复杂的文件。而 Portlet 中的内容正常来说是与其他 Portlet 的内容聚合而成为一个 Portal 网页。而 Portlet 的生命周期是被 Portlet Container 所管理控制的。客户端和 portlets 的互动是由 portal 通过典型的 request/response 方式实现,正常来说,客户会和 portlets 所产生的内容互动,举例来说,根据下一步的连接或者是确认送出的表单,结果 portal 将会接收到 portlet 的动作,将这个处理状况转向到目标 portlet。这些 portlet 内容的产生可能会因为不同的使用者而有不同的变化,完全是根据客户对于这个 portlet 的设置。

ch3 portlet 与 servlet 的关系

Portlet 和 Servlet 算是兄弟有那么一点点相似却又有那么一点点不同,因为 Servlet 和 Portlet 不尽然相同,所以研究小��Q定将 portlets 定义成为一个新的组件,因此定义了 portlets 一个新的并且明确的界面与行为。为了尽可能与现有的 servlet 结合达到重复使用的目的,portlet 的规范利用了 servlet 的规范,许多观念都很相似的,结合 portlets、servlets 及 jsp 在同一个网站系统中,我们称为 portlet application 。在同一个 portlet application 中,他们将分享同一个 classloader,context 及 session。

1) Portlet 和 Servlet 的相似之处

@ portlets 也是 Java 技术的 web 组件
@ portlets 也是有特定的 container 在管理
@ portlets 可以动态产生各种内容
@ portlets 的生命周期由 container 所管理
@ portlets 和客户端的互动是通过 request/response 的机制

2) Portlet 和 Servlet 也有一些不同

@ portlets 只产生 markup 信息片段,不是完整的网页文件。而 Portal 会将所有的 Portlet markup 信息片 段放到一个完整的 Portal 网页。
@ portlets 不会和 URL 有直接的关系
@ 客户端必须通过 portal 系统才能和 portlets 互动
@ portlets 有一些定义好的 request 处理,action request 以及 render request。
@ portlets 默认定义 portlet modes 及窗口状态可以指出在网页中该 portlet 的哪个功能正在执行及现在的 状态。
@ portlets 可以在同一个 portal 网页之中存在多个。

3) Portlet 有一些附加的功能是 Servlet 所没有的

@ Portlets 能够存取及储存永久配置文件及定制资料。
@ portlets 可以存取使用者数据
@ portlets 具有 URL 的重写功能在文件中去动态建立连结,允许 portal server 不用去知道如何在网页的片 段之中建立连结及动作。
@ portlets 可以储存临时性的数据在 portlet session 之中,拥有两个不同的范围 :
application-wide scope 及 portlet private scope 。

4) Portlet 不具有一些功能, 但是 Servlet 却有提供

@ servlet 具有设置�出的文字编码( character set encoding)方式
@ servlet 可以设置 HTTP 输出的 header
@ servlet 才能�蚪邮湛突Ф杂�portal 发出的 URL 请求

ch4 RI – pluto 冥王星计划

JSR 是由 JCP ( www.jcp.org ) 这个 Java 组织所定义出来的规范。几乎每个 JSR 都会产出 TCK* 及 RI**

*TCK ( Technology Compatibility Kit ) 兼容性测试组件
*RI ( Reference Implementation ) 实现参考

2003/10/27 JSR#168 Portlet Spec 1.0 已经正式公布。以后, 大家就可以开始根据这个规范开发兼容性的产品。而这个标准规范书的 RI 就是采用 Apache Jakarta Pluto 冥王星计划。至于为何叫做冥王星,我猜是 Sun 想要把光芒射到冥王星都会发光吧 :P

目前 pluto 尚未有正式的版本释放, 将来有兴趣的人可以从 jakarta 网站下载。不过目前我由 CVS 取得版本已经可以正常运行了。安装的方法十分简单.. 只需要执行 %pluto%/bin/install 就可以安装了,安装过程会询问你 tomcat 的目录,假设你 tomcat 根目录是 c:\tomcat4.1.27 ,你输入 c:\tomcat4.1.27 就可以了。

接着 http://localhost:8080/pluto/portal 就可以看到很漂亮的 portal 界面,至于操作模式与方法非常简单,请多加操控就可以慢慢了解 portlet 的控制方法了。

在 portlet spec 中定义的控制有分为
1) 基本的 Portlet Modes
VIEW – 你没有做任何动作仅仅做内容显示
EDIT – 编辑相关的设置
HELP – 寻求帮助

2) 基本的 Window States
NORMAL – 还原 portlet 窗口
MAXIMIZED – 最大化 portlet 窗口
MINMIZED – 最小化 portlet 窗口

其实, 这些动作都已经由 portal 所实现,portlet container 将接收与回应相关的动作。真正在程序开发上并不会考虑到这些细节,除非你要做一�� portlet container。而开发上要考虑的是什么人能�蜃鍪裁词虑椤@�如说尚未登陆的人应该只���doView / doHelp,而不能��doEdit 这种权限管控机制的开发。

ch5 css 定义

每个通过认证的使用者,就可以使用相关的 portlet 外观 ( Look&Feel )设置,而这些设置就是通过 css 来 编辑。在没有 portlet spec 之前,各家厂商都自行规定或由 ISV 各自完成,造成了�多 portlet 无法共用同一份 CSS 来实现,移植上将会有许多问题发生。

因此 css 的定义对于具有定制功能的 portal 是相当重要的。

0) Anchor
这个并没有定义 :P

1) Fonts ( font )
portlet-font
portlet-font-dim

2) Message ( paragraph .. )
portlet-msg-status
portlet-msg-info
portlet-msg-error
portlet-msg-alert
portlet-msg-success

3) Sections ( table, div, span … )
portlet-section-header
portlet-section-body
portlet-section-alternate
portlet-section-selected
portlet-section-subheader
portlet-section-footer
portlet-section-text

4) Forms ( form )
portlet-form-label
portlet-form-input-field
portlet-form-button
portlet-icon-label
portlet-dlg-icon-label
portlet-form-field-label
portlet-form-field

5) menus ( popup menu )
portlet-menu
portlet-menu-item
portlet-menu-item-selected
portlet-menu-item-hover
portlet-menu-item-hover-selected
portlet-menu-cascade-item
portlet-menu-cascade-item-selected
portlet-menu-description
portlet-menu-caption

基本上, 你要了解什么地方该用什么 css,这些 css 名称套用在你开发的 portlet 之中,你就可以移植到其他支持 jsr#168 的系统,不需要在花时间去更改成为他们的 Look&Feel。

ch6 信息片段 ( fragment markup ) 的限制

每个 portlet 输出都是一个信息片段,之前有提到, 这些 markup 有些限制。

如果你是生成 HTML 格式的信息片段,就*不可以*拥有以下这些 tag :
base, body, iframe, frame, frameset, head, html, 及 title

如果生成是 XHTML 或 XHTML-basic 格式的信息片段,就*不可以*拥有以下这些 tag :
base, body, iframe, head, html 及 title

ch7 其他细节

最后, portlet 需要考虑的还有 security, caching, taglib 等等..

Portal 是连结后端 EAI 处理的信息整合平台,提供了企业完整的解决方案,提供了单一登陆的机制,贴心的个人化页面设置,更可以提供各式各样平台如 pda, 手机等等的统一窗口。因此, 政府与大企业都 *应该* 采用这种解决方案,通过 Webservice 达成信息流/金流/物流 的效果….

Content Extract

十一月 29, 2004

1. Noncommercial Products:

http://www.etymon.com/epub.html

PJX specifically included significantly faster reading and writing of PDF documents, thread safety, “on demand” reading and parsing of PDF objects which greatly reduces memory usage and processing time, incremental update support to enable fast modification of PDF documents, reading PDF documents from either disk or memory, thorough documentation of the class library interface, support for J2SE collection classes and NIO, access to form/field objects, rudimentary support for insertion of images and watermarks, appending of large documents, and design patterns for recursive processing of PDF objects.

http://www.pdfbox.org/

PDFBox is a Java PDF Library. This project will allow access to all of the components in a PDF document. More PDF manipulation features will be added as the project matures. This ships with a utility to take a PDF document and output a text file.

http://www.foolabs.com/xpdf/about.html

Xpdf is an open source viewer for Portable Document Format (PDF) files. (These are also sometimes also called ‘Acrobat’ files, from the name of Adobe’s PDF software.) The Xpdf project also includes a PDF text extractor, PDF-to-PostScript converter, and various other utilities.

http://jakarta.apache.org/poi/index.html

The POI project consists of APIs for manipulating various file formats based upon Microsoft’s OLE 2 Compound Document format using pure Java. In short, you can read and write MS Excel files using Java. Soon, you’ll be able to read and write Word files using Java. POI is your Java Excel solution as well as your Java Word solution. However, we have a complete API for porting other OLE 2 Compound Document formats and welcome others to participate.

2. Commercial Products:

http://tonicsystems.com/products/

Tonic Systems is the leading PowerPoint® automation specialist. Each of our products has been born from our experience developing solutions to real life business challenges, and each has been proven extensively in enterprise environments.

We have developed our range of products in response to customer demand. These 100% java, server-side products are robust and scalable to meet the needs of the most demanding environments.

http://snowtide.com/home/PDFTextStream/

PDFTextStream is the ideal solution for Java applications and J2EE web services that need to rapidly and accurately extract text and document metadata from PDF files.

Update:

以上这些基本都是PDF的内容抽取,后来我使用过了Aperture这个框架,感觉很好用,虽然现在还没有正式发布,不过CVS上面的代码已经支持绝大多数格式的文档的信息抽取,包括Office系列(Word,Excel,PowerPoint,Publisher等,齐全的令人吃惊),OpenOffice系列,PDF,Plain Text等,还可以方便的进行扩展(我自己写了一些数据库的内容抽取),感觉是一个One size fits all的一站式的解决方案,很值得一试.

今年5月23日,比尔・盖茨先生在《华尔街日报》上撰文,支持和敦促美国政府给予中国永久性正常贸易国待遇。文中,他特别谈到了在清华大学与中国大学生那次对话的愉快经历以及因此而留下的深刻印象。
这篇文章令我不禁想到,在中国的这两年来,我工作中最大的享受也是到国内各高校与学生们进行交流。这些访问和交流使得我有机会与成千上万的青年学生就他们所关心的事业、前途等问题进行面对面的沟通。中国学生的聪明、好学和上进给我留下了非常深刻的印象。
在与这些青年学生的交流过程中,我发现有一些问题是大家都十分关心的。那些已经获得国外大学奖学金的学生,大都希望我谈一谈应该如何度过自己在美国的学习生涯;那些决定留在国内发展的学生,非常关心如何确定一个正确的方向,并以最快的速度在科研和学业方面取得成功;还有那些刚刚踏进大学校门的学生,则希望我能讲给他们一些学习、做人的经验之谈。最近,更有一些学生关心网络信息产业的发展,希望了解美国的大学生是如何创业和致富的。
看到这么多双渴求知识、充满希望的眼睛,我突然产生了一种冲动,那就是给中国的学生们写一封信,将我与同学们在交流过程中产生的一些想法以及我要对中国学生的一些忠告写出来,帮助他们在未来的留学、工作或者创业的过程中能够人格更完美、生活更顺利,事业更成功。

  坚守诚信、正直的原则

我在苹果公司工作时,曾有一位刚被我提拔的经理,由于受到下属的批评,非常沮丧地要我再找一个人来接替他。我问他:“你认为你的长处是什么?”他说,“我自信自己是一个非常正直的人。”我告诉他:“当初我提拔你做经理,就是因为你是一个公正无私的人。管理经验和沟通能力是可以在日后工作中学习的,但一颗正直的心是无价的。”我支持他继续干下去,并在管理和沟通技巧方面给予他很多指点和帮助。最终,他不负众望,成为一个出色的管理人才。现在,他已经是一个颇为成功的公司的首席技术官。
与之相反,我曾面试过一位求职者。他在技术、管理方面都相当的出色。但是,在谈论之余,他表示,如果我录取他,他甚至可以把在原来公司工作时的一项发明带过来。随后他似乎觉察到这样说有些不妥,特作声明:那些工作是他在下班之后做的,他的老板并不知道。这一番谈话之后,对于我而言,不论他的能力和工作水平怎样,我都肯定不会录用他。 原因是他缺乏最基本的处世准则和最起码的职业道德“诚实”和“讲信用”。如果雇用这样的人,谁能保证他不会在这里工作一段时间后,把在这里的成果也当作所谓“业余之作”而变成向其它公司讨好的“贡品”呢?这说明:一个人品不完善的人是不可能成为一个真正有所作为的人的。
在美国,中国学生的勤奋和优秀是出了名的,曾经一度是美国各名校最欢迎的留学生群体。而最近,却有一些学校和教授声称,他们再也不想招收中国学生了。理由很简单,某些中国学生拿着读博士的奖学金到了美国,可是,一旦找到工作机会,他们就会马上申请离开学校,将自己曾经承诺要完成的学位和研究抛在一边。这种言行不一的做法已经使得美国相当一部分教授对中国学生的诚信产生了怀疑。应该指出,有这种行为的中国学生是少数,然而就是这样的“少数”,已经让中国学生的名誉受到了极大的损害。另外,目前美国有很多教授不理会大多数中国学生的推荐信,因为他们知道这些推荐信根本就出自学生自己之手,已无参考性可言。这也是诚信受到损害以后的必然结果。
我在微软研究院也曾碰到过类似的问题。一位来这里实习的学生,有一次出乎意料地报告了一个非常好的研究结果。但是,他做的研究结果别人却无法重复。后来,他的老板才发现,这个学生对实验数据进行了挑选,只留下了那些合乎最佳结果的数据,而舍弃了那些“不太好”的数据。我认为,这个学生永远不可能实现真正意义的学术突破,也不可能成为一名真正合格的研究人员。
最后想提的是一些喜欢贪小便宜的人。他们用学校或公司的电话打私人长途、多报销出租车票。也许有人认为,学生以成绩、事业为重,其它细节只是一些小事,随心所欲地做了,也没什么大不了的。然而,就是那些身边的所谓“小事”,往往成为一个人塑造人格和积累诚信的关键。一些贪小便宜、耍小聪明的行为只会把自己定性为一个贪图小利、没有出息的人的形象,最终因小失大。对于这些行为,一言以敝之,就是“勿以恶小而为之”。

  生活在群体之中

与大多数美国学生比较而言,中国学生的表达能力、沟通能力和团队精神要相对欠缺一些。这也许是由于文化背景和教育体制的不同而造成的。今天,当我们面对一个正在走向高度全球化的社会时,生活在群体之中,做出更好的表现,得到更多的和收获,是尤为重要的。
表达和沟通的能力是非常重要的。不论你做出了怎样优秀的工作,不会表达,无法让更多的人去理解和分享,那就几乎等于白做。所以,在学习阶段,你不可以只生活在一个人的世界中,而应当尽量学会与各阶层的人交往和沟通,主动表达自己对各种事物的看法和意见,甚至在公众集会时发表演讲,锻炼自己的表达能力。
表达能力绝不只是你的“口才”。哈佛大学的Ambady教授最近做过一个非常有趣的实验,他让两组学生分别评估几位教授的授课质量。他把这几位教授的讲课录像带先无声地放两秒钟给一组学生看,得出一套评估结果。然后与那些已经听过这几位教授几个月讲课的学生的结果进行对比,两个小组的结论竟然惊人的相似。这表明,在表达自己思想的过程中,非语言表达方式和语言同样重要,有时作用甚至更加明显。这里所讲的非语言表达方式是指人的仪表、举止、语气、声调和表情等。因为从这些方面,人们可以更直观、更形象地判断你为人、做事的能力,看出你的自信和热情,从而获得十分重要的“第一印象”。
对于一个集体、一个公司、甚至是一个国家,团队精神都是非常关键性的。微软公司在美国以特殊的团队精神著称。象Windows 2000这样产品的研发,微软公司有超过3000名开发工程师和测试人员参与,写出了5000万行代码。没有高度统一的团队精神,没有全部参与者的默契与分工合作,这项工程是根本不可能完成的。
相对来说,以前我在别的公司时也曾见到这样的现象。一项工程布置下来,大家明明知道无法完成,但都心照不宣,不告诉老板。因为反正也做不完,大家索性也不努力去做事,却花更多的时间去算计怎么把这项工程的失败怪罪到别人身上去。就是这些人和这样的工作作风几乎把这家公司拖垮。
为了培养团队精神,我建议同学们在读书之余积极参加各种社会团体的工作。在与他人分工合作、分享成果、互助互惠的过程中,你们可以体会团队精神的重要性。
在学习过程中,你千万不要不愿意把好的思路、想法和结果与别人分享,担心别人走到你前面的想法是不健康的,也无助于你的成功。有一句谚语说,“你付出的越多,你得到的越多”。试想,如果你的行为让人觉得“你的是我的,我的还是我的”,当你需要帮忙时,你认为别人会来帮助你吗?反之,如果你时常慷慨地帮助别人,那你是不是会得到更多人的回报?
在团队之中,要勇于承认他人的贡献。如果借助了别人的智慧和成果,就应该声明。如果得到了他人的帮助,就应该表示感谢。这也是团队精神的基本体现。

  做一个主动的人

三十年前,一个工程师梦寐以求的目标就是进入科技最领先的IBM。那时IBM对人才的定义是一个有专业知识的、埋头苦干的人。斗转星移,事物发展到今天,人们对人才的看法已逐步发生了变化。现在,很多公司所渴求的人才是积极主动、充满热情、灵活自信的人。
作为当代中国的大学生,你应该不再只是被动地等待别人告诉你应该做什么,而是应该主动去了解自己要做什么,并且规划它们,然后全力以赴地去完成。想想今天世界上最成功的那些人,有几个是唯唯诺诺、等人吩咐的人?对待自己的学业和研究项目,你需要以一个母亲对孩子那样的责任心和爱心全力投入不断努力。果真如此,便没有什么目标是不能达到的。
一个积极主动的人还应该虚心听取他人的批评和意见。其实,这也是一种进取心的体现。不能虚心接受别人的批评,并从中汲取教训,就不可能有更大的进步。比尔・盖茨曾经对公司所有员工说过:“客户的批评比赚钱更重要。从客户的批评中,我们可以更好地汲取失败的教训,将它转化为成功的动力。”
除了虚心接受别人的批评,你还应该努力寻找一位你特别尊敬的良师。这位良师应该是直接教导你的老师以外的人,这样的人更能客观地给你一些忠告。这位良师除了可以在学识上教导你之外,还可以在其它一些方面对你有所指点,包括为人处世,看问题的眼光,应对突发事件的技能等等。我以前在苹果公司负责一个研究部门时,就曾有幸找到这样一位良师。当时,他是负责苹果公司全球运作和生产业务的高级副总裁,他在事业发展方面给我的许多教诲令我终身受益。如果有这样的人给你帮助,那你成长的速度一定会比别人更快一些。
中国学生大多比较含蓄、害羞,不太习惯做自我推销。但是,要想把握住转瞬即逝的机会,就必须学会说服他人、向别人推销自己或自己的观点。在说服他人之前,要先说服自己。你的激情加上才智往往折射出你的潜力,这就是人们常说的化学反应。一般来说,一个好的自我推销策略可以令事情的发展锦上添花。
例如,有一次我收到了一份很特殊的求职申请书。不同于已往大多数求职者,这位申请人的求职资料中包括了他的自我介绍、他对微软研究院的向往、以及他为什么认为自己是合适的人选,此外还有他已经发表的论文、老师的推荐信和他希望来微软作的课题等。尽管他毕业的学校不是中国最有名的学校,但他的自我推销奏效了。我从这些文件中看到了他的热情和认真。在我面试他时,他又递交了一份更充分的个人资料。最后,当我问他有没有问题要问我时,他反问我,:“你对我还有没有任何的保留?”当时,我的确对他能否进入新的研究领域有疑虑,于是就进一步问了他一些这方面的问题。他举出了两个很有说服力的例子。最后,我们雇用了这名应聘者。他现在做得非常出色。

  挑战自我、开发自身潜力

我在苹果公司工作的时候,有一天,老板突然问我什么时候可以接替他的工作?我非常吃惊,表示自己缺乏象他那样的管理经验和能力。但是他却说,这些经验是可以培养和积累的,而且他希望我在两年之后就可以做到。有了这样的提示和鼓励,我开始有意识地加强自己在这方面的学习和实践。果然,我真的在两年之后接替了他的工作。我个人认为:一个人的领导素质对于他将来的治学、经商或从政都是十分重要的。在任何时候、任何环境里,我们都应该有意识地培养自己的领导才能。同时, 我建议你给自己一些机会展示这方面的能力,或许象我一样,你会惊讶自己在这一方面的潜力远远超过了想象中那样。
给自己设定目标是一件十分重要的事情。目标设定过高固然不切实际,但是目标千万不可定得太低。在二十一世纪,竞争已经没有疆界,你应该放开思维, 站在一个更高的起点,给自己设定一个更具挑战性的标准,才会有准确的努力方向和广阔的前景,切不可做“井底之蛙”。另外,只在一所学校取得好成绩、好名次就认为自己已经功成名就是可笑的,要知道,山外有山,人上有人,而且,不同地方的衡量标准又不一样。所以,在订立目标方面,千万不要有“宁为鸡首,不为牛后”的思想。
一个一流的人与一个一般的人在一般问题上的表现可能一样,但是在一流问题上的表现则会有天壤之别。美国著名作家威廉・福克纳说过:“不要竭尽全力去和你的同僚竞争。你更应该在乎的是:你要比现在的你更强。”你应该永远给自己设立一些很具挑战性、但并非不可及的目标。
在确立将来事业的目标时,不要忘了扪心自问:“这是不是我最热爱的专业?我是否愿意全力投入?”我希望你们能够对自己选择所从事的工作充满激情和想象力,对前进途中可能出现的各种艰难险阻无所畏惧。谈到对工作的热爱,我认识的一位微软的研究员曾经让我深有感触。他经常周末开车出门说去见“女朋友”,后来,一次偶然机会我在办公室里看见他,问他“女朋友在哪里?”他笑着指着电脑说:“就是她呀。”对于工作的热爱,比尔・盖茨也曾有过非常精彩的阐述,他说:“每天早晨醒来,一想到所从事的工作和所开发的技术将会给人类生活带来的巨大影响和变化,我就会无比兴奋和激动。”
几个月前,《北京青年报》上曾有一场探讨比尔・盖茨和保尔・柯察金谁更伟大的讨论。由于从小在美国长大,我并不知道保尔和他的那些事迹。但是,我非常赞同保尔的这段名言:“人最宝贵的东西是生命,生命属于我们只有一次。人的一生应当这样度过,当他回首往事的时候,不因虚度年华而悔恨,也不因碌碌无为而羞耻……”所以,选择一个你真心热爱的事业,不断地挑战自我、完善自我,让自己的一生过得精彩和充实。
客观、直接了当的沟通
有一次,一位中国的大学教授找到我,希望我帮他找一位国外的专家在他组织的会议上去作主题演讲,末了还特意加了一句,最好是一个洋人。我很不以为然地对他说:“这个领域最具权威的人士就是在北京的一个中国人,为什么你一定要找一位洋人呢?”他表面上同意我的说法,但是他仍然请了一个美国人来作这个演讲,结果效果很差。所以,我们不应该陷入盲目的崇洋情结。我们应该用客观的眼光来判断事物,而不是以他的肤色或他的居住地来决定。
有一句话说,“真理总是掌握在少数人手中”。我们理解这句话的意思,应该有自己的眼光,有独立思考的能力,不一定大多数人认可的,或某个权威说的,就是对的。不论是作学问、搞研究还是经商,我们都不能盲从,要多想几个为什么。
有了客观的意见,你就应该直接了当地表达。如果做任何事情都象“打太极拳”,会让人不知所云,也会造成很多误会。有一次,在微软研究院工作的一位研究人员就自己所选择的研究方向来征求我的意见,我作了一番分析,认为这个方向有不少问题,我个人认为对学术界的贡献不大,但如果他坚持,我愿意支持他试着去做。结果他认为我这句话的意思实际上就是不允许他去做,所以他就选择了其它的方向。后来他要出差时,负责行政事务的人告诉他,你可以选择坐火车或者坐飞机。他认为行政人员实际上是在暗示他坐火车,因为坐飞机太贵。其实,他的猜测都是错误的。因为我们的沟通方式是直接了当,而他却在“打太极拳”。这之后,我们通过一系列的公司文化讲座,让员工们了解到:心里想什么就讲什么,不要把简单的问题复杂化。现在,研究院里这类的误会少了很多。
拐弯抹角,言不由衷,结果浪费了大家的宝贵时间。瞻前顾后,生怕说错话,结果是变成谨小慎微的懦夫。更糟糕的是还有些人,当面不说,背后乱讲,这样对他人和自己都毫无益处,最后只能是破坏了集体的团结。这样的人和作风既不能面对社会,也不可能在科学研究中走出新路,更不可能在激烈的商战中脱颖而出。
希望同学们能够做到开诚布公,敢于说“不”,这才是尊重自己思想意愿的表现。当然,在表达你的意见时,无论反对和批评都应是建设性的,有高度诚意的,而不是为批评而批评,为辩论而批评。我赞成的方式是提供建设性的正面的意见。在开始讨论问题时,任何人先不要拒人千里之外,大家把想法都摆在桌面上,充分体现个人的观点,这样才会有一个容纳大部分人意见的结论。当然,你也要学习用适当的方法和口气表达你的意见,比如说不要在很多人面前让别人难堪。这样,你的批评才会奏效。

  珍惜校园学习生活

几天前,报纸上登出一条消息,说有中学生辍学去开网络公司。我认为这并不值得提倡。对绝大多数学生来讲,在校生活是系统地学习基础理论知识,学习思考和解决问题方式的好机会。这些知识将成为你未来发展过程中所需要的最基本的知识和技能。就象建一栋高楼,如果不打好基础是经不起风吹雨打的。
在全球范围内,美国的研究水平无疑是世界一流的。而除了美国之外,你会发现英国的研究水平也是相当突出的。究其原因,其实就是语言问题。英国人可以毫无阻碍地阅读美国乃至全球各种最新的英文研究报告和资料。这对于他们把握研究方向,跟踪最新进展,发表研究成果都有很大的帮助。因此,英语学习对于我们作研究的人来说,也是相当重要的。只有加强这方面素质的培养,才能适应将来的发展。我建议:学英语先学听说,再学读写,而且务必在大学阶段完全解决英语学习的问题。等到年龄大了,要付出的代价相比就会大得多。
除了英语之外,数学、统计学对理工科学生也是很重要的基础课程,是不可忽视的。数学是人类几千年的智慧结晶,你们一定要用心把它学好,不能敷衍了事。我今天就很后悔自己当初没有花更多功夫把数学学得更好些。另外,计算机应用、算法和编程也都是每一个工科学生应该熟悉和掌握的,它们是将来人人必须会用的工具。
科技的发展可谓日新月异。在校学习的目的,其实就是掌握最基本的学习工具和方法。将来利用这些工具和方法,再去学习新的东西。比如:上课学会了C++, 能否自己学会Java? 上课学会了HTML, 能否自己学会XML? 与其说上大学是为了学一门专业,不如说是为了学会如何学习,让自己能够“无师自通”。
大学毕业后的前两年,同学们聚到一起,发现变化都还不算大。五年后再聚到一起,变化就大多了。一些人落伍了,因为他们不再学习,不再能够掌握新的东西,自然而然地落在了社会发展的后面。如果我们要在这个竞争激烈的社会中永不落伍,那就得永远学习。
我的老板 – Rick Rashid博士是目前微软公司主管研究的高级副总裁,他已经功成名就,却始终保持着一颗学习和进取的心。现在,他每年仍然编写大约50,000行程序。他认为:用最新的技术编程可以使他保持对计算机最前沿技术的敏感,使自己能够不断进步。今天,有些博士生带着低年级的本科生和硕士生做项目,就自满地认为自己已经没有必要再编程了。其实,这样的做法是很不明智的。
每次到清华和其它学校访问,被问到最多的就是学生打工的问题。我认为,打工从总体来说对学生是一件好事,是拓宽视野的一种方式。例如:在研究机构打工,可以学到最新的科技;在产品部门打工,可以学到开发的技术和技能;在市场部门打工,可以理解商业的运作。我认为每一个学生都应该有打工的经验,但不要打一些“没用的工”。首先要明白打工只是学生生活中的一种补充,学习才是最重要的。打工的目的是开阔眼界,不是提前上班。如果你把翻译书本、录入数据库所花的时间投入学习,将来可以赚更多的钱。那些钱将远远超出目前打工的收入。
此外,还有一些学生受到目前退学创业的鼓励,为成为中国的比尔・盖茨和迈克尔・戴尔而中途辍学。以我的观点,除了十分特殊的情况,我不建议在校学生退学创业。你所看到的那些退学创业的成功者实际上少之又少。目前,大部分学生虽有创业的想法,但缺少创业的经验,所以失败的可能性非常大。如果要成功,我建议你们先把书读好。如果是要学习创业的经验,你完全可以利用假期的时间先去一间公司边打工边学。比尔・盖茨也曾说过,“如果你正在考虑自己成立一家新公司,你应该首先明确地知道:创办公司需要巨大的精力投入,要冒巨大的风险。我觉得你们不必象我,一开始就创办一家公司。你应该考虑加盟其他公司并在这家公司中学习他们的工作、创业方法。”

  你想戴一顶什么样的博士帽

在我进入卡内基梅隆大学攻读计算机博士学位时,系主任曾对我讲,当你拿到你的博士学位时,你应该成为你所从事的研究领域里世界第一的专家。这句话对于初出茅庐的我来说简直高不可攀,但也让我踌躇满志、跃跃欲试。就这样,在经过五年寒窗、夜以继日的努力工作后,他所期待的结果就那么自然而然地出现了。一个打算攻读博士学位的人,就应该给自己树立一个很高的目标。如果没有雄心壮志,就千万不要自欺欺人,也许经商或从事其它工作,会有更大的成绩。
在目标确立之后,我建议你为自己设计一个三年的学习和科研计划。首先,你需要彻底地了解在相关领域他人已有的工作和成绩。然后再提出自己的想法和见解,做脚踏实地的工作。另外,还要不断跟踪这个领域的最新研究进展。只有这样,才可以把握好方向,避免重复性工作,把精力集中在最有价值的研究方向上。
在学术界,人们普遍认为“名师出高徒”。可见导师在你的成长道路中作用是多么的大。所以,你应该主动去寻找自己所研究的领域里最好的老师。除了你的老师之外,你还应该去求教于周围所有的专家。更不要忘了常去求教“最博学的老师”- Internet!现在,几乎所有的论文、研究结果、先进想法都可以在网上找到。我还鼓励你直接发电子邮件去咨询一些世界公认的专家和教授。以我的经验,对于这样的邮件,他们中的大部分都会很快给你回复。
我在攻读博士学位时,每周工作七天,每天工作16个小时,大量的统计结果和分析报告几乎让我崩溃。那时,同领域其他研究人员采用的是与我不同的传统方法。我的老师虽然支持我,但并不认可我的研究方向。我也曾不止一次地怀疑自己的所作所为是否真的能够成功。但终于有一天,在半夜三点时做出的一个结果让我感受到了成功的滋味。后来,研究有了突飞猛进的进展,导师也开始采用我的研究方法。我的博士论文使我的研究成为自然语言研究方面当时最有影响力的工作之一。读博士不是一件轻松的事,切忌浮躁的情绪,而要一步一个脚印,扎扎实实地工作。也不可受一些稍纵即逝的名利的诱惑, 而要200%的投入。也许你会疲劳,会懊悔,会迷失方向,但是要记住,你所期待的成功和突破也正孕育其中。那种一切都很顺利,谁都可以得到的工作和结果,我相信研究价值一定不高。
从一定意义上讲,一个人如果打算一辈子从事研究工作,那么从他在读博士学位期间所形成的做事习惯、研究方法和思维方式基本上就可以判断出他未来工作的轮廓。所以,你一定要做一个“有心人”,充分利用在校的时间,为自己的将来打好基础。

上述一些观点,是我在与同学们交往过程中的一些感受。我希望这些建议和想法能对正在未来之路上跋涉的你们有所启发,能对你们目前的学习有所帮助。或许因为观点不同、人各有志,或许因为忠言逆耳,这封信可能无法为每一位同学所接受。但是只要一百位阅读这封信的同学中有一位从中受益,这封信就已经比我所作的任何研究都更有价值。我真诚地希望,在新的世纪,中国学生无论是在国内,还是国外;无论是做研究,还是经商,都显得更成熟一些,成功的机率更大一些。

[转]伟大架构师的秘密

十一月 23, 2004

伟大架构师的秘密

By Don Awalt and Rick McUmber
RDA Corporation
摘要:所有伟大的架构师都掌握了在抽象的不同层次上概念化解决方案的技能。通过将解决方案组织到离散的层次,架构师可以专注于解决方案的单个方面而忽略所有剩余的复杂性。展示将抽象层次应用到 IT 解决方案的技术,并将其与其他工程学科相比较。

*

本页内容
http://blogger.org.cn/blog/将抽象层次应用到 IT 解决方案 将抽象层次应用到 IT 解决方案

将抽象层次应用到 IT 解决方案

企业架构师正受到其所面临的大量复杂性的挑战。开发一个能够自动处理企业任务的独立的部门应用程序是一回事。而设计并组成一个支持上万 IT 使用者的满是应用程序、服务器和数据库(全都支持多种企业活动)的 IT 实验室全球网络,则完全是另外一回事。要组合这些复杂性,IT 网络必须随时可用、响应迅速并保护企业宝贵的信息资产。除所有这些之外,IT 网络还必须足够灵活以支持企业永远变化的需要,并且采用出现的新技术。

一些架构师在这种复杂性方面明显非常出色,而且在不断进步。在我们的职业生涯中,能与一些真正伟大的分析师和架构师并肩工作是非常幸运的。反思这些经验,我们已经分析出是什么造就了杰出的架构师。

无一例外,所有伟大的架构师都掌握了在截然不同的抽象层次上概念化解决方案的技能。通过将解决方案组织到离散的层次,架构师可以将精力集中在解决方案的单个方面而忽略所有剩余的复杂性。他们一旦稳定了解决方案的某个部分,接下来就能继续处理其他方面,从而不断地将层次发展并完善到最终可以被实现的粘合模型中。

大多数软件开发人员懂得应该将解决方案分解到抽象层次。但是在实际的项目中,这是非常难于付诸实践的。当遇到第一个困难时,在急于开始编码时是很容易放弃这些层次的。伟大的架构师会经受这些挑战并在整个项目的生命周期中严格保持这些层次。他们意识到,如果不这样做,最终将淹没在复杂性中。

本文展示了将抽象层次应用到 IT 解决方案的技术。首先,我们会通过一个简单的示例演示此方法,然后提出一个基于正式抽象层次的系统产品的结构。

抽象层次:所有工程师的强大武器

其他的工程学科,比如土木工程师,几个世纪以来一直利用抽象层次复制复杂性。让我们学习一下其他更成熟的工程学科是如何应用抽象层次的,就从电子工程师开始吧,他们设计每次更新换代都变得更加复杂的计算机系统。

硬件工程师

系统设计师使用抽象层次为计算机系统建模。每个层次都是定义完善的,并提供了该系统的一个不同角度。许多系统是在三个主要层次上设计的:系统、子系统和组件,如 1 所示。

分层使工程师能够将庞大数量的复杂性集成到一个单一的工作计算机系统中。在其原子部分的层次上确切了解一台计算机是不可能的。在单独一块 Intel Itanium_ 芯片上有大约 25,000,000 个晶体管。

对 IT 相关学科来说,这种把复杂性分解到抽象层的方法当然不是惟一的。类似的方法被用于从航空工程到微生物学的无数其他学科。

应用抽象层次时的核心原则

所有工程师在应用抽象层次时都遵循这套核心原则。当把抽象层次应用到软件时,这些原则也同样适用。

这些层次的数量和范围是定义完善的,以便工程师能够在复杂的系统上协作,所有团队成员必须共享对层次的同一理解。只要设计师做出设计决定,他们必须将那些决定归档到相应的细节层次。

三个抽象层次定义如下:

greatarchitect_figithumb i. 定义的三个抽象层次

greatarchitect_figiithumb ii.抽象层次的一个简单框架

每个层次内的多个视图

一个单个层次内的复杂性可以变得非常多,以至于使人无法一次全部掌握。在这种情况下,工程师通过多个视图将设计展现于单个层次内。每个视图展现设计的一个单独方面,但保持在相同的抽象层次上。举例来说,母板工程师为板的每个层创建一个视图,从而为每层的连接路径的设计建模。

greatarchitect_fig1 1. 计算机系统的抽象层次

必须保持层次间的一致性

为了让系统按预期方式运行,每个后续的层必须是其父层的适当改进。如果计算机系统设计师从 IDE 总线切换到 SCSI 总线,那么所有设备的接口规范也必须切换到 SCSI。如果层次没有同步,那么系统就不会按预期方式在顶层执行。

将抽象层次应用到 IT 系统

既然我们已经分析了其他学科是如何应用抽象层次的,现在就让我们将此技术应用于 IT 解决方案1。下列部分展示了应用抽象层次为典型 IT 应用程序的需求、设计和实现建模的技术。这些技术是通过一个针对假想零售商的简单的、指导性的在线定单系统示例来展示的。在我们的示例中,我们不仅包括了体系结构,而且扩展了范围以包括系统需求和业务环境 ― 如同由零售业所定义的。

简单框架:四个抽象层次

我们的简单示例定义 IT 解决方案的如下四个抽象层次:

业务处理
逻辑
物理

在每个层次内,我们既展示了该特定层次行为的动态视图,又展示了其静态视图。动态视图为对象之间的消息建模,而静态视图为对象之间的结构和关系建模。

域抽象层次

应用了上面的范围规则,零售商就会作为域层次中的黑盒子中心的演员。客户作为外部的演员。域层次是从客户的角度来建模的。只为购买交互建模。用于完成购买的通讯形式不包括在这个层次,但是会在业务处理层次引入。

greatarchitect_fig2 2. 关于从零售商处购买物品的域层次动态视图

greatarchitect_fig3 3. 关于从零售商处购买物品的域层次静态视图

动态视图

域层次内的动态视图为客户和零售商之间的交互建模。下图汇总了域环境,并包含了简单的业务交互使用案例描述。

greatarchitect_fig4 4. 关于从零售商处购买物品的业务处理层次动态视图

静态视图

域层次的静态视图为类结构和在使用案例中出现的它们的对象的关系建模。换句话说,它说明了在这个抽象层次上,为了完成购买交易客户需要了解什么对象。 5 展示了域层次静态视图的类关系图。

greatarchitect_fig5 5. 关于从零售商处购买物品的业务处理层次静态视图

客户是 Person 的实例。客户和零售商之间的关系被具体化为 Account。所有的 Purchase 都与客户的 Account 相关。Purchase 与每个被购买的 Item 相关。每个 Item 都与特定的 Product 相关,这里 Product 遵循元类模式。Product 的实例实际上本身就是类。将其他 Product 添加到 Catalog 完全是一个数据驱动过程,而且不会对类模型产生影响,因此将 Product 建模为一个元类会使我们的模型更加灵活。围绕这些类,每个 Payment 都与其 Purchase 相关。

如您可能看到的,这个层次的模型对大多数零售商(无论类型为在线或传统,大型或小型)来说是有代表性的。这说明了为什么 [Industry] 域模型确实应该将公司定义为黑盒子中心的演员。同一个行业中的公司倾向于支持带有其外部演员的同一套业务交互。此外,域模型排除了公司的特定业务处理,这是因为在同一行业中的公司之间它们会有相当大的变化。

域层次严格集中在从外部演员的角度看到的业务交互。对此我们必须注意,不要将用于完成交互的实现机制包括进来。这些细节属于下一个抽象层次。因此,在本例中,我们只为浏览、选择、购买和支付建模。我们不为如何完成这些交互(通过电话、美国邮政、电子邮件、Web 应用程序、亲自前往、支票、信用卡或现金)建模。

业务处理抽象层次

下一个抽象层次为公司的业务处理建模,以实现在域层次捕获的交互。系统层次“内部缩放”公司的黑盒子,并标识为完成业务交易而协作的所有员工和系统。在这个层次,要开发的系统作为黑盒子中心的演员。

应用了系统层次的范围规则,在线定单系统就作为黑盒子中心的演员。客户和员工作为外部演员。系统层次是从客户和员工的角度来建模的。客户在线执行购买。支付是通过信用卡完成的。通过将物品运送到客户的收货地址履行定单。出货通知是由电子邮件发送的。

动态视图

动态视图重演了域层次购买交易,这次公开了零售商的内部业务处理。 4 汇总了业务处理环境,并包含了关于系统及其演员之间的交互的简单使用案例描述。

静态视图

这个层次的静态视图对类模型做了改进,以捕获在业务处理层次使用案例中出现的对象。换句话说,“为了在线创建一个定单并履行该定单,客户和雇员需要理解哪些对象?” 5 展示了业务处理层次静态视图的类关系图。我们修改域类模型以捕获在这个抽象层次上的角度。Person、Account 和 Company 抽象保持不变,Catalog 和 Product 也一样。但是,用 Order 替换了来自域模型的抽象 Purchase 事件。

Order 包括 LineItem,它与 Catalog 中的 Product 相关联。因为这个层次为公司的内部业务处理建模,所以我们需要获得现有的库存(最小库存单元 (SKU) 的一个属性,它表示在一个特定位置的物品的库存)。我们也为客户的 UserAccount 建模,它提供对在线系统的访问。Payment 是通过使用 CreditCardAccount 来完成的。Location 代表美国的一个地理位置,它作为账单邮寄地址,同时也作为 Order 的收货地址。Shipment 包含 Shipment 中包括的 Item。

我们在系统抽象层次创造方法来简化业务处理,因此该层次通常需要很多创造力。为此,通常使用业务处理层次上的若干不同形式来实现单个域层次交易。举例来说,一次购买可以通过在线、电话、邮件、传真一个定单表格或者亲自到零售店来完成。对于每一种形式,都需要在业务处理层次为其建模。请注意,尽管对零售商来说 Credit Authorizer 是一个外部演员,但是它还是在这个层次引入,这是因为只需要它实现在该层次首次出现的业务处理。

最后,请注意该系统是技术独立的。我们的在线购买系统可以用任何 Web 技术实现。在系统黑盒子内选择技术是一个体系结构决策。

逻辑抽象层次

逻辑层在系统黑盒子内缩放,从而公开高级别的系统设计。架构师选择技术并定义高级系统结构。在我们的简单示例中,系统是由承载表示层、业务层和数据访问层的 Microsoft IIS/Microsoft ASP.NET 服务器和承载持久性数据的 Microsoft SQL Server 数据库服务器组成的。

动态视图

逻辑层上的动态视图跟踪通过系统主要组件的消息流。如示例所示,在提交 ConfirmOrder Web 表单的时候, 6 跟踪这一消息流。

greatarchitect_fig6 6. 从零售商处在线购买物品的逻辑层次动态视图

静态视图

这个层次的静态视图也将我们的视角切换到系统内部。尽管业务处理层次为出现在业务处理中的真实抽象建立了模型,这个层次将抽象建模为其在系统中所要被表示的那样。在实际的系统中,架构师会为每个软件层(表示层、业务层和数据访问层)设计类。为了保持本文的简洁, 7 只展示了业务层的静态设计,以便说明系统层抽象是如何针对设计进行改进的。

greatarchitect_fig7thumb 7. 从零售商处在线购买物品的逻辑层次静态视图

架构师对系统层类进行改进以设计业务层接口。

因为系统中的所有账户和客户都是零售商的,所以创建一个单一的 Company 实例并使其与所有账户相关联是不切实际的,因此该层次中省略了 Company。我们只是存储 Payment 所带的信用卡号和账单邮寄地址,并非为每个 CreditCardAccount 创建一个单独的实例。此外,对系统来说,为每个出售的 Item 创建一个实例是不切实际的,因此从模型中删除了 Item,并改为由模型跟踪 LineItem 中订购的物品数量以及在新 ShippedItems 类中附带的物品数量。

架构师还定义业务层公开的服务间隔。对于本示例,业务层为 Account、UserAccount、Order、Shipment 和 Catalog 导出了 Create、Read、Update 和 Delete (CRUD) 服务。椭圆形指出了 CRUD 间隔。

请注意,即使本层次的类不是业务处理类的合适超集,架构师也可以通过直接改进业务处理类、将视角由系统外部更改为系统内部来实现这个设计。

物理抽象层次

物理抽象层次捕获系统实现的结构。系统作为一个节点的网络实现,每个节点都配置有硬件和软件。逻辑视图中的三个软件层(表示层、业务层和数据层)是以代码形式被物理实现,并部署到这些节点上。逻辑视图中的持久类物理存储在 SQL Server 数据库的关系表中。

动态视图

动态视图跟踪经过物理配置节点的消息流。ConfirmOrder HTTP post 从客户的浏览器通过 Internet 通过零售商的防火墙流动到 Web 服务器,在那里 Microsoft Windows 将其转发到 IIS,IIS 又将其传递到 Microsoft ASP.NET,然后 ASP.NET 调度 ConfirmOrder.aspx。幸运的是,现代开发工具将我们与多数物理网络隔离开来。但是,架构师需要了解物理层以避免网络瓶颈和安全暴露。

静态视图

静态视图( 8)将逻辑视图中的持久类改进为其物理表示形式。在我们的零售示例中,业务层类存储在下列 SQL Server 表中。

greatarchitect_fig8thumb 8. 从零售商处在线购买物品的物理层次静态视图

映射到关系表和属性的类作为列实现。一对一关系和一对多关系使用一个外键来实现。开放式并发通过给每个被“凝结”的父类分配一个 datetime 字段来实现。

在设计逻辑层次时,架构师主要集中关注于实现系统功能。在确信包含了系统功能之后,架构师就能够专注于在物理层次优化实现。

通过迭代发展层次

建立了这个框架后,架构师通过几次迭代对解决方案加以发展。每次迭代都合并额外的功能 ― 发票、待交定单、亲自订购、电话订购等等。在每种情况下,架构师都更新适当的抽象层次,然后将这些更新改进到物理实现层。

重访抽象层次核心原则

让我们对照核心抽象层次原则来测试我们的示例。

这些层次的数量和范围是定义完善的:我们有四个不同的层次:公司黑盒子、系统黑盒子、系统内的逻辑设计以及物理实现。
每个层次内的多个视图:在这个简单示例中,我们在每个层次上展示了一个动态视图和静态视图。
必须保持层次间的一致性:如果对域模型作出了更改,则更改也一定会影响到较低层次。举例来说,如果零售商决定为其产品提供维护合同,分析师就会将MaintenanceContract 添加到域模型,并将其改进为其物理表现形式。对于维护大型系统来说,同步所有层次是很重要的。因为提交了增强请求,所以分析师执行对相应细节层次的影响评估。一些增强请求影响域层次(并且因此影响所有后续层次)。其他请求只影响物理层次。

扩展层次以支持企业解决方案

既然我们已经展示了带有四个抽象层次的简单示例,现在就让我们扩展这个方法来支持 IT 企业的解决方案。 9 展示了一个 Rational 统一过程 (Rational Unified Process,RUP) 配置,它将项目产品组织到定义完善的抽象层次中。

表中的层次描述如下。

greatarchitect_fig9thumb 9. 将项目产品组织到定义完善的抽象层次中的 RUP 配置

。域层次捕获项目的业务环境。
项目洞察力。项目洞察力对系统将会有的对企业的业务影响进行通讯。它以投资回报分析量化了这个影响。项目洞察力表示该项目的最高抽象层次。
业务处理。系统层次为公司内的业务处理建模。对于极其复杂的单位来说,这个层次可以再细分到子层次:部门、部门间以及部门内。
UI 规范。UI 规范设计了实现业务处理的用户界面。它是由 UI 设计文档和功能 UI 原型组成的。
详细要求。详细要求指定了系统要求的最低层次抽象。它包括诸如数据类型格式和详细业务规则等详细信息。它还包括专业性要求,例如,性能、可用性、安全性、国际化、配置、可扩展性和灵活性要求等。
体系结构。系统的体系结构被组织到六个视图中:

逻辑。定义软件层和执行系统功能的主要抽象。
并发。捕获系统的并行方面,包括交易、服务器场和资源争用。
安全性。定义用于身份验证、授权、保护机密和日志记录的方法。
部署。定义网络拓扑和系统的部署配置。
组件。定义系统组件、其接口以及依赖项。
数据。定义持久性数据的设计结构。

优点

将系统产品组织到离散的抽象层次有若干优点:

它将系统要求分离到三个不同的抽象层次:业务处理、UI 规范和详细要求。我们不会再用令企业用户感到不知所措的单个整体功能规范了。取而代之,我们在三个改进的详细层次中对系统要求进行通讯。
分析师和架构师可以将复杂性控制在一个单一的、集成的系统模型中。
架构师可以专注于系统的单个方面,并将那些决策集成到整个解决方案中。
抽象层次形成了系统产品的结构。举例来说,软件体系结构文档为每个视图专设了一个小节。
抽象层次提供从要求到设计再到实现的直接可跟踪能力。可跟踪能力使小组能够在评测更改请求时执行精确的影响评估。
在使用同一框架开发几个系统之后,会在每个抽象层次形成模式。单位可以编录这些模式和每个抽象层次内的其他最佳实践。这个最佳实践的目录会作为过程改进计划的基础。

小结

为了处理复杂性,所有工程学科都应用正式抽象层次。软件也不例外。为了实现抽象层次的优点,项目必须:

正式标识层次,每个层次都有定义完善的范围。
将一个层次内的复杂性分开到多个视图。
在层次间保持一致性。

通过一个简单的示例,本文演示了如何应用抽象层次,然后将该方法扩展到支持企业 IT 解决方案。它提供了一个 RUP 配置框架,该框架将系统产品组织到定义完善的抽象层次。

自我评估

您当前的项目是否应用了抽象层次?
层次是否定义完善?
项目团队是否很好地理解了这些层次?
如果复杂性在一个层次中变得过大,团队是否将其分离到视图中呢?
团队是否在层次间保持一致性?
您的项目会从抽象层次中获益吗?

伟大的架构师本能地遵循这些原则。我们其余的人就必须有意识地应用抽象层次,并运用规则在整个项目生命周期中保持这些层次。

资源

Cockburn, Alistair. Writing Effective Use Cases. New Jersey: Addison-Wesley, 2001

Kroll, Per and Kruchten, Philippe. The Rational Unified Process Made Easy: A Practitioner’s Guide to the RUP. Boston MA: Pearson Education and Addison-Wesley, 2003

DeMarco, Tom and Plauger, P J Structured Analysis and System Specification. Prentice Hall PTR, 1979

要获得 DoD 标准 2167A 的联机副本,请访问 http://www2.umassd.edu/SWPI/DOD/MIL-STD-2167A/DOD2167A.html

脚注

1 很多人已经成功地将抽象层次应用于软件。Ed Yourdon 和 Tom DeMarco 在 1979 年提出了结构化分析和结构化系统设计的概念。美国政府的许多分支机构标准化了 DoD 的 2167A 标准,它要求系统由有层次的硬件和软件配置项组成。DBA 社区经常应用细节层次为关系数据库建模。特别地,Bachman 工具集和 James Martin 的信息工程方法学 (Information Engineering Methodology,IEM) 先为数据库逻辑建模,然后再为其物理建模。在 Google 上键入“software levels of abstraction”进行搜索会返回若干个结果,但其中大多数来自于学术社区,而且其内容看起来集中在正式计算机语言方面。

关于作者

Don Awalt 是 RDA Corporation 的创始人和 CEO,该公司是一家自定义软件工程公司,成立于 1988 年,在华盛顿特区、巴尔的摩、亚特兰大、费城和芝加哥都设有办事处。作为微软认证金牌伙伴 (Microsoft Gold Certified Partner),该公司专注于使用 .NET Framework 开发企业 Web 和富客户端系统。Don 目前是 Microsoft 华盛顿特区的区域总监,他以前曾经担任费城首任区域总监。Don 经常在行业活动中演讲,这些活动包括 Tech Ed、Developer Days、MSDN 活动和各种 SQL Server 及 Windows 活动。他是 SQL Server Magazine 和 PC Tech Journal Magazine 的特约编辑,并且也为其它出版物撰写稿件。Don 所擅长的技术领域包括 Web 服务、SQL Server、现代编程语言的发展,以及在 Microsoft 的 Prescriptive Architecture Group (PAG) 中可以看到的许多体系结构和处理工作。可以通过 AWALT@rdacorp.com 联系到 Don。

Rick McUmber 是 RDA 的质量和最佳实践总监。他为 IBM 和 Rational Software Corporation 一共工作了 11 年,致力于为美国运输部、国防部、NASA 和加拿大国防部开发系统。从 1994 年以来,他一直在 RDA 工作,致力于为其客户开发业务解决方案。可以通过 McUmber@rdacorp.com 联系到 Rick。

转到原英文页面

#msviFooter_pf {
BORDER-TOP: #ccc 1px solid; FONT: 70% Tahoma, Helvetica
}
#msviFooter_pf A {
FONT-WEIGHT: normal; BACKGROUND: none transparent scroll repeat 0% 0%; COLOR: #03c
}
#msviFooter_pf A:visited {
FONT-WEIGHT: normal; BACKGROUND: none transparent scroll repeat 0% 0%; COLOR: #03c
}
#msviFooter_pf A:hover {
FONT-WEIGHT: normal; BACKGROUND: none transparent scroll repeat 0% 0%; COLOR: #f60
}

1. Google之英文名查询 

今天做英语翻译,碰到一道题目里面要翻”叶利钦”的,不知道他名字的英文是什么,于是很自然的想到到Google上面去搜.不过不知道用什么关键字应该,满碰运气的试了一下”叶利钦 英文名”,结果搜出来一大堆关于叶利钦的新闻什么的,正失望的时候,突然发现在最上方居然有一小块:

叶利钦: Yeltsin
其他网上字典: Dr.eye线上字典

就好像Google提供的天气预报的服务一样的,不过天气预报的话关键字里面要加上”tq”,像”tq 上海”这样的,而上面这个明显智能多了,cool毙了简直!

2. Google之定义查询

在Google的搜索栏里面输入“define:”+keyword就可以找到该关键字的定义:

http://blogger.org.cn/blog/Google 首页  
所有网站 图像 新闻 New! 网上论坛 网页目录
高级搜索
使用偏好

Definitions of WiFi on the Web:

Wireless Fidelity – Otherwise known as Wireless Networking, commonly using the 802.11b protocol. Hardware that displays the WiFi logo claims 802.11b compliance should interconnect seamlessly
www.bb4g.org.uk/glossary.asp

is a way of transmitting information in wave form that is reasonably fast and is often used for notebooks.
highered.mcgraw-hill.com/sites/0072464011/student_view0/chapter6/glossary.html

The popular name for 802.11b wireless networking. This standard replaces the cables in an ethernet network.
home.attbi.com/~pdas/glossary.html

wireless local area network: a local area network that uses high frequency radio signals to transmit and receive data over distances of a few hundred feet; uses ethernet protocol
www.cogsci.princeton.edu/cgi-bin/webwn

Google的feature list

Sigh,真是郁闷,下载了最新release的MySQL 4.1.7,已经是general available的版本了,不知道为什么还是会有问题的,Jena在数据库中创建模型的时候抛出异常 WARN [main] (DriverRDB.java:382) – Problem formatting database
>> java.sql.SQLException: Syntax error or access violation message from server: “Specified key was too long; max key length is 1024 bytes”,
问了Jena的维护人Dave(很好的一个人,很快就回复我了,而且很认真,3q),得到的结论是MySQL在Jena里面设置key的长度不能超过250,否则就会抛出异常,但是默认应该不会超过250的,最后只能归结到Jena和MySQL 4.1.7的conflict上去了,换了MySQL 4.0.22果然就没有问题了(但是4.0.22的安装设置过程实在和4.1.7差太多了,不够人性化).浪费了很多时间在这个问题上,而且解决了之后并没有什么收获,唯一的感触是Jena-dev mailing list上有很多好人

Java Encoding Problem

十一月 16, 2004

这几天一直被Java的编码问题所困扰,开始使用Protege编辑RDF,然后用Jena进行解析,其中Java IDE用的又是Eclipse,几样东西全都是Java的,Java的I/O的API又极其复杂,一出来乱码都不知道到底是哪个环节出了问题.现在终于发现没有任何一个环节有问题,是自己代码有问题,不过问题还没有完全解决,仅仅是完全弄明白了是怎么回事.Protege用UTF-8来保存RDF文件,没问题.Jena解析RDF不牵涉字符编码,没问题.Eclipse根据Java VM所在的平台来选择编码,Windows下用的是GBK.Java I/O API中FileReader和FileWriter用平台的GBK编码,标准输出流System.out用GBK编码.

开始的时候没考虑编码,直接Jena就开始处理了,弄的一头雾水是.后来把Jena先撇开,直接IO读写RDF,结果还是乱码.再后来发现应该直接用FileReader,FileWriter来读写,应该用InputStreamReader和OutputStreamWriter,然后要将二者的编码设成UTF-8来处理文件.这样的话写到磁盘上的文件就不会出现乱码了.但是输出到标准输出流上还是乱码,也就是Eclipse里面的控制台看起来还是乱码(因为System.out是GBK编码).以上只是简要的说了一下开始和结果,中间弯路走了实在太多不再敖述.

这个问题到现在还没想通要怎么解决,想到了两种方法都不是很好,一种是将System.out重定向到某个文件去,用UTF-8输出,然后用外部编辑器查看,但是明显很不方便,不利于调试而且以后每次关于这个System.out的时候都要重定向一下也很不方便.另一种方法是看看行不行重写System.out这个类,将编码改为UTF-8.但是不知道怎么重写还,而且改成UTF-8以后Eclipse的控制台也不确定行不行显示(因为Eclipse是采用容器的GBK编码的,不知道控制台会不会根据System.out的编码而改变编码).Sigh,没想法了我已经…

浅谈Java的输入输出流

Java语言的输入输出功能是十分强大而灵活的,美中不足的是看上去输入输出的代码并不是很简洁,因为你往往需要包装许多不同的对象。在Java类库中,IO部分的内容是很庞大的,因为它涉及的领域很广泛:标准输入输出,文件的操作,网络上的数据流,字符串流,对象流,zip文件流….本文的目的是为大家做一个简要的介绍。

流是一个很形象的概念,当程序需要读取数据的时候,就会开启一个通向数据源的流,这个数据源可以是文件,内存,或是网络连接。类似的,当程序需要写入数据的时候,就会开启一个通向目的地的流。这时候你就可以想象数据好像在这其中“流”动一样,如下图:

Java中的流分为两种,一种是字节流,另一种是字符流,分别由四个抽象类来表示(每种流包括输入和输出两种所以一共四个):InputStream,OutputStream,Reader,Writer。Java中其他多种多样变化的流均是由它们派生出来的:

在这其中InputStream和OutputStream在早期的Java版本中就已经存在了,它们是基于字节流的,而基于字符流的Reader和Writer是后来加入作为补充的。以上的层次图是Java类库中的一个基本的层次体系,如果你感兴趣想了解更多内容的话,可以到Sun公司主页获取更多信息。

在这四个抽象类中,InputStream和Reader定义了完全相同的接口:

int read()
int read(char cbuf[])
int read(char cbuf[], int offset, int length)

而OutputStream和Writer也是如此:

int write(int c)
int write(char cbuf[])
int write(char cbuf[], int offset, int length)

这六个方法都是最基本的,read()和write()通过方法的重载来读写一个字节,或者一个字节数组。

更多灵活多变的功能是由它们的子类来扩充完成的。知道了Java输入输出的基本层次结构以后,本文在这里想给大家一些以后可以反复应用例子,对于所有子类的细节及其功能并不详细讨论。

import java.io.*;

    public class IOStreamDemo {

    public void samples() throws IOException {

    //1. 这是从键盘读入一行数据,返回的是一个字符串
    BufferedReader stdin =new BufferedReader(new InputStreamReader(System.in));
    System.out.print(“Enter a line:”);
    System.out.println(stdin.readLine());

    //2. 这是从文件中逐行读入数据

    BufferedReader in = new BufferedReader(new FileReader(“IOStreamDemo.java”));
    String s, s2 = new String();
    while((s = in.readLine())!= null)
    s2 += s + “\n”;
    in.close();

    //3. 这是从一个字符串中逐个读入字节
    StringReader in1 = new StringReader(s2);
    int c;
    while((c = in1.read()) != -1)
    System.out.print((char)c);

    //4. 这是将一个字符串写入文件
    try {
    BufferedReader in2 = new BufferedReader(new StringReader(s2));
    PrintWriter out1 = new PrintWriter(new BufferedWriter(new FileWriter(“IODemo.out”)));
    int lineCount = 1;
    while((s = in2.readLine()) != null )
    out1.println(lineCount++ + “: “ + s);
    out1.close();
    } catch(EOFException e) {
    System.err.println(“End of stream”);
    }
    }

    }

对于上面的例子,需要说明的有以下几点:

1. BufferedReaderReader的一个子类,它具有缓冲的作用,避免了频繁的从物理设备中读取信息。它有以下两个构造函数:

BufferedReader(Reader in)
BufferedReader(Reader in, int sz)

这里的sz是指定缓冲区的大小。

它的基本方法:

void close() //关闭流 void mark(int readAheadLimit) //标记当前位置

boolean markSupported() //是否支持标记

int read() //继承自Reader的基本方法

int read(char[] cbuf, int off, int len) //继承自Reader的基本方法

String readLine() //读取一行内容并以字符串形式返回

boolean ready() //判断流是否已经做好读入的准备

void reset() //重设到最近的一个标记

long skip(long n) //跳过指定个数的字符读取

2. InputStreamReaderInputStreamReader之间的桥梁,由于System.in是字节流,需要用它来包装之后变为字符流供给 BufferedReader使用。

3. PrintWriter out1 = new PrintWriter(new BufferedWriter(new FileWriter(“IODemo.out”)));

这句话体现了Java输入输出系统的一个特点,为了达到某个目的,需要包装好几层。首先,输出目的地是文件IODemo.out,所以最内层包装的是FileWriter,建立一个输出文件流,接下来,我们希望这个流是缓冲的,所以用BufferedWriter来包装它以达到目的,最后,我们需要格式化输出结果,于是将PrintWriter包在最外层。

Java提供了这样一个功能,将标准的输入输出流转向,也就是说,我们可以将某个其他的流设为标准输入或输出流,看下面这个例子:

import java.io.*;

public class Redirecting {

public static void
main(String[] args) throws IOException {
PrintStream console = System.out;
BufferedInputStream in = new BufferedInputStream( new FileInputStream( “Redirecting.java”));
PrintStream out = new PrintStream( new BufferedOutputStream( new FileOutputStream(“test.out”)));
System.setIn(in);
System.setOut(out);

BufferedReader br = new BufferedReader( new InputStreamReader(System.in));
String s;
while((s = br.readLine()) != null)
System.out.println(s);
out.close();
System.setOut(console);
}
}

在这里java.lang.System的静态方法

static void setIn(InputStream in)
static void setOut(PrintStream out)

提供了重新定义标准输入输出流的方法,这样做是很方便的,比如一个程序的结果有很多,有时候甚至要翻页显示,这样不便于观看结果,这是你就可以将标准输出流定义为一个文件流,程序运行完之后打开相应的文件观看结果,就直观了许多。

Java流有着另一个重要的用途,那就是利用对象流对对象进行序列化。下面将开始介绍这方面的问题。

在一个程序运行的时候,其中的变量数据是保存在内存中的,一旦程序结束这些数据将不会被保存,一种解决的办法是将数据写入文件,而Java中提供了一种机制,它可以将程序中的对象写入文件,之后再从文件中把对象读出来重新建立。这就是所谓的对象序列化Java中引入它主要是为了RMI(Remote Method Invocation)和Java Bean所用,不过在平时应用中,它也是很有用的一种技术。

所有需要实现对象序列化的对象必须首先实现Serializable接口。下面看一个例子:

import java.io.*;
import java.util.*;

public class Logon implements Serializable {

private Date date = new Date();
private String username;
private transient String password;

Logon(String name, String pwd) {
username = name;
password = pwd;
}

public String toString() {
String pwd = (password == null) ? “(n/a)” : password;
return “logon info: \n “ + “username: “ + username + “\n date: “ + date + “\n password: “ + pwd;
}


public static void
main(String[] args) throws IOException, ClassNotFoundException {
Logon a = new Logon(“Morgan”, “morgan83″);
System.out.println( “logon a = “ + a);
ObjectOutputStream o = new ObjectOutputStream( new FileOutputStream(“Logon.out”));
o.writeObject(a);
o.close();

int seconds = 5;
long t = System.currentTimeMillis() + seconds * 1000;
while(System.currentTimeMillis() < t) ;

ObjectInputStream in = new ObjectInputStream( new FileInputStream(“Logon.out”));
System.out.println( “Recovering object at “ + new Date());
a = (Logon)in.readObject();
System.out.println(“logon a = “ + a);
}
}

类Logon是一个记录登录信息的类,包括用户名和密码。首先它实现了接口Serializable,这就标志着它可以被序列化。之后再main方法里ObjectOutputStream o = new ObjectOutputStream( new FileOutputStream(“Logon.out”));新建一个对象输出流包装一个文件流,表示对象序列化的目的地是文件Logon.out。然后用方法writeObject开始写入。想要还原的时候也很简单ObjectInputStream in = new ObjectInputStream( new FileInputStream(“Logon.out”));新建一个对象输入流以文件流Logon.out为参数,之后调用readObject方法就可以了。

需要说明一点,对象序列化有一个神奇之处就是,它建立了一张对象网,将当前要序列化的对象中所持有的引用指向的对象都包含起来一起写入到文件,更为奇妙的是,如果你一次序列化了好几个对象,它们中相同的内容将会被共享写入。这的确是一个非常好的机制。它可以用来实现深层拷贝,有关深层拷贝的问题在JavaWorld上有一篇文章做了几种实现方法的介绍和比较,有兴趣者可以去看看。

关键字transient在这里表示当前内容将不被序列化,比如例子中的密码,需要保密,所以没有被写入文件。

对Java的输入输出功能,就浅浅的介绍到这里,本文的目的只是开一个好头,希望能让大家对Java输入输出流有个基本的认识,更多更为全面的信息在http://java.sun.com有权威的说明。

Software of Interest

十一月 15, 2004

1. Buddyspace,团队协作的IM工具

Buddyspace是又一款IM工具,由英国公开大学的Marc Eisenstadt等人开发。Buddyspace是基于Java的免费软件,与其它IM软件最大的区别在于软件中增加了“虚拟地图”,每个人位于地图上一点,例如可以在办公室的平面图显示每个员工的位置,绿色的点即表示该员工在线。如果团队成员在工作时用这个软件,会给大家一种更真实的感觉。软件也允许用户创建一个聊天室,其它用户在发表意见前需要“举手”。种种功能都是为了使软件的使用者感觉与现实更接近。有兴趣可以看看软件的演示,或者下载一个来试用。

2. RADIO.BLOG

他通过让用户安装一个程序,便可以把自己挑选的歌曲制作成一个列表,显示在自己的Blog页面上,然后允许用户通过一个Flash的播放器收听。

转自: bbs.xml.org.cn原贴

ChouBill:

我用Protege建立一个本体,关于Pizza的,有三个类,包括Pizza, PiazzaBase和PizzaTopping,他们互相Disjointwith,我原以为这三个类既然是在层次上对等的,那代码也应该差不多。但是当我查看源代码时发现自动生成的代码中,这三个类是不一样的,主要是有些用的是rdf:ID,有些用的是rdf:about,还有用rdf:resource的,如下:

<?xml version=”1.0″?>

<rdf:RDF

xmlns:owl=”http://www.w3.org/2002/07/owl#”

xmlns=”http://www.owl-ontologies.com/unnamed.owl#”

xmlns:rdfs=”http://www.w3.org/2000/01/rdf-schema#”

xmlns:rdf=”http://www.w3.org/1999/02/22-rdf-syntax-ns#”

xml:base=”‘ target=_blank>http://www.owl-ontologies.com/unnamed.owl”>

<owl:Ontology rdf:about=”"/>

<owl:Class rdf:ID=”PizzaBase”>

<owl:disjointWith>

<owl:Class rdf:ID=”Pizza”/>

</owl:disjointWith>

<owl:disjointWith>

<owl:Class rdf:ID=”PizzaTopping”/>

</owl:disjointWith>

</owl:Class>

<owl:Class rdf:about=”#Pizza”>

<owl:disjointWith rdf:resource=”#PizzaBase”/>

<owl:disjointWith>

<owl:Class rdf:about=”#PizzaTopping”/>

</owl:disjointWith>

</owl:Class>

<owl:Class rdf:about=”#PizzaTopping”>

<owl:disjointWith rdf:resource=”#PizzaBase”/>

<owl:disjointWith rdf:resource=”#Pizza”/>

</owl:Class>

</rdf:RDF>

我的疑问是同样的结构,为什么有些要用rdf:resource有些又用rdf:about,还有些用rdf:ID?这几个有什么区别呢?

orangebench:

1)rdf:ID和rdf:about的区别:
rdf:about的值是一个完整URIref,注意也可以是相对URI,(相对于xml:base);
rdf:ID是对rdf:about的值的缩写,其值是一个“ XML Name”,所以,不能是数字开头,不能有“/”符号等。

例如:rdf:ID=”PizzaBase” 等价于rdf:about=”(xml:base)+‘#’+‘PizzaBase’ ”
这个xml:base的值可以在XML文件头声明,如你例子中的,xml:base=”http://www.owl-ontologies.com/unnamed.owl”, 如果没有声明,则其值是RDF文件所放在的位置uri。

2)rdf:resource 和rdf:about

<owl:disjointWith rdf:resource=”#PizzaBase”/> 是

<owl:disjointWith >
<rdf:Description rdf:about=”#PizzaBase” />
</owl:disjointWith >
的缩写。这里必须没有对资源=”#PizzaBase” 做进一步的说明。所以,rdf:resource只能出现在表示属性的节点中,如这里的owl:disjointWith节点。

而 <owl:disjointWith>
<owl:Class rdf:about=”#PizzaTopping”/>
</owl:disjointWith>
是等价于:
<owl:disjointWith >
<rdf:Description rdf:about=”#PizzaTopping” >
<rdf:type rdf:resource=”&rdfs;Class” />
</rdf:Description>
</owl:disjointWith >

这里不能用rdf:resource了,因为声明了#PizzaTopping是一个类。

所以,我们可以看出:
说明了: <owl:Class rdf:ID=”PizzaBase”>
以后,后面的都是用:
<owl:disjointWith rdf:resource=”#PizzaBase”/>
了。

ChouBill:

非常感谢orangebench老大的详细说明,我觉得我好像有些理解了,把我的理解说一下看看理解得正不正确。

其实我们可以把rdf:ID看作和rdf:about一样的东西,rdf:ID只是一个缩写而已。所以
<owl:Class rdf:ID=”PizzaBase”>

<owl:disjointWith>

<owl:Class rdf:ID=”Pizza”/>

</owl:disjointWith>

<owl:disjointWith>

<owl:Class rdf:ID=”PizzaTopping”/>

</owl:disjointWith>

</owl:Class>
中,把所有的rdf:ID=”xxx”替换成rdf:about=”#xxx”也是可以的,这是我的第一个理解。

第二,为什么这里不能用rdf:resource呢,是因为到目前为止,Pizza类和PizzaTopping类还没有被定义,需要在这里申明它是一个类。如果Pizza类在之前就已经定义了,那么这里也可以用rdf:resource来简写。

上述理解正确吗?

orangebench:

我觉得是:
你的理解完全正确。
;-)

再补充一个rdf:ID和rdf:about的区别:

rdf:ID是用来定义一个资源,或者说引入一个新的资源名称;
rdf:about除了也可用来定义资源外,还可用来扩展对这个资源的定义(这可以出现在其他本体文件中)。

ChouBill:

能说得再详细点吗,免得理解起来有歧义

上面的例子中,定义了三个类:
<owl:Class rdf:ID=”PizzaBase”>
<owl:Class rdf:about=”#Pizza”>
<owl:Class rdf:about=”#PizzaTopping”>
我原来认为这三个都可以定义成rdf:ID,现在还是这么认为。你的意思是说如果Pizza和PizzaTopping的定义如果不在同一个文件中的话,就只能用rdf:about,对不对?

orangebench:

我也认为这三个定义都可以用rdf:ID来定义。
我的意思是:如果已经有本体定义了Pizza和PizzaTopping(用rdf:ID),你在其他的本体中要增加对Pizza和PizzaTopping的描述,应该用rdf:about,但是不是必须用,我没把握。

下一页 »