﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>博客园-Blue Voyage．ＮＥＴ</title><link>http://www.cnblogs.com/voyage/</link><description>我向往淡蓝色的未来 我体味淡蓝色的静谧 我永远都要争取机会 我希翼创造光彩未来！</description><language>zh-cn</language><lastBuildDate>Mon, 06 Jul 2009 10:37:29 GMT</lastBuildDate><pubDate>Mon, 06 Jul 2009 10:37:29 GMT</pubDate><ttl>60</ttl><item><title>J2EE体系结构设计 </title><link>http://www.cnblogs.com/voyage/archive/2004/07/16/24686.html</link><dc:creator>voyage</dc:creator><author>voyage</author><pubDate>Thu, 15 Jul 2004 17:50:00 GMT</pubDate><guid>http://www.cnblogs.com/voyage/archive/2004/07/16/24686.html</guid><wfw:comment>http://www.cnblogs.com/voyage/comments/24686.html</wfw:comment><comments>http://www.cnblogs.com/voyage/archive/2004/07/16/24686.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnblogs.com/voyage/comments/commentRss/24686.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/voyage/services/trackbacks/24686.html</trackback:ping><description><![CDATA[<TABLE cellSpacing=0 cellPadding=0 width=558 border=0>
<TBODY>
<TR>
<TD width=10></TD>
<TD vAlign=top><!--start story --><!-- BEGIN:CHANNEL HEADER --><!-- END:CHANNEL HEADER -->
<P><BR><B><SPAN class=h2>J2EE体系结构设计</B></SPAN> <BR><BR><BR><SPAN class=hui>作者： <A href="mailto:ghq12345@163.com"><FONT color=blue>务实</FONT></A></SPAN><BR><SPAN class=hui>Thursday, October 9 2003 3:30 PM</SPAN> <BR><BR>&nbsp; 一、J2EE的模型-视图-控制（MVC）体系结构<BR>&nbsp; 二、J2EE设计模式<BR>&nbsp;2-1、前控制器<BR>&nbsp;2-2、控制器<BR>&nbsp;2-3、视图&nbsp;&nbsp; <BR>&nbsp;2-4、视图帮助<BR>&nbsp;2-5、会话面<BR>&nbsp;2-6、 数据访问对象<BR>&nbsp;2-7、值对象或传输对象<BR>&nbsp;2-8、截取过滤器</P>
<P>&nbsp;参考资料：<BR>&nbsp;《J2EE设计开发编程指南》&nbsp;&nbsp;&nbsp;&nbsp; Rod Johnson&nbsp;&nbsp;&nbsp;&nbsp; 电子工业出版社<BR>&nbsp;《J2EE参考大全》&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Jim Keogh&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 电子工业出版社<BR>&nbsp;《实用J2EE设计模式编程指南》 Craig A.Berry&nbsp;&nbsp; 电子工业出版社<BR><BR><BR><BR></P><!-- BEGIN:STORY -->
<P>
<TABLE>
<TBODY>
<TR>
<TD class=text1>
<P>
<DIV>
<TABLE cellSpacing=0 cellPadding=0 width=0 align=right border=0>
<TBODY>
<TR>
<TD><!--start banner ad--><!--ba-->
<SCRIPT language=JavaScript1.1 src="http://ad.cn.doubleclick.net/adj/messagingplus.zdnet.com.cn/developer/tech;sz=1x1;ord=1269685644?"> </SCRIPT>
<!-- Sniffer Code for Flash 5 -->
<SCRIPT language=VBScript> 
on error resume next 
ShockMode = (IsObject(CreateObject("ShockwaveFlash.ShockwaveFlash.5")))
</SCRIPT>
<NOEMBED>
<a href="http://ad.cn.doubleclick.net/click%3Bh=v2|3149|3|0|%2a|y%3B7720504%3B0-0%3B0%3B6694713%3B31-1|1%3B4892528|4910424|1%3B%3B%3fhttp%3a%2f%2fhttp://ad.www.net.cn/ad/zdnet/zdnet_largeformat_index.htm" target="_blank"><IMG SRC="http://m2.cn.doubleclick.net/638159/cn_336_280.swf " WIDTH=468 HEIGHT=60 BORDER=0 ></a>
</NOEMBED><NOSCRIPT>
<a href="http://ad.cn.doubleclick.net/click%3Bh=v2|3149|3|0|%2a|y%3B7720504%3B0-0%3B0%3B6694713%3B31-1|1%3B4892528|4910424|1%3B%3B%3fhttp%3a%2f%2fhttp://ad.www.net.cn/ad/zdnet/zdnet_largeformat_index.htm" target="_blank"><IMG SRC="http://m2.cn.doubleclick.net/638159/cn_336_280.swf " WIDTH=468 HEIGHT=60 BORDER=0 ></a>
</NOSCRIPT><NOSCRIPT> <A HREF="http://ad.cn.doubleclick.net/jump/messagingplus.zdnet.com.cn/developer/tech;sz=1x1;ord=1269685644?"> <IMG SRC="http://ad.cn.doubleclick.net/ad/messagingplus.zdnet.com.cn/developer/tech;sz=1x1;ord=1269685644?" border=0 ></A> 
      </NOSCRIPT><!--end banner ad--></TD></TR></TBODY></TABLE>
<P>目前大多数企业采用J2EE技术的结构设计与解决方案。对于我们学习和研究J2EE体系结构来说，了解与掌握J2EE体系结构的设计方法及一些常用模式是必须的；模型-视图-控制(model-view-control，简称MVC)结构是目前最常见的J2EE应用所基于的体系结构，MVC主要适用于交互式的Web应用，尤其是存在大量页面及多次客户访问及数据显示；相比较而言，一个工作流体系结构更多应用于过程控制和较少交互的情况下；除了体系结构外，J2EE的设计模式对我们解决应用系统的设计也有很大的帮助。</P>
<H5>一、J2EE的模型-视图-控制（MVC）体系结构</H5>
<P>模型-视图-控制结构是交互式应用程序广泛使用的一种体系结构。它有效地在存储和展示数据的对象中区分功能模块以降低它们之间的连接度，这种体系结构将传统的输入、处理和输入模型转化为图形显示的用户交互模型，或者换一种说法，是多层次的Web商业应用；MVC体系结构具有三个层面：模型（Model）、视图(View)和控制(Controller)，每个层面有其各自的功能作用，MVC体系结构如下：</P>
<P><IMG height=346 src="http://www.zdnet.com.cn/i/developer/story/200310/39174509/image002.jpg" width=495></P>
<P>图1 &nbsp;MVC 体系结构</P>
<P>&nbsp;&nbsp; 模型层负责表达和访问商业数据，执行商业逻辑和操作。也就是说，这一层就是现实生活中功能的软件模拟；在模型层变化的时候，它将通知视图层并提供后者访问自身状态的能力，同时控制层也可以访问其功能函数以完成相关的任务。</P>
<P>&nbsp;&nbsp;&nbsp; 视图层负责显示模型层的内容。它从模型层取得数据并指定这些数据如何被显示出来。在模型层变化的时候，它将自动更新。另外视图层也会将用户的输入传送给控制器。</P>
<P>&nbsp;&nbsp;&nbsp; 控制层负责定义应用程序的行为。它可以分派用户的请求并选择恰当的视图以用于显示，同时它也可以解释用户的输入并将它们映射为模型层可执行的操作；在一个图形界面中，常见的用户输入包括点击按钮和菜单选择。在Web应用中，它包括对Web层的HTTP GET和POST的请求；控制层可以基于用户的交互和模型层的操作结果来选择下一个可以显示的视图，一个应用程序通常会基于一组相关功能设定一个控制层的模块，甚至一些应用程序会根据不同的用户类型具有不同的控制层设定，这主要是由于不同用户的视图交互和选择也是不同的。</P>
<P>在模型层、视图层和控制层之间划分责任可以减少代码的重复度，并使应用程序维护起来更简单。同时由于数据和商务逻辑的分开，在新的数据源加入和数据显示变化的时候，数据处理也会变得更简</P></DIV></TD></TR></TBODY></TABLE></P><BR>
<H5><B>二、J2EE设计模式</B></H5>
<TABLE cellSpacing=0 cellPadding=0 width=0 align=right border=0>
<TBODY>
<TR>
<TD><!--start banner ad--><!--ba-->
<SCRIPT language=JavaScript1.1 src="http://ad.cn.doubleclick.net/adj/messagingplus.zdnet.com.cn/developer/tech;sz=1x1;ord=693534656?"> </SCRIPT>
<!-- Sniffer Code for Flash 5 -->
<SCRIPT language=VBScript> 
on error resume next 
ShockMode = (IsObject(CreateObject("ShockwaveFlash.ShockwaveFlash.5")))
</SCRIPT>
<NOEMBED>
<a href="http://ad.cn.doubleclick.net/click%3Bh=v2|3149|3|0|%2a|y%3B7720504%3B0-0%3B0%3B6694713%3B31-1|1%3B4892528|4910424|1%3B%3B%3fhttp%3a%2f%2fhttp://ad.www.net.cn/ad/zdnet/zdnet_largeformat_index.htm" target="_blank"><IMG SRC="http://m2.cn.doubleclick.net/638159/cn_336_280.swf " WIDTH=468 HEIGHT=60 BORDER=0 ></a>
</NOEMBED><NOSCRIPT>
<a href="http://ad.cn.doubleclick.net/click%3Bh=v2|3149|3|0|%2a|y%3B7720504%3B0-0%3B0%3B6694713%3B31-1|1%3B4892528|4910424|1%3B%3B%3fhttp%3a%2f%2fhttp://ad.www.net.cn/ad/zdnet/zdnet_largeformat_index.htm" target="_blank"><IMG SRC="http://m2.cn.doubleclick.net/638159/cn_336_280.swf " WIDTH=468 HEIGHT=60 BORDER=0 ></a>
</NOSCRIPT><NOSCRIPT> <A HREF="http://ad.cn.doubleclick.net/jump/messagingplus.zdnet.com.cn/developer/tech;sz=1x1;ord=693534656?"> <IMG SRC="http://ad.cn.doubleclick.net/ad/messagingplus.zdnet.com.cn/developer/tech;sz=1x1;ord=693534656?" border=0 ></A> 
      </NOSCRIPT><!--end banner ad--></TD></TR></TBODY></TABLE>
<P>一个设计模式描述了对于特定设计问题被验证的解决方案，它综合了所有开发者对这个问题所在领域的知识和见解；同时也是对于常见问题的可重用方案，它们一般适用于单个问题，但是组织在一起就可以提供整个企业系统的解决方案。下面我们列举八种常用于J2EE平台的设计模式，并对每种模式作简单的介绍，便于大家学习、理解与灵活应用。</P>
<P><B>1、前控制器</B></P>
<P>&nbsp;&nbsp; 前控制器(front controller)主要提供一种可以集中式管理请求的控制器，一个前控制器可以接受所有的客户请求，将每个请求递交给相应的请求句柄，并适当地响应用户。</P>
<P>&nbsp;&nbsp; 前控制器也是表示层的设计模式，它的出现主要是由于表示层通常需要控制和协调来自不同用户的多个请求，而这种控制机制又根据不同的需要，可能会集中式控制或分散式控制。换句话说，就是应用系统需要对于表示层的请求提供一个集中式控制模块，以提供各种系统服务，包括内容提取、视图管理和浏览，如果系统中没有这种集中式控制模块或控制机制，每个不同的系统服务都需要进行单独的视图处理，这样代码的重复性就会提高，致使系统开发代价提高；同时，如果没有一个固定模块管理视图之间的浏览机制，致使其浏览功能下放于每个不同的视图中，最终必将使得系统的可维护性受到破坏；本文中我们主要讨论的是集中式控制模块，而不是分散式控制，因为前者更适合于大型的应用系统。</P>
<P>&nbsp; 基于上面所说的问题，研究人员提出了前控制器的设计模式。在这种模式中，控制器提供一个处理不同请求的控制点，这里的处理工作包括安全事务、视图选择、错误处理和响应内容的生成；通过将这些处理工作集中在一点进行，大大地减低了Java代码量，同时这种方法也可以减少在视图模块的程序逻辑，保证了在不同请求之间可以重用大量的逻辑代码。通常，控制器都是和一个分派组件联合工作的，分派组件主要是用于视图管理和浏览，也就是为用户选择下一个应该显示的视图，并同时提供对于相关显示资源的控制。分派组件可以包含在控制器之内，或是在另外一个单独的组件中；虽然前控制器模式推荐对于全部的请求使用统一处理，但是它也没有限制在一个系统中只能具有一个控制器，在系统中的每个层次都可以具有多个控制器，并且映射至不同的系统服务，下图2显示了前控制器的类图。</P>
<P><IMG height=206 src="http://www.zdnet.com.cn/i/developer/story/200310/39174509/image004.jpg" width=357></P>
<P>图2 前控制器的类图</P>
<P>&nbsp;</P>
<P>&nbsp;&nbsp; 图3显示了前控制器的序列图，表示一个控制器如何处理相关的请求。</P>
<P align=left><IMG height=269 src="http://www.zdnet.com.cn/i/developer/story/200310/39174509/image006.jpg" width=455></P>
<P>图3前控制器序列图</P>
<P>下面我们来讨论一下图3的各个组件。</P>
<P><B>2、控制器</B></P>
<P>&nbsp;&nbsp; 控制器(controller)是负责处理各种客户请求的控制点，并可以将一定的职能(如用户认证等)下放给帮助类。</P>
<P>&nbsp; (1)分派组件(Dispatcher)。一个分派组件主要是用于视图的管理和浏览，为用户选择下一个可以显示的视图，并管理相关的显示资源；分派组件可以在一个控制器内运行，或者作为一个单独的组件与控制器协同工作；开发人员可以在分派组件中实现静态的视图分派技术，或是复杂的动态分派。</P>
<P>&nbsp; (2)帮助类(Helper)。帮助类负责帮助一个视图或控制器来完成其处理工作，因此，帮助类具有多项职责，包括收集数据、存储中间数据模型等；另外，帮助类也可以在保证数据完整性和准确性的情况下，为不同显示需求修改数据模型；也就是说，根据用户的请求，帮助类可以向视图提供未经处理的原始数据，或是已经格式化后的Web内容，一个视图同时可以和多个帮助类协同工作，而后者通常是由JavaBeans和标签(tag)实现的。<BR><BR><BR></P>
<P><B>3、视图&nbsp;&nbsp; &nbsp;</B></P>
<P>&nbsp;&nbsp; 视图(view)负责向用户显示信息，而帮助类则负责支持视图的工作，即打包和建立相应的数据模型，下面我们介绍几种可以实现控制器的方法。</P>
<P><B>1）基于Servlet前控制器</B></P>
<P>这种方法建议使用servlet来实现一个控制器，尽管在语法上相差无几，但是它比使用JSP来实现要优越一些；因为控制器所进行的请求处理，多数都是与程序运行和控制流动相关的，这些处理工作虽然与显示模式相关，但是实际上是逻辑独立的，所以它们更适合在servlet中实现，而不是JSP技术中；使用这种方法也存在一些弱点，比如说servlet无法使用JSP运行环境的资源，如请求参数等，但是这个弱点也不是不能解决的，我们可以在servlet中建立相关的句柄来访问同样的资源，当然其代码会变得繁琐一点。</P>
<P><B>2）基于JSP的前控制器</B></P>
<P>&nbsp; 这种方法建议使用JSP页面实现控制器，尽管语法上相同，但是Servlet方案要比其优越一些；因为控制器所处理的逻辑一般都不是有关显示模式的，所以在JSP页面中实现控制器似乎有点风马牛不相及；使用这种方法也不利于开发团队的角色和职责的分配，即软件开发人员需要在负责显示逻辑的JSP页面中修改请求处理的代码，通常，这种工作都是相当复杂的，尤其考虑整个JSP页面的编程、编译、测试和调试错误。</P>
<P><B>3）控制器之中的分派组件</B></P>
<P>&nbsp; 如果分派组件没有较多功能，开发人员可以在控制器实现该组件。</P>
<P><B>4）基础前端</B></P>
<P>&nbsp; 基于使用servlet实现前控制器，这种方案建议实现一个控制器作为基础类，这样其他的控制器可以在其之上扩展；这个基础类可以包含一些通用的逻辑实现，它的子类就会重载这些实现代码，这种方法也有一定的缺陷，当有许多子类继承这个基础类，并大量地重用代码时，那么就有可能出现一个类的改变会影响到所有子类的情况。</P>
<P><B>5）用过滤器实现前控制器</B></P>
<P>&nbsp;&nbsp;&nbsp; 过滤器提供了与用户请求的中心处理相类似的功能，也就是说，控制器的一些功能可以由过滤器来实现，这种方案的过滤器主要负责处理请求的截取和解释，而不是请求的处理和响应的生成；通常可以为应用系统提供一个核心控制点，以处理所有的系统服务和程序逻辑，核心控制也就表明了所有的请求都可以简单地被跟踪和记录，从而方便各种服务功能的实施；当然，它也存在一些缺点，一个核心控制点的小问题可能会引发系统的崩溃，但在应用系统的实际开发中，这并不是个问题，因为通常我们都会在同一个层面上实现多个控制器，从而避免了这个缺陷；在控制器中，开发人员可以很方便地实现一个检查安全机制的组件，从而可以在最外层屏蔽对系统的恶意访问，另外使用控制器也会提高系统模块的可重用性，尤其在控制器同时使用帮助类的时候。</P>
<P><B>4、视图帮助</B></P>
<P>&nbsp;&nbsp; 视图帮助(View helper)是属于表示层的设计模式，一个视图帮助可以包含相关视图中的数据访问和内容显示的逻辑，并可以精炼简化视图；显示逻辑主要是关于如何格式化页面上的数据，而访问逻辑则是关于如何取出数据，视图帮助通常用来显示数据的JSP标记(tag)或是读取数据的JavaBean。</P>
<P>&nbsp;&nbsp; 这种设计模式的出现主要是由于目前的应用系统通常需要实时地开发显示内容，并且能处理动态的程序数据。如果这些程序数据的访问逻辑和显示逻辑的关系过于紧密，则系统的表示层就会经常需要改动，从而系统的灵活性、重用性会大大地受到破坏；同时在相同的模块中实现访问逻辑和显示逻辑将会影响系统的模块化，也会使得开发团队的任务划分不清。</P>
<P>&nbsp;一个视图通常包含格式化信息，并将其处理任务分发给自己的帮助类，后者通常是用JavaBeans或标记(tag)来实现的，帮助类同时可以存储视图的中间数据模型并实现数据适配器的功能，即适当地转化数据格式；开发人员可以采用多种方法实现视图组件，通常，开发人员可以使用JSP来实现，并且这也是一种值得推荐的方法。当然，相应地开发人员也可以使用Servlet来实现它，将视图中一定的程序逻辑植入到帮助类中，会有利于应用系统的模块化和可重用性。系统可以使用同一个帮助类为不同的用户显示不同的数据信息，并在不同的显示格式下显示；通常，如果开发人员发现视图的JSP页面中存在大量的脚本代码时，就可以考虑使用视图帮助这种模式了，因为在这种情况下，基本都是程序逻辑和显示逻辑具有过于紧密的联系；这时开发人员可以将一些适用于所有类型的请求的逻辑处理放置到一定的帮助类中，而根据需要，也可以将另外一些逻辑处理放置在视图层上的其他程序模块中，比如说以前讨论过的截取过滤器。&nbsp;&nbsp;&nbsp; </P>
<P>&nbsp;&nbsp; 视图帮助这种模式的设计理念主要是分离应用系统的逻辑职责，下面我们提供一些图示，以方便大家更好地理解这种模式。</P>
<P>&nbsp; 图4以类图(class diagram)的形式说明了视图帮助的系统结构。</P>
<P align=center><IMG height=93 src="http://www.zdnet.com.cn/i/developer/story/200310/39174509/image008.jpg" width=430></P>
<P align=center>图4 视图帮助类图</P>
<P align=center>&nbsp;</P>
<P>&nbsp; 图5表示了视图帮助模式的序列图，它表明了这种模式中的主要成分及互相之间的运行情况；不过需要说明的是，在很多应用系统中，客户端和视图层之间会存在一个控制器加以适当的调节。</P>
<P><IMG height=213 src="http://www.zdnet.com.cn/i/developer/story/200310/39174509/image010.jpg" width=539></P>
<P>图5视图帮助序列图</P>
<P>&nbsp;</P>
<P>&nbsp; 在类图表中，大家可以发现，可能存在没有任何相关帮助类的视图，这种情况下，通常代表视图的JSP页面会有一些静态的或小数量的脚本代码。</P>
<P>&nbsp; 这里我们对于序列图中的各个元素加以简单的介绍：</P>
<P>&nbsp; (1)视图(view)。视图负责向用户展示动态数据信息，而帮助类则负责支持视图的工作，即打包和建立相应的数据模型。</P>
<P>&nbsp; (2)帮助类(helper)。一个帮助类负责帮助视图或控制器完成相关的处理工作，包括收集数据、存储中间模型等；帮助类也可以在保证数据完整性和准确性的情况下，为不同显示需求修改数据模型，也就是说，根据用户的请求，帮助类可以向视图提供未经处理的原始数据，或是已经格式化后的Web内容；一个视图同时可以和多个帮助类协同工作，而后者通常是由JavaBeans和标记(tag)实现的。</P>
<P>(3)值bean(ValueBean)。值bean实际上是用于存储中间数据模型的帮助类的另一种叫法，例如在序列图5中，business service就根据请求返回了一个值bean。</P>
<P>&nbsp; (4)业务服务(business service)。业务服务是指用户试图得到的，应用系统可以提供的相关服务；通常来说，业务服务可以通过一个业务代表(business delegate)来访问，而后者主要是提供对于业务服务的控制和保护。</P>
<P>&nbsp;&nbsp;&nbsp; 在应用系统的视图模块中使用帮助类可以将不同的程序逻辑很好地分离开来，并在视图模块之外为开发人员提供设计程序逻辑的空间；基于JavaBean和标记(tag)所开发的帮助类通常都可以被多个视图模块重用，因此也提高了组件的重用性和可维护性；把显示逻辑从数据处理逻辑分离出来，也有利于开发团队中角色及人物的划分；比如说，如果各种程序逻辑过于结合的话，软件开发人员可能需要在HTML，网页中修改代码而Web设计师则需要在处理数据访问的JSP中修改页面布置，这些情况都可能会导致系统设计和开发中由于不同技术人员的介入，而产生相关的问题。</P>
<P><B>5、会话面</B></P>
<P>&nbsp;&nbsp; 会话面(session facade)模式在合作的企业对象间调节操作，并将应用函数合成一个单一简单的界面；它减少了类之间合作的复杂性，并使得类的调用者在该类变化的时候无需改动，这种模式通常以一个会话bean实现，以用来隐藏底层ejb的复杂交互。</P>
<P>&nbsp;&nbsp; 这种设计模式出现的背景在于EJB通常既包括程序数据，又包括程序逻辑，而这些代码都会通过一定的界面作用于客户层，在多层次的J2EE平台应用程序中，就会造成一定的困难。</P>
<P>&nbsp;&nbsp; 具体来说，在J2EE平台上的多层次系统中，通常会存在以下的问题：</P>
<P>&nbsp;&nbsp;&nbsp; (1)层次之间联系过于紧密，客户层和后端的业务对象具有较强的依赖关系；</P>
<P>&nbsp;&nbsp;&nbsp; (2)在客户和服务器之间有多次方法调用，因而导致了Web性能方面的问题；</P>
<P>&nbsp;&nbsp;&nbsp; (3)缺乏一定的客户访问机制，使得一些后台对象被随便访问。</P>
<P>&nbsp;&nbsp;&nbsp; 一个多层次的J2EE应用程序通常具有很多由EJB实现的服务器端对象，它们通常负责提供系统服务、数据信息等，也就是说作为业务对象，它们既包括相关的程序数据，也包括其程序逻辑；在J2EE应用系统中，负责程序逻辑的对象通常由会话bean实现，而表示持久性存储，并在多个用户间共享的对象则由实体bean来实现；当然，应用系统的用户需要访问企业对象来满足自己的需求，如果企业对象向用户提供接口，用户可以直接地与相关对象通信，但是这样一来，用户必须负责管理所调用的企业对象之间的关系，并且能够处理其间的业务流程；然而，如果用户和业务对象之间存在过于直接的交互，两者的联系就会过于紧密，同时也使得用户过于依赖企业对象的具体实现，并负责管理与交互过程有关的业务对象查找和创建，以及不同的对象间相互调用的关系，甚至一些时候用户还需要管理多次调用之间的事务管理环节。</P>
<P>&nbsp;&nbsp;&nbsp; 在用户需求不断增加时，这也是应用系统经常发生的情况，用户与不同的企业对象之间的交互也会变得越来越复杂，而企业对象可能需要一定内部的更新才能满足前者的需要，但是这样的话用户又需要根据企业对象实现的变化而做出相应的改变，这种情况将为应用系统带来相当大的麻烦；在访问EJB应用系统时，用户需要与远程对象进行交互。如果用户直接与所有相关的业务对象交互的话，将带来很大的Web负担；因为对于每一个ejb的激活，都将产生一次远程的调用，而如果存在大量的系统用户，用户与对象间的交互就将为Web通信带来很大的压力，使系统性能受到很大破坏；如果用户可以直接访问后端的企业对象，但是系统中又缺少一个统一的用户访问机制，那么这些访问很有可能变得杂乱无章，引起系统性能的下降，甚至导致一些安全问题。</P>
<P>&nbsp;&nbsp;&nbsp; 为了解决以上的问题，开发人员可以采用会话面的设计模式，即使用会话bean来实现一个面(facade)来包含一个工作流中所有相关对象的交互；这个会话面负责管理业务对象，并向用户提供一个统一的服务访问层，会话面可以面向底层对象的交互过程，并提供一个仅仅包含必须提供的接口的服务层，由此它将复杂的对象交互和用户之间隔离开来；&nbsp;&nbsp;&nbsp; 会话面也负责管理企业数据和企业对象之间的交互，并表达其中需要的企业逻辑，因此会话面也可以管理企业对象之间的作用关系；同时，根据工作流的需要，会话面也管理对象的创建、查找、修改和删除。</P>
<P>&nbsp;&nbsp;&nbsp; 在一个复杂的应用系统中，会话面可以将其生命周期的管理下放到一个单独的帮助对象去，比如说，会话面可以将管理会话和实体bean生命周期的工作交给服务定位对象；&nbsp;&nbsp;&nbsp; 同时，在应用系统中，检查业务对象之间的作用关系也是非常重要的，一些关系可能是暂时的，即只使用于一定的交互过程，而另外一些关系则是永久的，暂时的关系适合建模于会话面中的工作流，永久的关系则需要具体情况具体分析。</P>
<P>&nbsp;&nbsp;&nbsp; 图6中的类图简要描述了会话面的设计模式，图7给出了会话面的序列表示，即参与组件及其交互关系。</P>
<P align=center><IMG height=282 src="http://www.zdnet.com.cn/i/developer/story/200310/39174509/image012.jpg" width=521></P>
<P align=center>图6 会话面类图</P>
<P align=center>&nbsp;</P>
<P align=center><IMG height=293 src="http://www.zdnet.com.cn/i/developer/story/200310/39174509/image014.jpg" width=542></P>
<P align=center>图7会话面序列图</P>
<P align=center>&nbsp;</P>
<P>这里我们对于图7的各个组件加以简要的介绍：</P>
<P>&nbsp;&nbsp;&nbsp; (1)客户(Client)。这表示会话面的客户，即需要访问相关企业服务的客户端应用程序，当然也可以是在同一层面或不同层面的另外一个会话bean。</P>
<P>&nbsp;&nbsp;&nbsp; (2)会话面(Session Facade)。会话面通常是用会话bean来实现的，它管理着多个企业对象的作用关系并提供一个高层次的抽象界面给用户。</P>
<P>&nbsp;&nbsp;&nbsp; (3)业务对象(Business Object)。业务对象是一个可以使用多个不同设计方案的对象，例如会话bean、实体bean和数据访问对象。在图6中业务对象负责提供数据和服务，而会话面则需要与多个业务对象实例交互而获得相应的服务。</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp; 会话面实际上就是业务层的一个控制对象，它负责控制用户与企业数据和企业服务对象之间的交互；在一个复杂的应用系统中，甚至可能会有多个会话面作为用户和对象模块之间的中介。</P>
<P>&nbsp;&nbsp;&nbsp; 下面介绍两种实现会话面的常见方法。</P>
<P>&nbsp;&nbsp;&nbsp; <B>(1)无状态的会话面</B></P>
<P>&nbsp;&nbsp;&nbsp; 在实现会话面的时候，首先应该决定是用状态化还是无状态的会话bean来实现，这主要取决于会话面所建模的业务流程；如果一个业务流程只需要一次方法调用就可以实现其服务，那么就可以使用无状态的会话bean来实现它。</P>
<P>&nbsp;&nbsp;&nbsp; <B>(2)状态化的会话面</B></P>
<P>&nbsp;&nbsp;&nbsp; 当一个业务流程需要多次方法调用来实现其服务时，开发人员最好使用状态化的会话bean来实现这一流程，因为每次方法调用的状态信息都必须在会话bean中保存。</P>
<P>&nbsp;&nbsp;&nbsp; 通过在应用系统中采用会话面的设计模式，将在系统中得到以下的收益：</P>
<P>&nbsp;&nbsp;&nbsp; ①为用户提供一个简单的接口，并隐藏所有与系统组件复杂的交互过程；</P>
<P>&nbsp;&nbsp;&nbsp; ②减少暴露给用户的企业对象，从而降低它们之间的依赖关系；</P>
<P>&nbsp;&nbsp;&nbsp; ③向用户隐藏系统组件间的交互过程和依赖关系，从而使得系统更加容易管理，并提供相当的灵活性；提供一套统一的用户访问机制，便于管理用户对于系统服务的请求与访问。</P>
<P><B>6、 数据访问对象</B></P>
<P>&nbsp;&nbsp;&nbsp; 数据访问对象(data access object，DAO)模式将数据访问逻辑抽象为特殊的资源，也就是说将系统资源的接口从其底层访问机制中隔离出来；通过将数据访问的调用打包，数据访问对象可以促进对于不同数据库类型和模式的数据访问。</P>
<P>&nbsp;&nbsp;&nbsp; 这种模式出现的背景在于数据访问的逻辑极大程度上取决于数据存储的格式，比如说关系型数据库、面向对象数据库、磁盘文件等。</P>
<P>&nbsp;&nbsp;&nbsp; 目前大部分的J2EE应用程序都需要在一定程度上使用可持久性的数据，而实现持久性数据的方法因应用程序不同而异，并且访问不同存储格式数据的应用程序接口(API)也有着显著的差别；有的时候，应用程序还会访问存储在不同操作平台上的数据，这使得问题更为复杂，通常，应用程序会使用共享的分布式组件，如实体bean来表达持久性数据。应用程序可以使用bean管理的持久性实体bean，而在实体bean中植人数据访问逻辑，或者使用容器管理的持久性实体bean，从而使容器管理所有的事务和持久性细节；而如果应用程序对于数据访问的需求十分简单的话，也可以采用会话bean或Servlet直接访问持久性存储来读取和修改数据。</P>
<P>&nbsp;&nbsp;&nbsp; 一些应用程序可以使用JDBC应用程序接口来访问关系数据库中的数据，JDBC负责一般的持久性数据访问和管理，在J2EE应用程序中，JDBC中可以嵌入SQL语句，用以访问关系型数据库，当然根据数据库类型的不同，SQL语句的词法和语法也会有所不同；需要说明的是，当数据存储格式不同的时候，数据访问逻辑的区别就更加明显了，例如关系型数据库、面向对象数据库和磁盘文件，各自数据的访问逻辑各有千秋，这样一来就造成了程序代码和数据访问代码之间的依赖关系；当程序组件，即实体bean、会话bean或servlet、JSP等需要访问数据源时，它们会使用正确的应用程序接口来得到连接并管理数据源，但这样也会造成这些组件与数据源物理实现之间的依赖关系，从而使得应用程序很难从一个数据存储实体移植到另一个数据存储实体中去；当数据源的物理实现变化的时候，应用程序也必须相应地加以改变。</P>
<P>&nbsp;&nbsp;&nbsp; 基于以上所讨论的问题，开发人员开始采用数据访问对象的方法。数据访问对象实际上就是包含对于所有数据访问逻辑的对象，并管理着对于数据源的连接，根据数据源的不同，数据访问对象实现了不同的访问机制，这里所说的数据源可以是持久性存储介质，如关系型数据库，也可以是外部服务，如B2B的数据交换；不仅是用户，而且包括应用系统中的其他组件，也可以使用数据访问对象所提供的数据访问接口，数据访问对象将数据源的物理实现细节与其用户完全分离开来，并且在底层数据源变化的时候，数据访问对象向用户提供的接口是不会变化的；这种方法使应用系统使用数据访问对象时可以适应多种数据存储介质，总之，数据访问对象就是系统组件和数据源中间的适配器。</P>
<P>图8中的类图表示了数据访问对象设计模式的参与对象和之间的调用关系，图9是这种设计模式的序列图。</P>
<P align=center><IMG height=190 src="http://www.zdnet.com.cn/i/developer/story/200310/39174509/image016.jpg" width=497></P>
<P align=center>图8 数据访问对象类图</P>
<P align=center>&nbsp;</P>
<P align=center><IMG height=397 src="http://www.zdnet.com.cn/i/developer/story/200310/39174509/image018.jpg" width=437></P>
<P align=center>图9 数据访问对象序列图</P>
<P align=center>&nbsp;</P>
<P>对于图9序列图中的组件加以解释如下：</P>
<P>&nbsp;&nbsp;&nbsp; (1)业务对象(Business Object)。表示数据的用户，它需要对于数据的访问，一个业务对象可以用会话bean、实体bean或是其他Java程序来实现。</P>
<P>&nbsp;&nbsp;&nbsp; (2)数据访问对象(Data Access Object)。数据访问对象是这种模式中的主题，它提供了底层数据访问的对象，并将其提供给业务对象以使得后者能够透明地访问数据源；同时业务对象也将数据的加载和存储操作移交给数据访问对象处理。</P>
<P>&nbsp;&nbsp;&nbsp; (3)数据源(Data source)。这里指的是数据源的物理实现，这个数据源可以是一个数据库，包括关系型数据库、面向对象数据库或文件系统。</P>
<P>&nbsp;&nbsp;&nbsp; (4)传输对象(Transfer Object)。这里的传输对象指的是数据载体。数据访问对象可以使用传输对象来向用户返回数据，而数据访问对象同样可以从用户那里得到传输对象来对数据源中的数据进行更新。</P>
<P>&nbsp;&nbsp;&nbsp; 下面给出几种实现数据访问对象设计模式的方法。&nbsp;&nbsp;&nbsp; </P>
<P>&nbsp;&nbsp;&nbsp; <B>(1)自动数据访问对象代码的生成</B></P>
<P>&nbsp;&nbsp;&nbsp; 既然每一个业务对象都对应于一个数据访问对象，那么开发人员就可以建立业务对象、数据访问对象和底层实现的关系；一旦这种关系建立起来，开发人员就可以为所有的数据访问对象编写特殊的代码生成工具。</P>
<P>&nbsp;&nbsp;&nbsp; 生成数据访问对象的信息通常存储在一个开发人员定义的描述文件中，如果对于数据访问对象的要求过于复杂，开发人员可以考虑使用第三方工具来为关系型数据库提供对象对关系的映射。这些工具通常是一些GUI程序，可以用来将业务对象映射为持久性的存储对象，并定义中间运作的数据访问对象，在映射完成的时候，这些工具可以自动地生成代码，并提供一些相应的功能，如缓存结果、缓存查询、与应用服务器整合、与第三方产品整合等。</P>
<P>&nbsp;&nbsp;&nbsp; <B>(2)数据访问对象代理(Factory for Data Access Objects)</B></P>
<P>&nbsp;&nbsp;&nbsp; 当底层的数据存储不会轻易改变的时候，开发人员可以采取这种方法来实现相应的，数据访问对象，图10是这种方法的类图。</P>
<P>&nbsp;</P>
<P align=center><IMG height=364 src="http://www.zdnet.com.cn/i/developer/story/200310/39174509/image020.jpg" width=258></P>
<P align=center>图10 使用DAO代理类图</P>
<P align=left>&nbsp;&nbsp; 当底层的数据存储可能会变化的时候，开发人员可以采用抽象代理的方法来实现数据访问对象；抽象代理的方法会创建一些虚拟的数据访问对象代理和各种类型的实际数据访问对象代理，每种对象对应一种持久性存储介质的实现，一旦组件得到这些代理，就可以利用来创建需要使用的数据访问对象。</P>
<P>&nbsp;&nbsp;&nbsp; 图11给出了这种情况的类图。该类图表示了一个基础的数据访问对象代理，它是一个抽象类，被其他一些实际的数据访问对象代理继承以支持特定的数据访问函数；用户可以得到一个实际的数据访问对象，并利用它来创建需要的数据访问对象而访问相关的数据，每一个实际的数据访问对象都负责建立对于数据源的连接，并得到和管理所支持的业务数据。</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp; <IMG height=384 src="http://www.zdnet.com.cn/i/developer/story/200310/39174509/image022.jpg" width=464></P>
<P>图11&nbsp; 抽象代理使用DAO</P>
<P>下图12是这种情况下的序列图。</P>
<P align=left><IMG height=489 src="http://www.zdnet.com.cn/i/developer/story/200310/39174509/image024.jpg" width=546></P>
<P>图12抽象代理使用DAO序列图</P>
<P>这种设计模式的优势：</P>
<DIV></DIV>
<UL>
<LI>
<DIV><SPAN dir=ltr>透明性好。业务对象可以在不知道数据源实现细节的情况下访问数据。由于一切数据访问细节被数据访问对象所隐藏，所以这种访问过程是透明的。</SPAN></DIV>
<LI>
<DIV><SPAN dir=ltr>可移植性好。在应用系统中添加数据访问对象，可以使得前者能够很方便地移植到另外一种数据库实现上。业务对象与数据实现是隔离的，所以在移植过程中，仅仅对数据访问对象进行一些变化即可。</SPAN></DIV>
<LI>
<DIV><SPAN dir=ltr>减少业务对象的代码复杂度。由于数据访问对象可以管理所有的数据访问复杂细节，这也就简化了业务模块和其他数据客户的代码。同时也提高了应用系统的整体可读性和开发率。</SPAN></DIV>
<LI>
<DIV><SPAN dir=ltr>集中处理所有数据访问。由于所有的数据访问操作都移交给数据访问对象，这样应用系统其他部分就与数据访问实现隔离开来，而全部相关操作都与数据访问对象集中处理，这样也使得相关操作更加容易被维护和管理。</SPAN></DIV></LI></UL>
<DIV>
<P>这种设计模式的缺陷：</P></DIV>
<UL>
<LI>
<DIV><SPAN dir=ltr>对于容器管理的持久性不能利用。如果EJB容器采取容器管理的方式，那么所有对于持久性数据存储的管理都由容器负责。这样的话应用系统就无需实现数据访问对象了，因为应用服务将透明地提供这一功能。</SPAN></DIV>
<LI>
<DIV><SPAN dir=ltr>添加了额外的层面。数据访问对象在数据用户和数据源之间添加了一个层面，也就增加了一些额外的设计和实现的负担。当然，我们认为它是物有所值的。</SPAN></DIV></LI></UL>
<DIV>
<P>总之，在开发人员选择不同模式的时候，应该注意，一定的模式对应于一定的应用层次。比如说，与视图和显示相关的模式就是在Web层应用的。而一些与业务逻辑控制相关的模式则是与EJB层次相关的。另外一些关于读取数据和分派操作的模式则适用于不同的层次之间。</P></DIV>
<P><B>7、值对象或传输对象</B></P>
<P>&nbsp;&nbsp; 值对象(value object)模式通过减少分布式通信的消息而促进数据的交换，通常这里所指的通信是在Web层和EJB层之间。在一个远程调用中，一个单一值对象可以被用来取出一系列相关数据并提供给客户。</P>
<P>&nbsp;&nbsp; 这种设计模式的出现是基于客户需要与ejb大量地交换数据的情况。具体来说，在J2EE平台中，应用系统通常将服务器端的程序组件实现为会话bean和实体bean，而这些组件的部分方法则需要将数据返回给客户；这种情况下，通常一个用户会重复调用相关方法多次，直到它得到相关信息，应该注意的是，多数情况这些方法调用的目的都是为了取得单一的信息，例如用户名或者用户地址等。</P>
<P>&nbsp; 显而易见，在J2EE平台上，这种调用基本上都是来自远程的。也就是说，用户多次调用相应的方法会给Web带来极大的负担，即使用户和EJB容器加载相同的JVM、OS和计算机上运行EJB程序，由于方法调用被缺省地认为是远程任务，所以这种问题依然存在。</P>
<P>&nbsp;&nbsp; 由于以上所提到的问题，在远程方法的调用次数增加的时候，相关的应用程序性能将会有很大的下降，因此利用多次方法调用而取得单一的信息是非常低效的；在这种情况，J2EE的研究人员建议使用传输对象来包含所有的程序数据，即每次方法调用可以发送和接收这个传输对象；当用户向EJB发出对于程序数据的请求时，EJB会创建这个传输对象，将它的各个域赋以相关的数值，并将整个对象传送给用户。</P>
<P>&nbsp;&nbsp;&nbsp; 当EJB使用传输对象的时候，用户可以通过仅仅一次方法调用来取得整个对象，而不是使用多次方法调用以得到对象中每个域的数值；由于传输对象是通过值传递而交送给用户的，所以所有对于该传输对象的调用或取值都是本地调用，而不是远程方法调用。不过需要注意的是，这个传输对象必须具有对应于每个属性的访问方法，或者将所有属性都设为公共的。&nbsp;&nbsp;&nbsp; </P>
<P>&nbsp;&nbsp;&nbsp; 类图13表示了传输对象模式的体系结构。</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp; <IMG height=276 src="http://www.zdnet.com.cn/i/developer/story/200310/39174509/image026.jpg" width=386></P>
<P>图13 传输对象类图</P>
<P>在图13中，传输对象首先在EJB中创建，然后返回给远程客户；当然，传输对象也可以根据需要融合其他的设计模式。</P>
<P>&nbsp;&nbsp; 图14显示了传输对象模式中的参与模块和它们之间的交互。</P>
<P align=left><IMG height=306 src="http://www.zdnet.com.cn/i/developer/story/200310/39174509/image028.jpg" width=442></P>
<P>图14 传输对象序列图</P>
<P>&nbsp;&nbsp; 下面我们说明一下传输对象模式的各个参与模块：</P>
<P>&nbsp;&nbsp;&nbsp; (1)客户(Client)。客户代表了EJB所提供服务的使用者，通常是运行于用户终端的应用程序。</P>
<P>&nbsp;&nbsp;&nbsp; (2)业务对象。业务对象表示在一个模式中由会话bean、实体bean或数据访问对象(Data Access Object)实现的角色。业务对象通常负责创建传输对象，并根据请求将其传送到相关的用户；业务对象也可以从用户中取得一个传输对象格式的数据，并应用这些数据来执行一些更新。</P>
<P>&nbsp;&nbsp;&nbsp; (3)传输对象。传输对象是一个可序列化的Java对象。在这个对象的类中，通常会有一个包含所有域的构造函数，用来创建这个传输对象。</P>
<P>&nbsp;&nbsp;&nbsp; 这个传输对象中的成员变量基本都被定义为公共，从而无需为它们提供相关的访问方法。当然如果存在一定安全的需要，相关的成员变量也可以设为保护或私有，并且给定各自的访问方法。由此可见，传输对象的设计是随着应用系统的需要不同而改变的，是否将对象中的成员变量设为公共，或提供一定的访问方法，将是一个很重要的设计问题。</P>
<P>&nbsp;&nbsp;&nbsp; 通常在实现这个模式时，最多采取的是可更新的传输对象策略和多传输对象策略。&nbsp;&nbsp;&nbsp; 在可更新的传输对象策略中，传输对象不仅可以从服务于用户的业务对象中取得相关信息和数据，还可以从业务对象中得到用户对于数据所需要进行的改变。</P>
<P>&nbsp;&nbsp;&nbsp; 图15以类图表的形式表明了业务对象和传输对象之间的关系。</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <IMG height=256 src="http://www.zdnet.com.cn/i/developer/story/200310/39174509/image030.jpg" width=453></P>
<P>图15 可更新传输对象类图</P>
<P>&nbsp;&nbsp; 业务对象创建了传输对象。而用户通过访问业务对象，既得到了所需的信息，也对相关数据做出了一定的修改；为了能够使得用户可以修改业务对象各个域的取值，这个对象必须提供一定的变值方法，而出于对Web负担的考虑，业务对象所提供的方法最好以传输对象为参数。相应地，这些方法可以去调用传输对象所提供的方法，来设置传输对象的各个成员变量的取值；同时在传输对象的方法中，我们也可以植入数据验证和完整性检查的逻辑，这样在用户从业务对象的方法得到传输对象时，可以直接调用传输对象的成员方法进行本地数据访问，当然这种本地数据访问不会影响到业务对象。</P>
<P>&nbsp;&nbsp;&nbsp; 当用户调用业务对象的变值方法时，该方法会将用户端的传输对象序列化，再将它发送给业务对象；业务对象接收到更新的传输对象，便将这些更新写回到自己的对象拷贝中去；&nbsp;&nbsp;&nbsp; 这里需要说明的是，上面提到的写回只是涉及到被更新的变量，而不是全部变量的写回，因此我们需要在传输对象中另设置一个变量，来指定哪些成员变量被用户更新过，这也就使得这种模式的设计相对复杂，开发人员需要考虑同步化和版本控制的问题。</P>
<P>&nbsp;</P>
<P>图16显示了这个更新过程的序列图。</P>
<P align=left><IMG height=416 src="http://www.zdnet.com.cn/i/developer/story/200310/39174509/image032.jpg" width=524></P>
<P>图16 可更新传输对象序列图</P>
<P>&nbsp;&nbsp; 多传输对象的方法是指一个单一的业务对象可以根据用户请求制造多个不同的传输对象。也就是说，业务对象和它所创建的传输对象保持一对多的关系。类图17表示了这种实现方法的各个参与模块以及它们之间的调用关系。</P>
<P align=center><IMG height=336 src="http://www.zdnet.com.cn/i/developer/story/200310/39174509/image034.jpg" width=367></P>
<P align=center>图17 多传输对象类图</P>
<P align=center>&nbsp;</P>
<P>当一个用户需要A类型的传输对象时，他会激活相关EJB的getDataA()方法来取得传输对象A；当他需要B类型的传输对象时，他会激活getDataB()方法来获取传输对象B；依此类推。序列图18表示了这一过程。</P>
<P align=center><IMG height=308 src="http://www.zdnet.com.cn/i/developer/story/200310/39174509/image036.jpg" width=455></P>
<P align=center>图18 &nbsp;多传输对象序列图</P>
<P>&nbsp;&nbsp;&nbsp; </P>
<P>使用这种设计模式，应用系统的实体bean及其远程接口会变得十分简单。实体bean中无需再为每一个成员变量都实现一个set()和get()方法，并在远程接口中实现相应的定义。用户无需再进行多次的方法调用来取得信息和数据，所需要的只是一次方法调用以获得整个传输对象。当然这里需要考虑Web负担和大量数据一次传输的权衡。开发人员可以根据不同的需要来选择不同的实现方法。</P>
<P>&nbsp; 如上所述，用户和实体bean之间可以通过在一次方法调用中使用传输对象而交换所有的数据，也就是说传输对象作为数据载体工作，并减少了远程的方法调用，从而大大减轻了Web负担。通过使用传输对象的方法，我们也将有可能减少实体bean和其传输对象间的代码重复。不过在使用可更新的传输对象方法时，用户可以修改其本地的传输对象，之后再将其传送回业务对象中，后者将所需的更新整合到自己一端；但是这样一来，就会存在一个版本控制的问题，不同的客户可能在同时修改相同类型的传输对象，而如果相关的业务对象没有发现这一点的话，可能就会造成一些用户的数据没有得到及时更新，而另外一些用户的数据又被覆盖的情况；在系统设计中必须考虑这个问题。</P>
<P><B>8、截取过滤器</B></P>
<P>截取过滤器(intercepting filter)主要用于对于用户请求的之前处理和之后处理，也就是说它对于客户的请求使用了额外的操作。比如说，servlet可以处理一个网站的所有客户请求并提供一个核心的认证机制。</P>
<P>这种模式主要工作于表示层，负责处理不同类型的请求，同时也需要进行多种不同的处理。在这些请求中，有一些请求会直接传送给后端模块处理，而另外一些请求则先会在过滤器里解释或补充内容，之后才能传送给后端模块。这种模式的提出主要是由于一个客户的Web访问和系统响应都需要一定的预处理和后处理，例如用户身份、用户环境信息、用户请求的合法性等。通常这些处理的结果都会决定用户的请求是否能够进行，或是系统的响应应该用什么格式来表示。</P>
<P>对于这种预处理和后处理问题，传统上，开发人员会设计一系列额外的检测程序模块，也就是一整套if/else语句，并且指定如果其中任何一个检测失败，所有的处理工作都会退出。显然，这种方法是存在很大弊端的，即代码的可读性、可维护性都会被大大降低，同时将检测工作融于一般的程序模块，使得整个程序的模块性难以保证。</P>
<P>解决这种问题的关键在于，设计一种简单的技术，以能够添加或移除额外处理的模块，而这些模块通常都能够完成一定的检测和过滤功能。根据以上的讨论，J2EE研究人员提出了设计模式----截取过滤器作为解决方案，这种模式可以在不影响核心处理模块的情况下，实现可插入的过滤器来执行一般的处理功能。&nbsp;&nbsp;&nbsp; </P>
<P>从理论上来说，这种过滤器可以截取客户请求和系统响应，并进行相应的预处理和后处理；同时开发人员也可以随时根据需要移除这些过滤器，并不用担心会改变任何其他模块。&nbsp;&nbsp;&nbsp; </P>
<P>我们这里所说的预处理和后处理功能，通常是指一些基本的系统服务，如安全、登录，系统调试等。执行这些功能的过滤器通常是需要与核心模块分开的，并且由于系统职能或规则的变化，这些模块随时可能被添加或删除。</P>
<P>下面提供一些关于截取过滤器的图示，以帮助大家更好地理解这种设计模式，并合理地加以运用。图19表示了截取过滤器模式的整体结构，图19显示了截取过滤器中的参与模块和相互之间的联系。</P>
<P>&nbsp;&nbsp; <IMG height=229 src="http://www.zdnet.com.cn/i/developer/story/200310/39174509/image038.jpg" width=415></P>
<P>图19&nbsp; 截取过滤器模式</P>
<P>&nbsp;&nbsp;&nbsp; <IMG height=325 src="http://www.zdnet.com.cn/i/developer/story/200310/39174509/image040.jpg" width=531></P>
<P>图20 截取过滤器序列图</P>
<P>下面我们分别来说明图20中的各个模块：</P>
<P>(1)过滤管理器(Filter Manager)。过滤管理器负责过滤器的主要处理工作，即创建过滤器链对象以及相应的过滤器组建，并初始化整个处理过程。</P>
<P>(2)过滤器链(Filter Chain)。过滤器链是一组互不依赖的过滤器有序集合。</P>
<P>(3)过滤器1，过滤器2，过滤器3(FilterOne，FilterTwo，FilterThree)。这些都是提供不同服务的过滤器，而过滤器链则负责它们的协调工作。</P>
<P>通过采用这种设计模式，应用系统可以取得更方便的中心控制，这是由于过滤器可以提供处理多种请求的中心模块，并能根据后端的处理模块而解释和润色用户的请求，使得该请求能更好地与处理模块所提供的功能匹配。另外，过滤器通常可以将不同种类的服务聚集在一起，并提供相当灵活的服务组合，应用系统可以通过使用截取过滤器提高其重用性，过滤器可以随时根据需要从其他程序模块中插入或移除，并且由于它们通常具有标准的接口，开发人员可以使用一组类似的过滤器，并在不同的情况下进行全组的重用。</P>
<P>&nbsp; 采用这种设计模式也会带来一定的问题，即在过滤器之间共享信息将变得非常困难，这是由于根据其定义和需求，每个过滤器的设计和开发都大相径庭。因而如果在不同的过滤器之间需要共享信息的话，其代价将是非常昂贵的。</P>
<HR>

<P>作者：务实，多年从事J2EE网站及应用系统项目的开发和应用。</P>
<P><B>参考资料：</B></P>
<P>《J2EE设计开发编程指南》&nbsp;&nbsp;&nbsp;&nbsp; Rod Johnson&nbsp;&nbsp;&nbsp;&nbsp; 电子工业出版社</P>
<P>《J2EE参考大全》&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Jim Keogh&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 电子工业出版社</P>
<P>《实用J2EE设计模式编程指南》 Craig A.Berry&nbsp;&nbsp; 电子工业出版社</P>
<HR>

<P><BR><BR>责任编辑：<A href="mailto:zhang_yan@zdnet.com.cn?subject=http://www.zdnet.com.cn/developer/tech/story/0,2000081602,39174509-7,00.htm">炒饭</A><BR><FONT color=#ff0000><BR>欢迎<A href="http://forums.zdnet.com.cn/cgi-bin/leoboard.cgi" target=new>评论</A>或<A href="mailto:zhang_yan@zdnet.com.cn?subject=投稿：(稿件题目)">投稿</A> </P>
<P></P>
<P></FONT><BR></P></TD></TR></TBODY></TABLE><img src ="http://www.cnblogs.com/voyage/aggbug/24686.html?type=1" width = "1" height = "1" /><br/><br/>--------------------------<br/>新闻：<a href="http://news.cnblogs.com/n/48008/" target="_blank">IBM发布全球首款开源智能编译器</a><br/>网站导航: <a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://dotnet.cnblogs.com" target="_blank">.NET频道</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://zzk.cnblogs.com" target="_blank">找找看</a>]]></description></item><item><title>微软面试100题——要想成为盖茨就来试试！（转贴）</title><link>http://www.cnblogs.com/voyage/archive/2004/07/09/22780.html</link><dc:creator>voyage</dc:creator><author>voyage</author><pubDate>Fri, 09 Jul 2004 08:03:00 GMT</pubDate><guid>http://www.cnblogs.com/voyage/archive/2004/07/09/22780.html</guid><wfw:comment>http://www.cnblogs.com/voyage/comments/22780.html</wfw:comment><comments>http://www.cnblogs.com/voyage/archive/2004/07/09/22780.html#Feedback</comments><slash:comments>22</slash:comments><wfw:commentRss>http://www.cnblogs.com/voyage/comments/commentRss/22780.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/voyage/services/trackbacks/22780.html</trackback:ping><description><![CDATA[<P>&nbsp;</P>
<P>1为什么下水道的井盖是圆的？ <BR>　　 <BR>　　　　2美国有多少辆车？（一个常见的类似问题是：美国有多少家加油站？） <BR>　　 <BR>　　　　3美国有多少个下水道井盖？ <BR>　　 <BR>　　　　4你让某些人为你工作了七天，你要用一根金条作为报酬。这根金条要被分成七块。你必须在每天的活干完后交给他们一块。如果你只能将这根金条切割两次，你怎样给这些工人分？ <BR>　　 <BR>　　　5一列火车以每小时15英里的速度离开洛杉矶，朝纽约进发。另外一列火车以每小时20英里的速度离开纽约，朝洛杉矶进发。如果一只每小时飞行25英里的鸟同时离开洛杉矶，在两列火车之间往返飞行，请问当两列火车相遇时，鸟飞了多远？ <BR>　　 <BR>　　　　6假设一张圆盘像唱机上的唱盘那样转动。这张盘一半是黑色，一半是白色。假设你有数量不限的一些颜色传感器。要想确定圆盘转动的方向，你需要在它周围摆多少个颜色传感器？它们应该被摆放在什么位置？ <BR>　　 <BR>　　　　7假设时钟到了12点。注意时针和分针重叠在一起。在一天之中，时针和分针共重叠多少次？你知道它们重叠时的具体时间吗？ <BR>　　 <BR>　　　　8你有两个罐子，分别装着50个红色的玻璃球和50个蓝色的玻璃球。随意拿起一个罐子，然后从里面拿出一个玻璃球。怎样最大程度地增加让自己拿到红球的机会？利用这种方法，拿到红球的几率有多大？ <BR>　　 <BR>　　　　9中间只隔一个数字的两个奇数被称为奇数对，比如17和19。证明奇数对之间的数字总能被6整除（假设这两个奇数都大于6）。现在证明没有由三个奇数组成的奇数对。 <BR>　　 <BR>　　　　10一个屋子有一个门（门是关闭的）和3盏电灯。屋外有3个开关，分别与这3盏灯相连。你可以随意操纵这些开关，可一旦你将门打开，就不能变换开关了。确定每个开关具体管哪盏灯。 <BR>　　 <BR>　　　　11假设你有8个球，其中一个略微重一些，但是找出这个球的惟一方法是将两个球放在天平上对比。最少要称多少次才能找出这个较重的球？ <BR>　　 <BR>　　　　12假设你站在镜子前，抬起左手，抬起右手，看看镜中的自己。当你抬起左手时，镜中的自己抬起的似乎是右手。可是当你仰头时，镜中的自己也在仰头，而不是低头。为什么镜子中的影像似乎颠倒了左右，却没有颠倒上下？ <BR>　　 <BR>　　　　13 你有4瓶药。每粒药丸的重量是固定的，不过其中有一瓶药受到了污染，药丸的重量发生了变化，每个药丸增加了一点重量。你怎样一下子测出哪瓶药是遭到污染的呢？ <BR>　　 <BR>　　　　14下面玩一个拆字游戏，所有字母的顺序都被打乱。你要判断这个字是什么。假设这个被拆开的字由5个字母组成： <BR>　　 <BR>　　　　1． 共有多少种可能的组合方式？ <BR>　　 <BR>　　　　2． 如果我们知道是哪5个字母，那会怎么样？ <BR>　　 <BR>　　　　3． 找出一种解决这个问题的方法。 <BR>　　 <BR>　　　　15有4个女人要过一座桥。她们都站在桥的某一边，要让她们在17分钟内全部通过这座桥。这时是晚上。她们只有一个手电筒。最多只能让两个人同时过桥。不管是谁过桥，不管是一个人还是两个人，必须要带着手电筒。手电筒必须要传来传去，不能扔过去。每个女人过桥的速度不同，两个人的速度必须以较慢的那个人的速度过桥。 <BR>　　 <BR>　　　　第一个女人：过桥需要1分钟； <BR>　　 <BR>　　　　第二个女人：过桥需要2分钟； <BR>　　 <BR>　　　　第三个女人：过桥需要5分钟； <BR>　　 <BR>　　　　第四个女人：过桥需要10分钟。 <BR>　　 <BR>　　　　比如，如果第一个女人与第4个女人首先过桥，等她们过去时，已经过去了10分钟。如果让第4个女人将手电筒送回去，那么等她到达桥的另一端时，总共用去了20分钟，行动也就失败了。怎样让这4个女人在17分钟内过桥？还有别的什么方法？ <BR>　　 <BR>　　　　16如果你有一个5夸脱的水桶和一个3夸脱的水桶，如何准确量出4夸脱的水？ <BR>　　 <BR>　　　　17你有一袋糖，有红色的，蓝色的，绿色的。闭上眼睛，拿出两块颜色一样的糖，你需要拿多少次才能确保有两块颜色相同的？ <BR>　　 <BR>　　　　18如果你有两个桶，一个装的是红色的颜料，另一个装的是蓝色的颜料。你从蓝色颜料桶里舀一杯，倒入红色颜料桶，再从红色颜料桶里舀一杯倒入蓝颜料桶。两个桶中红蓝颜料的比例哪个更高？通过算术的方式来证明这一点。 <BR>　　 <BR>　　运算 <BR>　　 <BR>　　　　19链接表和数组之间的区别是什么？ <BR>　　 <BR>　　　　20做一个链接表，你为什么要选择这样的方法？ <BR>　　 <BR>　　 <BR>　　　　21选择一种算法来整理出一个链接表。你为什么要选择这种方法？现在用o(n)时间来做。 <BR>　　 <BR>　　　　22说说各种股票分类算法的优点和缺点。 <BR>　　 <BR>　　　　23用一种算法来颠倒一个链接表的顺序。现在在不用递归式的情况下做一遍。 <BR>　　 <BR>　　　　24用一种算法在一个循环的链接表里插入一个节点，但不得穿越链接表。 <BR>　　 <BR>　　　　25用一种算法整理一个数组。你为什么选择这种方法？ <BR>　　 <BR>　　　　26用一种算法使通用字符串相匹配。 <BR>　　 <BR>　　　　27颠倒一个字符串。优化速度。优化空间。 <BR>　　 <BR>　　　　28颠倒一个句子中的词的顺序，比如将&#8220;我叫克丽丝&#8221;转换为&#8220;克丽丝叫我&#8221;，实现速度最快，移动最少。 <BR>　　 <BR>　　　　29找到一个子字符串。优化速度。优化空间。 <BR>　　 <BR>　　　　30比较两个字符串，用o(n)时间和恒量空间。 <BR>　　 <BR>　　　　31假设你有一个用1001个整数组成的数组，这些整数是任意排列的，但是你知道所有的整数都在1到1000（包括1000）之间。此外，除一个数字出现两次外，其他所有数字只出现一次。假设你只能对这个数组做一次处理，用一种算法找出重复的那个数字。如果你在运算中使用了辅助的存储方式，那么你能找到不用这种方式的算法吗？ <BR>　　 <BR>　　　　32不用乘法或加法增加8倍。现在用同样的方法增加7倍。 <BR>　　 <BR>　　应用 <BR>　　 <BR>　　　　33如何将计算机技术应用于一幢100层高的办公大楼的电梯系统上？你怎样优化这种应用？工作日时的交通、楼层或时间等因素会对此产生怎样的影响？ <BR>　　 <BR>　　　　34你如何对一种可以随时存在文件中或从因特网上拷贝下来的操作系统实施保护措施， <BR>　　防止被非法复制？ <BR>　　 <BR>　　　　35你如何重新设计自动取款机？ <BR>　　 <BR>　　　　36假设我们想通过电脑来操作一台微波炉，你会开发什么样的软件来完成这个任务？ <BR>　　 <BR>　　　　37你如何为一辆汽车设计一台咖啡机？ <BR>　　 <BR>　　　　38如果你想给微软的word系统增加点内容，你会增加什么样的内容？ <BR>　　 <BR>　　　　39你会给只有一只手的用户设计什么样的键盘？ <BR>　　 <BR>　　　　40你会给失聪的人设计什么样的闹钟？ <BR>　　 <BR>　　头脑 <BR>　　 <BR>　　　　41如果你有一个许多部件可以拆卸的时钟，你将它一块块拆开，但是没有记住是怎样拆的。然后你将各个零件重新组装起来，最后发现有三个重要零件没有放进去。这时你如何重新组装这个时钟？ <BR>　　 <BR>　　 <BR>　　　　42如果你需要学习一门新的计算机语言，你会怎样做？ <BR>　　 <BR>　　　　43假设由你负责设计比尔&#183;盖茨的卫生间。当然，钱不成问题，但是你不可以和比尔谈。你会怎样做？ <BR>　　 <BR>　　　　44到目前为止，你遇到的最难回答的问题是什么？ <BR>　　 <BR>　　　　45如果微软公司说，我们愿意投资500万美元用来开发你提出的方案。那么你会做什么？为什么？ <BR>　　 <BR>　　　　46如果你将世界上所有的计算机制造商召集起来，告诉他们必须要做一件事，你会让他们做什么事？ <BR>　　 <BR>　　　　47如果你在五年内会得到一笔奖金，你认为会是因为什么？关注你的成绩的人会是谁？ <BR>　　 <BR>　　　　48你如何教自己的奶奶使用微软excel表格系统？ <BR>　　 <BR>　　　　49为什么当我们在任何一家宾馆打开热水龙头时，热水会马上流出来？ 50你为什么想在微软工作？ <BR>　　 <BR>　　　　51假设你回到家，进入自己的房间，打开电灯开关，可是一点反应都没有&#8212;&#8212;灯没有亮。这时，你在判断问题出在哪里时，会依次采取怎样的做法？ <BR>　　 <BR>　　请在a、b、c、d中选择正确的答案。 <BR>　　 <BR>　　　　52． 下列哪项叙述是错误的？ <BR>　　 <BR>　　　　（a）主观主义者可能也是相对论者。 <BR>　　 <BR>　　 <BR>　　　　（b）相对论者也可能是客观主义者。 <BR>　　 <BR>　　　　（c）绝对论者也可能是主观主义者。 <BR>　　 <BR>　　　　（d）客观主义者也可能是绝对论者。 <BR>　　 <BR>　　　　53． 如果就像萨特的存在主义所说的，&#8220;人要为自己的热情负责&#8221;，那么无论我们做什么，我们都： <BR>　　 <BR>　　　　（a）违背了自己的意愿。 <BR>　　 <BR>　　　　（b）没有经过思考。 <BR>　　 <BR>　　　　（c）是自由的。 <BR>　　 <BR>　　　　（d）是出于对上帝的蔑视。 <BR>　　 <BR>　　　　54．萨特宣称，对人类来说，&#8220;存在先于本质&#8221;，换言之： <BR>　　 <BR>　　　　（a）当人们理智的时候，他们才符合人类的本质。 <BR>　　 <BR>　　　　（b）根据上帝的指示，人们在本质上是注定要存在的。 <BR>　　 <BR>　　　　（c）人类可以自由选择，甚至选择不以任何方式做任何事。 <BR>　　 <BR>　　　　（d）人类是自由的，可以通过自己的行为而成为自己所愿意成为的任何角色。 <BR>　　 <BR>　　　　55． 萨特说，&#8220;根本没有人类本性这种东西&#8221;，他的意思是： <BR>　　 <BR>　　　　（a）作为具有自我意识的生命，我们可以决定而且确实决定了自己成为一种什么样的生命。 <BR>　　 <BR>　　　　（b）人类没有办法选择是痛苦还是绝望。 <BR>　　 <BR>　　　　（c）人类不具有可以从在生物角度把他们归为一个物种的遗传特征。 <BR>　　 <BR>　　　　（d）存在主义认为上帝的存在只是道德判断的先决基础。 <BR>　　 <BR>　　　　56．康德说，一个行为符合义务并不能令它成为道德行为，当执行者只为了尽义务或因为这是他的义务而做，他的行为才是道德行为。康德这样说是为了表明： <BR>　　 <BR>　　　　（a）一个人行为的后果可能是好的也可能是坏的，一切取决于这个行为产生了多少快乐。 <BR>　　 <BR>　　　　（b）出于自由意愿而做的行为永远是道德行为。 <BR>　　 <BR>　　　　（c）一个行为的道德价值是由执行者的动机决定的，不是由这个行为的结果决定的。 <BR>　　 <BR>　　　　（d）出于自身利益的行为不同于根据准则而做的行为。 <BR>　　 <BR>　　　　57．康德认为，决定一个行为是否道德的关键是这个行为所依据的准则，而不是这个单独的行为本身。因为： <BR>　　 <BR>　　　　（a）根据定义，一个个体行为是不可以被普遍化的。 <BR>　　 <BR>　　　　（b）我们的行为总是依据这样或那样的准则。 <BR>　　 <BR>　　　　（c）没有准则，我们将无从知道应该怎样做。 <BR>　　 <BR>　　　　（d）我们的准则是行为的客观法则，是我们行事的基础。 <BR>　　 <BR>　　　　58．根据康德的观点，一项具有无法被成功普遍化的动机或目的的行为： <BR>　　 <BR>　　　　（a）根据结果的不同，可以是道德的或不道德的。 <BR>　　 <BR>　　　　（b）根据该行为是否被该人所在社会所接受，可以是道德的或不道德的。 <BR>　　 <BR>　　　　（c）是不道德的。 <BR>　　 <BR>　　　　（d）根据该行为是否出于自由意愿，可以是道德的或不道德的。 <BR>　　 <BR>　　　　59．康德说，&#8220;我可以判断其他所有有理性的人是否和我一样有义务去做某件事&#8221;，判断依据是： <BR>　　 <BR>　　　　（a）某些行为是否被不同文化普遍接受。 <BR>　　 <BR>　　　　（b）其他人做和我一样的行为是否得到好的结果。 <BR>　　 <BR>　　　　（c）这个行为在所有人看来都是好的。 <BR>　　 <BR>　　　　（d）我的行为的动机可以被普遍化，没有被某些人抵触或不被接受。 <BR>　　 <BR>　　　　60．行为实用主义者说，我们应该一直做那些能带来最大幸福的事，即使这意味着违反道德原则。原则实用主义者不同意这种意见，说我们应该遵守道德原则，即使我们认为违背这些原则会产生更好的结果，因为： <BR>　　 <BR>　　　　（a）服从道德原则为社会整体带来的幸福通常多于为少数例外者带来的不幸福。 <BR>　　 <BR>　　　　（b）我们不应该成为任何道德原则的奴隶，道德只是个人选择问题。 <BR>　　 <BR>　　　　（c）通常来说，为大多数人谋求最大幸福的行为并不总是符合道德的。 <BR>　　 <BR>　　　　（d）即使我们服从道德原则，也总难免造成某些人的不幸福。 <BR>　　 <BR>　　　　61．行为实用主义者指出，有时候违反某一道德准则能比遵守准则带来更大的幸福。他们认为，在这种情况下，违反道德准则是允许的： <BR>　　 <BR>　　　　（a）只要保证下不为例。 <BR>　　 <BR>　　　　（b）只要这个行为所影响的人没有感到不快。 <BR>　　 <BR>　　　　（c）只要实施行为者的动机或意图是为了尽自己的义务而不计后果。 <BR>　　 <BR>　　　　（d）实用主义原则本身甚至要求人们这样做。 <BR>　　 <BR>　　62.元帅领兵 <BR>　　 <BR>　　　　元帅统领八员将，每将各分八个营，每营里面摆八阵，每阵配置八先锋，每个先锋八旗头，每个旗头有八队，每队分设八个组，每组带领八个兵。请你掐指算一算，元师共有多少兵？ <BR>　　 <BR>　　 <BR>　　　　63.运算符号的妙用 <BR>　　 <BR>　　　　在1、2、3、4、5、6、7、8、9这一串数字中间，加入运算符号&#8220;＋&#8221;或&#8220;－&#8221;，使其代数和等于99，按（1 &#8230;&#8230; 9）可以有17种解，倒过来的后者（9 &#8230;&#8230; 1）可以有11种解。有兴趣的读者，不妨一试。 <BR>　　 <BR>　　　　64.两龟赛跑 <BR>　　 <BR>　　　　有两只乌龟一起赛跑。甲龟到达10米终点线时，乙龟才跑到9米。现在如果让甲龟的起跑线退后1米，这时两龟再同时起跑比赛，问甲、乙两龟是否同时到达终点？ <BR>　　 <BR>　　　　65.电视机的价格 <BR>　　 <BR>　　　　麦克因工作繁忙，决定临时请尼克来协助他工作。规定以一年为期限，一年的报酬为600美元与一台电视机。 <BR>　　 <BR>　　　　可是尼克做了7个月后，因急事必须离开麦克，并要求麦克付给他应得的钱和电视机。由于电视机不能拆散付给他，结果尼克得到了150美元和一台电视机。 <BR>　　 <BR>　　　　现在请你想一想：这台电视机值多少钱？ <BR>　　 <BR>　　　　66.这块石头究竟有多重 <BR>　　 <BR>　　　　有4个小孩看见一块石头正沿着山坡滚下来，便议论开了。 <BR>　　 <BR>　　　　&#8220;我看这块石头有17公斤重，&#8221;第一个孩子说。 <BR>　　 <BR>　　　　&#8220;我说它有26公斤，&#8221;第二个孩子不同意地说。 <BR>　　 <BR>　　　　&#8220;我看它重21公斤&#8221;，第三个孩子说。 <BR>　　 <BR>　　　　&#8220;你们都说得不对，我看它的正确重量是20公斤，&#8221;第四个孩子争着说。 <BR>　　 <BR>　　　　他们四人争得面红耳赤，谁也不服谁。最后他们把石头拿去称了一下，结果谁也没猜准。其中一个人所猜的重量与石头的正确重量相差2公斤，另外两个人所猜的重量与石头的正确重量之差相同。当然，这里所指的差，不考虑正负号，取绝对值。请问这块石头究竟有多重？ <BR>　　 <BR>　　　　67.三只砝码称东西 <BR>　　 <BR>　　　　现在有三种不同重量的标准砝码1克、3克、9克。请问可以称出多少不同物品的重量？在进行称量时，要称的东西与已知的标准砝码可以任意地放在天平的两盘之一。另外，每种砝码都只有一只，而且不准复制。 <BR>　　 <BR>　　　　68.称米 <BR>　　 <BR>　　　　现有米9公斤以及50克和200克的砝码各一个。问怎样在天平上只称量三次而称出2公斤米？ <BR>　　 <BR>　　　　69.比萨饼交易 <BR>　　 <BR>　　　　在我最喜欢的那家比萨饼店中，10寸的比萨卖4.99美元。店主说，他们有一笔12寸比萨饼的交易，定价为每份5.39美元。请问：该店在这笔比萨饼交易中给予了买方多少折扣？ <BR>　　 <BR>　　70.伊沙贝拉时装精品屋 <BR>　　 <BR>　　　　纽约伊沙贝拉时装精品屋，新近从意大利购进了一件女式冬装。这衣服的购入价格再加二成，是该店标出的销售价。 <BR>　　 <BR>　　　　出于半个月内未卖出去，女老板又将这个定价减去了一成，很快被一位漂亮小姐买走了 <BR>　　。女老板获利400元。 <BR>　　 <BR>　　　　请问，这件高档女式冬装购入价是多少？ <BR>　　 <BR>　　　　71.称量罐头 <BR>　　 <BR>　　　　为罐头工厂工作的送货员a，给一家食品公司送了10箱菠萝罐头。每个罐头重量是800克，每箱装20个。 <BR>　　 <BR>　　　　正当他送完了货，要回工厂的时候，接到了从工厂打来的电话，说这10箱中有一箱由于机器出了问题而混进了次品，每个罐头缺50克的分量，要送货员把这箱罐头送回工厂以便更换。但是，怎样从中找出到底哪一箱是次品呢？最需要的当然是秤，可是手边又没有。 <BR>　　 <BR>　　　　正在这时，他忽然发现不远的路旁有一台自动称量体重的机器，也就是投进去1元硬币就可以称量一次重量。他的口袋里刚好就有一个1元硬币。当然也就只能量一次。那么他应该怎么充分利用这只有一次的机会，来找到那一箱不符合规格的产品呢？ <BR>　　 <BR>　　　　72.按劳取酬 <BR>　　 <BR>　　　　有一个农场主，雇用了两个临时工帮忙种小麦。其中一个叫做汤姆，是一个耕地能手，但是他不会播种；而另一个叫做尼克，他并不擅长于耕地，但是，他却是播种的好手。这个农场主决定要种十公顷小麦，让他们各自包一半，于是，汤姆从东头开始耕地，而尼克从西头开始耕地。耕一亩地汤姆只要用二十分钟，而尼克却需要四十分钟，但是尼克播种的速度比汤姆要快三倍。 <BR>　　 <BR>　　　　他们播种完工后，农场主按照他们的工作量给予他俩一共一百元的工钱。请问：他们应该怎么样分这份工钱才最合理？ <BR>　　 <BR>　　　73.四兄弟的年龄 <BR>　　 <BR>　　　　一家有4个兄弟，他们4个的年龄乘起来的积为14。那么，他们各自的年龄是多大?当然年龄应该是整数。 <BR>　　 <BR>　　　　74.爱的程度 <BR>　　 <BR>　　　　在一所乡村学校中，一个刚刚毕业的男数学老师s很幸运地同时得到了两个女教师a、b的青睐。s满脑袋数字，在无法从两者之中选择的情况下，他只好对这两位女教师说，&#8220;希望你们用数字或者数学公式，来表示你们对我的爱的程度。&#8221; <BR>　　 <BR>　　　　a说，&#8220;与b比起来，我是一百倍地爱你。&#8221; <BR>　　 <BR>　　　　b说，&#8220;a对你的感情当然没有我对你的感情深。与a相比，我是一千倍地爱你。&#8221; <BR>　　 <BR>　　　　听了她们深情的话语，不知为什么数学老师s反而神情沮丧地说，&#8220;这不就等于说，你们两个都是完全不爱我吗？&#8221; <BR>　　 <BR>　　　　这究竟是怎么回事？ <BR>　　 <BR>　　　　75.爬楼梯 <BR>　　 <BR>　　　　一位先生要到10层楼的第8层去办事，不巧正赶上停电，电梯无法使用，他只能够步行上楼。如果他从第1层爬到第4层需要用48秒，那么请问，以同样的速度走到第8层需要多少秒？ <BR>　　 <BR>　　　　76.空姐分配物品 <BR>　　 <BR>　　　　在一架飞机上，中间是一条过道，两边是座位，每一排为三人。两位空姐a和b每人负责一边，对每位旅客分配旅行物品。 <BR>　　 <BR>　　　　开始的时候，a给右边的旅客发放了6份，此时，b过来对她说，左边应该由a负责。于是a重新到左边开始发放，b接着给右边剩下的旅客发放物品，之后，又帮a发了15份，最后两人同时结束工作。 <BR>　　 <BR>　　　　请问：a和b谁发的多？多发了多少份？ <BR>　　 <BR>　　生产中需要一段铁链，库房中只有五截每截只有三个铁环的铁链，这五截铁链连起来的长度正好是所需要的。 <BR>　　 <BR>　　　　问：在只切断三个铁环的情况下，怎样将这五截三铁环连起来？ <BR>　　 <BR>　　 <BR>　　　　77.巧分飞机票 <BR>　　 <BR>　　　　旅行社刚刚为三位旅客预定了飞机票。这三位旅客是荷兰人科尔、加拿大人伯托和英国人丹皮。他们三人一个去荷兰，一个去加拿大，一个去英国。据悉科尔不打算去荷兰，丹皮不打算去英国，伯托则既不去加拿大，也不去英国。 <BR>　　 <BR>　　　　问：这三张飞机票分别应该是他们谁的？ <BR>　　 <BR>　　　　78.白帽和黑帽 <BR>　　 <BR>　　　　老师让6名学生围坐成一圈，另让一名学生坐在中央，并拿出七顶帽子，其中四顶白色，三顶黑色。然后蒙住七名学生的眼睛，并给坐在中央的学生戴一顶帽子，而只解开坐在圈上的六名学生的眼罩。这时，由于坐在中央的学生的阻挡，每个人只能看到五个人的帽子。老师说：&#8220;现在，你们七人猜一猜自己的头上戴的帽子颜色。&#8221;大家静静地思索了好大一会。最后，坐在中央的、被蒙住双眼的学生举手说：&#8220;我猜到了。&#8221; <BR>　　 <BR>　　　　问：中央的被蒙住双眼的学生带的是什么颜色的帽子？他是怎样猜到的? <BR>　　 <BR>　　　　79.急中生智 <BR>　　 <BR>　　　　有个农民挑了一对竹筐，赶集去买东西。当他来到一座独木桥上，对面来了个孩子，他想退回去让孩子先过桥，但是回身一看，后面也来了个孩子。正在进退两难之际，农民急中生智，想了个巧办法，使大家都顺利地通过了独木桥，而且三人之中谁也没有后退过一步。 <BR>　　 <BR>　　　　问：农民是用的什么方法？ <BR>　　 <BR>　　　　80.巧入房间 <BR>　　 <BR>　　　　某地质勘探队有12名队员，他们同住在一栋楼的12个房间内。由于工作关系，资料不能集中，各人的房间内都有别人需要查对的资料。 <BR>　　 <BR>　　　　这天，12位队员又要外出作业了。临行前，队长对大家说：&#8220;在外出作业期间，12个人一起回来是不可能的，如有队员回来查资料就困难了。现在咱们每个人都有打开自己门锁的两把钥匙，只准带走其中一把钥匙，余下的一把不准挂在门上，因为不安全，每个房间的门窗也必须关严，大家想一想，怎样才能使任何一个人回来都能打开12个房间呢？&#8221; <BR>　　 <BR>　　　　问：如果你是队员之一，你能想出办法来吗？ <BR>　　 <BR>　　　　81.女儿的错 <BR>　　 <BR>　　　　父亲打电话给女儿，要她替自己买一些生活用品，同时告诉她，钱放在书桌上的一个信封里。女儿找到信封，看见上面写着98，以为信封内有98元，就把钱拿出来，数也没数放进书包里。 <BR>　　 <BR>　　　　在商店里，她买了90元的东西，付款时才发现，她不仅没有剩下8元，反而差了4元。 <BR>　　 <BR>　　　　回到家里，她把这事告诉了父亲，怀疑父亲把钱点错了。父亲笑着说，他并没有数错，错在女儿身上。 <BR>　　 <BR>　　　　问：女儿错在什么地方？ <BR>　　 <BR>　　　　82.找硬币 <BR>　　 <BR>　　　　3个日本孩子翻衣兜，他们把兜里所有的钱都掏出来，看看一共有多少钱。结果一共有320日元。其中有两枚硬币是100日元的，两枚是50日元的，两枚是10日元的。每一个孩子所带的硬币中没有相同的。而且，没带100日元硬币的孩子也没带10日元的硬币，没带50日元硬币的孩子也没带100日元的硬币。你能弄清楚这3个日本孩子原来各自带了什么硬币吗？ <BR>　　 <BR>　　　　83.入睡与醒来 <BR>　　 <BR>　　　　请问：从你生下来的那一刻起，你入睡和醒来的次数哪个多？多多少次？ <BR>　　 <BR>　　84. 什么书中毛病最多？ <BR>　　 <BR>　　　　85. 为什么好马不吃回头草？ <BR>　　 <BR>　　　　86. 什么东西说&#8220;父亲&#8221;是不会相碰，叫&#8220;爸爸&#8221;时却会碰到两次？ <BR>　　 <BR>　　 <BR>　　　　87. 农夫养10头牛，只有19只角，为什么？ <BR>　　 <BR>　　　　88. 打什么东西既不花力气又舒服？ <BR>　　 <BR>　　　　89. 托尼总是喜欢把家里的闹钟整坏，妈妈为什么总是让不会修理钟表的爸爸代为修理？ <BR>　　 <BR>　　　　90. 戴夫走路从来脚不沾地，这是为什么？ <BR>　　 <BR>　　　　91. 生米不小心煮成熟饭时该怎么办？ <BR>　　 <BR>　　　　92. 制造日期与有效日期是同一天的产品是什么？ <BR>　　 <BR>　　　　93. 时钟敲了十三下，请问现在该做什么呢？ <BR>　　 <BR>　　11. 在罗马数字中，零该怎么写？ <BR>　　 <BR>　　　　94. 有对一模一样的双胞胎兄弟，哥哥的屁股有黑痣，而弟弟没有。但即使这对双胞胎穿着相同的服饰，仍然有人可立刻知道谁是哥哥，谁是弟弟。究竟是谁呢？ <BR>　　 <BR>　　　　95. 家有家规，国有国规，那动物园里有啥规？ <BR>　　 <BR>　　 <BR>　　　　96. 先有男人，还是先有女人？ <BR>　　 <BR>　　　　15. 什么人每天靠运气赚钱？ <BR>　　 <BR>　　　　97. 玛丽整天说个不停，可有一个月她说的最少，那是为什么？ <BR>　　 <BR>　　　　98. 戴维手里拿着火柴走到厨房，这有一个煤气灶和一个酒精灯，他如果想烧开水，请问：他应该先该点燃什么？ <BR>　　 <BR>　　　　99. 老师说蚯蚓切成两段仍能再生，西恩照老师的话去做，蚯蚓却死了，为什么? <BR>　　 <BR>　　　　100. 汽车在右转弯时,哪只轮胎不转? <BR></P><img src ="http://www.cnblogs.com/voyage/aggbug/22780.html?type=1" width = "1" height = "1" /><br/><br/>--------------------------<br/>新闻：<a href="http://news.cnblogs.com/n/48007/" target="_blank">IE颓势不减 微软下月公布最新浏览器架构</a><br/>网站导航: <a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://dotnet.cnblogs.com" target="_blank">.NET频道</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://zzk.cnblogs.com" target="_blank">找找看</a>]]></description></item><item><title>Tapestry+Spring+Hibernate整合工作小结</title><link>http://www.cnblogs.com/voyage/archive/2004/07/09/22774.html</link><dc:creator>voyage</dc:creator><author>voyage</author><pubDate>Fri, 09 Jul 2004 07:49:00 GMT</pubDate><guid>http://www.cnblogs.com/voyage/archive/2004/07/09/22774.html</guid><wfw:comment>http://www.cnblogs.com/voyage/comments/22774.html</wfw:comment><comments>http://www.cnblogs.com/voyage/archive/2004/07/09/22774.html#Feedback</comments><slash:comments>8</slash:comments><wfw:commentRss>http://www.cnblogs.com/voyage/comments/commentRss/22774.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/voyage/services/trackbacks/22774.html</trackback:ping><description><![CDATA[<P><SPAN class=postbody>下面是我发在Spring中文论坛上的文字, 但是没有得到回应, 希望在这里能得到帮助. 谢谢大家<IMG alt=Smile src="http://forum.javaeye.com/images/smiles/icon_smile.gif" border=0> <BR>-------------------------------------- <BR><BR>Tapestry+Spring+Hibernate整合工作小结 <BR><BR>Cyberwing <BR><BR><BR>FrankSoo是我的项目经理。前段时间公司决定作个新的J2EE二次开发平台，以替换公司原有的开发平台。公司让FrankSoo和我组成平台开发项目组，FrankSoo担任项目经理。现在这个平台整合开发阶段已经结束，进入项目应用阶段。下面是我们的整合工作小结，介绍一下我们在工作中遇到的问题，以及我们选择的解决方案. <BR><BR><BR>1、架构的选择 <BR><BR>首先，我们都同意以我们现有的能力，没有足够的时间和资源自行开发一套完整的平台。在已有的众多开源项目中选择若干优秀的项目进行整合，才可能按时完成项目，达到项目目的。 <BR><BR>但是在平台项目开始前，我们对平台的技术架构有各自的构想。FrankSoo原来的构想是Struts+Spring+Hibernate，而我的构想是Tapestry+Hibernate。 <BR><BR>不过FrankSoo非常open，在我向他演示了Tapestry的经典范例workbench，介绍了Tapestry基于组件的编程方式之后，他同意选用Tapestry作为实现Web展现层的框架。我想FrankSoo以前的Struts开发经验(painful)也是他做出这个决定的因素之一。 <BR><BR>FrankSoo gave me a nice introduction of Spring Framework. Wow, what an amazing framework! IOC, Declarative Transaction Support, Hibernate Session Management, Hibernate DAO Support&#8230; These features are just what we need for a middle tire container. <BR><BR>至于Hibernate，这个最成功的开源ORM项目，我们都投了它一票^_^ <BR><BR>最后我们确定平台的技术架构是Tapestry+Spring+Hibernate. <BR><BR>2、架构整合 <BR><BR>最初的平台架构借鉴了一篇介绍如何集成Tapestry与Spring的文章［1］中提到的架构： <BR><BR><IMG src="http://java.blogger.cn/images/java.blogger.cn/cyberwing/557/o_Libra_old.GIF" border=0> <BR><BR>Web层的Tapestry负责数据输入输出, 响应用户事件，及输入校验的工作, 通过访问预先加载的WebApplicationContext(由Spring提供, 包含着所有Service bean)获得Service层的Service Bean, 把业务操作都委托给它们. <BR><BR>Service层的bean则负责use case逻辑, domain相关的逻辑委托给domain model中的bean去实现. Service通过DAO完成对domain model的持久化工作. Service负责数据库事务和Hibernate Session的管理(通过Spring的声明式事务管理和与之集成的Hibernate Session管理). Service层的另一项重要工作是权限和访问控制。 <BR><BR>Domain model负责表示问题域的数据和domain logic. DAO使用Hibernate持久化数据以及查询. 在实现DAO时, 我们使用了Spring的Hibernate DAO Support,极大地简化了代码, 很多方法都只用简单的一行完成. 有意思的是, 最后完成的HibernateDAO的代码量居然比我写的MockDAO的代码少了一半还多 <BR><BR>这样的架构优点很明显, 层次清晰, 各层的职责也明确, 便于分层设计与开发, 结合mock和spring的IOC, unit test也是非常容易的. 而且后台(Service, domain model and DAO)的代码不依赖于Web容器或是EJB容器的API, 移植性非常好, 同样的代码可以在Web app中使用也可在普通的Java app中使用, 只需更换UI层. <BR><BR>按照这个整合的构架，我们实现一个简单的实例，实现了列表分页查询和显示，数据增删改，基于Hibernate Criteria Query提供了一个比较通用的查询机制。利用Middlegen和Velocity我们可以从已经建好的数据库表结构自动生成Hibernate映射文件，实体类和DAO，极大地减少了工作量。我们还对这个小例子进行了压力测试（测试时的数据量为10万条记录），确定平台不存在性能问题。 <BR><BR>通过这个实例我们把整个架构基本走通一遍，并总结了使用这套架构开发时适用的开发流程和需要做的工作。 <BR><BR>3、困扰我们的问题 <BR><BR>在实现例子和现在的项目应用过程中，我们发现了若干头疼的问题，有的解决了，有的还没有。 <BR><BR>问题1：要不要使用DTO？ <BR><BR>在上面的架构中我们并没有明确Service和Web层间的数据传输是如何进行的。我们讨论好久要不要使用DTO，最后的结论是不用。 <BR><BR>使用DTO有两个主要的理由：1、减少Web层和Service层间的方法调用，通过一个方法调用就将Web需要的数据都传给Web。2、隔离domain model和Web层。 <BR><BR>第一个理由在我们的架构下是不成立的。因为我们的架构是集中式的，Web和Service是在同一个JVM中，它们之间的方法调用是没有EJB远程访问的巨大消耗的。 <BR><BR>第二个理由还是需要考虑的。如果允许把domain model中的对象传给Web层，那么修改domain model，就会影响到Web层。如果使用DTO，那么domain model实现上的变化就不会影响到Web。但是大量的变化不是domain model实现上的变化，而是domain model接口的变化，比如一个domain model的对象上添加了一个属性，而这个属性需要用户修改，那么这时候必须修改Web层，不管是不是用了DTO。而且使用DTO，就需要维护着一大堆对象，或是它们的生成器，这是非常无聊、且容易出错的工作。 <BR><BR>基于这些考虑，我们没有使用DTO，而是选择把domain model直接传到Web层。下面是修改后的架构图（呵呵，修改了别人的图［2］）。 <BR><BR><IMG src="http://java.blogger.cn/images/java.blogger.cn/cyberwing/557/o_Libra.GIF" border=0> <BR><BR><BR>问题2：Entity like domain model or rich domain model? <BR><BR>我们使用Middlegen自动生成Hibernate映射文件，Entity类和DAO类, 但是生成的Entity只含有简单的属性和getter, setter方法。因此我们遇到了一个问题：我们的domain model还要不要包含domain logic？如果包含，那么和自动生成工具如何结合？ <BR><BR>我们讨论后认为一个rich domain model还是非常有必要的，可以减少Service中的重复代码，提高复用性。 <BR><BR>如何同自动生成结合？使用 
<META>标签，生成抽象基类，我们继承这些自动生成的基类，添加业务方法。 <BR><BR>问题3：Model driven or Data driven? <BR><BR>采用Model driven还是Data driven的方式大家有过热烈的讨论。我们主要是受到Rod Johnson［3］的影响，采用了Data driven的方式。先作数据库设计，生成库表，然后用Middlegen反向生成Hibernate映射文件和Entity及DAO。但是我们在进入项目应用之后发现这种方法有两个问题： <BR><BR>a） 数据库设计仅说明了系统要管理的静态数据，我们还是得作面向对象分析，以反映系统的动态行为。特别是当系统的业务不仅仅是简单的CRUD操作时，这个问题更严重。 <BR>b） 数据库设计为了优化性能，可能会把好几个应该是单独实体的数据放入一个实体中。这样如果直接把这种极粗粒度实体映射成Entity类，那简直是不可接受的。面向对象的分析设计模型得到的类都是相当细粒度的。这种情况还得作面向对象的分析，明确到底这个粗粒度的大表应该映射成那几个细粒度的对象。 <BR><BR>或许我们应该试试Model driven，用AndroMDA生成domain model，Hibernate DAO，Hibernate mapping，数据库表，简单的Service和前台的Tapestry页面。 <BR><BR>问题4：Hibernate Session生命周期如何管理？ <BR><BR>对于Hibernate Session的生命周期我们采用的是Session-per-Transaction模式，未采用Open Session in View模式。 虽然Hibernate team认为这种方法没什么不好，而且FreeRoller和Atlassian的confluence都使用了Open Session In View这种模式，但是我们对它可能产生的影响还没有很好的把握，所以暂时弃置不用。 如果Web层要访问lazy load的数据, 需要先调用Service的业务方法, 以获得数据. <BR><BR>问题5：Use case logic 和domain logic 如何区分？ <BR><BR>Service负责use case logic，domain model负责domain logic。这样的划分看起来很好，实现起来就很麻烦。如何确定什么是use case logic，什么是domain logic？TBD. <BR><BR><BR>问题6：Service粒度如何确定？ <BR><BR>这个问题真是很烦，原先考虑使用usecase controller的方式，每个usecase对应一个Service，但是发现这样复用性太低，而且好多地方必须复用相同的功能 <BR><BR>另一种方法是用package level service，每个package作个service，这样倒是可以重用，但是感觉太死了，不好。 <BR><BR>现在也没有什么很好的办法，只好在详细设计时根据具体情况确定需要多少个Service了。TBD. <BR><BR>问题7：权限如何设定？如何检查？ <BR><BR>权限设定也是个头疼的问题。我们本想是按照use case设定权限，每个用例一个权限。在角色设定的时候直接处理的都是业务意义非常明确的权限。但是在权限验证过程中发现了问题：如果在Service的方法中验证权限，而且这个方法在多个用例中用到（复用Service），那么这个Service的方法就需要检查多个权限; 如果每个Service方法对应一个权限, 那么权限又太细了, 不像use case权限那样代表一个完整的业务. 真的是很麻烦阿！TBD. <BR><BR><BR><BR>Ok, 这些就是我们这段工作的结果。希望能给大家一些启发，也希望能得到大家的帮助，帮我们出出主意，谢谢大家。 <BR><BR><BR><BR>Reference: <BR>[1] Integrating Tapestry and Spring Framework. 原来Spring网站上有单独的文章，现在合入Spring Reference中了，见Spring Reference, chapter 12, section 7. <A href="http://www.springframework.org/docs/reference/view.html#view-tapestry" target=_blank>http://www.springframework.org/docs/reference/view.html#view-tapestry</A> <BR>[2] Wiring Your Web Application with Open Source Java, Mark Eagle, 2004/04/07, O&#8217;Reilly OnJava.com, <A href="http://www.onjava.com/pub/a/onjava/2004/04/07/wiringwebapps.html" target=_blank>http://www.onjava.com/pub/a/onjava/2004/04/07/wiringwebapps.html</A> <BR>[3] Expert one-on-one J2EE Design and Development, Rod Johnson, 2003, Wrox Press.</SPAN><SPAN class=postbody></SPAN><SPAN class=gensmall></SPAN></P>
<P class=postfoot><A id=_ctl0__ctl9_HomePageDays_DaysList__ctl2_DayItem_DayList__ctl0_PostTime title=permalink href="http://java.mblogger.cn/ctms/posts/3807.aspx">20:58</A> | <A class=itemdesc id=_ctl0__ctl9_HomePageDays_DaysList__ctl2_DayItem_DayList__ctl0_FeedBackCount title="comments, pingbacks, trackbacks" href="http://java.mblogger.cn/ctms/posts/3807.aspx#FeedBack">评论 (0)</A> </P>
<DIV class=post>
<H2><A id=_ctl0__ctl9_HomePageDays_DaysList__ctl2_DayItem_DayList__ctl1_TitleUrl href="http://java.mblogger.cn/ctms/posts/3805.aspx">VO, PO, BO, DTO... 辨别一些名词</A></H2>VO, PO, BO, DTO... 辨别一些名词： <BR>1、VO: 实际上很模糊，通常指ValueObject和ViewObject <BR>2、View Object: 界面展现需要的对象，如Struts的FormBean <BR>3、Value Object: 早期被作为ValueObject和Transfer Object的总称。实际上Value Object的真正意义在于它的内容，而不是身份 <BR>4、Data Transfer Object(DTO): 数据传输对象，在应用程序不同层次之间传书对象，在一个分布式应用程序中，</DIV><img src ="http://www.cnblogs.com/voyage/aggbug/22774.html?type=1" width = "1" height = "1" /><br/><br/>--------------------------<br/>新闻：<a href="http://news.cnblogs.com/n/48007/" target="_blank">IE颓势不减 微软下月公布最新浏览器架构</a><br/>网站导航: <a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://dotnet.cnblogs.com" target="_blank">.NET频道</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://zzk.cnblogs.com" target="_blank">找找看</a>]]></description></item><item><title>Spring Framework,ioc容器(转)</title><link>http://www.cnblogs.com/voyage/archive/2004/07/09/22773.html</link><dc:creator>voyage</dc:creator><author>voyage</author><pubDate>Fri, 09 Jul 2004 07:46:00 GMT</pubDate><guid>http://www.cnblogs.com/voyage/archive/2004/07/09/22773.html</guid><wfw:comment>http://www.cnblogs.com/voyage/comments/22773.html</wfw:comment><comments>http://www.cnblogs.com/voyage/archive/2004/07/09/22773.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cnblogs.com/voyage/comments/commentRss/22773.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/voyage/services/trackbacks/22773.html</trackback:ping><description><![CDATA[摘要: Spring Framework,ioc容器(转)October 2003 You may have heard the buzz this summer around the Spring Framework. In this article, I&#8217;ll try to explain what Spring sets out to achieve, and how I believe&nbsp;&nbsp;<a href='http://www.cnblogs.com/voyage/archive/2004/07/09/22773.html'>阅读全文</a><img src ="http://www.cnblogs.com/voyage/aggbug/22773.html?type=1" width = "1" height = "1" /><br/><br/>--------------------------<br/>新闻：<a href="http://news.cnblogs.com/n/48007/" target="_blank">IE颓势不减 微软下月公布最新浏览器架构</a><br/>网站导航: <a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://dotnet.cnblogs.com" target="_blank">.NET频道</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://zzk.cnblogs.com" target="_blank">找找看</a>]]></description></item><item><title>Introducing to Spring Framework（中文修订版）</title><link>http://www.cnblogs.com/voyage/archive/2004/07/09/22769.html</link><dc:creator>voyage</dc:creator><author>voyage</author><pubDate>Fri, 09 Jul 2004 07:41:00 GMT</pubDate><guid>http://www.cnblogs.com/voyage/archive/2004/07/09/22769.html</guid><wfw:comment>http://www.cnblogs.com/voyage/comments/22769.html</wfw:comment><comments>http://www.cnblogs.com/voyage/archive/2004/07/09/22769.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cnblogs.com/voyage/comments/commentRss/22769.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/voyage/services/trackbacks/22769.html</trackback:ping><description><![CDATA[<P>转摘： Introducing to Spring Framework（中文修订版）<BR>Introducing to Spring Framework </P>
<P>作者：Rod Johnson <BR>译者：yanger，taowen <BR>校对：taowen </P>
<P>关于Spring Framework，今年夏天你可能已经听见很多的议论。在本文中,我将试图<BR>解释Spring能完成什么，和我怎么会认为它能帮助你开发J2EE应用程序。 </P>
<P>又来一个framework？ </P>
<P>你可能正在想&#8220;不过是另外一个的framework&#8221;。当已经有许多开放源代码(和专有) <BR>J2EE framework时，为什么你还要耐下心子读这篇文章或去下载Spring Framework？ </P>
<P>我相信Spring是独特的，有几个原因： </P>
<P>&nbsp;</P>
<P>它关注的领域是其他许多流行的Framework未曾关注的。Spring要提供的是一<BR>种管理你的业务对象的方法。 </P>
<P>Spring既是全面的又是模块化的。Spring有分层的体系结构，这意味着你能选<BR>择仅仅使用它任何一个独立的部分，而它的架构又是内部一致。因此你能从<BR>你的学习中，得到最大的价值。例如，你可能选择仅仅使用Spring来简单化<BR>JDBC的使用，或用来管理所有的业务对象。 </P>
<P>它的设计从一开始就是要帮助你编写易于测试的代码。Spring是使用测试驱动<BR>开发的工程的理想框架。 </P>
<P><BR>Spring不会给你的工程添加对其他的框架依赖。Spring也许称得上是个一站式解决方<BR>案，提供了一个典型应用所需要的大部分基础架构。它还涉及到了其他framework没<BR>有考虑到的内容。 </P>
<P>尽管它仅仅是一个从2003年2月才开始的开源项目，但Spring有深厚的历史根基。这<BR>个开源工程是起源自我在2002年晚些时候出版的《Expert One-on-One J2EE设计与开<BR>发》书中的基础性代码。这本书展示了Spring背后的基础性架构思想。然而，对这<BR>个基础架构的概念可以追溯到2000年的早些时候,并且反映了我为一系列商业工程开<BR>发基础结构的成功经验。 </P>
<P>2003年1月，Spring已经落户于SourceForge上了。现在有10个开发人员，其中6个是高<BR>度投入的积极分子。 </P>
<P>Spring架构上的好处 </P>
<P>在我们进入细节之前，让我们来看看Spring能够给工程带来的种种好处： </P>
<P>&nbsp;</P>
<P>Spring能有效地组织你的中间层对象，不管你是否选择使用了EJB。如果你仅仅<BR>使用了Struts或其他为J2EE的 API特制的framework，Spring致力于解决剩下的问题。 </P>
<P>Spring能消除在许多工程中常见的对Singleton的过多使用。根据我的经验，这是一<BR>个很大的问题，它降低了系统的可测试性和面向对象的程度。 </P>
<P>通过一种在不同应用程序和项目间一致的方法来处理配置文件，Spring能消除各种<BR>各样自定义格式的属性文件的需要。曾经对某个类要寻找的是哪个魔法般的属性<BR>项或系统属性感到不解，为此不得不去读Javadoc甚至源编码？有了Spring，你仅仅<BR>需要看看类的JavaBean属性。Inversion of Control的使用（在下面讨论）帮助完成了<BR>这种简化。 </P>
<P>通过把对接口编程而不是对类编程的代价几乎减少到没有，Spring能够促进养成好<BR>的编程习惯。 </P>
<P>Spring被设计为让使用它创建的应用尽可能少的依赖于他的APIs。在Spring应用中的<BR>大多数业务对象没有依赖于Spring。 </P>
<P>使用Spring构建的应用程序易于单元测试。 </P>
<P>Spring能使EJB的使用成为一个实现选择,而不是应用架构的必然选择。你能选择用<BR>POJOs或local EJBs来实现业务接口，却不会影响调用代码。 </P>
<P>Spring帮助你解决许多问题而无需使用EJB。Spring能提供一种EJB的替换物，它们适<BR>用于许多web应用。例如，Spring能使用AOP提供声明性事务管理而不通过EJB容器，<BR>如果你仅仅需要与单个数据库打交道，甚至不需要一个JTA实现。 </P>
<P>Spring为数据存取提供了一个一致的框架,不论是使用的是JDBC还是O/R mapping产品<BR>（如Hibernate）。 </P>
<P><BR>Spring确实使你能通过最简单可行的解决办法来解决你的问题。而这是有有很大价值的。 </P>
<P>Spring做了些什么？ </P>
<P>Spring提供许多功能，在此我将依次快速地展示其各个主要方面。 </P>
<P>任务描述 </P>
<P>首先,让我们明确Spring范围。尽管Spring覆盖了许多方面，但我们对它应该涉什么，什么<BR>不应该涉及有清楚的认识。 </P>
<P>Spring的主要目的是使J2EE易用和促进好编程习惯。 </P>
<P>Spring不重新轮子。因此，你发现在Spring中没有logging，没有连接池，没有分布式事务调<BR>度。所有这些东西均有开源项目提供(例如我们用于处理所有日志输出的Commons Logging<BR>以及Commons DBCP)，或由你的应用程序服务器提供了。出于同样的的原因，我们没有<BR>提供O/R mapping层。对于这个问题已经有了像Hibernate和JDO这样的优秀解决方案。 </P>
<P>Spring的目标就是让已有的技术更加易用。例如，尽管我们没有底层事务协调处理，但我<BR>们提供了一个抽象层覆盖了JTA或任何其他的事务策略。 </P>
<P>Spring没有直接和其他的开源项目竞争，除非我们感到我们能提供新的一些东西。例如，<BR>象许多开发人员一样，我们从来没有对Struts感到高兴过，并且觉得到在MVC web <BR>framework中还有改进的余地。在某些领域，例如轻量级的IoC容器和AOP框架，Spring确实<BR>有直接的竞争，但是在这些领域还没有已经较为流行的解决方案。(Spring在这些领域是开<BR>路先锋。) </P>
<P>Spring也得益于内在的一致性。所有的开发者都在唱同样的的赞歌，基础想法依然与Expert <BR>One-on-One J2EE设计与开发中提出的差不多。 并且我们已经能够在多个领域中使用一些中<BR>心的概念，例如Inversion of Control。 </P>
<P>Spring在应用服务器之间是可移植的。当然保证可移植性总是一种挑战，但是我们避免使用<BR>任何平台特有或非标准的东西，并且支持在WebLogic，Tomcat，Resin，JBoss，WebSphere和<BR>其他的应用服务器上的用户。 </P>
<P>Inversion of Control 容器 </P>
<P>Spring设计的核心是 org.springframework.beans 包, 它是为与JavaBeans一起工作而设计的。 这<BR>个包一般不直接被用户使用，而是作为许多其他功能的基础。 </P>
<P>下一个层面高一些的抽象是"Bean Factory"。一个Spring bean factory 是一个通用的Factory，它<BR>使对象能够按名称获取，并且能管理对象之间的关系。 </P>
<P>Bean factories 支持两种模式的对象： </P>
<P>&nbsp;</P>
<P>Singleton：在此模式中，有一个具有特定名称的共享对象实例，它在查找时被获取。这<BR>是默认的，而且是最为经常使用的。它对于无状态对象是一种理想的模式。 </P>
<P>Prototype：在此模式中，每次获取将创建一个独立的对象。例如，这可以被用于让用户<BR>拥有他们自己的对象。 </P>
<P>&nbsp;</P>
<P>由于 org.springframwork.beans.factory.BeanFactory是一个简单的接口，它能被大量底层存储方法<BR>实现。你能够方便地实现你自己的BeanFactory，尽管很少用户需要这么做。最为常用的<BR>BeanFactory定义是： </P>
<P>&nbsp;</P>
<P>XmlBeanFactory： 可解析简单直观的定义类和命名对象属性的XML结构。 我们提供了一<BR>个DTD来使编写更容易。 </P>
<P>ListableBeanFactoryImpl：提供了解析存放在属性文件中的bean定义的能力，并且可通过编<BR>程创建BeanFactories。 </P>
<P><BR>每个bean定义可能是一个POJO（通过类名和JavaBean初始属性定义），或是一个FactoryBean。FactoryBean接口添加了一个间接层。通常，这用于创建使用AOP或其他方法的代理对象：例如，<BR>添加声明性事务管理的代理。（这在概念上和EJB的interception相似，但实现得更简单。） </P>
<P>BeanFactories能在一个层次结构中选择性地参与，继承ancestor（祖先）的定义。这使得在整个<BR>应用中公共配置的共享成为可能，虽然个别资源，如controller servlets，还拥有他们自己的独立<BR>的对象集合。 </P>
<P>这种使用JavaBeans的动机在《Expert One-on-One J2EE Design and Development》的第四章中有描<BR>述，在TheServerSide网站上的有免费的PDF版本(<A href="http://www.theserverside.com/resources/article.jsp?l=RodJohnsonInterview">http://www.theserverside.com/resources/article.jsp?l=RodJohnsonInterview</A>)。 </P>
<P>通过BeanFactory概念，Spring成为一个Inversion of Control的容器。(我不怎么喜欢container这个词，<BR>因为它使人联想到重量级容器，如EJB容器。Spring的BeanFactory是一个可通过一行代码创建的<BR>容器，并且不需要特殊的部署步骤。) </P>
<P>Inversion of Control背后的概念经常表述为Hollywood原则的：&#8220;Don&#8217;t call me， I&#8217;ll call you。&#8221;<BR>IoC将控制创建的职责搬进了框架中，并把它从应用代码脱离开来。涉及到配置的地方，意思<BR>是说在传统的容器体系结构中，如EJB，一个组件可以调用容器并问&#8220;我需要它给我做工作的<BR>对象X在哪里?&#8221;；使用IoC容器则只需指出组件需要X对象，在运行时容器会提供给它。容器<BR>是通过查看方法的参数表（例如JavaBean的属性）做到的，也可能根据配置数据如XML。 </P>
<P>IoC有几个重要的好处，例如： </P>
<P>&nbsp;</P>
<P>因为组件不需要在运行时间寻找合作者，所以他们可以更简单的编写和维护。在Spring版<BR>的IoC里，组件通过暴露JavaBean的setter方法表达他们依赖的其他组件。这相当于EJB通过<BR>JNDI来查找，EJB查找需要开发人员编写代码。 </P>
<P>同样原因，应用代码更容易测试。JavaBean属性是简单的，属于Java核心的，并且是容易<BR>测试的：仅编写一个自包含的Junit测试方法用来创建对象和设置相关属性即可。 </P>
<P>一个好的IoC实现保留了强类型。如果你需要使用一个通用的factory来寻找合作者，你必<BR>须通过类型转换将返回结果转变为想要的类型。这不是一个大不了的问题，但是不雅观。<BR>使用IoC，你在你的代码中表达了强类型依赖，框架将负责类型转换。这意味着在框架配<BR>置应用时，类型不匹配将导致错误；在你的代码中，你无需担心类型转换异常。 </P>
<P>大部分业务对象不依赖于IoC容器的APIs。这使得很容易使用遗留下来的代码，且很容易的<BR>使用对象无论在容器内或不在容器内。例如，Spring用户经常配置Jakarta Commons DBCP数<BR>据源为一个Spring bean：不需要些任何定制代码去做这件事。我们说一个IoC容器不是侵入<BR>性的：使用它并不会使你的代码依赖于它的APIs。任何JavaBean在Spring bean factory中都能<BR>成为一个组件。 </P>
<P><BR>最后应该强调的是，IoC 不同于传统的容器的体系结构，如EJB，应用代码最小程度地依靠于容<BR>器。这意味着你的业务对象可以潜在的被运行在不同的IoC 框架上&#8212;&#8212;或者在任何框架之外&#8212;&#8212;<BR>不需要任何代码的改动。 </P>
<P>以我和其他Spring用户的经验来说，再怎么强调IoC给应用程序代码带来的好处也不为过。 </P>
<P>IoC不是一个新概念，但是它在J2EE团体里面刚刚到达黄金时间。 有一些可供选择的IoC 容器: <BR>例如 Apache Avalon, PicoContainer 和 HiveMind。Avalon 从没怎么流行，尽管它很强大而且有很<BR>长的历史。Avalon相当的重和复杂，并且看起来比新的IoC解决方案更具侵入性。 PicoContainer<BR>是一个轻量级而且更强调通过构造函数表达依赖性而不是JavaBean 属性。 与Spring不同，它的设<BR>计允许每个类型一个对象的定义(可能是因为它拒绝任何Java代码外的元数据导致的局限性)。在Spring， PicoContainer 和其他 IoC frameworks之间做比较，可参看文章Spring网站上的"The Spring Framework - A Lightweight Container"位于<A href="http://www.springframework.org/docs/lightweight_container.html">http://www.springframework.org/docs/lightweight_container.html</A>。<BR>这个页面里面包含了PicoContainer站点的链接 。 </P>
<P>Spring BeanFactories 是非常轻量级的。用户已经成功地将他们应用在applets和单独的Swing应用中。(它们也很好地工作在EJB容器中。) 没有特殊的部署步骤和察觉得到的启动时间。这个能力表明<BR>一个容器在应用的任何层面几乎立即可以发挥非常大的价值。 </P>
<P>Spring BeanFactory 概念贯穿于Spring始终， 而且是Spring如此内在一致的关键原因。在IoC容器中，Spring也是唯一的，它使用IoC作为基础概念贯穿于整个功能丰富的框架。 </P>
<P>对应用开发人员，最重要的是，一个或多个BeanFactory提供了一个定义明确的业务对象层。这类<BR>似于local session bean层，但比它更简单。与EJBs不同，在这个层中的对象可能是相关的，并且他<BR>们的关系被拥有它们的factory管理。有一个定义明确的业务对象层对于成功的体系结构是非常重<BR>要的。 </P>
<P>Spring ApplicationContext 是BeanFactory的子接口，为下列东西提供支持： </P>
<P>&nbsp;</P>
<P>信息查找，支持着国际化 </P>
<P>事件机制，允许发布应用对象以及可选的注册以接收到事件 </P>
<P>可移植的文件和资源访问 </P>
<P><BR>XmlBeanFactory 例子 </P>
<P>Spring用户通常在XML的&#8220;bean定义&#8221;文件中配置他们的应用。Spring的XML bean定义文档的根<BR>是 元素。该元素包含一个或多个 定义。我们一般给每个bean定义的指定类和属性。我们还必<BR>须指定ID作为标识，这将成为在代码中使用该bean的名字。 </P>
<P>让我们来看一个简单的例子，它配置了三个应用程序对象，之间的关系在J2EE应用中常常能够<BR>看到： </P>
<P>&nbsp;</P>
<P>J2EE DataSource </P>
<P>使用DataSource的DAO </P>
<P>在处理过程中使用DAO的业务对象 </P>
<P><BR>在下面的例子中，我们使用一个来自Jakarta Commons DBCP项目的BasicDataSource。这个class（和<BR>其他许多已有的class一样）可以简单地被应用在Spring bean factory中，只要它提供了JavaBean格式<BR>的配置。需要在shutdown时被调用的Close方法可通过Spring的"destroy-method"属性被注册，以避免BasicDataSource需要实现任何Spring 的接口。 </P>
<P>代码: </P>
<P><BR>&nbsp; class="org.apache.commons.dbcp.BasicDataSource" <BR>destroy-method="close"&gt; <BR>&nbsp;&nbsp;&nbsp; com.mysql.jdbc.Driver <BR>&nbsp;&nbsp;&nbsp; jdbc:mysql://localhost:3306/mydb <BR>&nbsp;&nbsp;&nbsp; root <BR>&nbsp;&nbsp; </P>
<P>BasicDataSource中我们感兴趣的所有属性都是String类型的，因此我们用元素来指定他们的值。如<BR>果必要的话，Spring使用标准的 JavaBean属性编辑器机制来把String转换为其他的类型。 </P>
<P>现在，我们定义DAO，它有一个对DataSource的bean引用。Bean间关系通过元素来指定： </P>
<P>代码: <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; class="example.ExampleDataAccessObject"&gt; <BR>&nbsp;&nbsp;&nbsp; <BR>&nbsp; </P>
<P>The business object has a reference to the DAO, and an int property (exampleParam): <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; class="example.ExampleBusinessObject"&gt; <BR>&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp; 10 <BR>&nbsp; </P>
<P>&nbsp;</P>
<P>对象间的关系一般在配置中明确地设置，象这个例子一样。我们认为这样做是件好事情。然而<BR>Spring还提供了我们称做"autowire"的支持， 一个la PicoContainer，其中它指出了bean间的依赖关<BR>系。这样做的局限性&#8212;&#8212;PicoContainer也是如此&#8212;&#8212;是如果有一个特殊类型的多个Bean，要确定<BR>那个类型所依赖的是哪个实例是不可能。好的方面是，不满足的依赖可以在factory初始化后被捕<BR>获到。（Spring 也为显式的配置提供了一种可选的依赖检查，它可以完成这个目的） </P>
<P>在上面的例子中，如果我们不想显式的编写他们的关系，可使用如下的autowire特性： </P>
<P>代码: <BR>&nbsp;&nbsp; class="example.ExampleBusinessObject" <BR>&nbsp;&nbsp; autowire="byType"&gt; </P>
<P>&nbsp;&nbsp;&nbsp; 10 <BR>&nbsp; </P>
<P><BR>使用这个特性，Spring会找出exampleBusinessObject的dataSource属性应该被设置为在当前<BR>BeanFactory中找到的DataSource实现。在当前的BeanFactory中，如果所需要类型的bean不存在或<BR>多于一个，将产生一个错误。我们依然要设置exampleParam属性，因为它不是一个引用。 </P>
<P>Autowire支持和依赖检查刚刚加入CVS并将在Spring 1.0 M2(到10/20,2003)中提供。本文中所讨论<BR>的所有其他特性都包含在当前1.0 M1版本中。 </P>
<P>把管理从Java代码中移出来比硬编码有很大的好处，因为这样可以只改变XML文件而无需改变<BR>一行Java代码。例如，我们可以简单地改变myDataSource的bean定义引用不同的bean class以使用<BR>别的连接池，或者一个用于测试的数据源。 XML节变成另一种，我们可以用Spring的<BR>JNDI location FactoryBean从应用服务器获取一个数据源。 </P>
<P>现在让我们来看看例子中业务对象的java 代码。注意下面列出的代码中没有对Spring的依赖。不<BR>像EJB容器，Spring BeanFactory不具有侵入性：在应用对象里面你通常不需要对Spring的存在硬编码。 </P>
<P>代码: <BR>public class ExampleBusinessObject implements MyBusinessObject { </P>
<P>&nbsp;&nbsp; private ExampleDataAccessObject dao; <BR>&nbsp;&nbsp; private int exampleParam; </P>
<P>&nbsp;&nbsp; public void setDataAccessObject(ExampleDataAccessObject dao) { <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.dao = dao; <BR>&nbsp;&nbsp; } </P>
<P>&nbsp;&nbsp; public void setExampleParam(int exampleParam) { <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.exampleParam = exampleParam; <BR>&nbsp;&nbsp; } </P>
<P>&nbsp;&nbsp; public void myBusinessMethod() { <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // do stuff using dao <BR>&nbsp;&nbsp; } <BR>} </P>
<P>注意那些property setter，它们对应于bean定义文档中的XML引用。这些将在对象被使用之前由<BR>Spring调用。 </P>
<P>这些应用程序的bean不需要依赖于Spring：他们不需要实现任何Spring的接口或者继承Spring的类。<BR>他们只需要遵守JavaBeans的命名习惯。在Spring 应用环境之外重用它们是非常简单的，例如，在<BR>一个测试环境中。只需要用它们的缺省构造函数实例化它们，并且通过调用setDataSource()和setExampleParam()手工设置它的属性。如果你想以一行代码支持程序化的创建，只要你有一个无<BR>参数的构造器，你就可以自由定义其他需要多个属性的构造函数。 </P>
<P>注意在业务接口中没有声明将会一起使用的JavaBean属性。 他们是一个实现细节。我们可以&#8220;插入&#8221;带有不同bean属性的不同的实现类而不影响连接着的对象或者调用的代码。 </P>
<P>当然，Spring XML bean factories 有更多的功能没有在这里描述，但是，应当让你对基本使用有了<BR>一些感觉。以及，简单的属性，有JavaBean属性编辑器的属性，Spring可以自动处理lists，maps和java.util.Properties。 </P>
<P>Bean factories 和application contexts 通常和J2EE server定义的一个范围相关联，例如： </P>
<P>&nbsp;</P>
<P>Servlet context.：在spring 的MVC 框架里, 每一个包含common objects的web 应用都定义有一个<BR>应用程序的context。Spring提供了通过listener或者servlet实例化这样的context的能力而不需要<BR>依赖于Spring 的MVC 框架，因而它也可以用于Struts，WebWork 或者其他的web框架之中。 </P>
<P>A Servlet：在Spring MVC 框架里每一个servlet控制器都有它自己的应用程序context，派生于<BR>根（全应用程序范围的）应用程序context。在Struts或者其他MVC框架中实现这些也很容意。 </P>
<P>EJB：Spring 为EJB提供方便的超类，它们简化了EJB的创建并且提供了一个从EJB Jar 文件<BR>中的XML文档载入的BeanFactory。 </P>
<P><BR>这些J2EE规范提供的hook通常避免了使用Singleton来创造一个bean factory。 </P>
<P>然而，如果我们愿意的话可以用代码创建一个BeanFactory，虽然是没有什么意义的。例如，我<BR>们在以下三行代码中可以创建bean factory并且得到一个业务对象的引用： </P>
<P>代码: <BR>InputStream is = getClass().getResourceAsStream("myFile.xml"); <BR>XmlBeanFactory bf = new XmlBeanFactory(is); <BR>MyBusinessObject mbo = (MyBusinessObject) bf.getBean("exampleBusinessObject"); </P>
<P>&nbsp;</P>
<P>这段代码将能工作在一个应用服务器之外：甚至不依赖J2EE，因为Spring 的IoC容器是纯java的。</P>
<P><BR>JDBC 抽象和数据存储异常层次 </P>
<P>数据访问是Spring 的另一个闪光点。 </P>
<P>JDBC 提供了还算不错的数据库抽象，但是需要用痛苦的API。这些问题包括： </P>
<P>&nbsp;</P>
<P>需要冗长的错误处理代码来确保ResultSets，Statements以及（最重要的）Connections在使用<BR>后关闭。这意味着对JDBC的正确使用可以快速地导致大量的代码量。它还是一个常见的<BR>错误来源。Connection leak可以在有负载的情况下快速宕掉应用程序。 </P>
<P>SQLException相对来说不能说明任何问题。JDBC不提供异常的层次，而是用抛出<BR>SQLException来响应所有的错误。找出到底哪里出错了&#8212;&#8212;例如，问题是死锁还是无效的SQL？&#8212;&#8212;要去检查SQLState或错误代码。这意味着这些值在数据库之间是变化的。</P>
<P>Spring用两种方法解决这些问题： </P>
<P><BR>提供API，把冗长乏味和容易出错的异常处理从程序代码移到框架之中。框架处理所有的<BR>异常处理；程序代码能够集中精力于编写恰当的SQL和提取结果上。 </P>
<P>为你本要处理SQLException程序代码提供有意义的异常层次。当Spring第一次从数据源取得<BR>一个连接时，它检查元数据以确定数据库。它使用这些信息把SQLException映射为自己从org.springframework.dao.DataAccessException派生下来的类层次中正确的异常。因而你的代码<BR>可以与有意义的异常打交道，并且不需要为私有的SQLState或者错误码担心。Spring的数据<BR>访问异常不是JDBC特有的，因而你的DAO并不一定会因为它们可能抛出的异常而绑死在<BR>JDBC上。</P>
<P>Spring提供两层JDBC API。第一个时，在org.springframework.jdbc.core包中，使用回调机制移动控<BR>制权&#8212;&#8212;并且因而把错误处理和连接获取和释放&#8212;&#8212;从程序的代码移到了框架之中。这是一种<BR>不同的Inversion of Control，但是和用于配置管理的几乎有同等重要的意义。 </P>
<P>Spring使用类似的回调机制关注其他包含特殊获取和清理资源步骤的API，例如JDO（获取和释放<BR>是由PersistenceManager完成的），事务管理（使用JTA）和JNDI。Spring中完成这些回调的类被称<BR>作template。 </P>
<P>例如，Spring的JdbcTemplate对象能够用于执行SQL查询并且在如下的列表中保存结果： </P>
<P>代码: <BR>JdbcTemplate template = new JdbcTemplate(dataSource); <BR>final List names = new LinkedList(); <BR>template.query("SELECT USER.NAME FROM USER", <BR>&nbsp;&nbsp; new RowCallbackHandler() { <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void processRow(ResultSet rs) throws SQLException { <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; names.add(rs.getString(1)); <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } <BR>&nbsp;&nbsp; }); </P>
<P><BR>注意回调中的程序代码是能够自由抛出SQLException的：Spring将会捕捉到这些异常并且用自己<BR>的类层次重新抛出。程序的开发者可以选择哪个异常，如果有的话，被捕捉然后处理。 </P>
<P>JdbcTemplate提供许多支持不同情景包括prepared statements和批量更新的方法。Spring的JDBC抽<BR>象有比起标准JDBC来说性能损失非常小，甚至在当应用中需要的结果集数量很大的时候。 </P>
<P>在org.springframework.jdbc.object包中是对JDBC的更高层次的抽象。这是建立在核心的JDBC回调<BR>功能基础纸上的，但是提供了一个能够对RDBMS操作&#8212;&#8212;无论是查询，更新或者是存储过程&#8212;&#8212;<BR>使用Java对象来建模的API。这个API部分是受到JDO查询API的影响，我发现它直观而且非常有<BR>用。 </P>
<P>一个用于返回User对象的查询对象可能是这样的： </P>
<P>代码: </P>
<P>class UserQuery extends MappingSqlQuery { </P>
<P>&nbsp;&nbsp; public UserQuery(DataSource datasource) { <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; super(datasource, "SELECT * FROM PUB_USER_ADDRESS WHERE USER_ID = ?"); <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; declareParameter(new SqlParameter(Types.NUMERIC)); <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; compile(); <BR>&nbsp;&nbsp; } </P>
<P>&nbsp;&nbsp; // Map a result set row to a Java object <BR>&nbsp;&nbsp; protected Object mapRow(ResultSet rs, int rownum) throws SQLException { <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; User user = new User(); <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; user.setId(rs.getLong("USER_ID")); <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; user.setForename(rs.getString("FORENAME")); <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return user; <BR>&nbsp;&nbsp; } </P>
<P>&nbsp;&nbsp; public User findUser(long id) { <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Use superclass convenience method to provide strong typing <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return (User) findObject(id); <BR>&nbsp;&nbsp; } <BR>} <BR>&nbsp;</P>
<P>这个类可以在下面用上： <BR>代码: </P>
<P>User user = userQuery.findUser(25); <BR>&nbsp;</P>
<P>这样的对象经常可以用作DAO的inner class。它们是线程安全的，除非子类作了一些超出常规的事情。 </P>
<P>在org.springframework.jdbc.object包中另一个重要的类是StoredProcedure类。Spring让存储过程通过带<BR>有一个业务方法的Java类进行代理。如果你喜欢的话，你可以定义一个存储过程实现的接口，意味着你能够把你的程序代码从对存储过程的依赖中完全解脱出来。 </P>
<P>Spring数据访问异常层次是基于unchecked（运行时）exception的。在几个工程中使用了Spring之后，我越来越确信这个决定是正确的。 </P>
<P>数据访问异常一般是不可恢复的。例如，如果我们不能链接到数据库，某个业务对象很有可能就<BR>不能完成要解决的问题了。一个可能的异常是optimistic locking violation，但是不是所有的程序使用optimistic locking。强制编写捕捉其无法有效处理的致命的异常通常是不好的。让它们传播到上层的handler，比如servlet或者EJB 容器通常更加合适。所有的Spring对象访问异常都是DataAccessException的子类，因而如果我们确实选择了捕捉所有的Spring数据访问异常，我们可以很容易做到这点。 </P>
<P>注意如果我们确实需要从unchecked数据访问异常中恢复，我们仍然可以这么做。我们可以编写代<BR>码仅仅处理可恢复的情况。例如，如果我们认为只有optimistic locking violation是可恢复的，我们可<BR>以在Spring的DAO中如下这么写： </P>
<P>代码: </P>
<P>try { <BR>&nbsp;&nbsp; // do work <BR>} <BR>catch (OptimisticLockingFailureException ex) { <BR>&nbsp;&nbsp; // I'm interested in this <BR>} <BR>&nbsp;</P>
<P>如果Spring的数据访问异常是checked的，我们需要编写如下的代码。注意我们还是可以选择这么写： <BR>代码: </P>
<P>try { <BR>&nbsp;&nbsp; // do work <BR>} <BR>catch (OptimisticLockingFailureException ex) { <BR>&nbsp;&nbsp; // I'm interested in this <BR>} <BR>catch (DataAccessException ex) { <BR>&nbsp;&nbsp; // Fatal; just rethrow it <BR>} <BR>&nbsp;</P>
<P>第一个例子的潜在缺陷是&#8212;&#8212;编译器不能强制处理可能的可恢复的异常&#8212;&#8212;这对于第二个也是如此。因为我们被强制捕捉base exception（DataAccessException），编译器不会强制对子类（OptimisticLockingFailureException）的检查。因而编译器可能强制我们编写处理不可恢复问题的代码，但是对于强制我们处理可恢复的问题并未有任何帮助。 </P>
<P>Spring对于数据访问异常的unchecked使用和许多&#8212;&#8212;可能是大多数&#8212;&#8212;成功的持久化框架是一致的。（确实，它部分是受到JDO的影响。）JDBC是少数几个使用checked exception的数据访问API之一。例如TopLink和JDO大量使用unchecked exception。Gavin King现在相信Hibernate也应该选择使用unchecked exception。 </P>
<P>Spring的JDBC能够用以下办法帮助你： </P>
<P>&nbsp;</P>
<P>你决不需要在使用JDBC时再编写finally block。 </P>
<P>总的来说你需要编写的代码更少了 </P>
<P>你再也不需要挖掘你的RDBMS的文档以找出它为错误的列名称返回的某个罕见的错误代码。你的程序不再依赖于RDBMS特有的错误处理代码。 </P>
<P>无论使用的是什么持久化技术，你都会发现容易实现DAO模式，让业务代码无需依赖于任<BR>何特定的数据访问API。 </P>
<P><BR>在实践中，我们发现所有这些都确实有助于生产力的提高和更少的bug。我过去常常厌恶编写<BR>JDBC代码；现在我发现我能够集中精力于我要执行的SQL，而不是烦杂的JDBC资源管理。 </P>
<P>如果需要的话Spring的JDBC抽象可以独立使用&#8212;&#8212;不强迫你把它们用作Spring的一部分。<BR>O/R mapping 集成 </P>
<P>当然你经常需要使用O/R mapping，而不是使用关系数据访问。你总体的应用程序框架也必须支<BR>持它。因而提供了对Hibernate 2.x和JDO的集成支持。它的数据访问架构使得它能和任何底层的数<BR>据访问技术集成。Spring和Hibernate集成得尤其好。 </P>
<P>为什么你要使用Hibernate加Spring，而不是直接使用Hibernate？ </P>
<P>&nbsp;</P>
<P>Session 管理 Spring提供有效率的，简单的以并且是安全的处理Hibernate Session。使用<BR>Hibernate的相关代码为了效率和恰当的事务处理一般需要使用相同的Hibernate &#8220;Session&#8221;对象。Spring让它容易透明地创建和绑定Session到当前的线程，要么使用声明式，AOP的<BR>method interceptor方法，要么在Java代码层面使用显式的，&#8220;template&#8221;包装类。因而Spring解<BR>决了在Hibernate论坛上经常出现的用法问题。 </P>
<P>资源管理 Spring的应用程序context能够处理Hiberante SessionFactories的位置和配置，JDBC数<BR>据源和其他相关资源。这使得这些值易于管理和改变。 </P>
<P>集成的事务管理 Spring让你能够把你的Hibernate代码包装起来，要么使用声明式，AOP风格<BR>的method interceptor，要么在Java代码层面显式使用&#8220;template&#8221;包装类。在两种做法中，事务<BR>语义都为你处理了，并且在异常时也做好了恰当的事务处理（回滚，等）。如下面讨论的，<BR>你还获得了能够使用和替换不同transaction manager，而不会让你相关Hibernate代码受到影响的能力。额外的，JDBC相关的代码能够完全事务性的和Hibernate代码集成。这对于处理没有在Hibernate实现的功能很有用。 </P>
<P>如上描述的异常包装 Spring能够包装Hibernate异常，把它们从私有的，checked异常转换为一<BR>套抽象的运行时异常。这使得你能够仅仅在恰当的层面处理大部分不可恢复的持久化异常，<BR>而不影响样板catch/throw，和异常声明。你仍然能够在任何你需要的地方捕捉和处理异常。<BR>记住JDBC异常（包括DB特有的方言）也被转换到相同的层次中，意味着你能在一致的编程<BR>模型中对JDBC执行相同的操作。 </P>
<P>为了避免和厂商绑定 Hibernate是强大的，灵活的，开放源代码并且免费，但是它仍然使用<BR>私有的API。给出了一些选择，使用标准或者抽象API实现主要的程序功能通常是你想要的，当你需要因为功能，性能，或者其他考虑要转换到使用其他实现时。 </P>
<P>让测试变简单 Spring的Inversion of Control方法使得改变Hibernate的session factories，数据源，transaction manager的实现和位置很容易，如果需要的话还能改变mapper object的实现。这使<BR>得更加容易分离和测试持久化相关的代码。 <BR>事务管理 <BR>抽象出一个数据访问的API是不够的；我们还需要考虑事务管理。JTA是显而易见的选择，<BR>但是它是一个直接用起来很笨重的API，因而许多J2EE开发者感到EJB CMT是对于事务管<BR>理唯一合理的选择。 </P>
<P>Spring提供了它自己对事务管理的抽象。Spring提供了这些： </P>
<P>&nbsp;</P>
<P>通过类似于JdbcTemplate的回调模板编程管理事务，比起直接使用JTA要容易多了 </P>
<P>类似于EJB CMT的声明式事务管理，但是不需要EJB容器 </P>
<P><BR>Spring的事务抽象式唯一的，它不绑定到JTA或者任何其他事务管理技术。Spring使用事务<BR>策略的概念把程序代码和底层的事务架构（例如JDBC）解藕。 </P>
<P>为什么你要关心这些？JTA不是所有事务管理的最好答案吗？如果你正在编写仅仅使用一<BR>个数据库的程序，你不需要JTA的复杂度。你不关心XA事务或者两阶段提交。你甚至不需<BR>要提供这些东西的高端应用服务器。但是另一方面，你不会希望在需要和多个数据源打交<BR>道的时候重写你的代码。 </P>
<P>假定你决定通过直接使用JDBC或者Hibernate的事务以避免JTA带来的额外负担。一旦你需<BR>要处理多个数据源，你必须剥开所有的事务管理代码并且使用JTA事务来替代。这不是非<BR>常有吸引力的并且导致大部分J2EE程序员，包括我自己，推荐只使用全局JTA事务。然而<BR>使用Spring事务抽象，你只需要重新配置Spring让它使用JTA，而不是JDBC或者Hibernate的<BR>事务策略，就一切OK了。这是一个配置上的改变，而不是代码的改动。因而，Spring使得<BR>你能够自由缩放应用。<BR>AOP </P>
<P>最近在应用AOP来解决企业关注点方面大家有了很大的兴趣，例如事务管理，这些都是EJB<BR>所要解决的。 </P>
<P>Spring的AOP支持的首要目标是要给POJOs提供J2EE服务。这类似于JBoss 4的目标，Spring <BR>AOP由它能够在应用服务器之间移植的优势，因而没有绑死在厂商身上的风险。它既可以<BR>在web或者EJB容器中使用，也能够在WebLogic，Tomcat，JBoss，Resin，Jetty，Orion和许多<BR>其他应用服务器和web容器上使用。 </P>
<P>Spring AOP支持method interception。所支持关键的AOP概念包括： </P>
<P>&nbsp;</P>
<P>Interception：自定义行为能够在对接口和类的调用之前和之后插入。这类似于AspectJ<BR>术语中类似的&#8220;around advice&#8221;。 </P>
<P>Introduction：指定advice会导致对象实现额外的接口。这混乱了继承。 </P>
<P>静态和动态的pointcuts：在interception发生的程序执行处指定points。静态pointcuts <BR>concern函数签名；动态pointcuts也可以在point被求值的地方考虑函数的参数。Pointcuts<BR>独立interceptors单独定义，使得标准interceptor可以应用于不同应用程序和代码上下文。 </P>
<P><BR>Spring既支持有状态（一个advised对象一个实例）也支持无状态的interceptors（所有advice使<BR>用一个实例）。 </P>
<P>Spring不支持field interception。这是一个经过深思熟虑的设计决定。我总是感觉field interception<BR>违反了封装。我比较倾向于把AOP作为补全物，而不是与OOP冲突的东西。如果在5年或者<BR>10年后，我们在AOP学习曲线上走得更远了并且觉得应该在程序设计的桌面上给AOP一个位置，我不会惊讶的。（然而在那个时候基于语言的解决方案例如AspectJ可能比它们今天看来更加具有吸引力。） </P>
<P>Spring使用动态代理实现AOP（其中存在一个接口）或者在运行时使用CGLIB生成字节码（这使得能够代理类）。两种方法都能够在任何应用服务器中使用。 </P>
<P>Spring是第一个实现AOP Alliance interfaces的AOP 框架（<A href="http://www.sourceforge.net/projects/aopalliance">www.sourceforge.net/projects/aopalliance</A>）。这些是定义在不同AOP框架中能够互操作interceptors的尝试。 </P>
<P>在TheServerSide和其他地方有一个正在进行但是不是那么引人注目的争论，就是这种<BR>interception是不是&#8220;true AOP&#8221;。我倒不怎么在意它叫什么；仅仅需要知道它是否在实践中<BR>有用就好了。我也乐于称它为&#8220;declarative middleware&#8221;（声明式中间件）。把Spring AOP认<BR>做简单，轻量级的无状态beans的替代物，这样就不需要monolithic EJB容器了，而这些仅仅是<BR>让你能够构建有你需要的服务的容器。我不推荐advising任何一个POJO，对local SLSBs的类<BR>比有助于你理解推荐的粒度。（然而，与EJB不同的是，在恰当但是少见的情况下，你可以<BR>自由地把Spring的AOP应用到粒度更好的对象上。） </P>
<P>因为Spring在实例上advises 对象，而不是在class loader层面上，使用有不同advice的同一个类<BR>的多个实例是可能的，或者与advised实例一道使用unadvised 实例。 </P>
<P>可能Spring AOP最常见的应用是声明式事务管理。这是基于前面描述的TansactionTemplate抽<BR>象上的，并且可以给任何POJO提供声明式事务管理。取决于事务策略，底层的机制可以是JTA，JDBC，Hibernate或者任何其他提供事务管理的API。 </P>
<P>Spring的声明式事务管理类似于EJB CMT，在以下方面有些不同： </P>
<P>&nbsp;</P>
<P>事务管理能够应用于任何POJO。我们推荐业务对象实现接口，但是这只是一个好的<BR>编程习惯的问题，而不是由框架强制的。 </P>
<P>通过使用Spring的事务API能够在事务性POJO中实现编程回调。我们为此提供静态的方法，使用ThreadLoacal变量，因而你不需要传播诸如EJBContext这样的context对象来确保回滚。 </P>
<P>你可以声明式地定义&#8220;回滚规则&#8221;。EJB不会在未捕捉程序异常的时候自动回滚（仅仅在unchecked exceptions和其他Throwables的时候），应用程序开发者经常需要在任何异常发生时回滚。Spring事务管理让你能够声明式地指定什么异常什么子类能够导致自动回滚。缺省的行为和EJB是一致的，但是你能够在checked和unchecked异常时自动回滚。这个在最少化自编程回调代码方面有很大好处，而回调依赖于Spring的事务API（因为EJB的编程回调时在EJBContext中完成的）。 </P>
<P>事务管理不绑定于JTA。如前面解释过的，Spring的事务管理能够在不同事务策略中使用。 </P>
<P><BR>当然还可以使用Spring AOP实现程序特有的aspects。取决于你对AOP概念的接受程度，决定你是否选择这么做，而不是Spring的能力，但是它确实非常有用。我们所见过的成功例子包括： </P>
<P>&nbsp;</P>
<P>自定义的security interception，当安全检查的复杂度超出了J2EE安全架构的能力的时候 </P>
<P>在开发中使用的调试和profiling aspects </P>
<P>发送email通知管理员用户不寻常的举动的Interceptors </P>
<P><BR>程序自定的aspects能够成为消除需要许多函数的样板代码的有利武器。 </P>
<P>Spring AOP透明地与Spring BeanFactory概念集成。包含一个来自Spring BeanFactory对象地代码<BR>不需要知道它是还是不是advised。和任何对象一样，契约实在接口和对象实现中定义的。 </P>
<P>下面的XML片断展示了如何定义一个AOP代理： <BR>代码: </P>
<P>&nbsp;&nbsp; class="org.springframework.aop.framework.ProxyFactoryBean"&gt; <BR>&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; org.springframework.beans.ITestBean <BR>&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; txInterceptor <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; target <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp; </P>
<P>&nbsp;</P>
<P>注意bean类的定义总是AOP框架的ProxyFactoryBean，虽然bean的类型在引用中使用或者由BeanFactory的getBean()方法返回时依赖的是代理接口。（多个代理方法是被支持的。）ProxyFactoryBean的&#8220;interceptorNames&#8221;属性需要一个字符串列表。（因为如果代理是一个&#8220;prototype&#8221;而不是singleton，有状态interceptors可能需要创建新的实例，所以必须使用Bean<BR>的名字而不是bean的引用。）列表中的名字可以是interceptor或者pointcuts（interceptors和有关<BR>它们合适被使用的信息）。列表中的&#8220;target&#8221;值自动创建一个&#8220;invoker interceptor&#8221;封装<BR>target对象。实现代理接口的是在factory中的bean的名字。这个例子中的myTest可以和其他<BR>bean factory中的bean一样使用。例如，其他对象可以使用元素引用它而且这些引用是由Spring IoC设置的。 </P>
<P>还可以不用BeanFactory，编程构建AOP代理，虽然这个很少用得上： </P>
<P>代码: </P>
<P>TestBean target = new TestBean(); <BR>DebugInterceptor di = new DebugInterceptor(); <BR>MyInterceptor mi = new MyInterceptor(); <BR>ProxyFactory factory = new ProxyFactory(target); <BR>factory.addInterceptor(0, di); <BR>factory.addInterceptor(1, mi); <BR>// An "invoker interceptor" is automatically added to wrap the target <BR>ITestBean tb = (ITestBean) factory.getProxy(); <BR>&nbsp;</P>
<P>我们相信最好把程序装配从Java代码中移出来，而AOP也不例外。 </P>
<P>Spring在它的AOP能力方面的直接竞争者是Jon Tirsen的Nanning Aspects（<A href="http://nanning.codehaus.org">http://nanning.codehaus.org</A>）。 </P>
<P>我觉得AOP作为EJB的替代无提供企业服务这个用法方面的进步是重要的。随着时间，这将<BR>成为Spring很重要的关注点。<BR>MVC web 框架 </P>
<P>Spring包括一个强大而且高度可配置的MVC web 框架。 </P>
<P>Spring的MVC model类似于Struts。在多线程服务对象这点上，Spring的Controller类似于Struts Action，只有一个实例处理所有客户的请求。然而，我们相信Spring的MVC比起Struts有很多<BR>优点，例如： </P>
<P>&nbsp;</P>
<P>Spring在controllers，JavaBean，models和views提供了一个非常清晰的划分。 </P>
<P>Spring的MVC是非常灵活的。不像Struts，它强制你的Action和Form对象进入固化的层<BR>次之中（因而你迫使你使用Java的实体继承），Spring MVC完全是基于接口的。而且，通过插入你自己的接口几乎Spring MVC 框架的所有部分都是可配置的。当然我们也<BR>提供了方便的类作为实现选择。 </P>
<P>Spring MVC是真正的view无关的。你不会被强制使用JSP，如果你不想那么做的话。<BR>你可以使用Velocity，XSLT或其他view技术。如果你想要使用自定义的view机制&#8212;&#8212;例如，你自己的模板语言&#8212;&#8212;你可以简单实现Spring的View接口并且把它集成进来。 </P>
<P>和其他对象一样，Spring的Controllers是通过IoC配置的。着使得它们易于测试，并且完<BR>美地和其他由Spring管理的对象集成。 </P>
<P>Web层变成了业务对象层之上的薄薄一层。这鼓励了好的习惯。Struts和其他专门的<BR>web框架让你去实现你自己的业务对象；Spring提供了你应用程序所有层的集成。 </P>
<P><BR>如在Struts 1.1中所见的，你可以有和你在Spring MVC 应用程序中所需要的一样多的dispatcher servlets。 </P>
<P>下面的例子展示了一个简单的Spring Controller如何能够访问定义在应用程序context中的业务对象。这个controller在它的handleRequest()方法中执行了Google搜索： </P>
<P>代码: </P>
<P>public class GoogleSearchController <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; implements Controller { </P>
<P>&nbsp;&nbsp; private IGoogleSearchPort google; </P>
<P>&nbsp;&nbsp; private String googleKey; </P>
<P>&nbsp;&nbsp; public void setGoogle(IGoogleSearchPort google) { <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.google = google; <BR>&nbsp;&nbsp; } </P>
<P>&nbsp;&nbsp; public void setGoogleKey(String googleKey) { <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.googleKey = googleKey; <BR>&nbsp;&nbsp; } </P>
<P>&nbsp;&nbsp; public ModelAndView handleRequest( <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HttpServletRequest request, HttpServletResponse response) <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; throws ServletException, IOException { <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String query = request.getParameter("query"); <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; GoogleSearchResult result = <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Google property definitions omitted... </P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Use google business object <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; google.doGoogleSearch(this.googleKey, query, <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; start, maxResults, filter, restrict, <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; safeSearch, lr, ie, oe); </P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return new ModelAndView("googleResults", "result", result); <BR>&nbsp;&nbsp; } <BR>} <BR>&nbsp;</P>
<P>这段代码使用的prototype中，IGoogleSearchPort是一个GLUE web services代理，由Spring FActoryBean返回。然而，Spring把controller从底层web service库中分离出来。接口可以使用<BR>普通的Java对象，test stub，mock对象或者如下面要讨论的EJB代理实现。这个contorller不包<BR>括资源查找；除了支持它的web交互的必要代码之外没有别的什么了。 </P>
<P>Spring还提供了数据绑定，forms，wizards和更复杂的工作流的支持。 </P>
<P>对Spring MVC 框架的优秀简介是Thomas Risberg的Spring MVC 教程（<A href="http://www.springframework.org/docs/MVC-step-by-step/Spring-MVC-step-by-step.html">http://www.springframework.org/docs/MVC-step-by-step/Spring-MVC-step-by-step.html</A>）。还可<BR>以参见&#8220;Web MVC with the Spring Framework&#8221;（<A href="http://www.springframework.org/docs/web_mvc.html">http://www.springframework.org/docs/web_mvc.html</A>）。 </P>
<P>如果你乐于使用你钟情的MVC框架，Spring的分层架构使得你能够使用Spring的其他部分而<BR>不用MVC层。我们有使用Spring做中间层管理和数据访问，但是在web层使用Struts，<BR>WebWork或者Tapestry的用户。<BR>实现EJB </P>
<P>如果你选择使用EJB，Spring能在EJB实现和客户端访问EJB两方面都提供很大的好处。 </P>
<P>对业务逻辑进行重构，把它从EJB facades中取出到POJO已经得到了广泛的认同。（不讲别的，这使得业务逻辑更容易单元测试，因为EJB严重依赖于容器而难于分离测试。）Spring<BR>为session bean和message driver bean提供了方便的超类，使得通过自动载入基于包含在EJB Jar<BR>文件中的XML文档BeanFactory让这变得很容易。 </P>
<P>这意味着stateless session EJB可以这么获得和使用所需对象： </P>
<P>代码: </P>
<P>import org.springframework.ejb.support.AbstractStatelessSessionBean; </P>
<P>public class MyEJB extends AbstractStatelessSessionBean <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; implements MyBusinessInterface { <BR>&nbsp;&nbsp; private MyPOJO myPOJO; </P>
<P>&nbsp;&nbsp; protected void onEjbCreate() { <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.myPOJO = getBeanFactory().getBean("myPOJO"); <BR>&nbsp;&nbsp; } </P>
<P>&nbsp;&nbsp; public void myBusinessMethod() { <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.myPOJO.invokeMethod(); <BR>&nbsp;&nbsp; } <BR>} <BR>&nbsp;</P>
<P>假定MyPOJO是一个接口，它的实现类&#8212;&#8212;以及任何它需要的配置，注入基本的属性和更多<BR>的合作者&#8212;&#8212;在XML bean factory 定义中隐藏。 </P>
<P>我们通过在ejb-jar.xmldeployment descriptor中名为ejb/BeanFactoryPath的环境变量定义告诉Spring<BR>去哪儿装载XML文档。如下： </P>
<P>代码: </P>
<P><BR>&nbsp;&nbsp; myComponent <BR>&nbsp;&nbsp; com.test.ejb.myEjbBeanLocalHome <BR>&nbsp;&nbsp; com.mycom.MyComponentLocal <BR>&nbsp;&nbsp; com.mycom.MyComponentEJB <BR>&nbsp;&nbsp; Stateless <BR>&nbsp;&nbsp; Container </P>
<P>&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ejb/BeanFactoryPath <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; java.lang.String <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /myComponent-ejb-beans.xml <BR>&nbsp;&nbsp;&nbsp; </P>
<P>&nbsp;</P>
<P>myComponent-ejb-beans.xml 文件将会从classpath装载：在本例中，是EJB Jar文件的根目录。每<BR>个EJB都能指定自己的XML文档，因而这个机制能在每个EJB Jar文件中使用多次。 </P>
<P>Spring 的超类实现了EJB中诸如setSessionContext()和ejbCreate()的生命周期管理的方法，让应<BR>用程序开发者只需选择是否实现Spring的onEjbCreate()方法。<BR>使用EJB </P>
<P>Spring还让实现EJB变得更加容易。许多EJB程序使用Service Locator和Business Delegate模式。<BR>这些比在客户代码中遍布JNDI查找强多了，但是它们常见的实现方式有显著的缺点，例如： </P>
<P>&nbsp;</P>
<P>使用EJB的典型代码依赖Service Locator或者Business Delegate singletons，使得测试难于进行。 </P>
<P>在Service Locator模式没有使用Business Delegate的情况下，程序代码还要在EJB home中<BR>调用create()方法，并且处理可能导致的异常。因而仍然绑定在EJB API身上，忍受着<BR>EJB 编程模型的复杂度。 </P>
<P>实现Business Delegate模式通常导致显著的代码重复，其中我们必须编写大量仅仅是调<BR>用EJB同等方法的方法。 </P>
<P><BR>基于这些和其他原因，传统的EJB访问，如在Sun Adventure Builder和OTN J2EE Virtual Shopping Mall中展示的那样，会降低生产率并且带来显著的复杂度。 </P>
<P>Spring通过引入codeless business delegate前进了一步。有了Spring，你不再需要再编写另一个Service Locator，另一个JNDI查找，或者在硬编码的Business Delegate中重复代码，除非你肯<BR>定这增加了价值。 </P>
<P>例如，假定我们有使用local EJB的web controller。我们将遵循最佳实践，使用EJB Business Methods Interface模式，EJB的local interface extend非EJB专有的业务方法接口。（这么做的主<BR>要的一个原因是确保在本地接口和bean实现类中方法签名的自动同步。）让我们调用这个<BR>业务方法接口MyComponent。当然我们还需要实现local home接口并且提供实现SessionBean<BR>和MyComponent业务方法的bean的实现类。 </P>
<P>用了Spring EJB 访问，我们把我们的web层controller和EJB实现挂接上所需要进行的Java编码<BR>仅仅是在我们的controller中暴露一个类型MyComponent的setter方法。这将如下保存作为实<BR>例变量的引用： </P>
<P>代码: </P>
<P>private MyComponent myComponent; </P>
<P>public void setMyComponent(MyComponent myComponent) { <BR>&nbsp;&nbsp; this.myComponent = myComponent; <BR>} <BR>&nbsp;</P>
<P>我们随后在任何业务方法中使用这个实例变量。 </P>
<P>Spring自动完称剩下的工作，通过像这样的XML bean定义。LocalStatelessSessionProxyFactoryBean是一个可以用于任何EJB的通用factory bean。它创建的<BR>对象能够自动被Spring转型为MyComponent类型。 </P>
<P>代码: </P>
<P>class="org.springframework.ejb.access.LocalStatelessSessionProxyFactoryBean"&gt; </P>
<P>&nbsp;&nbsp; myComponent <BR>&nbsp;&nbsp; com.mycom.MyComponent </P>
<P><BR>&nbsp;&nbsp; class = "com.mycom.myController" <BR>&gt; <BR>&nbsp;&nbsp;&nbsp; </P>
<P>&nbsp;</P>
<P>在幕后有许多魔法般的事情发生，Spring AOP framework的殷勤，虽然不强迫你使用AOP的<BR>概念享受这些结果。&#8220;myComponent&#8221;bean定义为EJB创建一个代理，它实现了业务方法的<BR>接口。EJB local home在启动的时候被缓存，因而只需要一次JNDI查找。每次EJB被调用的<BR>时候，代理调用local EJB中的create()方法并且调用EJB中对应的业务方法。 </P>
<P>myController bean定义为这个代理设置controller类的myController属性。 </P>
<P>这个EJB访问机制极大简化了应用程序的代码： </P>
<P>&nbsp;</P>
<P>Web层的代码不依赖于EJB的使用。如果你想要使用POJO，mock object或者其他test <BR>stub替代EJB引用，我们可以简单地改动一下myComponent bean定义而不影响一行Java<BR>代码 </P>
<P>我们还不需要写一行JNDI查找或者其他EJB plumbing code。 </P>
<P><BR>在实际程序中的性能测试和经验标明这种方法（包括对目标EJB的反射调用）的性能影响<BR>是很小的，在典型的应用中检测不出。记住无论如何我们都不希望使用fine-grained的EJB调<BR>用，因为会有有关应用服务器上的EJB的底层架构方面的代价。 </P>
<P>我们可以把相同方法应用于远程EJB，通过类似org.springframework.ejb.access.SimpleRemoteStatelessSessionProxyFactoryBean factory bean的方法。然而我们无法隐藏远程EJB的业务方法接口中的RemoteException。<BR>测试 </P>
<P>如你可能已经注意到的，我和其他Spring开发这是全面单元测试重要性的坚定支持者。我们<BR>相信框架被彻底单元测试过的是非常重要的，而且我们框架设计的主要目标是让建立在框<BR>架之上的程序易于单元测试。 </P>
<P>Spring自身有一个极好的单元测试包。我们的1.0 M1的单元测试覆盖率是75%，而且我们希<BR>望在1.0 RC1的时候能够达到80%的单元测试覆盖率。我们发现在这个项目中测试优先的开<BR>发带来的好处是实实在在的。例如，它使得作为国际化分布式开发团队的工作极端有效率，<BR>而且用户评论CVS snapshots趋向于稳定和使用安全。 </P>
<P>因为以下理由，我们相信用Spring构建的应用程序是非常易于测试的： </P>
<P>&nbsp;</P>
<P>IoC推动了单元测试 </P>
<P>应用程序不包括直接使用注入JNDI的J2EE服务的plumbing code，这些代码一般让测试<BR>难于进行 </P>
<P>Spring bean factories和contexts能够在容器外设置 </P>
<P><BR>在容器外可以设置Spring bean factory的能力提供了对开发过程有趣的可选项。在几个使用<BR>Spring的web应用中，工作是从定义业务接口和在web容器外集成测试开始的。在业务功能<BR>已经足够完整之后，web接口不过是添加在其上的薄薄一层。<BR>&nbsp; <BR>&nbsp;<BR>谁在使用Spring </P>
<P>虽然相对来说Spring还是一个新的项目，但是我们已经有了一个令人印象深刻并且不断增长<BR>的用户群。它们已经有许多产品使用着Spring。用户包括一个主要的全球投资银行（做大型<BR>项目的），一些知名的网络公司，<BR>几个web开发顾问机构，卫生保健公司，以及学院机构。 </P>
<P>许多用户完整地使用Spring，但是一些只单独使用一些组件。例如，大量用户使用我们地<BR>JDBC或者其他数据访问功能。</P>
<P>&nbsp;<BR>Roadmap </P>
<P>在今年晚些时候我们主要要做的是让Spring发布release 1.0。然而，我们还有一些更长远的目标。 </P>
<P>为1.0 final规划地主要改进式源代码级地元数据支持，它主要用于（但不局限于）AOP框架。<BR>这将使得C#风格的attribute驱动的事务管理，并且让声明式企业服务在典型应用情况下非常<BR>容易配置。Attribute支持将会在Spring的1.0 final release支持中加入，并且设计的是在发布的那<BR>个时候能与JSR-175集成。 </P>
<P>1.0之后，一些可能的改进地方包括： </P>
<P>&nbsp;</P>
<P>通过对我们的JDBC和事务支持的一个相当抽象来支持JMS </P>
<P>支持bean factories的动态重配置 </P>
<P>提供web services的能力 </P>
<P>IDE和其他工具支持 </P>
<P><BR>作为一个敏捷项目，我们主要是受到用户需求的驱动。因而我们不会开发没有一个用户需要<BR>的特性，并且我们会仔细倾听来自用户群的声音。<BR>总结 </P>
<P>Spring是一个解决了许多在J2EE开发中常见的问题的强大框架。 </P>
<P>Spring提供了管理业务对象的一致方法并且鼓励了注入对接口编程而不是对类编程的良好习惯。Spring的架构基础是基于使用JavaBean属性的Inversion of Control容器。然而，这仅仅是完<BR>整图景中的一部分：Spring在使用IoC容器作为构建完关注所有架构层的完整解决方案方面<BR>是独一无二的。 </P>
<P>Spring提供了唯一的数据访问抽象，包括简单和有效率的JDBC框架，极大的改进了效率并<BR>且减少了可能的错误。Spring的数据访问架构还集成了Hibernate和其他O/R mapping解决方案。 </P>
<P>Spring还提供了唯一的事务管理抽象，它能够在各种底层事务管理技术，例如JTA或者JDBC<BR>纸上提供一个一致的编程模型。 </P>
<P>Spring提供了一个用标准Java语言编写的AOP框架，它给POJOs提供了声明式的事务管理和其<BR>他企业事务&#8212;&#8212;如果你需要&#8212;&#8212;还能实现你自己的aspects。这个框架足够强大，使得应用程<BR>序能够抛开EJB的复杂性，同时享受着和传统EJB相关的关键服务。 </P>
<P>Spring还提供了可以和总体的IoC容器集成的强大而灵活的MVC web框架。<BR>更多信息 </P>
<P>参见以下资源获得关于Spring的更多信息： </P>
<P>&nbsp;</P>
<P>Expert One-on-One J2EE Design and Development（Rod Johnson，Wrox，2002）。虽然<BR>Spring在书出版之后已经极大地进步和改进了，它仍然是理解Spring动机的极佳途径。 </P>
<P>Spring的主页：<A href="http://www.springframework.org">http://www.springframework.org</A>。这里包括Javadoc和几个教程。 </P>
<P>在Sourceforge上的论坛和下载 </P>
<P>Spring用户和Spring开发者的邮件列表 </P>
<P><BR>我们正在尽我们可能去改进Spring的文档和示例。我们还为在信件和邮件列表中极好的回<BR>复率自豪。我们希望你能快速融入我们的社区！<BR>关于作者 </P>
<P>Rod Johnson 作为Java开发者和架构师已经有了7年的经验了并且在J2EE平台出现之初就在其<BR>上进行开发了。他是《Expert One-on-One J2EE Design and Development》(Wrox，2002)的作者<BR>并且贡献了其他好几本关于J2EE的书。他当前正在为Wiley撰写另外一本有关J2EE架构的书。Rod在两个Java标准委员会服务并且经常师大会发言人。现在他在UK做一个咨询顾问。</P><img src ="http://www.cnblogs.com/voyage/aggbug/22769.html?type=1" width = "1" height = "1" /><br/><br/>--------------------------<br/>新闻：<a href="http://news.cnblogs.com/n/48007/" target="_blank">IE颓势不减 微软下月公布最新浏览器架构</a><br/>网站导航: <a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://dotnet.cnblogs.com" target="_blank">.NET频道</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://zzk.cnblogs.com" target="_blank">找找看</a>]]></description></item><item><title>Web Services何时才能更具意义?</title><link>http://www.cnblogs.com/voyage/archive/2004/07/09/22616.html</link><dc:creator>voyage</dc:creator><author>voyage</author><pubDate>Thu, 08 Jul 2004 18:21:00 GMT</pubDate><guid>http://www.cnblogs.com/voyage/archive/2004/07/09/22616.html</guid><wfw:comment>http://www.cnblogs.com/voyage/comments/22616.html</wfw:comment><comments>http://www.cnblogs.com/voyage/archive/2004/07/09/22616.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnblogs.com/voyage/comments/commentRss/22616.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/voyage/services/trackbacks/22616.html</trackback:ping><description><![CDATA[<H2><A id=_adad54bc3e5_HomePageDays_DaysList__ctl6_DayItem_DayList__ctl0_TitleUrl HREF="/visual%20icers/archive/2004/02/20/1419.aspx"><FONT color=#223355></FONT></A>&nbsp;</H2>
<DIV class=postbody>
<TABLE class=resourcetable cellSpacing=0 cellPadding=6 width=140 align=right border=1 xmlns:fo="http://www.w3.org/1999/XSL/Format">
<TBODY>
<TR>
<TD align=middle><FONT color=#223355></FONT></TD></TR></TBODY></TABLE><B xmlns:fo="http://www.w3.org/1999/XSL/Format">在构建程序之前，确定将你的函数作为Web service来提供的优势是大于其劣势的。</B><BR xmlns:fo="http://www.w3.org/1999/XSL/Format"><SPAN class=AboutAuthor xmlns:fo="http://www.w3.org/1999/XSL/Format">by Douglas Kerwin </SPAN>
<P xmlns:fo="http://www.w3.org/1999/XSL/Format">目前Web services还是一门相当新的技术，而且不是每个人都知道该如何充分利用它们。以我的经验（我曾在Web services底层架构上构建了一个完整的企业软件产品），我发现Web services有这样两个主要用途：将多个系统整合到一起，以及将功能函数(function)作为组件提供给远程调用。本文我将介绍在使用后一种方法时需要注意的问题。</P>
<P xmlns:fo="http://www.w3.org/1999/XSL/Format">当你想要用Web service来提交一个新的函数或service给可能要远程调用的客户端时，你需要考虑到许多因素。不论这个函数是用于内部还是用于外部的客户或合作者，在Visual Studio .NET中开始一个新的Web service项目之前先设计一个大纲会帮你节省不少时间。比如，在要求访问专属数据库时以及/或者在很难实现本地部署或造价太高时，将一个功能函数作为一个Web service来提供就会很有意义。用于执行简单计算的函数不要求访问专属数据，同时在进行本地部署或维护方面也没那么复杂。</P>
<P xmlns:fo="http://www.w3.org/1999/XSL/Format">当功能函数需要一个复杂的安装过程或一个复杂的、昂贵的硬件配置时，使用Web services或许是你的最佳选择。在这种情况下，将功能函数作为一个Web service来提供会为你的客户解决很多麻烦事，因为他们不用在本地部署它。如果你经常需要发布一个功能函数的新版本，那么你也该考虑用Web services。一个Web service会提供一种简便的方法给所有使用该功能函数的客户发布升级版本，而无需在每次发布新版本时让他们重新部署一遍。公众所期望的通过Web service接口提供需要访问专属数据的功能函数是不容易得到的。不管怎样，客户端需要能够得到数据，而Web service显然是一个比传送普通文件（flat file）数据更好的方法。最后，最好能将依赖于经常改变数据的功能函数作为Web services来提供。在更新数据速度和更改数据大小方面的提高会使远程访问专属数据的优势更为明显。</P>
<P xmlns:fo="http://www.w3.org/1999/XSL/Format">在你决定是否将一个功能函数作为一个Web service来提供时，部署问题是一个最重要的因素。Web services会使软件的部署更简单。比如，如果你在构建一个指导驾驶的应用程序，你就不需要担心如何安装地图软件。或者如果你有一个需要经常升级的功能函数，你就不需要每几个月就回到公司让他们帮你部署更新。</P>
<P xmlns:fo="http://www.w3.org/1999/XSL/Format"><B><FONT color=#333399>明智地选择Web Services</FONT></B><BR>然而，你要了解并非Web services的所有方面都是好的，它们也有优点和缺点。当然，在开始你的项目之前你得确认其优点是多于缺点的。否则你唯一需要用到新的Web service的地方就是在你的简历中了。</P>
<P xmlns:fo="http://www.w3.org/1999/XSL/Format">比如说，一个运行于其他架构中的Web service肯定不如在你自己的服务器中运行的那么可靠。即便是保护最完善的和维护得最好的网络在某些方面也并不是完全牢靠的。你必须能够向你的客户证明，无论是在内部还是外部，在service的部署和维护方面有很大优势来弥补本身固有的在一个易出错的网络中远程访问功能函数所带了的不足之处。</P>
<P xmlns:fo="http://www.w3.org/1999/XSL/Format">我最喜欢用平方根功能函数来说明一个典型的&#8220;错误&#8221;使用Web service的例子（<A href="http://www.fawcette.com/china/DotNetMagazine/2003_06/xml2html.asp?xmlfile=MakeSense/Table1.xml&amp;xslfile=../../include/xsl/Table.xsl"><FONT color=#1d58d1>见表1</FONT></A>）。虽然这个场景有点夸张，但却很能说明问题。平方根功能函数没有体现任何Web service所提供的优势，相反却体现了其所有的缺陷。对它进行部署并非难事，而且它没有（至少最近没有）因为发生了变化而需要进行重新部署，这样一来就使Web services部署优势不能够体现出来了。而且，它不需要访问任何数据库或者专属数据来实现计算功能。然而它的确需要将功能函数请求发送到Web服务器，这会致使Web service因为其本身固有的缓慢或无网络链接问题而执行地很慢。在这种情况下，一个象平方根这样的小函数会导致一个很大的应用程序的机能完全停止。在你首次尝试Web services时，它会试图将一些应用函数（utility function）作为Web services来发布――一些将位图（bitmap）转化为JPEG的函数或压缩位图数据的函数。这些功能函数或许是非常便利的，但它们并不适合用Web services提供。</P>
<P xmlns:fo="http://www.w3.org/1999/XSL/Format">当数据可能会对其他部门有用时，内部的department-to-department (D2D) Web services可能会适用于所有功能函数，甚至是一些很难部署的功能函数。Web services提供了一种很棒的方法能够快速高效地在企业内部实现对软件部署和维护，而无需去访问防火墙以外的Web services。因为D2D Web services是在你的网络内部运行的，这样就减少了由于网络问题而导致程序中断的可能性，而且volume的层级也更容易预测。</P>
<P xmlns:fo="http://www.w3.org/1999/XSL/Format">通常在一个部门构建需要访问其他部门管制的数据的程序时，持有这些数据的部门会设置一个数据输出程序（data export procedure）将一个包含该数据的普通文件传输到所需要的部门，这样他们便可以将数据导入数据库中了。遗憾的是这种极不方便的共享数据方法还是非常普遍的。Web services提供了一种更好的方法为内部部门数据共享加载普通文件数据。Web services不是将原始数据传送过去让客户端程序自己进行数据处理，而是更多地让你来控制，它们会提供计算功能而不是用来计算的数据。这不仅是一种更稳定的信息共享的方法，而且它还提供了一种机制来增强和数据有关的商业规则。</P>
<P xmlns:fo="http://www.w3.org/1999/XSL/Format">尽管采用了同样的方法，对需要通过Web services来提供给外部的功能函数的评估还是非常重要的。使用一个外部企业提供的Web service的危险性更大一些。然而，这种危险性会被它们能充分利用分布程序跨防火墙而无需在本地部署service的优势所抵消（见<A href="http://www.fawcette.com/china/DotNetMagazine/2003_06/xml2html.asp?xmlfile=MakeSense/Table2.xml&amp;xslfile=../../include/xsl/Table.xsl"><FONT color=#1d58d1>表2</FONT></A>）。</P>
<P xmlns:fo="http://www.w3.org/1999/XSL/Format"><B><FONT color=#333399>考虑以下问题</FONT></B><BR>在你向公司建议将某一功能函数作为一个Web service 提供给你的商业伙伴或用户时，你需要说明其优势是否大于劣势。先考虑下面这些问题的答案会对你有所帮助：</P>
<P xmlns:fo="http://www.w3.org/1999/XSL/Format">
<TABLE cellSpacing=5>
<TBODY>
<TR>
<TD>
<TD>
<LI>对使用的程序而言，该功能的紧急性有多高？</LI></TD></TR></TBODY></TABLE>
<TABLE cellSpacing=5>
<TBODY>
<TR>
<TD>
<TD>
<LI>传入或输出Web service 的数据有多敏感?</LI></TD></TR></TBODY></TABLE>
<TABLE cellSpacing=5>
<TBODY>
<TR>
<TD>
<TD>
<LI>数据源是什么? 它多长时间更新一次?是否是公开的? </LI></TD></TR></TBODY></TABLE>
<TABLE cellSpacing=5>
<TBODY>
<TR>
<TD>
<TD>
<LI>你多久参与一次该功能新版本的发布？</LI></TD></TR></TBODY></TABLE>
<TABLE cellSpacing=5>
<TBODY>
<TR>
<TD>
<TD>
<LI>谁在控制Web service所处的架构? 该架构是否可靠?</LI></TD></TR></TBODY></TABLE></P>
<P xmlns:fo="http://www.w3.org/1999/XSL/Format">Web services在大多数IT企业都具有利用潜力，尤其是在软件部署方面，但你也不能将它随意使用到任何地方。你要避免毫无意义地将功能函数或服务用做Web services。有时在本地部署是非常有必要的。 </P><BR xmlns:fo="http://www.w3.org/1999/XSL/Format"><FONT color=#666666 xmlns:fo="http://www.w3.org/1999/XSL/Format"><I>关于作者:</I></FONT><BR xmlns:fo="http://www.w3.org/1999/XSL/Format">Douglas Kerwin是Metaverse Corporation公司的创始人及执行总裁，这家公司位于Princeton, N.J.，主要从事将Web Content Management软件作为一个service来提供，其产品以Microsoft.NET作为开发平台。你可以通过<A href="mailto:dkerwin@metaverse.cc" target=_blank xmlns:fo="http://www.w3.org/1999/XSL/Format"><FONT color=#1d58d1>dkerwin@metaverse.cc</FONT></A>和他联系。<BR xmlns:fo="http://www.w3.org/1999/XSL/Format"></DIV><img src ="http://www.cnblogs.com/voyage/aggbug/22616.html?type=1" width = "1" height = "1" /><br/><br/>--------------------------<br/>新闻：<a href="http://news.cnblogs.com/n/48007/" target="_blank">IE颓势不减 微软下月公布最新浏览器架构</a><br/>网站导航: <a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://dotnet.cnblogs.com" target="_blank">.NET频道</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://zzk.cnblogs.com" target="_blank">找找看</a>]]></description></item><item><title>选择一种UML建模工具</title><link>http://www.cnblogs.com/voyage/archive/2004/07/04/21013.html</link><dc:creator>voyage</dc:creator><author>voyage</author><pubDate>Sat, 03 Jul 2004 18:22:00 GMT</pubDate><guid>http://www.cnblogs.com/voyage/archive/2004/07/04/21013.html</guid><wfw:comment>http://www.cnblogs.com/voyage/comments/21013.html</wfw:comment><comments>http://www.cnblogs.com/voyage/archive/2004/07/04/21013.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cnblogs.com/voyage/comments/commentRss/21013.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/voyage/services/trackbacks/21013.html</trackback:ping><description><![CDATA[<H1>选择一种UML建模工具</H1><BR>
<TABLE cols=2 rules=none frame=void>
<TBODY>
<TR>
<TD width=200>信息仓储支持</TD>
<TD width=180>双向工程</TD></TR>
<TR>
<TD>HTML文档化</TD>
<TD>完全UML1.3支持</TD></TR>
<TR>
<TD>选择列表</TD>
<TD>数据建模</TD></TR>
<TR>
<TD>版本控制</TD>
<TD>模型导航</TD></TR>
<TR>
<TD>打印支持</TD>
<TD>图表视图</TD></TR>
<TR>
<TD>图表输出</TD>
<TD>脚本</TD></TR>
<TR>
<TD>健壮性</TD>
<TD>平台</TD></TR>
<TR>
<TD>升级</TD>
<TD>未来...</TD></TR></TBODY></TABLE>
<TABLE rules=none width=400 frame=void>
<TBODY>
<TR>
<TD width=400><BR>
<P class=text>以下标准用于评估一种UML工具。当然，除了已被列出的以外，可以用这些标准来评估的产品还很多，但如果你想选择最好的，请花时间按照清单对产品作测试。如果你特别重视某项标准而在清单中没有列出， <A href="mailto:uml-tools@objectsbydesign.com">请告诉我们。</A></P>
<TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD class=section><A name=Repository>信息仓储支持</A></TD>
<TD align=right><A href="http://www.sawin.com.cn/doc/SD/UML/selectatool.htm#top"></A></TD></TR></TBODY></TABLE>
<P class=text>对于一个大项目，信息仓储(Repository)对在开发人员之间共享组件设计是必要的。两个以上的开发人员可以共享同一模型的的组件，甚至可以通过在适当级别上定义所有权和共享权来合作进行单一组件的开发。 
<P class=text>信息仓储通常用提供数据共享和并发控制等特性的数据库来实现。 通过提供锁定和只读访问，信息仓储允许一个开发人员拥有整个模型而其他人对该模型及其组件只读访问，或者将这些组件结合到自己的设计中。<B><I>重要的是：</I></B> 这种工具应该允许你从另一个模型只引入<I>你所需要的组件</I>而不必引入整个模型。</P>
<P class=text>构造信息仓储的另一个令人感兴趣的方法是利用项目的源代码，使用源码控制系统来提供并发控制。这种方法的好处是在源码和模型之间有更高级别的同步，另一个好处是更除去了另一个数据源--别忘了，如果你为信息仓储使用了数据库，你必须对各种存储数据分别备份并完成在模型、信息仓储和源代码之间的三方同步，而不止是在代码和模型之间的两方同步。</P>
<P class=text>有了建模工具对信息仓储的支持，对任何组件的修改将被自动传播到所有引入该组件的设计。</P>
<TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD class=section><A name=Round-Trip>双向工程</A></TD>
<TD align=right><A href="http://www.sawin.com.cn/doc/SD/UML/selectatool.htm#top"></A></TD></TR></TBODY></TABLE>
<P class=text>对源代码(Java, C++, CORBA IDL)的正向和逆向工程的能力是一项复杂的需求，不同厂商在不同程度上成功地支持这一点。对正向和逆向工程这两方面的成功结合，定义为双向工程。</P>
<P class=text>正向工程在第一次从模型产生代码时非常有用，这将为你节省许多用于编写类、属性、方法代码的琐碎工作的时间。</P>
<P class=text>在以前没有模型存在的情况下，将代码转换成模型；或者在迭代结束，重新同步模型和代码时，逆向工程非常有用。</P>
<P class=text>在一个迭代开发周期中，一旦一个模型作为迭代的一部分被修改，另一轮的正向工程应允许所有加入该模型的新的类、方法、属性的代码被更新。这个步骤通常不被开发者采用，因为许多工具在这个过程中没有办法管理源代码，问题在于源代码中不只包含与模型有关的信息。工具必须精于对在新一轮正向工程之前已有的源代码进行重新构造。</P>
<P class=text>至少，建模工具应成功支持一开始的正向工程和全过程的逆向工程。同样，建模工具对纯Java语言的逆向工程的支持应该毫无问题。一定要针对你自己的源代码确认这一点，因为我们见到过优秀的工具在对Java的一些特性如内联类(inner classes)等进行逆向工程时失败了，每一次进行逆向工程时，你不得不把讨厌的代码注释掉----确实非常痛苦。</P>
<TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD class=section><A name=HTML>HTML文档化</A></TD>
<TD align=right><A href="http://www.sawin.com.cn/doc/SD/UML/selectatool.htm#top"></A></TD></TR></TBODY></TABLE>
<P class=text>对象建模工具应能为对象模型及其组件无缝地产生HTML文档。HTML文档提供对象模型的静态视图，以便开发者通过浏览器迅速查询而不需要加载建模工具本身。另外，通过产生HTML文档，所需建模工具的许可证(licenses)会因减去那些对模型只需要有只读权限的人而减少。</P>
<P class=text>HTML文档应包括模型中每个图形的一张位图，并允许通过超链接浏览整个模型。产生HTML文档所需的时间应是合理的。现在许多产品在不同程度上成功支持这一点。再说一遍，你必须亲自测试这个特性，在特征表上有打勾并不能保证成功支持。</P>
<TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD class=section><A name="UML 1.3">完全UML1.3支持</A></TD>
<TD align=right><A href="http://www.sawin.com.cn/doc/SD/UML/selectatool.htm#top"></A></TD></TR></TBODY></TABLE>
<P class=text>虽然许多工具声称完全支持UML1.3，实际上，这是一项复杂的需求，一些工具并不能做到广告所声称的完全支持。至少应支持的图表有：<I>用例图(Use Case diagrams)，类图(Class diagrams)，协作图(Collaboration diagrams)，顺序图(Sequence diagrams)，包图(Package diagrams)，状态图(State diagrams)。</I></P>
<TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD class=section><A name="Pick Lists">类和方法的选择列表</A></TD>
<TD align=right><A href="http://www.sawin.com.cn/doc/SD/UML/selectatool.htm#top"></A></TD></TR></TBODY></TABLE>
<P class=text>建模工具应在一些关键界面上提供选择列表:</P>
<P class=text><B><I>协作图(Collaboration Diagrams)和顺序图(Sequence Diagrams)</I></B> --工具应允许从模型的类列表中选择一个类，把一个对象分配给它，并允许对象间传送的消息能够从接收消息对象(类)的有效方法列表中选取。</P>
<P class=text><B><I>类图(Class Diagram)</I></B> --工具应允许从别的包或模型的类列表中选择并引入类 。</P>
<P class=text>选择列表特性在直观上对建模工具至关重要，可以看作是必备特性。能够迅速从列表中选择一个对象到另一个对象的消息，给开发顺序图和协作图带来很大的方便。</P>
<TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD class=section><A name="Data Modeling">数据建模集成</A></TD>
<TD align=right><A href="http://www.sawin.com.cn/doc/SD/UML/selectatool.htm#top"></A></TD></TR></TBODY></TABLE>
<P class=text>对象建模工具应允许集成数据建模工具。有许多方法可以提供这种功能。一种方法是UML工具提供将对象模型转换成DDL(数据定义语言，用于为类创建表的SQL)。另一种方法是UML工具输出元数据到能够输入这些元数据的数据建模工具，并将其作为数据模型的基础。一套先进、完整的工具应允许数据模型和对象模型之间在每次设计的迭代之后同步。</P>
<TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD class=section><A name=Versioning>版本控制</A></TD>
<TD align=right><A href="http://www.sawin.com.cn/doc/SD/UML/selectatool.htm#top"></A></TD></TR></TBODY></TABLE>
<P class=text>建模工具应允许储存各种版本，以便后续迭代开始时，以前的版本仍然可以得到，并用于重建或保持基于该版本的已有代码。</P>
<TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD class=section><A name=Navigation>模型导航</A></TD>
<TD align=right><A href="http://www.sawin.com.cn/doc/SD/UML/selectatool.htm#top"></A></TD></TR></TBODY></TABLE>
<P class=text>建模工具应提供强的导航支持以允许开发者全盘浏览模型中的所有图表和类。一种方法是提供一个按名字排序的类目录或选择列表，以便设计人员随意跳到图表中想去的类。</P>
<P class=text>对于大的图表，工具应使得在缩放和平移时，能够轻松实现浏览。</P>
<P class=text>工具也应允许在使用双向工程时，对类的源代码轻松浏览。</P>
<TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD class=section><A name=Printing>打印支持</A></TD>
<TD align=right><A href="http://www.sawin.com.cn/doc/SD/UML/selectatool.htm#top"></A></TD></TR></TBODY></TABLE>
<P class=text>建模工具应允许一张大图表能够准确地用多个页面打印出来，并提供打印预览和缩放功能，轻松地使图表能够在所需页数内放置。允许将一张图表放置在单页中的能力在清单中是高要求。不幸的是，我们发现许多工具很难用无缝的方式完成这项重要的任务。</P>
<TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD class=section><A name=Diagram>图表视图</A></TD>
<TD align=right><A href="http://www.sawin.com.cn/doc/SD/UML/selectatool.htm#top"></A></TD></TR></TBODY></TABLE>
<P class=text>建模工具应能方便定制类及其细节的视图。例如，它应有可能从图表中排除所有的get/set方法，因为它们会对阐明一个图表造成混乱。方法的全部信息应允许容易地根据不同级别细节的需要显示或隐藏。属性和方法的可见性(private, protected, public)是用于选择什么该显示，什么该隐藏的另一个尺度。</P>
<TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD class=section><A name=Exporting>输出图表</A></TD>
<TD align=right><A href="http://www.sawin.com.cn/doc/SD/UML/selectatool.htm#top"></A></TD></TR></TBODY></TABLE>
<P class=text>一个经常被忽略的关键特性是用某种格式输出图表，以便引入到文字处理文档或Web页面中。用于输出的最流行图像格式是GIF、PNG和JPEG。输出时，工具应允许你定义所产生图形的首选分辨率和尺寸。这个功能需求来自那些野心勃勃，需要写一本包括图表的UML书籍的作者，或者希望将他们的工作展示在网站上的人。</P>
<TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD class=section><A name=Scripting>脚本</A></TD>
<TD align=right><A href="http://www.sawin.com.cn/doc/SD/UML/selectatool.htm#top"></A></TD></TR></TBODY></TABLE>
<P class=text>用脚本编程是建模工具应该支持的另一个强大的特性。有了脚本功能，高级用户可以创建能在建模工具内直接访问对象模型的脚本来添加其它功能，例如：为当前开发的项目做的项目管理表格，定制文档，定制代码，报表和度量。一个定制代码的例子是集合类和用于访问集合类的get/set方法。</P>
<P class=text>为了方便使用脚本，建模工具应公开访问自身对象模型的接口，以便在开发时能提供对对象模型组件的访问。(如果这一句听起来有点绕口，请再读一遍。)例如，脚本编写者应能在整个迭代周期中访问类图中类的集合，从而能够通过类对象的accessor方法来访问类的属性。当然，脚本语言自身应该是面向对象的；一个明显的选择就是Java语言本身，另一种选择就是Python脚本语言。</P>
<TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD class=section><A name=Robustness>健壮性(Robustness)</A></TD>
<TD align=right><A href="http://www.sawin.com.cn/doc/SD/UML/selectatool.htm#top"></A></TD></TR></TBODY></TABLE>
<P class=text>你的UML工具需要象岩石般坚固可靠，以防止设计期间工具崩溃而使用户的时间和生产率在不知不觉中损失，或者在模型没有备份的情况下崩溃。我们曾亲眼见过许多领先的工具因为崩溃或文件损坏而引起数小时的工作成果丢失。如果你是一位开发人员，你知道那种因&#8220;生产率高的软件&#8221;反而比粗糙的代码工具生产率要低而产生的蔑视感觉。如果你是一位经理，你会看到被要求使用一种不可靠的工具时开发人员的愤恨。</P>
<P class=text>今天，健壮性常被发现于用Java实现的应用程序(JVM运行时保护)或开放源码的项目(在web范围内并行调试)。发现某种特定的UML工具是否健壮的最快方法是在comp.object等新闻组四处询问，你一定会听到许多抱怨的！</P>
<P class=text>可用于此处的另一个策略可以借鉴有效率的办公应用程序，我们也推荐工具开发商采用这种策略。该策略就是让UML工具每隔一定时间间隔就在背后自动保存模型。</P>
<TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD class=section><A name=Platform>平台</A></TD>
<TD align=right><A href="http://www.sawin.com.cn/doc/SD/UML/selectatool.htm#top"></A></TD></TR></TBODY></TABLE>
<P class=text>为了使你在建模工具上的投资得到最大回报，请慎重地考虑工具将运行在哪种平台上。你需要为Windows还是Unix开发软件？还是二者都要？<I>将在哪种平台上开发？</I></P>
<P class=text>最近的各种事件一起推翻了这个神话：一流的跨平台图形用户界面还不能实现或者拥有一个"最少共同支配者"的视感。很长时间以来,这是不可能的(除了基于HTML的应用程序之外)，直到最近Java的Swing用户界面的出现。但是，跨平台工具需要在Linux等常用平台得到支持，以大规模地被程序员们采用。</P>
<P class=text>Sun最初几乎没有做什么事情来促进Java在Linux上的应用。但最近工业界元老们，主要是IBM，IBM保证在他们所有的硬件平台上为Linux提供无限广泛的支持，并支持Apache/Jakarta项目, IBM现正快速地在Linux上推广Java。也许因为IBM已经开始为主要的Linux厂商发放它的JDK 1.1.8版本，Sun被迫支持在Linux上的 <A href="http://java.sun.com/products/jdk/1.2/download-linux.html">全功能JDK 1.2</A> （带Swing的Java2）的发放。通过<A href="http://www.javasoft.com/features/2000/02/blackdown.html">Blackdown小组</A>的努力，这个Linux上的Java端口大部分已被完成。</P>
<P class=text>迄今为止我们已经测试了一种Linux平台上基于Swing的领先Linux工具，结果优秀。但要告诫的是：128M内存是必需的。</P>
<TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD class=section><A name=Releases>版本更新</A></TD>
<TD align=right><A href="http://www.sawin.com.cn/doc/SD/UML/selectatool.htm#top"></A></TD></TR></TBODY></TABLE>
<P class=text>你需要选择一种将会不断通过修正错误、改进性能、添加新特性来进行改进的建模工具，毕竟你在时间和金钱上进行了一项大的投资，而且改换到另一种建模工具并不容易。</P>
<P class=text>小心那些已经被大公司拥有的产品。在兑现所有期权之后，最初的开发者常常会离开公司，寻找下一次大的机会。寻找有才能的、能读懂<I>和</I>维护最初并非由其编码的软件复杂模块的程序员并不容易。这种场景也会出现在开放源码项目上。</P>
<P class=text>如何能知道一种产品是否在改进？向销售代表询问下一版本发放的详细时间表以及该产品将来的蓝图。密切观察产品改进和添加新特性的速度。产品计划什么时候支持UML 1.3？图形界面是否支持最新的流行样式？你也可以看看该公司的网站：如果产品发布和外界评论是旧的，就是可疑的。</P><BR>
<TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD class=section><A name=Future>未来...</A></TD>
<TD align=right><A href="http://www.sawin.com.cn/doc/SD/UML/selectatool.htm#top"></A></TD></TR></TBODY></TABLE>
<P class=text>现在我们来看看对未来有什么希望。建模工具的当前成熟程度表明，工具厂商准备通过添加高级特性来使产品达到新的高度。我们希望在下一代产品中看到以下特性的出现。</P>
<TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD class=section><A name=Editor>集成编辑器</A></TD>
<TD align=right><A href="http://www.sawin.com.cn/doc/SD/UML/selectatool.htm#top"></A></TD></TR></TBODY></TABLE>
<P class=text>在模型的迭代开发过程中，将UML图表和相邻窗口的源代码匹配，是非常有效率的。支持这种视图协调的产品可以给模型设计者的工具箱添加一个额外的功能选项，以直接给建模工具添加强大的源代码编辑特性。当建模工具不必作为设计者的首选编辑器时，能够在代码里直接更改方法的名字或原型，并立即反映到模型中。</P>
<P class=text>最想要的特性是类似emacs等流行编辑器的键盘仿真，另一个热门特性是通过改变颜色来突出语言关键字，注释等等，提高了代码的易读性。一个重要特性是在类图中选择一个类、属性或方法时跳转到匹配代码行的能力。 最重要的是, 编辑器应该是快速易用的。</P>
<P class=text>作为变通的方法，另一种解决方案是允许建模工具和开发者喜爱的编辑器通信。例如，通过一个热键，允许建模工具从当前活动窗口跳转到伴随编辑器的匹配代码行。</P>
<TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD class=section><A name=Auto-generation>自动生成</A></TD>
<TD align=right><A href="http://www.sawin.com.cn/doc/SD/UML/selectatool.htm#top"></A></TD></TR></TBODY></TABLE>
<P class=text>我们真正想在不久的将来看到的一个特性是，建模工具帮助产生交互图和状态图的能力。</P>
<P class=text>工作方式是：在一个已有的程序的执行过程中，建模工具应容易生成一个追踪文件，目的是获取对象间互相传递信息时的交互。产生追踪文件后，建模工具将被用于分析该追踪文件，以发现对象交互的模式。建模工具应允许用户从一组类中选择一个来分析，然后展示被追踪文件记录的每个类唯一的一套交互，允许用户为模型选择交互。最后，工具应能够产生一张基于真实记录对象交互的顺序或协作图。</P>
<P class=text>很酷吗？它并不象听起来的那样太过前卫。因为追踪技术已经十分成功地应用在帮助开发人员追捕他们的程序中性能瓶颈的工具中。这类产品一个很好的例子就是KL Group的JProbe，用于分析Java程序的性能。</P>
<P class=text>使用同样的技术自动产生状态图也是可能的。对以前描述过的顺序的修改将允许用户为状态机里的状态指定基类的名称。建模工具将追踪基类的衍生类之间的交互。从这种追踪，建模工具能够通过描绘每次被记录的状态迁移来创建状态图。</P>
<TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD class=section><A name=Management>管理工具</A></TD>
<TD align=right><A href="http://www.sawin.com.cn/doc/SD/UML/selectatool.htm#top"></A></TD></TR></TBODY></TABLE>
<P class=text>如果你是项目经理中的一员，你最有可能想要能够估量你的O-O项目进展如何。一个应被集成到建模工具中的很好的特性是能够输出模型信息到允许你追踪项目设计和实现进程的工具中。由于它的通用性和可塑性，电子表格是实施这个解决方案的理想工具。项目管理工具也是理想的候选。</P>
<P class=text>这个特性如何工作呢？在高层次，通常你想追踪的是模型中的类和负责在这些类上工作的的人。 你想知道什么时候有人开始在该类上工作，完成任务到了哪种水平。在下一层次的细节上，你想要知道每个类的方法。在这一层次，你可能想要知道哪种方法已经包括在交互图中，或在实施阶段，每种方法完成了多少代码量。</P>
<P class=text>要使这个特性起作用，你需要&#8220;敏捷&#8221;地更新你的项目管理信息。不象报表工具那样总是从头产生一个新报表，你只需要在第一次输出所有东西。产生初始报表后，你的建模工具应该只被要求用新信息来修改你的管理工具。根据用户需要控制的级别，建模工具能在输出之前展现给用户一个修改的清单。</P>
<P class=text>建立一个项目管理链接的一个美妙的好处是，提供把分析和设计阶段的完成日期作为目标的能力。具体方法是通过计算进展速度，并基于完成模型所需的剩余的工作，使用这个速度来计算预期的完成日期。</P>
<TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD class=section><A name=Metrics>度量(Metrics)</A></TD>
<TD align=right><A href="http://www.sawin.com.cn/doc/SD/UML/selectatool.htm#top"></A></TD></TR></TBODY></TABLE>
<P class=text>当你的项目开始成熟时，你可能需要知道你的模型的度量。度量能在一个特殊的模型的生存质量上给面向对象分析员一些即时的反馈。一些感兴趣的度量包括：类层次中的超类数量，每个类中方法的数量，每个类中属性的数量，get/set的数量，方法重载的数量，每个方法的代码行数，public、private和protected方法的百分比，每个类的耦合度（该类知道另外的类的数量），以及被注释方法的百分数。</P>
<P class=text>度量可以通过一个报表界面提供，或者，更好的是，通过一个到电子表格的链接，类似于前面描述的项目管理链接。</P>
<TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD class=section><A name=SVG>SVG: 矢量图形</A></TD>
<TD align=right><A href="http://www.sawin.com.cn/doc/SD/UML/selectatool.htm#top"></A></TD></TR></TBODY></TABLE>
<P class=text>为达到真正的、标准化的矢量图形输出/输入功能，UML工具厂商即将有一种选择。W3C的<A href="http://www.w3.org/TR/2000/03/WD-SVG-20000303/index.html" target=_blank>可缩放矢量图形(Scalable Vector Graphics, SVG)建议</A>是可格式化图形的一种XML语法，成熟的1.0版本规范已经进展到&#8220;最后预览&#8221;阶段(3/3/2000)。一旦被完全认可，你可以留意HTML浏览器厂商什么时候在他们的下一代浏览器中提供支持。</P>
<P class=text>为什么是SVG？因为一套用这种矢量图形格式输出的UML图表可以被链接到网页上。&#8220;over the web&#8221;的UML设计文档的读者将能够使用这种图形浏览技术，如在浏览器内缩放和平移，来更轻松地浏览一张大的UML图表。还有，和GIF格式图形相比，这种格式将戏剧性地提高通过web加载大图形的速度。请看今天Macromedia Flash的展示在浏览器中加载是如何之快，就可以证明这一点！</P>
<P class=text>为了强调GIF图形和可缩放图形在出版环境中的强烈差别，我们准备了一个模拟，通过创建包括两个类图实例的Adobe PDF文件，其中一张是输入的GIF图形，另一张是矢量图形。你可以下载这个PDF文档并在Adobe Acrobat中观看。尝试放大到很高的水平如800%或1600%，然后比较GIF图形和矢量图形的结果。这个实验并非不切实际：你可能需要准备一张被缩放到一个可读性提高的水平的演示图。</P>
<P class=text><A href="http://www.objectsbydesign.com/tools/gif_vs_wmf.pdf">下载GIF和矢量图形对比的PDF例子文件</A>.</P>
<P class=text>为了展望UML和SVG的未来，我们也准备了一个使用SVG在浏览器中显示类图的演示。为了观看这个演示，你必须首先为你的浏览器下载一个SVG察看器。我们推荐来自优秀的<A href="http://www.adobe.com/svg/viewer/install/" target=_blank>Adobe SVG站点</A>的插件。这样你就可以观看<A href="http://www.objectsbydesign.com/tools/svg.html">用SVG显示的图形模型</A>演示。</P>
<TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD class=section><A name=XMI>XMI: 把所有东西捆绑在一起</A></TD>
<TD align=right><A href="http://www.sawin.com.cn/doc/SD/UML/selectatool.htm#top"></A></TD></TR></TBODY></TABLE>
<P class=text>对UML开发团体来说，对象管理组织(OMG)的XMI标准是最近最令人振奋的进展。XMI是一种有潜力最终允许在领先的开发工具之间无缝共享模型的交换格式。例如，与其在UML建模工具中书写脚本来创建报表，不如让用户简单地在开发时使用XMI输出该模型，然后引入到一种特定的报表书写工具中。事实上，这个范例将平等地、很好地应用到前面讨论过的特性：O-O度量追踪和项目管理。此外，自从XMI使用XML来表示模型信息，一批XML解决方案很快会出笼，例如为基于浏览器表示提供的XSL格式表和为搜索兼容性提供的 XQL查询工具。 
<P>　 
<P class=text>XMI标准是复杂的，在被广泛使用之前，它将需要时间来适应许多不可避免的兼容性问题(谁说标准经不起解释？)。但是，既然XMI是由IBM和Unisys等领先的工业巨头开发的，可以预期产品很快会出现。一直到用户团体不断要求厂商来驱动在UML工具中的XMI支持的需求。关于XMI的进一步信息，请看优秀的<A href="http://www.software.ibm.com/ad/features/xmi.html">IBM网页</A>。</P>
<P class=text>作为XMI如何投入使用的例子，请看我们的项目， <A href="http://www.objectsbydesign.com/projects/xmi_to_html.html">转换XMI到HTML</A>. 这个项目展示了XSL格式表如何能被用来产生UML模型的HTML翻译。</P>
<P class=tag>读者建议 
<P class=text>如果您对在清单中未列出的UML建模工具新特性有什么想法， <A href="mailto:uml-tools@objectsbydesign.com">我们将很乐意听到。</A> 
<P class=text>谢谢曾经把他们的UML工具评价标准Email给我们的读者。他们的原始建议<A href="http://www.objectsbydesign.com/tools/reader_input.html">在这儿。</A></P>
<P class=text><BR>2001-3-20<BR>原文来自objectsbydesign.com）</P></TD></TR></TBODY></TABLE><img src ="http://www.cnblogs.com/voyage/aggbug/21013.html?type=1" width = "1" height = "1" /><br/><br/>--------------------------<br/>新闻：<a href="http://news.cnblogs.com/n/48002/" target="_blank">竞争日趋激烈 微软欲借 Windows 7 扭转战局</a><br/>网站导航: <a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://dotnet.cnblogs.com" target="_blank">.NET频道</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://zzk.cnblogs.com" target="_blank">找找看</a>]]></description></item><item><title>UML三大硬伤 </title><link>http://www.cnblogs.com/voyage/archive/2004/07/04/21012.html</link><dc:creator>voyage</dc:creator><author>voyage</author><pubDate>Sat, 03 Jul 2004 18:19:00 GMT</pubDate><guid>http://www.cnblogs.com/voyage/archive/2004/07/04/21012.html</guid><wfw:comment>http://www.cnblogs.com/voyage/comments/21012.html</wfw:comment><comments>http://www.cnblogs.com/voyage/archive/2004/07/04/21012.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.cnblogs.com/voyage/comments/commentRss/21012.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/voyage/services/trackbacks/21012.html</trackback:ping><description><![CDATA[<SPAN class=atitle><STRONG><FONT color=#008000>UML三大硬伤</FONT></STRONG></SPAN> 
<P align=left>撰文/高展<BR>程序员杂志2002年第5期<BR><BR><BR>&nbsp;&nbsp; <FONT size=2>本文从UML建模连贯性方面存在的问题，以管理软件开发为例，针对与UML模型衔接的上游、下游、模型内部关系三个方面，分析了采用UML建模造成的三大隔阂，希望与众多建模爱好者共同探讨。</FONT><BR>&nbsp; &nbsp;在国内的公开报道中，几乎众口一致地充斥着对统一建模语言UML（Unified Modeling Language）的褒奖，即便有公开抱怨也只是怪自己无法理解三位UML创始人的深不可测，怪自己的水平不够，没有料到UML本身存在着种种问题。本文作者只在北京大学计算机系的同行那里发现了他们撰文对UML的有效性提出了质疑。与公开报道相左，业界私下流行观点形象地说明了UML存在问题为软件开发设置的障碍，那就是&#8220;上不着天、下不着地、一盘散沙&#8221;：<BR>&nbsp; （1）&#8220;上不着天&#8221;这种隔阂使建模结果无法与用户沟通确认所谓的需求，埋下了软件危机的祸根；<BR>&nbsp; （2）&#8220;下不着地&#8221;这种隔阂使千辛万苦得到的建模结果无法指挥程序员编码，最后得到的软件与用户期望的结果很远，返工、误工、烦恼无穷；<BR>&nbsp; （3）&#8220;一盘散沙&#8221;这种隔阂让建模图形之间的关系凌乱不堪，建模过程千辛万苦，建模结果很难自圆其说。<BR>&nbsp;&nbsp; 这三大隔阂造成的建模硬伤使UML辜负了人们的殷切期望，&#8220;高不成、低不就&#8221;说明了UML建模在软件生命周期中步履蹒跚，&#8220;一盘散沙&#8221;说明了UML在建模内容中并未实现Unified的原旨，图 1是UML存在问题的可视化表达。 </P>
<P align=center><IMG height=186 src="http://www.sawin.com.cn/doc/SD/UML/xuml1.jpg" width=503 border=0><BR><BR><FONT size=2>图 1 采用UML描述的建模结果&#8220;分崩离析&#8221;</FONT>&nbsp;&nbsp;&nbsp;</P>
<P>诚然，掌握UML很容易谋到一份很好的系统分析员工作，但用它却很难做好系统分析员的分内工作，使用UML肯定可以100%蒙住用户，因为用户对满篇的建模图表只有招架之功，绝无理解反驳之力，使用UML也几乎可以100%蒙住软件公司老板，因为老板不是系统分析员，不知道使用UML进行建模的千辛万苦，系统分析员无法向老板反映UML存在的问题，因为这样很容易招致水平不高的责难。</P>
<P>　</P>
<P><STRONG><FONT size=4>一、UML上不着天&#8212;&#8212;与用户/领域专家无法沟通获得真正的需求<BR>&nbsp;&nbsp; </FONT></STRONG>所谓&#8220;上不着天&#8221;是指使用UML建模后很难与处于软件开发上游的企业用户沟通，因为UML的表达方式与上游用户的行业知识相差甚远，用户一看见满篇的软件工程术语与符号就发怵，根本无法理解使用UML所描述的业务流程，也难以真正理解UML所陈述的需求，与业务专家交流无工而返，导致软件大厦一开始就建立在沙子上，需求不清不楚，没完没了的胡子工程就此落下病根，这种情况造成了软件开中的第一个隔阂，是UML的第一大硬伤。</P>
<P align=left>&nbsp;&nbsp; 对企业用户来讲，他们关心的是如何在其组织结构、业务流程、业务信息的描述基础上，定位企业的宏观管理水平的需求和微观管理操作的需求。</P><STRONG>1 UML难以完整全面地描述企业的分工结构</STRONG> 
<P>　</P>
<P align=left>&nbsp;&nbsp; 图 2是采用全程建模方法组成结构树描述的企业分工组成，它以直观、彻底、一目了然的方式将一个企业按层次地展现为部门、岗位、职责、步骤、直至原子步骤，如&#8220;核对数量、核对规格、签字、填写入库日期&#8221;等。</P>
<P align=center><IMG height=302 src="http://www.sawin.com.cn/doc/SD/UML/xuml2.jpg" width=521 align=left border=0></P>
<P align=center>　</P>
<P align=center>　</P>
<P align=center>　</P>
<P align=center>　</P>
<P align=center>　</P>
<P align=center>　</P>
<P align=center>　</P>
<P align=center>　</P>
<P align=center><FONT size=2>图 2 采用全程建模方法描述的分工组成结构可以</FONT></P>
<P align=center><FONT size=2>细化到原子级工作步骤</FONT></P>
<P align=left>&nbsp;&nbsp; 图 3是采用UML的Use Case 图来描述组织结构，它只能描述到岗位职责，对岗位职责中的工作步骤无法描述。对业务的描述粗枝大叶，结果需求也是粗枝大叶，但用户往往不知道需要特别重视这一点，更不知道这种粗枝大叶会给项目带来灾难。<STRONG>这是纠缠不清的胡子工程问题点之一</STRONG>。</P>
<P align=center><IMG height=432 src="http://www.sawin.com.cn/doc/SD/UML/xuml3.jpg" width=402 border=0><BR><FONT size=2><BR>图 3 采用UML描述的分工组成结构至多只能描述到职责级</FONT></P>
<P><STRONG>2 UML难以从宏观把控业务流程的完整与准确<BR></STRONG>&nbsp;&nbsp; 图 4是用全程建模方法顺序图描述的业务协作流程&#8212;&#8212;&#8220;采购&#8221;，它将业务事件序列与业务活动有机地集成在一个图形中，用户可以直观地判断软件开发人员描述的业务流程是否正确、完整。</P>
<P align=center><IMG height=350 src="http://www.sawin.com.cn/doc/SD/UML/xuml4.jpg" width=434 border=0><BR><FONT size=2><BR>图 4 采用全程建模方法的顺序图描述业务协作流程</FONT></P>
<P align=left>&nbsp;&nbsp;&nbsp; 图 5与图 6分别用UML顺序图和活动图描述的业务协作流程&#8212;&#8212;&#8220;采购&#8221;，问题其一是用户需要左一眼、右一眼、上一眼、下一眼地对照两张图，费时费力，检查两种图时在所难免地会出现遗漏、不一致；问题其二是UML顺序图缺少条件分支的表达方法，表达内容不完整；问题其三是UML顺序图和活动图从形式上到内容上不存在等价关系。<BR>&nbsp;&nbsp;&nbsp; 使用UML描述业务流程很难让人放心，因为描述业务流程时产生的遗漏、不一致、不完整，同样会给项目带来灾难。这是纠缠不清的胡子工程问题点之二。</P>
<P align=center><IMG height=380 src="http://www.sawin.com.cn/doc/SD/UML/xuml5.jpg" width=381 border=0></P>
<P align=center><IMG height=356 src="http://www.sawin.com.cn/doc/SD/UML/xuml6.jpg" width=570 border=0></P>
<P><STRONG>3 UML无法从微观把控业务信息的操作过程<BR></STRONG>&nbsp;&nbsp;&nbsp; 图 7从微观上用全程建模方法PAD图描述了职责细化流程&#8212;&#8212;库管员如何&#8220;入库&#8221;，它不仅描述了岗位职责展开的具体逻辑步骤，同时也描述了如何对业务信息进行操作，如对&#8220;入库单&#8221;的 &#8220;实际入库数量、入库日期&#8221;等栏目进行填写操作，对&#8220;入库单&#8221;的 &#8220;商品规格、采购数量&#8221;等栏目及&#8220;采购计划&#8221;的等&#8220;商品规格、计划采购数量&#8221;等栏目进行读取操作。</P>
<P align=center><BR><IMG height=199 src="http://www.sawin.com.cn/doc/SD/UML/xuml7.jpg" width=498 border=0><BR><FONT size=2><BR>图 7 采用全程建模方法的PAD图描述的职责细化流程</FONT></P>
<P align=left>&nbsp;&nbsp;&nbsp; UML根本无法从微观上描述业务信息的操作过程，只能等到编程时再由有经验、责任心强的程序员去了解，这无疑于边盖楼边考虑在哪里开窗户，最后各种问题盘根错节，摁倒葫芦起了瓢。软件公司练就了不少救火高手，但不容否认的是充满了救火队员项目常常意味着灭顶之灾。这是纠缠不清的胡子工程问题点之三。</P>
<P align=left><STRONG>4 UML无法彻底全面描述用户的需求</STRONG><BR>&nbsp;&nbsp;&nbsp; 图 8是采用全程建模方法组成结构树进行功能定义，它可以细致到原子工作步骤级，比如&#8220;签字入库&#8221;仍然需要手工进行。</P>
<P align=center><IMG height=267 src="http://www.sawin.com.cn/doc/SD/UML/xuml8.jpg" width=484 border=0><BR><FONT size=2><BR>图 8 采用全程建模方法组成结构树进行功能定义</FONT></P>
<P align=left>&nbsp;&nbsp;&nbsp; 采用UML无法对这种功能需求直观地定位，结果是开发人员好心好意地实现了电子签名，而客户却毫不领情，应为中国用户不相信计算机的签名，去掉这个功能也是一件麻烦事。<BR>&nbsp;&nbsp;&nbsp; 另外常常发生的情况是开发软件遗漏了大量用户需要的功能，如用户需要计算机自动核对&#8220;采购计划&#8221;中的&#8220;计划采购数量&#8221;与&#8220;入库单&#8221;中的&#8220;计划采购数量&#8221;，如果需求定位没有细致到这种程度，程序员如果没有经验或责任心不强，自然会忘记这些，那么在测试阶段或者系统上线运行后用户肯定会发现要求修改，改来改去的麻烦又会特别多，反反复复修改的工作量极大地加大了软件公司的开发成本。这是纠缠不清的胡子工程问题点之三。</P>
<P align=left><STRONG>5 UML是造成信息不对称的&#8220;功臣&#8221;</STRONG><BR>&nbsp;&nbsp;&nbsp; 可以说UML为用户（甲方）与开发方（乙方）的信息不对称提供了&#8220;有力的手段&#8221;，双方都互占&#8220;便宜&#8221;，因为这种信息不对称不但表现在有关信息产品和信息技术的知识上，还表现在乙方对甲方的业务理解上。由于乙方对甲方的业务术语理解不一定全面和准确，有可能在乙方看来含义非常简单的一个业务功能在甲方的经典著作或国家标准中含义非常丰富，需要做大量的工作。这样在使用UML的情况下，乙方按照自己的理解与甲方签了协议，但真正实施时却必须按甲方的国家标准去实施，这种扯皮的事在项目实施过程中大量存在。在信息项目的对策模型中，很难说乙方就一定能在合同中处于优势。<BR>&nbsp;&nbsp;&nbsp; 由于信息化热潮的影响，许多公司纷纷进入IT项目建设市场，这些公司中难免有不少是属于鱼目混珠一类的，他们可以在报价中拚命地压低价格赢得标书，但在实际建设中却以各种手段欺骗用户，使用户蒙受巨大损失。还有一些很有名气的院校和公司承接IT项目建设业务之后，由于各种业务量太大，对其中一些中小项目投入精力不够，雇请一些新手作项目，囫囵吞枣，出了问题要么说用户当时没有说清楚，要么说用户水平太低不会用。<BR>&nbsp;&nbsp;&nbsp; 即使乙方很勤奋，将方案做得很先进、很完美，充分考虑各模块的设置，也重视信息安全等问题，在使用UML的情况下，因为UML存在的种种问题，仍有可能因为乙方对甲方业务信息的理解能力不够，而使得乙方的方案和产品偏离甲方的真实需求。</P>
<P align=left><STRONG>二、UML下不着地&#8212;&#8212;无法提供直接到位的素材指导程序员编程</STRONG><BR>&nbsp;&nbsp;&nbsp; 所谓&#8220;下不着地&#8221;是指费尽心力地使用UML建模后，很难让处于软件开发下游的程序员直接接受去编程，因为UML的表达方式不直接支持详细设计，程序员还得费尽周折地琢磨如何把建模结果转换成程序代码，这种情况造成了软件开中的第二个隔阂，是UML的第二大硬伤。<BR>&nbsp;&nbsp;&nbsp; 与现代编译器对接的是结构化程序设计，如伪代码、PAD（问题分析图），前者为80%的美国公司使用，后者为80%的日本公司使用。伪代码的优点是从语法结构上与通常的高级语言非常接近，PAD由于可视化的特点十分便于人的理解，在图 9中，全程建模方法建立了这两种详细设计的联系，可以轻松地将PAD转换成伪代码。</P>
<P align=center><IMG height=271 src="http://www.sawin.com.cn/doc/SD/UML/xuml9.jpg" width=618 border=0><BR><BR><FONT size=2>图 9 采用全程建模方法PAD图描述的模块级流程与伪代码</FONT></P>
<P align=left>&nbsp;&nbsp;&nbsp; 另外，UML没有对系统级、模块级接口的考虑，这在大型复杂系统开发重视不可想象的，图 10采用全程建模方法中数据汇总图自动描述的系统之间的接口。</P>
<P align=center><IMG height=133 src="http://www.sawin.com.cn/doc/SD/UML/xuml10.jpg" width=485 border=0><BR><FONT size=2><BR>图 10 采用全程建模方法中数据汇总图描述的系统之间的接口</FONT></P>
<P align=left><STRONG>三、UML一盘散沙&#8212;&#8212;没有在细微之处建立建模图形之间的联系</STRONG><BR>&nbsp;&nbsp;&nbsp; UML建模图形之间的内部联系十分松散，这种隔阂造成了UML的第三大硬伤，由于篇幅的关系，这种硬伤造成的潜在危害不再讨论，本文只是将&#8220;散沙&#8221;&#8220;罗列&#8221;如下：<BR>1 状态转移图中，事件与外部Actor、Class、Package等无关；<BR>2无法从语法上建立状态转移图与顺序图的联系；<BR>3 无法从语法上活动图应与顺序图在流程描述关系；<BR>4 协作图和顺序图中与Message相伴的参数与类图无关。</P>
<P align=left>&nbsp;&nbsp;&nbsp; 虽然UML有这样那样的问题，不过UML也是从版本0.9发展到现在的1.4版，我们期待UML的升级，但在将要发布的2.0版中却没有&#8220;改过&#8221;的迹象。<BR>&nbsp;&nbsp;&nbsp; 本文对UML攻击颇多，实际上全程建模方法从UML及其前身OMT（Object Modeling Technique）获益匪浅，作者也是经过对OMT、OOSE、UML以及OOA/OOD的深入剖析，取长补短而建立了全程建模方法，所以理所应当向相关的面向对象大师们表示敬意。<BR>&nbsp;&nbsp;&nbsp; 本文在写作过程中得到了战复东先生的热情帮助，在此表示感谢。</P>
<P align=left>=======================================================以下为很多的评论：</P>
<P align=left>tata1 (2002-6-17 16:40:37)&nbsp;<BR><BR>感想： 高展先生的文章已引起不小的风波，有人认同，有人迟疑，有人反对。我认为，我们每个人都应该感想高先生，是他与作为&#8220;软件开发标准技术&#8221;的UML唱了反调，他敢于挑起一场风波，而这场风波早应该发生了。 软件开发是一个技术研究与应用实践紧密结合的过程，程序员必需具备科学的研究精神，辩证的思考问题而不是沉迷于某项新技术，新思想的玩弄，或迷信于某个理论的说法。如果伽利略不敢否认亚里士多得，如果爱因斯坦不敢否认牛顿，那么今天会是怎么样呢？ 我敢肯定，即使那些拥护UML的人对UML也不全是很精通的。为什么所谓标准就无澥可击了，聘什么认为老外做的东西就是好的？中国软件应该发起一场革命，铲除那些形而上学，教条主义的思想，建立统一的正确的认识。用哲学的发展，全面，辩证的思想来认识问题，认识软件工程。&nbsp;<BR><BR><BR>tata1 (2002-6-12 16:10:18)&nbsp;<BR><BR>UML手册已经说明UML是一个建模符号体系，不适合完成全过程的设计应用。所以，高先生说UML&#8220;上不着天，下不着地，一盘散沙&#8221;有点偏激了。 我认为，UML确实存在使用，普及困难的问题。UML加上RUP后，内容太多，还要学习面向对象技术，确实使软件开发难度很大。一个设计思想或设计工具的运用主要是为了缩短开发周期，提高代码的利用率，可维护性等方面。所以我非常同意高先生的全程建模思想，我最近也产生了一些类似的构想。我希望理想的设计工具如下：一：归纳各软件开发阶段的问题，和解决问题的方法和技巧，指导性地分析设计。二：有层次，有联系的表达各阶段，各模块，各对象等元素的构成。三：和代码保持同步。即设计到代码的正反向功能。 ... 我的Mail:kmbaojun@msn.com 欢迎讨论&nbsp;<BR><BR>zy422 (2002-6-11 10:15:19)&nbsp;<BR><BR>我是一个有个编程经验多年的人，我也用 ROSE 来设计个一些东西，但我感觉到 ROSE 在给程序员一个交代时做得很不够，应为程序员最关心的是这个函数要做什么事、怎么在这个函数里做，函数里到底要使用到设计的那些类和函数，这 ROSE 实在是做得不好，所以现在我们公司里的程序员一般都不看 ROSE 图，靠和设计人员直接交流来完成对设计要求的认识。我希望 ROSE 在以后的版本中能做一些好的，能和程序员交流的工具或表达视图。 UML 还有很长的一段路要走，我真正用好了的只有类设计，其他的我实在是用不好了。 我个人的观点，实用的就是好的，管它是面向对象还是面向过程，关键是要大家都用，都能够用好,多能方便的使用。对于 UML 我认为它站得太高了，现在很多人都还不能用好。&nbsp;<BR><BR>gale (2002-6-7 14:38:57)&nbsp;<BR><BR>3boy说的不错，但离题了，希望不是枪手，更不要顾左右而言它让我们重新看一下问题,作者说的是：UML的三大硬伤抛开工具，考虑一下思路这个UML三大硬伤的认识是错误的，理由我在前面的贴子已经描述过了我希望大家能就这&#8220;三大硬伤&#8221;提出意见，而不要偏离主旨 1,再驳&#8220;上不着天&#8221; 有什么形式化的方法能对问题域进行信息无损的描述？？？理论上还没有，目前走在业界前面的，是国际标准的，就是UML了 XX建模方法我不熟悉，没有发言权，但....这个不是国际标准 2，再驳&#8220;下不着地&#8221; XX建模方法有类和对象级的表达语法吗？反正在这篇文章里没有看到哎，我也不行，做不出自己的建模方法来，我&#8220;五十步笑百步&#8221; 3，再驳&#8220;一盘散沙&#8221; 昨日在《程序员》上拜读了高先生的《XX建模方法》不用我说，各位明眼的人就能看的出哪种方法的形式化推导关系更严密了&nbsp;<BR><BR>3boy (2002-6-7 9:31:32)&nbsp;<BR><BR>我觉的以上的言论太过偏激了，火药味太过于浓厚了，软件分析的目的是为了让大家都弄明白一个目的，那就是 &#8220;你该做什么？你要做什么？或则你要其别人做什么？&#8221;，而所谓的Rational产品，以及高先生的Playcase包括其它的一些建模工具都充其量和word差不多，只不过使用方便一些而已，&#8220;人&#8221;的因数还是最重要的，这就是对系统分析设计人员的素质要求。我觉的我们不能&#8220;神话&#8221;建模工具，而忽略了人，即使我们没有好的&#8220;画图&#8221;工具只要有人在，我们甚至可以&#8220;手绘&#8221;全部工作流，以上的争论好像就在讨论&#8220;画图板&#8221;的优劣，而不是在探讨软件工程真正的要旨，我觉的应该讨论的是&#8220;如何让大家都明白，你要做什么，我能为你做什么，你有些什么可以为我而提供的，你是这样的吗？。。。。。&#8221; 软件工程是一个不确定标准的学科，不确定的原由是，每个人都有自己的主张，不管主张的好坏，至少要知道你在为谁分析，你的对象是如何的，如果你画的东西别人都不理解，或者他们要花费很大的代价去理解，我认为那就是失败的方法，那么我们就必须寻求其他的途径去让人理解。 &#8220;我的三大忠告&#8221; 1、&#8220;条条大路通罗马&#8221; 2、&#8220;能解决问题的方法才是好方法&#8221; 3、&#8220;好的画家，即使没有丰富的颜料，和优良的画笔，依旧可以做出优秀的传世之作&#8221;&nbsp;<BR><BR>3boy (2002-6-7 9:26:54)&nbsp;<BR><BR>我觉的以上的言论太过偏激了，火药味太过于浓厚了，软件分析的目的是为了让大家都弄明白一个目的，那就是 &#8220;你该做什么？你要做什么？或则你要其别人做什么？&#8221;，而所谓的Rational产品，以及高先生的Playcase包括其它的一些建模工具都充其量和word差不多，只不过使用方便一些而已，&#8220;人&#8221;的因数还是最重要的，这就是对系统分析设计人员的素质要求。我觉的我们不能&#8220;神话&#8221;建模工具，而忽略了人，即使我们没有好的&#8220;画图&#8221;工具只要有人在，我们甚至可以&#8220;手绘&#8221;全部工作流，以上的争论好像就在讨论&#8220;画图板&#8221;的优劣，而不是在探讨软件工程真正的要旨，我觉的应该讨论的是&#8220;如何让大家都明白，你要做什么，我能为你做什么，你有些什么可以为我而提供的，你是这样的吗？。。。。。&#8221; 软件工程是一个不确定标准的学科，不确定的原由是，每个人都有自己的主张，不管主张的好坏，至少要知道你在为谁分析，你的对象是如何的，如果你画的东西别人都不理解，或者他们要花费很大的代价去理解，我认为那就是失败的方法，那么我们就必须寻求其他的途径去让人理解。 &#8220;我的三大忠告&#8221; 1、&#8220;条条大路通罗马&#8221; 2、&#8220;能解决问题的方法才是好方法&#8221; 3、&#8220;好的画家，即使没有丰富的颜料，和优良的画笔，依旧可以做出优秀的传世之作&#8221;&nbsp;<BR><BR>gale (2002-6-3 11:07:14)&nbsp;<BR><BR>1，技术是不分国界的，你用手在白板上画UML图是无需支付任何费用给US的 2，不要动不动就把技术问题上升到政治和民族主义 3，&#8220;拿来主义&#8221;，英美都能虚心拿去中国的火药制造枪炮来打中国，你难道不能学美国的 UML来打败US的软件产业？？！！ 4，作为中科院的人物，讲话是要负很大责任的，因为你的错误讲影响千千万万的人如果你错了并且是个权威，你将造就&#8220;十年浩劫&#8221;！！&nbsp;<BR><BR>chinakid (2002-6-3 10:06:48)&nbsp;<BR><BR>我想不通！为什么高展先生一说UML不好，就有人跳出来大骂，为什么，为什么？难到美国人的东西就不能批评吗？难倒中国人的智慧就比美国人差吗？中国人，不要轻易低下你高贵的头！&nbsp;<BR><BR><BR>gale (2002-6-1 0:38:51)&nbsp;<BR><BR>1，&#8220;上不着天&#8221; 错，UML中的 Business Use Case Model 和 Business Object Model就是干这个的。最少现在还没有比UML描述业务更通用，更清楚的 2，&#8220;下不着地&#8221; 又错，Rose可以生成代码，再加上 XDE与Visual Studio.NET的集成 3，&#8220;一盘散沙" 还是错，Business UC Model--》Business UC Realizations--》Business Object Model Business Worker --》; Actor --》 Use Case --》Use Case Realization --》Analysis Model --》 Design Model --》Imp model 都是有严密的推导关系的什么&#8220;专家&#8221;？？！！纯粹是误人子弟！！补充：好像牛顿先生说：&#8220;我之所以伟大是因为站在巨人的肩膀上&#8221; 软件开发领域里&#8220;巨人的肩膀&#8221;就是前人工作的结果和经验 US的软件比中国强原因之一是国人（我也是）都喜欢重新发明轮子 UML是一个标准，不是R$的产品，你要是真有水平应该提交UML2.0给OMG，而不是自己闭门造车弄个什么XX建模方法出来。 建议高先生好好看看UML+RUP+UCM这整个的思想体系，真正研究上一年再发表点有趣的文字。&nbsp;<BR><BR>gale (2002-6-1 0:22:04)&nbsp;<BR><BR>1，&#8220;上不着天&#8221; 错，UML中的 Business Use Case Model 和 Business Object Model就是干这个的。最少现在还没有比UML描述业务更通用，更清楚的 2，&#8220;下不着地&#8221; 又错，Rose可以生成代码，再加上 XDE与Visual Studio.NET的集成 3，&#8220;一盘散沙" 还是错，Business UC Model--&gt;Business UC Realizations--&gt;Business Object Model Business Worker --&gt; Actor --&gt; Use Case --&gt;Use Case Realization --&gt;Analysis Model --&gt; Design Model --&gt;Imp model 都是有严密的推导关系的什么&#8220;专家&#8221;？？！！纯粹是误人子弟！！PlayCase版权费的驱动＋浅薄＋无耻&nbsp;<BR><BR>kjxia (2002-5-29 15:15:13)&nbsp;<BR><BR>我想csdn给我们提供的是一个技术论坛，作用是大家可以在这里进行交流和讨论，通过交流可以解决一些实际问题，或是达到开阔视野、增长知识的目的，有不同的观点自然可以提出，但目的是为了探讨，有些用户把对别人观点的不认同转化为了莫名的人身攻击，这是很令人痛心的。&nbsp;<BR><BR><BR>ysmstoneman (2002-5-25 16:10:43)&nbsp;<BR><BR>呵呵,我懂得中国的软件为什么比不上国外的了。建议那些搞人身攻击的&#8220;同志&#8221;们，或持反对观点比较强烈的&#8220;专家&#8221;们都去看看《谁动了我的奶酪》这本书。记着，&#8220;我们都在害怕变化&#8221;。 UML强大，难道它就真的没有缺点了吗？是啊！如果我精通Delphi，我真希望其他的开发工具都她吗的消失。但它们消失了吗？没有，C#出来了，什么.net出来了，据说什么以色列的魔术师之类的东东也出来了，&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;不知道以后还有什么东东&#8230;&#8230; 我知道原来我错了，是我没有适应那么快的变化，IT这行确实变得太快，永远都有新东西出现，那应该是好事，要不，这世界上的技术怎么会发展的那么快呢？长期以来，分析工具一直是我国的空白，高展先生好不容易弄出了PLAYCASE（也许不是他一个人的功劳，但怎么说中国也出了这么个东东了），就因为这篇文章，用得着把人家骂成那样吗？&nbsp;<BR><BR><BR>hostoop (2002-5-22 17:45:10)&nbsp;<BR><BR>不管是UML还是其它的什么，它都只是个工具，是用得好还是用得差，靠的是用工具的人。每个工具在不同的领域有不同的作用，我不会用VB来写硬件驱动程序，也不会用汇编语言写财务软件。我现在在Linux环境下用C语言写邮件服务器程序，如果按照高先生的思路，我是不是该出来写写&#8221;VB的三大硬伤&#8220;、&#8221;Windows的X大硬伤&#8220;？&nbsp;<BR><BR><BR>2001sky (2002-5-21 13:28:50)&nbsp;<BR><BR>真正成功的软件是不依靠什么UML和PLAYCASE的系统分析的作用就是把客户的意思传达到程序员那里系统分析就是一个调制解调的过程如果你行，用WORD就可以了如果你要蒙人，用什么都不行什么样的人可以做系统分析？没有做出过成功软件（客户满意，代码稳定）的人永远没资格做系统分析，博士也不行请不要攻击任何工具，他不是万能的，只是一个助手&nbsp;<BR><BR>asp_boy (2002-5-21 8:57:20)&nbsp;<BR><BR>不知道分析员是不是都是高高在上的，还是在CSDN中的特产。只要提出一个不能被多数人接受的观点，就会被骂得狗血淋头。 争论是一定会有的。但如果指人，这与市井流氓有什么区别？有人说&#8220;PLAYCASE那玩意纯熟垃圾&#8221;，想必他能设计一个比PLAYCASE更好的玩意，如果设计不出，也应该指出PLAYCASE的不足。空口说白话，谁不会说啊。 最后一点， PLAYCASE是免费的，却有人说&#8220;鄙人初次接触PlayCase, 就发现PlayCase有许多优点......高展先生，您的PlayCase卖了几套了？&#8221;。 可见，很多人都是推崇自己正在使用的工具。 存在偏见的人不会是好的分析员。&nbsp;<BR><BR>shhao (2002-5-20 15:50:44)&nbsp;<BR><BR>我认为主要问题是作者未理解（当然更谈不上掌握）面向对象的思想和方法。&nbsp;<BR><BR>zhaott (2002-5-20 13:15:12)&nbsp;<BR><BR>工具不是主要的，主要的是人，是规格&nbsp;<BR><BR>telescope (2002-5-20 13:06:05)&nbsp;<BR><BR>一个老农拿鞭子敲敲拖拉机骂道，这东西没他妈我的驴好使，不懂人话，就算费点劲把它开起来，还不得把我的地压硬喽？驴一拉就走，这东西他妈不要说让我拉，就是驴也拉不动，然后还得花油钱，这是拖拉机的硬伤啊。&nbsp;<BR><BR>telescope (2002-5-20 13:04:30)&nbsp;<BR><BR>一个老农拿鞭子敲敲拖拉机骂道，这东西没他妈我的驴好使，不懂人话，就算费点劲把它开起来，还不得把我的地压硬喽？驴一拉就走，这东西他妈不要说让我拉，就是驴也拉不动，然后还得花油钱，这是拖拉机的硬伤啊。&nbsp;<BR><BR>blacktigers (2002-5-20 12:07:57)&nbsp;<BR><BR>推荐一篇文章：转载自企业工程论坛 http://www.ee-forum.org/ 标题：复杂系统的层级原理与模型驱动软件体系结构　 作者：余彤鹰 2002-5-17 -------------------------------------------------------------------------------- 写在前面　　最近看到模型驱动在国内渐渐被更多的人注意，前几天又看到一些关于UML优劣和应用方面的争论。作为繁忙工作中的一种休息，从过往的研究笔记中整理一点东西放在这里，与大家交流。 层级理论是构建复杂软件体系的基本原则　　诺贝尔奖获得者赫伯特 A. 西蒙曾论述到：&#8220;要构造一门关于复杂系统的比较正规的理论，有一条路就是求助于层级理论&#8230;&#8230;我们可以期望，在一个复杂性必然是从简单性进化而来的世界中，复杂系统是层级结构的&#8221;。对于软件这样复杂的人造事务，发现层级和运用层级，是分析和构建的基本原则。 软件的体系结构是层级的　　粗略地观察一下软件表述方式（语言）的发展：从穿孔纸带（机器的语言）开始，首先是汇编语言，然后是高级语言，再往后有面向对象语言和所谓第四代语言（FGL）出现&#8230;&#8230;应当留意：每一代的语言并不是在&#8220;取代&#8221;前一代语言，而是用上一代语言来&#8220;写&#8221;下一代语言。在这个自然的进化过程中，西蒙所论述的复杂体系的层级特征清晰地出现了。 　　进一步看，在由简单到复杂的进化道路上，软件的体系结构、软件开发的体系结构、软件开发工具的体系结构等等，都呈现出层级的特征。&#8220;好&#8221;的软件体系具有更加清晰的层级。 一维语言之后是模型　　这里不想展开讨论这个问题，只是提出一些思考的结果。与自然语言类似，现有的&#8220;程序设计语言&#8221;是单维的，它的基本语法是以前后顺序为基础的。当系统的复杂程度提高时，用这样的语言精确描述复杂系统变得越发困难，更遑论有效地修改维护；可视化开发平台、代码管理工具（甚至某种意义上共享组件也可包括在内）等的出现对此是一种补充，但仍然不是最终的解决方法。软件描述体系进化到这里，面临着一次突变，将有新的物种出现，这个新物种可能就是模型。笔者认为，模型与程序语言主要的区别不在于图形化，也不在于抽象的程度，而在于表达方式突破了&#8220;单一顺序&#8221;的限制，最简单的例子就是二维表。模型可以更容易和直接地表达复杂的结构。 模型和语言都是对系统的描述　　传统的编程语言和模型都是一种表述的体系，前者适合表述顺序过程，后者适合表述复杂结构。模型的必要性可以通过下面这个例子看出来： 　　为了精确地复现，你可以用语言精确地叙述一个立方体，甚至10个立方体组合的形状，但你不会试图用语言描述一栋房子，适当的方式是用工程图纸。 　　建立企业应用系统的情形可以从以上例子得到启发，企业系统要表述的，主要是复杂的结构，过程占的比重很小，因此，模型就变得更加重要乃至必要了。 OMG组织的MDA战略　　OMG最新的战略，是建立模型驱动体系架构（Model Driven Architecture, MDA），它的意义不是三言两语可以说清楚的，但从软件进化的角度来说，可能带有一种必然性，从上面的讨论，至少可以引申出两个理由： 更有效地描述复杂系统的需要； 系统复杂化带来的层级区分的需要。 关于模型的几个分析要素　　笔者认为，以下特征对软件体系中模型的运用是十分重要，或者有特殊意义的： 模型的时效性（time-effectiveness of model）：关于这一点最重要的区分在于，是&#8220;运行期模型&#8221;（Run-Time Model），还是开发期模型？这个区别，有点类似于解释的语言和编译的语言间的区别，但其意义却非同一般，笔者认为，&#8220;运行期模型&#8221;，揭示了模型驱动的本质。 模型的可进化性（evolutionableness of model）：是否可以在系统的应用过程中，持续地适应应用环境与需求的变化，不断地由应用者或自适应地对模型进行改进？这是对模型&#8220;性能&#8221;的一种度量。 模型的层级性（hierarchy of model）：正如语言有多个层次一样，没有理由认为模型只有一个层次，当系统足够复杂时，模型的层次划分将会是必要的。 UML和企业模型　　运用上面的要素分析一下，可以发现： 　　UML是&#8220;紧贴&#8221;高级软件语言（例如C++）的模型体系，其时效是在软件生命周期的开发期间，而不是运行期间，其描述的层级是在软件的组件、对象一级，典型要素是软件中的对象，软件上一个操作的动作等。 　　企业模型（比如ARIS, CIM-OSA, GERAM），典型的要素是组织，产品，过程等，它们是从企业的业务对象着眼的。二者在层级上有差距，而且企业模型追求的最终结果，是从&#8220;开发期模型&#8221;到达&#8220;运行期模型&#8221;，并且，笔者认为它最终应当是一种可进化的模型，这与UML的设计目标并不符合。 　　它们两者间并不相互排斥，而应当考虑它们的&#8220;层接&#8221;。按照笔者的理解，OMG的MDA即使全面实现，也仍然不能做为或替代企业模型，但有可能成为企业模型的基础，这不是模型好坏或能力的问题，而是层级定位的问题。 写在后面　　面向对象（Object Oriented, OO）作为软件体系结构方面的一种演进而出现，也曾经被一些人误解为对过程化语言（或面向过程的体系结构）的取代。笔者认为，尽管OO反应了一种世界观，是一种思维的方式，但并不代表一切；且从层级和进化的观点上，也不应当将它看作是对既有东西的一种简单的取代。模型或模型驱动同样如此，它可能是继面向对象之后，软件体系结构的又一个重大的进化，但不是用来取代面向对象或结构化设计。笔者在1998年撰写《迈向21世纪的企业信息技术应用》一文时，对于模型的地位和作用并没有今天这样的认识，现在我坚信，对于企业信息系统这样复杂的系统，要想做到有效、可控制地规划与构建乃至具有&#8220;柔性&#8221;、可在运行期间不断地调整，&#8220;模型&#8221;是必须的，而且，表达与构建复杂企业系统时所需的模型，可能是多层次的，所谓&#8220;通用企业平台上的专用执行系统&#8221;，就应当是一个由运行期模型驱动的系统。 --------------------------------------------------------------------------------&nbsp;<BR><BR>chinakid (2002-5-20 9:41:02)&nbsp;<BR><BR>偶尔路过看到这些评论，我很气愤。一帮美国的走狗！ UML，CMM都是人家美国人定下的标准，可笑的是软件公司象哈巴狗一样，跟在美国人后面摇尾巴。高展的playcase我没有用过，但我知道一点：中国人从来不输给别人！！！！！政府能扶助制造自己的CPU，自己的操作系统，自己的Office软件，也可以再扶助一个建模软件！这样我们就不用再仰视别人的鼻息！！！美国人的一套Rose多少钱？赚去了中国人多少血汗钱？而高展的playcase是免费下载的！！！为国家安全和产业利益，政府都应该对自主开发的软件进行扶持！起来，挑战UML霸权！&nbsp;<BR><BR>bigbat (2002-5-19 21:25:25)&nbsp;<BR><BR>"UML 没有排斥任何特殊的软件开发方法或过程；它只不过标准化了标记法的格式。"Granville Miller 语不是UML的问题。是开发者对面向对象的方法掌握的问题。高先生的方法是可能是一种好方法。但你应弄清楚你只是其中的一种。不要弄不清楚问题的实质就大贬一通。我觉得你说的三个发面都不对！ 1&#8220;上不着天&#8221;这种隔阂使建模结果无法与用户沟通确认所谓的需求，埋下了软件危机的祸根； USE CASE 图是一种很好的用来表达用户需求的工具。何以&#8220;上不着天&#8221;？ 2&#8220;下不着地&#8221;这种隔阂使千辛万苦得到的建模结果无法指挥程序员编码，最后得到的软件与用户期望的结果很远，返工、误工、烦恼无穷； CLASS 图是程序编写的图纸。看着它就可以来写代码。coder 们不需要了解设计的全部就可以施工。何以&#8220;下不着地&#8221;？ 3&#8220;一盘散沙&#8221;这种隔阂让建模图形之间的关系凌乱不堪，建模过程千辛万苦，建模结果很难自圆其说。目前在 UML 规范中有九种图。重不同的视角反映需求。你的设计&#8220;一盘散沙&#8221;。UML有何罪之有？ 高先生你认真对待你的&#8220;惊世&#8221;高论。您是一位学者！！！！！！！&nbsp;<BR><BR>elkel (2002-5-19 19:31:36)&nbsp;<BR><BR>真好笑，作者根本不懂UML，拿着Rose胡画，还对UML妄加评论。恶心... 本人忍受胃痉挛的痛苦，读完此文。力图修正作者使用UML的错误，提醒初学者不要象他一样胡画。（其实我也是初学者:)）对于Playcase，我没用过，不敢妄加评论，以免犯与作者一样的错误。但我可以确定我今生今世都不会用它。 西门吹雪忽然道：&#8220;你学剑?&#8221; 叶孤城道：&#8220;我就是剑。&#8221; 西门吹雪道：&#8220;你知不知道剑的精义何在?&#8221; 叶孤城道：&#8220;你说。&#8221; 西门吹雪道：&#8220;在于诚。 叶孤城道：&#8220;诚?&#8221; 西门吹雪道：&#8220;唯有诚心正义，才能到达剑术的颠峰，不诚的人，根本不足论剑。&#8221; 好，现在开始切入正题 1. 图3，作者应该画的是用例图吧。首先，用例图不能用来描述企业的组织结构。其次，作者用包来表示企业和部门是胡画，包在C++和java中分别映射为namespace和package。另外，作者用用例表示职责，算沾了一点边，但是这仍然是错误的，用例应该代表业务过程中角色的行为。作者所提的&#8220;不能直观地将职责展开为步骤&#8221;，应该用协作图表示。以作者的观点看来，建模是以企业组织结构为中心，而UML的观点是以业务为中心。以企业组织结构为中心，就要根据企业组织结构建立业务流，以业务为中心，企业组织结构要适应业务流程。哪个合理，很明显。（扯的太远了） 2. 图5，作者的目的是描述业务流程吗？那么请用协作图吧，虽然顺序图和协作图可以互相转换，但它们是有区别的，顺序图是针对开发人员的，协作图才是针对领域专家的。 3. 图6，作者画了泳道吧？胡画！！角色的职责应该在这里表现，每一个泳道应属于一个角色，泳道内的活动就是角色的职责。这是活动图吗？起始和结束点在哪呢？ 作者提出的UML三大硬伤，更本不能成立，作者根本不懂UML。&nbsp;<BR><BR>grantguo (2002-5-19 14:59:52)&nbsp;<BR><BR>还是那句话：没有银弹。。。。软件开发过程中没有银弹 啊。&nbsp;<BR><BR>kendy_yin (2002-5-19 11:24:16)&nbsp;<BR><BR>其实你未必要去评论uml的好坏，就象linux的爱好者去说windows的坏话一样。如果你的产品真的好地话，时间可以证明一切的。觉得还是多花点心事集他人之长，补己之短吧。希望能见到你更好的产品。其实我都不知道作者是写什么的，从上面评论看，你是不是playcase的作者呀？&nbsp;<BR><BR><BR>maxsuy (2002-5-18 19:17:38)&nbsp;<BR><BR>作者的人品确实存在问题。 PLAYCASE我用过，我承认国内的公司能弄出这么一个东西确实不容易，可是你也犯不着这么咒骂UML吧。 PLAYCASE那玩意纯熟垃圾。做出设计来到最后呢，还是没有用。放厕所里都嫌PLAYCASE臭。&nbsp;<BR><BR>pattern (2002-5-18 19:07:48)&nbsp;<BR><BR>作为一个又搞分析，又编码的软件工程师（存在于大多数有中国特色的软件公司）。有一条经验应该铭记在心：不要指望可以完全掌握用户的需求，大多情况下，业务领域专家也无法给你一个细化到原子级的需求。所以，才有object-oriented 软件工程的出现，才有增量开发方法，才有敏捷建模，这些都是告诉我们要顺应人的思维习惯，渐进开发，逐步挖掘需求，层次建模。软件工程与建筑工程有很多共通点，但他们有一个根本的不同就是：软件最终是可以被修改的，但你不会为一个不很合理的自动扶梯设计而修改造好的大楼，只能将就着用。所以建筑工程的需求可以被认为是确定的，而软件则是相反。&nbsp;<BR><BR>whack (2002-5-17 23:53:21)&nbsp;<BR><BR>呵呵，弄了半天才是一个软件的作者在说自己的软件比别人的好，怪不得口气和论述都是说得那么具有商业的味道。那我们也不妨来看看文中的几个技术的例子： 1。面向对象开发中和用户交流的关键描述工具是use case图。所以一个工具在这个阶段对用户最重要的就是构造use case描述（必要地时候也需要对一些重要的类或者包，以及相关的一些交互细节做某种程度的描述），通常component的构造细节在和用户交流过程中通常用到得很少。 那么use case图作者会怎么描述呢？从文章中的对一个需求的建模结果看，也是类似的一系列图形和符号描述方式，但是不同的是在作者的表达方式和uml有所不同，更重要的是作者列举自己的建模图例和uml的图例的时候，设计的程度是不一样的，作者的建模图例其实是uml中的&#8220;静态图（类，包等）+ 一些usecase + 一些时序图（或者顺序图）&#8221;，也就是说作者的图形里面其实是夹杂了uml中的好几种图形（当然是把uml的描述方式有所简化和变化），但是在列举uml的设计图形的时候，却缺少了类的动态成分的表达（也就是方法及其顺序），但是在uml中有很多的图可以更进一步细化类或者包的设计（序列图，交互图，conponent图等）。 这反映了作者对于面向对象系统描述的理解不同，uml之所以把几种图形分别描述，一是当需求比较复杂的时候，几种图加在一起的方式可能会变得无法描述，因为一张图形可能变得已经画不下来了。二是uml的方式认为系统具有一系列的特性，不同的特性需要有专门的方式来分别描述。图形多看不过来，但是混合在一起，如果描述同样的细节程度，恐怕还是很长。 2。对于微观设计，那就要看是系统分析阶段还是系统开发了。系统分析的时候做很多细节，有必要吗？本来系统开发就是有很多细节要到系统实现阶段来进行的。而且同样的，对于任何一个小模块，同样地画出component 图，序列图，交互图（只不过粒度不同），想不出来这时候为什么不可以编码？所谓的伪代码不就是一种这些图形的文字描述方式吗？在描述留成的时候，其本质上是同构的（只不过伪代码是结构化的流程图方式来描述类或者方法的关系）。 3。实在弄不懂作者遗漏用户需求的意思，遗漏了用户功能是系统分析没做完的问题，和怎么描述实在联系不上。作者在某个流程上加了个注解，这是解决方法啊？ 4。作者认为uml中间的好几种图形和某些元素无关，或者不能转化为逻辑语句。这就是对uml的语法的理解问题了。这些图形用系统工具现在都可以直接生成c++或者java代码，那么语法转化还需要什么。 5。uml的描述方法里面还存在着某些复杂性或者戎余，包括rose工具对于某些图形的构造方法也存在着需要改进的部分，这些不用多讨论了，只要是软件或者标准，都是在不断进行版本修订中。 看了一下原文我怎么有点儿怀疑作者到底用uml做了多少项目，如果是为了宣传产品，没有必要做那些并不特别的例子，有些例子就只有一个自己的分析结果，就来了个结论。要知道很多在编码过程中好像很&#8220;好看&#8221;的东西，构造成一个产品后，就成了一堆不能维护的零件了。大家都用自己&#8220;喜欢&#8221;的，结果却往往是不能用的。&nbsp;<BR><BR>andy2ray (2002-5-17 21:44:20)&nbsp;<BR><BR>UML三位大师开宗明义，UML是一种语言，而不是方法，因此他本身不提供软件开发的过程指导。如果你不清楚或想获得在软件开发上的过程指导，可以参考RUP。这点不知高先生是否注意到？&nbsp;<BR><BR>111222 (2002-5-17 15:41:31)&nbsp;<BR><BR>写的很好，UML本来就是垃圾！&nbsp;<BR><BR>enlightenment (2002-5-17 15:22:06)&nbsp;<BR><BR>有句话是对的：尽信XX则不如无XX！&nbsp;<BR><BR>wuhan_wanhui (2002-5-17 14:14:50)&nbsp;<BR><BR>UML&#8221;三大硬伤&#8221;之我见 2002年第5期高展先生的文章《UML&#8220;三大硬伤&#8220;》以管理软件为实例，阐述了UML的三大硬伤，叙述的十分精彩。软件开发过程中的一些问题都被高先生提出，使我受益匪浅。但是高先生的许多观点，我不敢苟同。 UML是一种建模语言，语言是来供人们来交流，也就是供不同领域的人来交流的一个标准，就好像世界语。因此UML不是一种方法，UML建模和软件开发过程是两个不同的概念。UML适用于很多重软件开发过程。因此高先生有把用UML建模的软件开发过程和UML混淆的嫌疑，把软件开发过程中出现的硬伤归于UML，实属误解。 &#8220;上不着天&#8221;论。文中说，&#8220;建模结果无法于用户沟通确认所谓的需求&#8221;，&#8220;用户专家无法理解UML所描述的业务流程&#8221;。实际上业务流程是很细致的，以前我们用系统流程图直接处理这些业务流程，用户专家能得到很好的沟通。而现在用UML来描述业务流程，是不是有点赶时髦的嫌疑？软件开发过程中的问题并不是UML建模都能解决的，可以这么说用UML来描述业务流程曲解了建模的本义。三位大师的著作《UML参考手册》中说道，&#8220;模型从某一个建模观点出发，抓住事物最重要的方面而简化或忽略其他方面&#8221;，&#8220; U M L是一个建模型语言，不是对开发过程的细节进行描述的工具&#8221;。可见建模是要抓关键和重要的东西，高展先生文中说到，&#8220;UML难以从宏观把控业务流程的完整与准确&#8221;，并举了UML不能描述到原子级工作步骤，这与建模的思想是相违背的，建模需要的只是到关键的一定层次（如文中所述的职责级），而不是详细的细枝末节。可以说这正是UML的精华之处，只关注重要和关键而不关心细节。详细的细节问题属于软件开发过程中的问题。 &#8220;下不着地&#8221;论。建模只是建立了一个模型，至于具体的详细设计、编码当然需要程序员去理解和思想。试想，模型和详细设计之间不存在这个隔阂的话，从事详细设计的软件蓝领都不要下岗了？UML存在的意义在于作为一种通用的建模语言，提供了一种建模者之间交流的标准，这当然也适用于上游的分析员和下游程序员之间的交流。UML其实也向下着地，着于这种相互之间的交流上。从模型转换到程序代码属于case工具的范畴，并不能说是UML的硬伤。再说现在Rational Rose对于模型到代码的转换工作已经取得令人惊喜的效果。&nbsp;<BR><BR>dearmite (2002-5-17 11:31:19)&nbsp;<BR><BR>看了这么多，想写点什么，其实我这两种工具都没用过，ROSE只是听说，不过，没下过鸡蛋，总还见过，别人用的时候，唉，我总是很羡慕！为什么？不是UML多么高、多么好，也不是他那东西真的能转换多少价值， 因为他开的钱比我多！我们学这些、那些建模做什么，不是做事业，我们是为了钱！ 从文章的受益度讲，从文章的深度讲，我想这一点，高先生一定是最高分！ 但是问题是为什么IBM的OS/2没有比过MICROSOFT的Windows呢，因为市场！如果是我，boss让我又做建模，又做程序，那我一定不用UML，用高先生的东西没错！因为一切为了实用嘛， 但是问题是，建模的人不写代码，写代码的人不建模，建模的人把关系搞好就能弄到钱，你的程序多好，你的公司通过cmm,但是你卖的程序真的用了CMM了么，不是！，都是为了多挣一点钱罢了，所以我只能以心灵上赞助高先生，如果我要学，我还是要学UML，因为这就是钱！全程建模大家一看就懂，那还了得，客户还能买单？他不懂就对了，这就是UML的最最高明之处！&nbsp;<BR><BR>SouthPole (2002-5-17 11:10:11)&nbsp;<BR><BR>我想很多读者(包括我自己)对这篇文章非常不满，主要是因为： 1 作者对UML及其产品缺乏足够了解和实际使用经验，所指的所谓&#8220;硬伤&#8221;，很多并不是UML的问题，而是对基于UML产品的错误理解。例如：&#8220;采用UML的Use Case 图来描述组织结构，它只能描述到岗位职责，对岗位职责中的工作步骤无法描述&#8221; UML本身主要是用于REQUIREMENT和HIGH-LEVEL DESIGN，如你希望描述工作步骤，使用UP中USE CASE TEMPLATE即可 2 作者对UML的许多评价偏激，&#8220;上不着天、下不着地、一盘散沙&#8220;，近于全盘否定，就是当年批判GOTO时恐怕也没到这种地步&nbsp;<BR><BR>twinsant124 (2002-5-17 10:28:23)&nbsp;<BR><BR>1、文章的论点：关于UML，我可没有啥敢维护的，我是UML的初学者^_^，犯不着一上来就维护这么一个只不过是工具的东西；关于什么全程建模，咋更不敢放什么厥词了，偶可没有高老师对自己都不熟悉的东西大加批判，点人家死穴的勇气和魄力。 2、作者写技术论文的作风：作为国内很有名的软件过程专家，请注意自己的言行可能造成初学者的迷茫和彷徨，三思而行，文章之道也。&nbsp;<BR><BR><BR>waterusage (2002-5-17 9:25:11)&nbsp;<BR><BR>很多人不是在驳斥高展的论点，而是在批评他的PLAYCASE，批评他的为人了。 本来还是一个技术上的争论，现在就成了闹剧。 该收场了吧？吵完以后，谁也得不到好处。 但是，肯定也有人旁观了这场争论后，再使用UML时，多留了一个心眼。&nbsp;<BR><BR>rayking (2002-5-17 8:58:14)&nbsp;<BR><BR>从高先生以前写的文章看，所用的手段都是比较传统的。UML其实比较年轻，正是为了弥补数据流图（所谓的&#8220;地&#8221;）和业务流程图（所谓的&#8220;天&#8221;）等的不足而产生的。UML当然有缺点，这些缺点在几乎所有UML书籍里都有提及。希望高先生自己先用一下UML，相信会喜欢上她的。&nbsp;<BR><BR>softdance (2002-5-16 23:08:54)&nbsp;<BR><BR>高先生批评UML本着学术自由的原则没错，高先生的PlayCase我用过在也还算不错，而且我也相信大部分的同志也绝对不是攻击PlayCase这种工具本身，那高先生错在何处啊，何以招致如此多人群起而攻之。在这我只想说一句话：你可以批评大象皮糙肉厚，身体笨重，行走缓慢不如你的骡子外观漂亮，身轻体健，奔跑如飞，我保证没人说你什么，但是如果你批评大象不如你的骡子鼻子长牙俏,我同样可以保证保险公司都不敢保你。点穴要点死穴才能要人命，希望高先生下一次能准一点。&nbsp;<BR><BR>softdance (2002-5-16 22:56:59)&nbsp;<BR><BR>高先生批评UML本着学术自由的原则没错，高先生的PlayCase我用过在也还算不错，而且我也相信大部分的同志也绝对不是攻击PlayCase这种工具本身，那高先生错在何处啊，何以招致如此多人群起而攻之。在这我只想说一句话：你可以批评大象皮糙肉厚，身体笨重，行走缓慢不如你的骡子外观漂亮，身轻体健，奔跑如飞，我保证没人说你什么，但是如果你批评大象不如你的骡子鼻子长牙俏,我同样可以保证保险公司都不敢保你。点穴要点死穴才能要人命，希望高先生下一次能准一点。&nbsp;<BR><BR>washine (2002-5-16 20:39:35)&nbsp;<BR><BR>什么是好的建模工具？我认为其本身有多精辟或有多深奥并不重要，重要的是是否简单易懂。 为什么要建模呢？就是要越来越生动，便于理解，说得难听点，最好让傻瓜也一看就懂。 建模是给谁看的呢？并不是给软件设计者和项目经理看的，它是连接开发人员和客户的桥梁。 成功的建模应该具备极强的沟通能力及连贯性，条理清晰且容易接受。在这一点上UML明显先天不足（说老实话有很多程序员都看不懂更别说客户了）。从某种意义上说UML过于专业，熟悉面向对象的软件设计师或许能体会它的精妙，但从一般的客户及普通程序员来讲，他们需要的是一个生动的模型，而这个模型或许并不是UML。 国人有能力有魄力推出有价值的东西，我们为何不站出来给予支持呢？哪怕它仅有一个优点，也胜过一味地跟随。全程建模有他的可取之处，肯定也有许多不足之处（比如不够面向对象），但一般人（包括不懂设计的程序员）却更容易看懂它。我们要讨论的不是要用谁，摒弃谁，而是哪种方法更适合项目开发，给出更佳的效率。对任何事物都不要一棍子打死，难道就不能让它们共存么？&nbsp;<BR><BR>wangqiyy (2002-5-16 17:17:45)&nbsp;<BR><BR>各打50大板！ 1、人无完人，金无足赤。每一种软件工程方法都有其独到的特点和所要解决的问题，UML的方法着重业务模型的建立，而I2DEF的全程建模的思想确实不错，对于工具Rose和Playcase我都接触过。我认为UML主要在描述做什么，逐步逐步提升到怎么做，最后到内部的类，最后编程实现；而I2DEF的感觉就像是岗位责任书，每个角色各司其职，所有的责任和角色组成整个业务。如果单单使用某一表示方法，我还没有听说哪家公司成功过，例如Rational自己，它就有一系列产品（像什么Request之类的工具）支持，只有把这些都用上了，才有可能是解决软件工程问题的方法，而单独使用都是有缺陷的，Rose内部也是建议使用大量的文档嵌入来描述其细节和关系的。老实说，如果全部使用符合UML的工具来分析实现系统，我认为首先要解决的问题是成本（资金、时间），其次是思想的普及，只有深刻理解了UML的思想，才可能真正正确的是用它表示业务。 2、顺应潮流，如果和外界交流，用UML吧！英语比起我们的汉语，那算什么啊！原始的垃圾！但是老外都说，没办法，学呗！ 3、UML是发展的，它的存在是合理的。 4、与其在此争执孰是孰非，不如静下心，学习吧！&nbsp;<BR><BR>youyuan (2002-5-16 16:17:35)&nbsp;<BR><BR>看到此君的文章不禁想起了冯小刚电影《大腕》中那个搜狗网的c*o,他说要想网站要想火就要雇一帮写手，谁火啐谁，谁火灭谁，它就像这种写手，哈哈哈，我看他是想造个轰动效果，借以让自己成名，无聊的很，我想uml的用况在诞生时就已经说得很清楚: Use Cases are a critical technique in developing an application. Within the UML Use Cases are used primarily to capture the high level user-functional requirements of a system. This long winded description is important because Use Cases cannot usefully be used to capture non-functional requirements. Nor can they usefully be used to capture "internal" functional requirements. Attempting either or both is a sure path to disaster for two reasons. Firstly because Use Cases are an informal and imprecise modelling technique. But then they were never intended to be anything else. Secondly because the other use that we make of Use Cases is to define the fundamental structure of our application. The Use Case is not only important as a unit of requirement definition but also as our unit of estimation and our unit of work.&nbsp;<BR><BR>softdance (2002-5-16 12:20:58)&nbsp;<BR><BR>C++三大死穴 看了高先生的三大硬伤犹如提壶灌顶，真是顿觉自己愚笨。我的PlayC++ 已经诞生五年有余了，但一直是皇上老婆没人要，让我沮丧不已。但与PlayC++相比，C++是伤痕累累啊，经我以及清华的一些同事对C++的深入研究发现它的三大死穴。 一. 运行效率无与轮比的差。C++虽然编译速度挺快，但是运行效率却是太差，据我反复测试在同样的操作环境中比PlayC++慢了3-5倍。 二. 语言表达不够简练，丰富。别的且不说，就说程序的开始,C++ 用的是Begin.... end 格式，而且变量的声明以及函数的格式都太死板一点不灵活，根本无法满足我们多变的编程风格。反观我的PlayC++用花括号：{}代表开始结束，变量可以随用随叫，多么简洁。 三. 不支持面向过程编程。尽管目前是面向对象的天下，但是还是有很多场合要用面向过程的方法进行开发，例如最近非常火爆的CASE工具PlayCase就是一款优秀的过程工具。但是C++这一点做的太差，彻底抛弃了他们，采用了纯面向对象的方式，据我深入研究，C++的任何类型都是类结构，这对于广大的面向过程爱好者是及不公平的。不过不用担心，现在PlayC++可以让你为所欲为，它支持面向对象同样也没有忘记面向过程，这样你就可以用面向对象的语言来开发面向过程的设计，你以前的方法都可以保留。 当然C++也不是一无是处，例如它的垃圾回收功能，数组的上下界自动检测。但这些功能的实现是要付出代价的。 本文对C++攻击颇多，实际上PlayC++从C++获益匪浅，鄙人也是经过对C++非常深入的剖析，取长补短而建立了PlayC++，能有今天的成就理所应当向相关的面向对象大师们表示敬意。&nbsp;<BR><BR>wildhorseli (2002-5-16 9:40:03)&nbsp;<BR><BR>首先声明，本人不会写程序，本人用过高先生的东东（只是一个工具）；本人以为，UML只是一种符号，表达一种思想，正如高先生的东东一样，只是为了大家方便，清晰；以OO为思想，目的是代码的复用，可读，效率，适应外界的变化（这是重点）；本人认为UML的表达确实不错，本人不会写代码，但从用例上来看，清晰的很，业务清晰的很，一切看起来很自然，最起码你能感觉到是面向对象；由此可见，UML不在UML，在OO的功底，但从另一方面UML完全适应OO并且很适应，PlayCase或其他，我觉得大家完全可以用word，当然高先生可以用wps（国产的），甚或用草纸一样做出大家都能理解的UML；&nbsp;<BR><BR>zergcom (2002-5-15 18:22:49)&nbsp;<BR><BR>什么样的人可以评论UML： 1。真正了解和熟悉UML的人，而不是仇视UML的人。 2。用UML真正做过应用的人，而不是纸上谈兵的人。 3。能提出更好方案的人，而不是吹毛求疵的人。 4。不是井底之蛙的人。&nbsp;<BR><BR>hamzsy (2002-5-15 16:44:57)&nbsp;<BR><BR>高先生的PLAYCASE早就开始用了，除非不得已，用户有要求，否则我是不会用UML的，可能是我没有很好的理解UML的缘故。高先生的观点我很容易接受，所以PLAYCASE也用的很顺畅。 UML确实很好，由于其是面向对象的，在分析时整体把握还可以，遇到一些细节时就有点力不从心了，而往往这些细节是项目成败的关键。&#8212;&#8212;很少有软件整体把握出错的！高先生的话或许有些偏激，但您有没有具体的思考过是不是真象他说的那样&#8220;糟糕&#8221;。希望大家不要象许多老百姓那样给人&#8220;害怕新事物&#8221;的感觉。也难怪，国产软件在程序员中的地位确实比较低啊！但PLAYCASE绝对是国产中的精品，虽然她还没有长大！大家还是来多关心关心他吧，不要老是躺在别人的床上高枕无忧！&nbsp;<BR><BR>lwd2k (2002-5-15 13:20:56)&nbsp;<BR><BR>原来作者是playcase的作者，在此表示敬意。我学习使用playcase，觉的简单易用，生成代码很好，所以一直有一个版本保存。但出于商业和拓展市场的需要，用户要求的文档应符合UML标准，其实Visio功能比Rose多，但由于介绍Rose的书多，所以就用了Rose. 对于分析工具来说，做为用户，分析员，程序员之间的交流工具，只要说清楚了问题，不必看是用了什么方法。但目前来说，本人非常相信UML，所以一直想弄好它.&nbsp;<BR><BR>mach (2002-5-15 13:06:43)&nbsp;<BR><BR>使用UML可以清楚的描述业务流程，但不是用序列图，而是活动图，对于高先生的全程建模我还不太理解，粗浅的认为大概就是标准的RUP过程加上其中作为选项的业务建模吧。至于用活动图描述业务流程，这是肯定可以的，而且很方便，用活动图可以非常清楚地定义工作流，不仅可以在业务层次上抽象，包括在其后的系统分析、设计过程中，可以继续细该活动图得到业务过程的具体实现方式。从高先生文章中的论述，和其对用例图、序列图的使用方法来看，可以断定，高先生对UML还不是太了解。至于Playcase，我只是下载过，不是很理解其中应用的方法论，因此没有资格对其进行评价。&nbsp;<BR><BR>jnwen (2002-5-15 11:28:07)&nbsp;<BR><BR>我觉得关键是语言还没有对信息流很好的支持,什么面向对象的建模方法都不好,面向过程的方法最自然.&nbsp;<BR><BR>JohnYale (2002-5-15 10:40:32)&nbsp;<BR><BR>平心而论，高先生的PlayCase是比较少见的优秀产品（至少在国内），肯定花费了高先生很大的心血，但不被市场认可，我们应该考虑这是什么原因？如果说国内公司不相信国内公司的产品尚可解释的话，可是世界上那么多大公司，为什么鲜有发现PlayCase的？PlayCase使用的IDEF(具体拼法已记不清了)，在国内只发现一本书予以介绍，与连篇累牍的介绍UML的书籍形成巨大反差，难道真的是整个IT业都错了？真理往往掌握在少数人手里？&nbsp;<BR><BR>HYhuyan (2002-5-15 9:30:13)&nbsp;<BR><BR>众人皆醒我独醉 1.任何技术上的争论我们都应该支持； 2.任何带有利己目的的攻击我们都应该鄙视。&nbsp;<BR><BR>fltwt (2002-5-15 9:13:07)&nbsp;<BR><BR>只是觉得原作者还没有很好的理解UML。也没有真正的用过UML。从这篇文章中，看得出作者很推崇结构化，看不出面向对象。 UML的核心应该是建立在面向对象上的吧。用UML进行面向过程的系统设计开发，好象牛头不对马嘴。&nbsp;<BR><BR>mis98zb (2002-5-15 8:28:54)&nbsp;<BR><BR>不过RUP几大核心工作流之间的衔接、UML几大视图的演化，以及业务模型到实现模型的转化，确实很少有讲解的资料，这也使得现实中ROSE建模缺乏连贯性。&nbsp;<BR><BR>JohnYale (2002-5-14 23:47:36)&nbsp;<BR><BR>众人皆醉我独醒。高展先生为了推广 全程建模方法，几年来一直极力攻击UML, 其执着比麦克尼利有过之而无不及，在如今建模方面尚无完美方案的情况下，全程建模方法 无疑是当今世上绝无仅有的、至高至上的、无可匹敌的解决方案，是中国软件的代表，高展先生万岁万岁万万岁！！！ 2年（？）前，鄙人初次接触PlayCase, 就发现PlayCase有许多优点，但由于本人愚鲁，未能成功说服公司采用PlayCase（老板是蠢材？），致使公司现在一直使用Rose建模（边用边摸索），真是罪该万死。没有办法，市场决定一切。高展先生，您的PlayCase卖了几套了？&nbsp;<BR><BR>//www.csdn.net/develop/Article/13/13680.shtm CSDN是技术交流与传播的平台，我们鼓励技术的讨论与争论。 我们不会因为不同意别人的观点而删除任何文章，只会删除人身攻击和粗言秽语等有污视听的帖子。&nbsp;<BR><BR>ripper (2002-5-14 21:27:48)&nbsp;<BR><BR>使用UML描述业务流程很难让人放心，因为描述业务流程时产生的遗漏、不一致、不完整，同样会给项目带来灾难。这是纠缠不清的胡子工程问题点之二 看看这句话，再看看下面对比用的图，高展这老小子连顺序图是做什么的都没有搞明白就信口开河&nbsp;<BR></P>
<P align=left>讨论文章见：UML 谁的硬伤 http://www.csdn.net/develop/Article/13/13680.shtm</P><img src ="http://www.cnblogs.com/voyage/aggbug/21012.html?type=1" width = "1" height = "1" /><br/><br/>--------------------------<br/>新闻：<a href="http://news.cnblogs.com/n/48002/" target="_blank">竞争日趋激烈 微软欲借 Windows 7 扭转战局</a><br/>网站导航: <a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://dotnet.cnblogs.com" target="_blank">.NET频道</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://zzk.cnblogs.com" target="_blank">找找看</a>]]></description></item><item><title>基于ROSE的Web Service建模 </title><link>http://www.cnblogs.com/voyage/archive/2004/07/04/21011.html</link><dc:creator>voyage</dc:creator><author>voyage</author><pubDate>Sat, 03 Jul 2004 18:16:00 GMT</pubDate><guid>http://www.cnblogs.com/voyage/archive/2004/07/04/21011.html</guid><wfw:comment>http://www.cnblogs.com/voyage/comments/21011.html</wfw:comment><comments>http://www.cnblogs.com/voyage/archive/2004/07/04/21011.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnblogs.com/voyage/comments/commentRss/21011.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/voyage/services/trackbacks/21011.html</trackback:ping><description><![CDATA[<P><B><FONT size=3>基于ROSE的Web Service建模</FONT></B> </P>
<P>曹伟（来自软件工程专家网中国系统分析员协会（CSAI）　　　<BR>2003年01月02日&nbsp;<BR><BR><B>第一部分 使用UML为Web Service架构建模<BR></B><BR><BR>作者注：<BR><BR>　　此部分根据RUP的资料进行整理，作者将此部分为序言，逐步分析以UML建模的实现Web Service架构，以下的将采用以WebLogic提供服务，基于Java实现为例说明。此部分作者直接引用资料或相关图片知识产权属于RUP提供商。<BR><BR><BR>　　近年来，IT 词汇表中出现了一条新的术语，它就是"Web 应用程序"。参与业务软件系统的所有人似乎都有构建 Web 应用程序的计划，而在与业务不相关的软件方面也有很多人对此感兴趣。对于很早前就采用这种构架的许多人来说，Web 应用程序这个词象系统本身一样，已经从成功的小型 Web 站点插件发展成了强壮的 n 层应用程序。Web 应用程序可以同时为分布在世界各地的、成千上万的用户提供服务，这种情况早已司空见惯。构建 Web 应用程序是一件严肃的事情。<BR><BR><BR>　　在实际应用中，Web 应用程序这个词对不同的人而言含义略有不同。一些人认为凡是用到 Java 的都是 Web 应用程序，而另一些人则认为凡是使用 Web 服务器的都是 Web 应用程序。多数人的意见介于这两者之间。站在本文的角度，我们将 Web 应用程序大体定义为 Web 系统（Web 服务器、网络、HTTP、浏览器），在这个系统中，用户的输入（导航和数据输入）会影响到业务状态。该定义试图将 Web 应用程序确立为一个具有业务状态的软件系统，并且它的"前端"基本上是通过 Web 系统传递的。<BR><BR><BR>　　Web 应用程序的总体构架是一个客户机服务器系统，但二者有几点显著的区别。Web 应用程序最重要的优点之一在于它的部署。部署 Web 应用程序通常指的是建立网络的服务器端构件。客户端不需要特别的软件或配置。两者的另一个重大差异在于客户机和服务器通信的本质。Web 应用程序的基本通信协议是 HTTP，这是一个无连接协议，它不是为最大的通信吞吐量设计的，而是为强壮性和容错而设计的。在 Web 应用程序中，客户机和服务器的通信通常围绕 Web 页导航进行，而不是在服务器端和客户端对象之间直接通信。在一定的抽象程度上，Web 应用程序中所有的信息传递都可描述为 Web 页实体的请求和接收。通常所说的 Web 应用程序构架与动态 Web 站点的构架并无太大区别。<BR>Web 应用程序与 Web 站点，甚至是与动态 Web 站点的区别都要涉及到使用。Web 应用程序实现的是业务逻辑，它的使用改变了业务的状态（其状态为系统捕获）。这是很重要的，因为它确定了建模工作的重点。Web 应用程序执行业务逻辑，因此大多数重要的系统模型都侧重于业务逻辑和业务状态，而不是表示细节。表示很重要（否则系统将毫无用处），不过应尽量将业务和表示所关注的问题区分开。如果表示问题是重要的，甚至是复杂的，那么也需要对它们建模，但不必将它们作为业务逻辑模型的构成部分。此外，用于表示的资源更注重外观设计，而与实施业务规则关系不大。<BR><BR><BR>　　关系管理方法 (RMM) 是与 Web 系统开发有关的一种方法/表示法。RMM 是一种用于设计、构建和维护 Intranet 及 Internet Web 系统的方法。它的根本目标是降低动态数据库驱动的 Web 站点的维护成本。它提倡系统进行形象化表示，以便展开设计上的讨论。它是一个迭代式过程，包括 Web 页可视元素的分解，及这些元素与数据库实体的关联关系。RMM 是一种用于动态 Web 站点创建和维护的"完整详尽"的方案。<BR><BR><BR>　　不过，在构建 Web 应用程序方面 RMM 就显得无能为力了。Web 应用程序以业务逻辑为中心，它包括了许多实施业务逻辑的技术机制，而这些内容在 RMM 表示法中并未充分说明。客户端脚本编写、Applet 和 ActiveX 控件等技术为促进系统业务规则的执行发挥了重大作用。另外，Web 应用程序还可用作分布式对象系统的交付机制。Applet 和 ActiveX 控件可以包含那些独立于 Web 服务器，通过 RMI 或者 DCOM 与服务器端构件异步交互的构件。复杂应用程序还可利用多个浏览器实例和客户机上的框架，建立并维护自己的通信机制。&nbsp;<BR><BR><BR>　　既然所有这些机制都对系统的业务逻辑有促进作用，因此同样也需要为它们建模。而且，由于它们只表示部分业务逻辑，它们需要与其余的系统模型集成。在很多情况下，大部分业务逻辑在 Web 服务器后、服务器端的某一层执行。建模语言和表示法的选择通常要按照这一端的应用程序的需要来决定。随着 UML 作为一种正式的对象建模语言被 OMG 所接受，越来越多的系统开始用 UML 表示。许多人选择 UML 作为软件密集型系统的建模语言。于是 Web 应用程序建模的主要问题变成了："如何在应用程序的其余部分表示在特定 Web 构件中执行的业务逻辑？"答案取决于我们用 UML 在那些特定的 Web 元素和技术中表示系统业务逻辑执行的能力。<BR><BR><BR>　　本文旨在简要介绍 Web 应用程序建模存在的问题和可能的解决方案。其中着重讲述在构架上对 Web 应用程序有重要意义的构件，以及如何使用 UML 对它们进行建模。本文假定读者熟悉 UML、面向对象技术的原理和 Web 应用程序开发。文中描述的工作基于一些无偏向性的假设。&nbsp;<BR><BR><BR>　　&#183; Web 应用程序是日益复杂的软件密集型系统，它们在关键的任务中发挥着越来越重大的作用。&nbsp;<BR><BR><BR>　　&#183; 管理软件系统复杂性的一种方法是对它们进行抽象和建模。&nbsp;<BR><BR><BR>　　&#183; 软件系统一般有多个模型，每一个模型代表一个不同的观点、不同的抽象和详细级别。&nbsp;<BR><BR><BR>　　&#183; 哪个抽象和详细级别是合适的，这取决于开发流程中的工件和角色活动。&nbsp;<BR><BR><BR>　　&#183; 软件密集型系统的标准建模语言是统一建模语言 (UML)。&nbsp;<BR><BR><B>建模<BR></B><BR><BR>　　通过简化一些细节，模型可以帮助我们理解系统。如何选择建模对象对理解问题和提供解决方案有重大影响。Web 应用程序与其他软件密集型系统一样，通常由用例模型、实施模型、部署模型、安全模型等一组模型来表示。Web 系统还另有一个专用模型，即站点图。站点图是对贯穿整个系统的 Web 页和导航路线的抽象。<BR><BR><BR>　　目前采用的大部分建模方法都适用于各种 Web 应用程序模型的开发，因而无需对它们进行进一步的讨论。不过，有一个非常重要的模型，分析/设计模型 (ADM)，在尝试将 Web 页、与其相关的可执行代码和其他元素纳入模型时，确实出现了一些困难。<BR><BR><BR>　　在决定如何建模时，确定正确的抽象和详细级别对于是否能让模型用户享受到建模带来的好处至关重要。一般而言，最好对系统的工件建模。工件就是那些为生成最终产品而构建和操纵的真实生活中的实体。对 Web 服务器的内部构件建模，或者对 Web 浏览器的具体构成部分建模，这对于 Web 应用程序的设计员和构架设计师并没有什么帮助。页、页之间的链接、构成页的所有动态内容，以及在客户机上出现过的页的动态内容，对这些建模才是重要的，而且是非常重要的。设计员设计的、实施员实施的正是这些工件。页、超链接、客户机和服务器上的动态内容正是需要建模的对象。&nbsp;<BR><BR><BR>　　下一步是将这些工件映射到建模元素。例如，超链接自然映射到模型中的关联关系元素。超链接代表了从某一页到另一页的导航路径。将这种思路进行扩展，页就可以映射到模型逻辑视图中的类。如果 Web 页是模型的一个类，那么页的脚本自然就映射为这个类的操作。脚本中的所有页范围 (内的) 变量映射为类属性。Web 页可能包括一套在服务器上执行的脚本（准备页的动态内容），以及另一套完全不同的只在客户机上执行的脚本（如 JavaScript），考虑到这一点时，一个问题就出现了。在这种情况下，当我们查看模型中的 Web 页类时，我们搞不清楚在准备页的过程中哪些操作、属性甚至关系在服务器上处于活动状态，而当用户与页交互时哪些在客户机上处于活动状态。另外，Web 应用程序中传递的 Web 页最好是作为系统构件建模。简单地将 Web 页映射到 UML 类不会对我们理解系统有所帮助。<BR>UML 的创始人意识到总会存在这样的情况：初始的 UML 不足以获取一个特定领域或构架的相关语义。为了解决这个问题，他们确定了一种正式扩展机制，允许实践者扩展 UML 的语义。该机制允许定义可应用到模型元素的构造型、标注值和约束。<BR><BR><BR>　　构造型是一种修饰，允许我们为建模元素定义新的语义。标注值是可以与建模元素相关联的键值对，允许我们在建模元素?quot;标注"任何值。约束是定义模型外形的规则。它们可表示为任何形式的文本，或者用更正式的对象约束语言 (OCL) 表示。<BR><BR><BR>　　本文讨论的工作引入了为 Web 应用程序所作的一种 UML 扩展。这种扩展从整体上看超出了本文的范围，然而这里还是讨论了其中大部分的概念和解释。<BR><BR><BR>　　关于建模最后还要注意一点，一定要明确区分业务逻辑和表示逻辑。对于典型的业务应用程序而言，只有业务逻辑才应成为 ADM 的一部分。表示细节，如动画按钮、浮动帮助和其他 UI 增强方式通常不属于 ADM。如果为应用程序单独构建一个 UI 模型，则可在其中纳入表示细节。ADM 需要始终将重点放在业务问题和解决方案的表达上。在今天这个 Web 设计师的时代，对 Web 页外观的设计和实现最好由专业人员（技术绘图师）取代传统的开发人员来完成。<BR><BR><B>Web 应用程序构架<BR></B><BR><BR>　　Web 应用程序的基本构架包括浏览器、一个网络和一个 Web 服务器。浏览器向服务器请求"Web 页"。每一页都是内容和以 HTML 表达的格式指令的组合。一些页包括客户端脚本，它们由浏览器解释。这些脚本为显示的页定义了其他动态行为，而且它们经常与浏览器、页内容和页中包含的其他控件（Applet、ActiveX 控件和插件）交互。用户查看页中的内容，并与其交互。有时，用户在页的字段元素中输入信息，并提交给服务器处理。用户还可以通过超链接导航到系统的其他页，与系统进行交互。无论是哪种情况，用户都在向系统提供输入，这样就可能改变系统?quot;业务状态"。<BR><BR><BR>　　从客户端来看，Web 页总是一个采用 HTML 格式的文档。然而在服务器端，"Web 页"可表现为多种形式。在最早的 Web 应用程序中，动态 Web 页用公共网关接口 (CGI) 构建。CGI 定义了一个供脚本和已编译模块使用的接口，它们通过该接口访问与页请求一起传递的信息。在基于 CGI 的系统中，通常在 Web 服务器上配置一个特殊的目录，以便针对页请求来执行脚本。在请求 CGI 脚本时，服务器会用解译器（通常是一个 PERL shell）处理或执行相应的文件，以流的形式将输出返回给发出请求的客户机，而不仅仅是返回文件内容（就像处理 HTML 格式的文件时一样）。处理的最终结果是 HTML 格式的流，它会被返回给发出请求的客户机。业务逻辑在处理文件的同时在系统中执行。在这段时间内，它能够与服务器端资源（如数据库和中间层构件）交互。<BR><BR><BR>　　目前的 Web 服务器已经在这个基本设计上有所改进。它们现在已非常注重安全性，而且包含了一些特性：如在服务器端的客户机状态管理、事务处理集成、远程管理、资源共享等，这里只列举了其中的几种。总的来说，最新一代 Web 服务器处理的都是那些对构架设计师来说非常重要的问题，它们关系到任务至上、可缩放和强壮的应用程序。<BR>根据 CGI 脚本的作用，可以将现今的 Web 服务器分为三大类：脚本页、编译页，以及两者的混合体。在第一类中，客户机浏览器能请求的每一个 Web 页在 Web 服务器的文件系统中都用一个脚本文件来表示。这个文件一般是 HTML 和其他一些脚本语言的混合。对页发出请求后，Web 服务器委派一个可识别该页的引擎对其进行处理，最终结果以格式为 HTML 的流的形式返回给发出请求的客户机。Microsoft 的 Active Server Pages、Java Server Pages 和 Cold Fusion 都属于这一类。<BR><BR><BR>　　在第二类中，Web 服务器加载并执行一个二进制构件。这个构件和脚本页一样，有权访问与页请求一起发送的所有信息（表单字段值和参数）。经过编译的代码利用请求的详细信息，并通常要访问服务器端的资源，以生成 HTML 流并返回给客户机。编译页包含的功能往往比脚本页大，尽管并未明确这一规律。通过向编译页请求传递不同的参数，可获得不同的功能。任何一个编译构件实际都可以包含整个目录脚本页的所有功能。Microsoft 的 ISAPI 和 Netscape 的 NSAPI 就是表示这种构架类型的技术。<BR><BR><BR>　　第三类指的是那些一旦发出请求即进行编译的脚本页，以后的所有请求都使用编译过的页。只有最初页的内容谋淞耍靡巢呕峤辛硪淮伪嘁搿Ｕ饫嘁辰橛诹榛畹慕疟疽澈透咝У谋嘁胍持洹?&nbsp;<BR><BR><BR><B>Web 页建模<BR></B><BR><BR>　　Web 页，不管是脚本页还是编译页，都一对一地映射到 UML 中的构件。构件是系统的"物理"可更换部件。模型的实施视图（构件视图）描述了系统的构件及它们之间的关系。在 Web 应用程序中，这个视图描述了系统的所有 Web 页及它们彼此之间的关系（如超链接）。在一定程度上，Web 系统的构件图就相当于站点图。<BR><BR><BR>　　由于构件仅仅代表了接口的物理打包方式，它们并不适用于对页内部的协作关系建模。这一抽象级别仍需要成为模型的组成部分，而且对设计员和实施员而言极其重要。为引入正题，我们可以说每个 Web 页在模型的设计视图（逻辑视图）中都是一个 UML 类，它与其他页的关系（关联关系）即代表了超链接。但如果考虑到任何 Web 页都可能既代表一组只存在于服务器上的功能和协作，同时又代表只存在于客户机上的一组完全不同的功能和协作，那么这种抽象就不成立了。举例来说，使用动态 HTML（客户端脚本）作为部分输出的所有服务器 Web 脚本页都是这样的页。对这个问题的直接反应可能就是为类中的每个属性或操作设计原型，指明它是在服务器端还是在客户端有效。至此，运用模型倒让问题变得复杂了，而我们的初衷是要简化问题。<BR><BR><BR>　　一个更好的解决方案是"分别考虑"。从逻辑上讲，服务器端的 Web 页行为与客户端是完全不同的。在服务器上执行时，页有权访问服务器端资源（中间层构件、数据库、文件系统等），即与这些资源具有某些关系。同一页（或者是该页的 HTML 流输出）在客户端有完全不同的行为和关系集。在客户端，脚本页与浏览器本身（通过文档对象模型，即 DOM），以及该页指定的所有 Java Applet、ActiveX 控件或插件相关。对于认真的设计员而言，页还可能与客户机上在另一个 HTML 框架或浏览器实例出现的其他"活动"页相关。<BR><BR><BR>　　通过分别考虑，我们就可以用一个类为 Web 页的服务器端建模，用另一个类为客户端建模。我们采用 UML 扩展机制为两者分别定义构造型和图标?quot;server page" 和 "client page"，以此来区分两者。UML 中的构造型允许我们为建模元素定义新的语义。已指定构造型的类在 UML 图中可用定制图标表示，或者仅仅用 ("") 之间的构造型名称说明。图标对概述图很有用，在概述图中，最好使用简单的标记对显示出的类属性和操作进行标注。<BR><BR><BR>　　对于 Web 页，构造型指出了类是客户机或服务器上 Web 页逻辑行为的抽象。两种抽象通过两者之间的定向关系相互关联关系。这种关联关系的构造型为："build"，因为可以说服务器页构建了客户机页（图 1）。每个动态 Web 页（即页内容在运行时才能决定的页）都用一个服务器页构建。每个客户机页至多只能用一个服务器页构建，而一个服务器页可以构建多个客户机页。<BR><BR><BR>　　Web 页之间通过超链接建立公共关系。Web 应用程序中的超链接代表系统的一条导航路径。这种关系在模型中用一个构造型为 "link" 的关联关系表示。关联关系总是从客户机页出发，指向另一个客户机页或服务器页。<BR><BR><BR>　　超链接作为 Web 页请求在系统中实施，Web 页作为实施视图中的构件来建模。指向客户机页的链接关联关系大体等同于指向构建该客户机页的服务器页的链接关联关系。这是因为链接实际是一个页请求，不是上述两种类抽象。由于 Web 页构件同时实现两种页抽象，因此指向由该页构件实现的任何类的链接都是等同的。<BR><BR><BR>　　标注值用于定义随链接请求一起传递的参数。"link" 关联关系标注值"Parameters"是一个参数名（和可选值）的列表，处理请求的服务器页要用到它。在图 2 中，SearchResults 页包含数目可变的指向 GetProduct 服务器页的超链接 (0..*),每一个链接都有一个不同的 productId 参数值。GetProduct 页用于构建 productId 参数所指定产品的 ProductDetail 页。<BR><BR><BR><IMG height=173 src="http://www.sawin.com.cn/doc/SD/UML/roseweb0.gif" width=368><BR><BR>图 1. 服务器页构建客户机页<BR><BR><BR><IMG height=341 src="http://www.sawin.com.cn/doc/SD/UML/roseweb1.gif" width=452> </P>
<P>图 2. 使用超链接参数<BR><BR><BR>　　使用这些构造型简化了对页脚本和关系的建模。"server page" 类的操作变为页服务器端脚本的函数，它的属性变为页范围变量（页函数可对其进行全局访问）。"client page" 类的操作和属性也同样变为在客户机上可见的函数和变量。将服务器端页和客户端页作为不同的类考虑，其最大好处在于明确页与系统的其他类之间的关系。客户机页根据它们与客户端资源的关系进行建模。客户端资源有：DOM、Java Applet、 ActiveX 控件和插件（图 3）。服务器页根据它们与服务器端资源的关系进行建模。服务器端资源有：中间层构件、数据库存取构件、服务器操作系统等(图 4)。<BR><BR><BR></P>
<P align=center><IMG height=523 src="http://www.sawin.com.cn/doc/SD/UML/roseweb2.gif" width=522></P>
<P><BR>图 3. 客户机协作<BR><BR></P>
<P align=center><IMG height=405 src="http://www.sawin.com.cn/doc/SD/UML/roseweb3.gif" width=578></P>
<P><BR>图 4. 服务器协作<BR><BR><BR>　　用类构造型对 Web 页的逻辑行为建模的最大优势在于：页与服务器端构件的协作可以基本上用其他任意服务器端协作所使用的方式来表示。"server page" 仅仅是参与系统业务逻辑的另一个类。上升到概念的层次来讲，服务器页一般扮演控制者的角色，协调必要的业务对象活动，以满足浏览器页请求所提出的业务目标。<BR><BR><BR>　　客户端的协作更复杂一些。部分原因可归咎于可用技术的多样性。即使是最简单的客户机页，至少也是一个既包含内容又包含表示信息的 HTML 文档。浏览器利用页的格式指令提供 HTML 页，有时还带有单独的样式表。在逻辑模型中，这一关系可用客户机页对构造型为 "Style Sheet" 的类的依赖关系来表示。样式表基本上是一个表示问题，通常不包含在 ADM 内。<BR><BR><BR><B>表单<BR></B><BR><BR>　　Web 页的基本数据输入机制是表单。表单在 HTML 文档中用 &lt;form&gt; 标记来定义。每个表单都会指明它自身要提交到哪一页。表单包括许多输入元素，它们全用 HTML 标记表示。最常用的标记是 &lt;input&gt;、&lt;select&gt; 和 &lt;textarea&gt;。输入标记多种多样，它可以是一个文本字段、复选框、单选按钮、按钮、图像、隐藏字段，还有其他一些不太常见的类型。对表单建模要使用另一个类构造型："Form"。"Form" 没有操作，这是因为可能在 &lt;form&gt; 标记中定义的所有操作实际上都为客户机页所有。表单的输入元素都是 "Form" 类的建有构造型的属性。"Form" 可以与作为输入控件的 Applet 或者 ActiveX 控件有关系。表单还与服务器页有关系，服务器页即是处理表单提交内容的页。这种关系的构造型为 "submit"。由于表单完全包含在 HTML 文档内，所以它们在 UML 图中用一种强聚合关系形式表示。图 5 是一个简单的购物车页，它定义了一个表单，显示了与要处理表单的服务器页的提交关系。<BR><BR></P>
<P align=center><IMG height=401 src="http://www.sawin.com.cn/doc/SD/UML/roseweb4.gif" width=594></P>
<P><BR>图 5. 表单提交给服务器页<BR><BR>　　在图 5 中，以 "JavaScript" 为构造型的类是一个代表购物车中的商品项的对象。对于可有多种输入可能的字段，它们的表单属性说明中使用了数组语法。在这个例子中，这意味着购物车可以有零到多个项，每个项都有一个 Qty、AllowSubs、Cost 和 Total &lt;input&gt; 元素。<BR><BR><BR>　　由于客户机页内的所有活动都用 JavaScript 执行，而 JavaScript 是一种无类型的语言，所以为这些属性指定的数据类型只是为了便于实施员辨认。在 JavaScript 中执行或作为 HTML 输入标记执行时，该类型将被忽略。这对函数参数也成立，函数参数是模型的一部分，尽管本图并未明确显示。<BR><BR><BR><B>框架<BR></B><BR><BR>　　HTML 框架从刚被引入 Web 站点和 Web 应用程序时就引发了极大的争论，且意见呈两极分化。框架允许在某一时刻有多个页激活，并对用户可见。目前最常用的浏览器还具备一组最新的特性，允许用户机器上同时打开多个浏览器实例。使用动态 HTML 脚本，这些页中的构件可以彼此交互。客户端复杂交互的潜力非常大，使得对此建模的需要变得更大。<BR><BR><BR>　　是否在应用程序中采用框架或多个浏览器实例，这要由构架设计师决定。如果决定采用，客户端行为的模型就需要在 ADM 中表示出来，原因如上所述。要对框架的使用进行建模，我们又定义了两种类构造型："frameset" 和关联关系构造型 "targeted link"。框架集类代表一个容器对象，直接映射到 HTML&lt;frameset&gt; 标记。它包含客户机页和目标。目标类是一个被其他客户机页引用的指定框架或浏览器实例。目标链接关联关系是指向另一个页的超链接，但它要在特定目标中才能提供。在图 6 的示例中，浏览器显示了一个使用两个框架的常用大纲视图。一个框架根据目标命名为 Content，另一个框架只包含一个客户机页。这一客户机页框架包含书的目录 (TOC)。该页的超链接是有目标的，因此超链接指向的内容在 Content 框架中显示。得到的效果就是页左侧的一个静态目录，以及页右侧的书中每一章的内容。<B><BR></B></P><img src ="http://www.cnblogs.com/voyage/aggbug/21011.html?type=1" width = "1" height = "1" /><br/><br/>--------------------------<br/>新闻：<a href="http://news.cnblogs.com/n/48002/" target="_blank">竞争日趋激烈 微软欲借 Windows 7 扭转战局</a><br/>网站导航: <a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://dotnet.cnblogs.com" target="_blank">.NET频道</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://zzk.cnblogs.com" target="_blank">找找看</a>]]></description></item><item><title>建模动力：UML2.0使模型驱动的开发更加容易</title><link>http://www.cnblogs.com/voyage/archive/2004/07/04/21010.html</link><dc:creator>voyage</dc:creator><author>voyage</author><pubDate>Sat, 03 Jul 2004 18:14:00 GMT</pubDate><guid>http://www.cnblogs.com/voyage/archive/2004/07/04/21010.html</guid><wfw:comment>http://www.cnblogs.com/voyage/comments/21010.html</wfw:comment><comments>http://www.cnblogs.com/voyage/archive/2004/07/04/21010.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnblogs.com/voyage/comments/commentRss/21010.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/voyage/services/trackbacks/21010.html</trackback:ping><description><![CDATA[<STRONG>建模动力：UML2.0使模型驱动的开发更加容易&nbsp;<BR><BR></STRONG>Louis Chua　　&nbsp;<BR><BR>UML规约的新版本将很快提交给OMG，新的改动希望能够简化模型驱动的开发。<BR><BR>Rational公司新加坡分部的高级软件工程专家，Mark Hermeling认为：UML2.0根据工业界使用UML1.x的经验作了相应改进，目的就是为了帮助简化模型驱动的开发。<BR><BR>UML的目前版本是1.4,它提供了方便开发团队在分析设计、需求管理等活动中进行交流的整套工具，以及一个软件开发生命周期模型。<BR><BR>有人将UML描述为交流的符号集，这意味着可以直接写在纸上或者画在白板上。但大多数用户还是选择使用工具，目前业界的领导是Rational，它和其它的工具提供商一起提供各种UML产品。<BR><BR>1996年，UML刚诞生的时候，广受欢迎。在UML之前，建模方法非常多，这大大阻碍了基于模型的设计，而UML实现了建模语言一定程度上的统一。<BR><BR>进行面向对象设计的时候，第一步就要对现实世界进行建模，UML正是为之定义的一套标准符号，它由三种面向对象的分析设计方法发展并整合而来：Grady Booch 描述对象及其相互关系的方法、James Rumbaugh的对象建模技术(OMT) 以及 Ivar Jacobson的方法，在Ivar Jacobson的方法中引入了use case方法的使用。<BR><BR>经过多年的发展，在Rational 公司的Booch、Rumbaugh、Jacobson 三友以及其它专家的努力下，UML中还融入了很多其它的思想，现在，UML已经成为OMG认可的标准。<BR><BR>尽管UML只是帮助参与开发的所有人员对模型进行交流的一套符号系统。但Martin Fowler在其著作《UML Distilled》中指出，UML是由描述开发过程和有关模型的使用的方法论发展而来的。尽管目前没有被广泛接受的统一过程，UML的使用者使用的方法实际上都非常相似。UML规约中有关建模的概念是对象、类、关联、职责、活动、接口、use case、包、顺序、协作和状态。<BR><BR>在使用当前版本进行UML模型驱动的架构时，使用者发现还缺少一些支持，如bug修复等，UML2.0中将增加这部分内容，它将成为适用于企业建模和数据建模的庞大而灵活的符号语言。在UML2.0中，将对语意部分进行增强，这一点可以帮助UML模型更好地生成代码，以得到更加实用的模型。在即将推出的版本中，还将包括增强的组件处理、对商业过程模型的支持，并更好地支持元数据交换。这些努力都是为了使UML作为一种胜过大多数文本语言的高层次的语言，能够生成代码和进行反工程，甚至直接生成某些可执行的UML模型。<BR><BR>目前，在各种工具之间进行模型交换时，只能保存非图形化的信息，而象绘制的各种图、尺寸、坐标这样的内容都会丢失。在UML2.0中，将提供保留图形信息的能力。<BR><BR>来自Rational公司的Hermeling认为，工程师与开发人员将越来越多地看到对建模的需求。他认为，对于一个较大的开发团队来说，需要有一个可视化的模型以保证所有人员都能理解总体的设计思路，建模的需求是显而易见的。<BR><BR>利用业务过程建模，应用UML可以得到业务的可视化模型，其作用类似于建筑工程中的结构图。这个可视化模型可以使你在构造整个软件系统之前，就可以理解并预知设计的一些关键特性，判断设计是否可行。事实上，除了软件工程，在众多工程领域中，建模都是非常关键的规避风险的技术。<BR><BR>但是，在Fowler眼里，软件工程和其它工程是不同的。<BR><BR>首先，对建筑工程来说，工程师一般都有多年的经验并且对所用的各种工程符号了如指掌，而UML的设计可能在纸上画出来看着很好，真正编程时却会发现很多问题。另外，在建筑工程上，关键设计都是可以经过数学分析进行验证的；而在UML设计中，类似的手段只有同行评审，虽然有一定作用，却并不能避免错误的发生。<BR><BR>另外，在成本比例方面，软件设计和其它领域的工程也是截然不同的。举修桥的例子来说吧，设计成本可能也就占全部成本的 10％,而在软件设计中，这个比率是50％。<BR><BR>UML最早是由Rational公司提出的，但已经被很多公司使用，这里面最重要的就是OMG。公众对UML的接受刺激了以模型为中心的开发，OMG提供了支持这种开发的一系列标准的框架MDA（Model-Driven Architecture）。MDA的关键特点就是软件开发的重点和输出不再是程序，而是各种模型，开发人员的工作是不断拓展模型，只有到了最后阶段才会考虑将其实现。<BR><BR>OMG认为，利用MDA可以得到更好的&#8220;高层抽象&#8221;设计框架，更好地得到针对今天各种语言的&#8220;通用化&#8221;代码。和正在酝酿之中的基于XMI的数据交换一样，基于MDA的数据交换方法将给开发商和用户双方带来好处。<BR>XMI（XML Metadata Interchange）试图通过XML语言为程序员和其它用户提供一种交换元数据信息的标准途径。XMI希望能够帮助使用各种语言和开发工具的UML开发人员自由地交换数据模型，另外，XML也可以用于数据仓库信息的交互；最重要的是，XMI制定了描述各种元数据定义的统一标准，并要求跨行业和跨操作环境的用户使用一致的方法读取数据。<BR><BR>今年6月，包含OMG MDA标准，促进模型交互的UML基础库修改版已经正式提交讨论。参与讨论的包括用户熟悉的很多开发商，包括I-Logix, Oracle, Rational, Telelogic and Computer Associates等等。<BR>UML2.0中还将包括对组件建模的改进。近几年来，随着J2EE和微软的.NET技术的出现，组件技术得到很大发展。这方面，UML2.0中将考虑如下内容：如何更好地描述组件描述的语意以及构建.NET和企业JavaBeans的专门模块。<BR><BR>Jim Duggan ，artner公司的副总裁和研发总监，认为UML2.0中要处理的首要问题就是保证标准的扩展性，他认为现行的标准中扩展机制定义得不够，导致各开发商使用了不同的扩展方法。另外，还必须提供对组件开发、面向服务的框架以及web services的支持。<BR><BR>有人提倡，UML的发展应该是向下兼容的，要保证过去基于UML1.x的用户和工具开发商所做的努力不会全部作废。UML2.0中应该提高精确度，可以选择加入少量的一些新特性，要避免导致&#8220;语言膨胀&#8221;的困境。而现在有一个不妙的苗头： UML将变得越来越大，而在最初，OMG声称的目标本来是简单化的。<BR><BR>Gartner公司的Duggan认为，&#8220;新的规约正在变得越来越复杂，变得非常大，难以管理、理解和实施。标准委员会曾经说过将要把物理模型和逻辑模型分开。但是，一旦规约复杂化了，要做到这一点就不大可能，而且规约本身也开始失去作用。&#8221;<BR><BR>Alistair Cockburn，Humans and Technology的顾问，在他的论文中表达了同样的意思。&#8220;在软件开发中把人也当成了非线性的、第一位的组件&#8221;，Cockburn认为那些重量级的开发方法中试图为一切建模，这是导致成功率不高的重要原因。他认为在软件开发中人是最重要的，在设计符号中把人当成一个组件，就是最大的失败之源。<BR><BR>其它公司，如Telelogic也在致力于利用UML2.0从图形化的用户模型中自动生成代码。Telelogic在新加坡和亚洲其它地区创建了开发中心，力图提供帮助从概念模型转化到组件的软件。Scott Raskin（如图），Telelogic公司亚太地区总裁，认为亚洲是这方面增长最快的地区。&#8220;UML允许组织从计划到嵌入式系统实现的全部生命周期实现自动化&#8221;但是，对于有些程序员而言，并不需要UML，他们完成的代码中通常都很难找到相似的地方，对他们来说，模型是多余的。<BR><BR>Gartner公司的Dugguan警告说，&#8220;要记住，UML只是一种符号，并不是什么方法论&#8221;。但事实上，几乎所有的面向对象分析与设计（OOAD）工具和业务模型都是使用的UML。Dugguan指出，根据Gartner公司的估计，在所有项目中，使用OO A&amp;D方法论的大概有10%到12%，和过去使用CASE工具的峰值数值几乎相同。Dugguan认为这个数字还会继续增加到15%到20%。在数据建模领域，IDEF符号还在广泛使用，但UML也开始进入。<BR><BR>Dugguan认为，设计工具的总体使用率还是很低，在项目中使用设计驱动开发方式的大概有10%，通常是那些对质量和持久性要求很高的项目。而数据建模工具在项目中使用的比率大概是35%，大多数情况下都是由DBA使用。<BR><BR>尽管UML可以和白板一起使用，但它还是复杂了些。Gartner公司认为有以下原因导致了UML的低使用率。首先，在小的短期项目和开发周期中根本不用设计，都是采取的快速开发和演进。Dugguan说，&#8220;根本不需要最佳实践，能用的实践就够了。&#8221;第二个原因是大多数遗留的程序都是面向过程的，不需要UML或者什么工具。但他又加了一句：&#8220;新的事件驱动和对象驱动的程序开发技术可以从UML工具中受益，新的开发人员很多都学过这些符号，而且会用相关工具&#8221;。<BR><BR>事实上，UML正在将工具开发商们凝聚在一起，很多公司都参与了UML2.0的修改过程。除了Rational之外， Microsoft、Sun、IBM、Oracle、Borland、Telelogic等公司也都是UML协会的成员。<BR><BR>（2002/10，UMLChina摘自computerworld，袁峰 译，仅供学习交流，不得转载用于商业用途）<img src ="http://www.cnblogs.com/voyage/aggbug/21010.html?type=1" width = "1" height = "1" /><br/><br/>--------------------------<br/>新闻：<a href="http://news.cnblogs.com/n/48002/" target="_blank">竞争日趋激烈 微软欲借 Windows 7 扭转战局</a><br/>网站导航: <a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://dotnet.cnblogs.com" target="_blank">.NET频道</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://zzk.cnblogs.com" target="_blank">找找看</a>]]></description></item></channel></rss>