﻿<?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>BlogJava-kapok-随笔分类-UML与RUP</title><link>http://www.blogjava.net/kapok/category/1658.html</link><description>垃圾桶,嘿嘿，我藏的这么深你们还能找到啊，真牛！</description><language>zh-cn</language><lastBuildDate>Tue, 27 Feb 2007 10:24:46 GMT</lastBuildDate><pubDate>Tue, 27 Feb 2007 10:24:46 GMT</pubDate><ttl>60</ttl><item><title>架构蓝图--软件架构 "4+1" 视图模型</title><link>http://www.blogjava.net/kapok/archive/2005/09/20/13574.html</link><dc:creator>笨笨</dc:creator><author>笨笨</author><pubDate>Tue, 20 Sep 2005 13:14:00 GMT</pubDate><guid>http://www.blogjava.net/kapok/archive/2005/09/20/13574.html</guid><wfw:comment>http://www.blogjava.net/kapok/comments/13574.html</wfw:comment><comments>http://www.blogjava.net/kapok/archive/2005/09/20/13574.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/kapok/comments/commentRss/13574.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/kapok/services/trackbacks/13574.html</trackback:ping><description><![CDATA[<A href="http://www-128.ibm.com/developerworks/cn/rational/r-4p1-view/">http://www-128.ibm.com/developerworks/cn/rational/r-4p1-view/</A>
<TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR vAlign=top>
<TD colSpan=5><IMG height=15 alt="" src="http://www.ibm.com/i/c.gif" width=5 border=0></TD></TR>
<TR vAlign=top>
<TD width=2><IMG height=1 alt="" src="http://www.ibm.com/i/c.gif" width=2 border=0></TD>
<TD><SPAN class=atitle>架构蓝图--软件架构 "4+1" 视图模型</SPAN></TD>
<TD width=8><IMG height=1 alt="" src="http://www.ibm.com/i/c.gif" width=8 border=0></TD>
<TD align=right width=180><NOBR>
<TABLE cellSpacing=0 cellPadding=0>
<TBODY>
<TR vAlign=top>
<TD align=right></TD>
<TD width=46>
<FORM action=https://www-130.ibm.com/developerworks/secure/email-it.jsp><INPUT type=hidden value="本文基于多个并发视图的使用情况来说明描述软件密集型系统架构的模型。使用多重视图允许独立地处理各'风险承担人'：最终用户、开发人员、系统工程师、项目经理等所关注的问题，并且能够独立地处理功能性和非功能性需求。本文分别对五种视图进行了描述，并同时给出了捕获每种视图的表示方法。这些视图使用以架构为中心的、场景驱动以及迭代开发过程来进行设计。" name=body><INPUT type=hidden value='架构蓝图--软件架构 "4+1" 视图模型' name=subject><INPUT type=hidden value=cn name=lang><INPUT type=image src="http://www-128.ibm.com/developerworks/cn/i/icon-email.gif" border=0 name=email></FORM></TD></TR></TBODY></TABLE></NOBR></TD>
<TD width=6><IMG height=1 alt="" src="http://www.ibm.com/i/c.gif" width=6 border=0></TD></TR>
<TR vAlign=top>
<TD bgColor=#000000 colSpan=5><IMG height=1 alt="" src="http://www.ibm.com/i/c.gif" width=100 border=0></TD></TR>
<TR vAlign=top>
<TD bgColor=#ffffff colSpan=5><IMG height=8 alt="" src="http://www.ibm.com/i/c.gif" width=100 border=0></TD></TR></TBODY></TABLE>
<TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR vAlign=top>
<TD width=5><IMG height=1 alt="" src="http://www.ibm.com/i/c.gif" width=5 border=0></TD>
<TD width="100%">
<TABLE cellSpacing=0 cellPadding=0 width=168 align=right border=0>
<TBODY>
<TR>
<TD width=8><IMG height=21 alt="" src="http://www.ibm.com/i/c.gif" width=5></TD>
<TD width=160>
<TABLE cellSpacing=0 cellPadding=0 width=160 border=0>
<TBODY>
<TR>
<TD width=160 bgColor=#000000 height=1><IMG height=1 alt="" src="http://www.ibm.com/i/c.gif" width=160></TD></TR>
<TR>
<TD align=middle background=/developerworks/cn/i/bg-gold.gif height=5><B>内容：</B></TD></TR>
<TR>
<TD width=160 bgColor=#666666 height=1><IMG height=1 alt="" src="http://www.ibm.com/i/c.gif" width=160></TD></TR>
<TR>
<TD>
<TABLE cellSpacing=0 cellPadding=0 width=160 border=0>
<TBODY>
<TR>
<TD><A href="http://www-128.ibm.com/developerworks/cn/rational/r-4p1-view/#N10043">引言</A></TD></TR>
<TR>
<TD height=1><IMG height=5 alt="" src="http://www.ibm.com/i/c.gif" width=160></TD></TR>
<TR>
<TD><A href="http://www-128.ibm.com/developerworks/cn/rational/r-4p1-view/#N10050">架构模型</A></TD></TR>
<TR>
<TD height=1><IMG height=5 alt="" src="http://www.ibm.com/i/c.gif" width=160></TD></TR>
<TR>
<TD><A href="http://www-128.ibm.com/developerworks/cn/rational/r-4p1-view/#N1034D">结束语 </A></TD></TR>
<TR>
<TD height=1><IMG height=5 alt="" src="http://www.ibm.com/i/c.gif" width=160></TD></TR>
<TR>
<TD><A href="http://www-128.ibm.com/developerworks/cn/rational/r-4p1-view/#N10368">致谢</A></TD></TR>
<TR>
<TD height=1><IMG height=5 alt="" src="http://www.ibm.com/i/c.gif" width=160></TD></TR><!--Standard links for every dw-article-->
<TR>
<TD><A href="http://www-128.ibm.com/developerworks/cn/rational/r-4p1-view/#resources">参考资料 </A></TD></TR>
<TR>
<TD height=1><IMG height=5 alt="" src="http://www.ibm.com/i/c.gif" width=160></TD></TR>
<TR>
<TD><A href="http://www-128.ibm.com/developerworks/cn/rational/r-4p1-view/#author1">关于作者</A></TD></TR>
<TR>
<TD height=1><IMG height=5 alt="" src="http://www.ibm.com/i/c.gif" width=160></TD></TR>
<TR>
<TD><A href="http://www-128.ibm.com/developerworks/cn/rational/r-4p1-view/#rating">对本文的评价</A></TD></TR>
<TR>
<TD><IMG height=10 alt="" src="http://www.ibm.com/i/c.gif" width=160></TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE>
<TABLE cellSpacing=0 cellPadding=0 width=160 border=0>
<TBODY>
<TR>
<TD width=160 bgColor=#000000 height=1><IMG height=1 alt="" src="http://www.ibm.com/i/c.gif" width=160></TD></TR>
<TR>
<TD align=middle background=/developerworks/cn/i/bg-gold.gif height=5><B>订阅:</B></TD></TR>
<TR>
<TD width=160 bgColor=#666666 height=1><IMG height=1 alt="" src="http://www.ibm.com/i/c.gif" width=160></TD></TR>
<TR>
<TD>
<TABLE cellSpacing=0 cellPadding=1 width=160 border=0>
<TBODY>
<TR>
<TD><A href="http://www-128.ibm.com/developerworks/cn/newsletter/">developerWorks 时事通讯</A></TD></TR>
<TR>
<TD height=1><IMG height=5 alt="" src="http://www.ibm.com/i/c.gif" width=160></TD></TR>
<TR>
<TD><A href="http://www-128.ibm.com/developerworks/cn/rational/rationaledge/">The Rational Edge</A></TD></TR>
<TR>
<TD height=1><IMG height=5 alt="" src="http://www.ibm.com/i/c.gif" width=160></TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE>
<TABLE cellSpacing=0 cellPadding=0 width=160 border=0>
<TBODY>
<TR>
<TD width=150 bgColor=#000000 colSpan=2 height=2><IMG height=2 alt="" src="http://www.ibm.com/i/c.gif" width=160></TD></TR>
<TR>
<TD width=150 bgColor=#ffffff colSpan=2 height=2><IMG height=2 alt="" src="http://www.ibm.com/i/c.gif" width=160></TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE>
<P><A href="http://www-128.ibm.com/developerworks/cn/rational/r-4p1-view/#author1"><NAME>Philippe Kruchten</NAME></A><BR>高级技术专员<BR>2005 年 1 月 </P>
<BLOCKQUOTE>本文基于多个并发视图的使用情况来说明描述软件密集型系统架构的模型。使用多重视图允许独立地处理各"风险承担人"：最终用户、开发人员、系统工程师、项目经理等所关注的问题，并且能够独立地处理功能性和非功能性需求。本文分别对五种视图进行了描述，并同时给出了捕获每种视图的表示方法。这些视图使用以架构为中心的、场景驱动以及迭代开发过程来进行设计。</BLOCKQUOTE>
<P><A name=N10043><SPAN class=atitle2>引言</SPAN></A><BR>我们已经看到在许多文章和书籍中，作者欲使用单张视图来捕捉所有的系统架构要点。通过仔细地观察这些图例中的方框和箭头，不难发现作者努力地在单一视图中表达超过其表达限度的蓝图。方框是代表运行的程序吗？或者是代表源代码的程序块吗？或是物理计算机吗？或仅仅是逻辑功能的分组吗？箭头是表示编译时的依赖关系吗？或者是控制流吗？或是数据流吗？通常它代表了许多事物。是否架构只需要单个的架构样式？有时软件架构的缺陷源于过早地划分软件或过分的强调软件开发的单个方面：数据工程、运行效率、开发策略和团队组织等。有时架构并不能解决所有"客户"（或者说"风险承担人"，USC 的命名）所关注的问题。许多作者都提及了这个问题：Garlan &amp; Shaw <A href="http://www-128.ibm.com/developerworks/cn/rational/r-4p1-view/#resources" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">1</A>、CMU 的 Abowd &amp; Allen、SEI 的 Clements。作为补充，我们建议使用多个并发的视图来组织软件架构的描述，每个视图仅用来描述一个特定的所关注的方面的集合。 </P>
<P><A name=N10050><SPAN class=atitle2>架构模型</SPAN></A><BR>软件架构用来处理软件高层次结构的设计和实施。它以精心选择的形式将若干结构元素进行装配，从而满足系统主要功能和性能需求，并满足其他非功能性需求，如可靠性、可伸缩性、可移植性和可用性。Perry 和 Wolfe 使用一个精确的公式来表达，该公式由 Boehm 做了进一步修改： </P>
<P>软件架构 ＝ {元素，形式，关系/约束}</P>
<P>软件架构涉及到抽象、分解和组合、风格和美学。我们用由多个视图或视角组成的模型来描述它。为了最终处理大型的、富有挑战性的架构，该模型包含五个主要的视图（请对照图 1）：</P>
<UL xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<LI>逻辑视图（Logical View），设计的对象模型（使用面向对象的设计方法时）。 
<LI>过程视图（Process View），捕捉设计的并发和同步特征。 
<LI>物理视图（Physical View），描述了软件到硬件的映射，反映了分布式特性。 
<LI>开发视图（Development View），描述了在开发环境中软件的静态组织结构。 </LI></UL>
<P>架构的描述，即所做的各种决定，可以围绕着这四个视图来组织，然后由一些用例 （use cases）或场景(scenarios)来说明，从而形成了第五个视图。正如将看到的，实际上软件架构部分从这些场景演进而来，将在下文中讨论。</P>
<P><A name=N10073><B>图 1 － "4＋1"视图模型</B></A><BR><IMG height=322 alt='图 1 － "4＋1"视图模型' src="http://www-128.ibm.com/developerworks/cn/rational/r-4p1-view/images/image002.jpg" width=456 border=0 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> </P>
<P>我们在每个视图上均独立地应用 Perry &amp; Wolf 的公式，即定义一个所使用的元素集合（组件、容器、连接符），捕获工作形式和模式，并且捕获关系及约束，将架构与某些需求连接起来。每种视图使用自身所特有的表示法－蓝图（blueprint）来描述，并且架构师可以对每种视图选用特定的架构风格（architectural style），从而允许系统中多种风格并存。</P>
<P>我们将轮流的观察这五种视图，展现各个视图的目标：即视图的所关注的问题，相应的架构蓝图的标记方式，描述和管理蓝图的工具。并以非常简单的形式从 PABX 的设计中，从我们在Alcatel 商业系统（Alcatel Business System）上所做的工作中，以及从航空运输控制系统（Air Traffic Control system）中引出一些例子―旨在描述一下视图的特定及其标记的方式，而不是定义这些系统的架构。 </P>
<P>"4+1"视图模型具有相当的"普遍性"，因此可以使用其他的标注方法和工具，也可以采用其他的设计方法，特别是对于逻辑和过程的分解。但文中指出的这些方法都已经成功的在实践中运用过。 </P>
<P><A name=N1008C><SPAN class=atitle3>逻辑结构</SPAN></A><BR>面向对象的分解</P>
<P>逻辑架构主要支持功能性需求――即在为用户提供服务方面系统所应该提供的功能。系统分解为一系列的关键抽象，（大多数）来自于问题域，表现为对象或对象类的形式。它们采用抽象、封装和继承的原理。分解并不仅仅是为了功能分析，而且用来识别遍布系统各个部分的通用机制和设计元素。我们使用 Rational/Booch 方法来表示逻辑架构，借助于类图和类模板的手段 <A href="http://www-128.ibm.com/developerworks/cn/rational/r-4p1-view/#resources" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">4</A>。类图用来显示一个类的集合和它们的逻辑关系：关联、使用、组合、继承等等。相似的类可以划分成类集合。类模板关注于单个类，它们强调主要的类操作，并且识别关键的对象特征。如果需要定义对象的内部行为，则使用状态转换图或状态图来完成。公共机制或服务可以在类功能 （class utilities）中定义。对于数据驱动程度高的应用程序，可以使用其他形式的逻辑视图，例如 E-R 图，来代替面向对象的方法（OO approach）。 </P>
<P>逻辑视图的表示法</P>
<P>逻辑视图的标记方法来自 Booch 标记法4。当仅考虑具有架构意义的条目时，这种表示法相当简单。特别是在这种设计级别上，大量的修饰作用不大。我们使用 Rational Rose? 来支持逻辑架构的设计。</P>
<P><A name=N100A4><B>图 2 － 逻辑蓝图的表示法</B></A><BR><IMG height=309 alt="图 2 － 逻辑蓝图的表示法" src="http://www-128.ibm.com/developerworks/cn/rational/r-4p1-view/images/image004.jpg" width=444 border=0 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> </P>
<P>逻辑视图的风格 </P>
<P>逻辑视图的风格采用面向对象的风格，其主要的设计准则是试图在整个系统中保持单一的、一致的对象模型，避免就每个场合或过程产生草率的类和机制的技术说明。</P>
<P>逻辑结构蓝图的样例</P>
<P>图 3 显示了 Télic PABX 架构中主要的类。 </P>
<P><A name=N100C2><B>图 3 － a. Télic PABX 的逻辑蓝图 b.空中交通系统的蓝图</B></A><BR><IMG height=269 alt="图 3 － a. Télic PABX 的逻辑蓝图 b.空中交通系统的蓝图" src="http://www-128.ibm.com/developerworks/cn/rational/r-4p1-view/images/image006.jpg" width=468 border=0 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> </P>
<P>PABX 建立终端间的通信连接。终端可以是电话设备、中继线（例如，连接到中央办公室）、连接线（PABX 专线到 PABX 线)、电话专线、数据线、ISDN 等等。不同的线路由不同的接口卡提供支持。线路 controller 对象的职责是在接口卡上对所有的信号进行解码和注入，在特定于接口卡的信号与一致性的小型事件集合之间进行相互转换：开始、停止、数字化等。controller 对象同时承载所有的实时约束。该类派生出许多子类以满足不同的接口类型。terminal 对象的责任是维持终端的状态，代表线路协调各项服务。例如，它使用 numbering plan 服务来解释拨号。conversation 代表了会话中的一系列终端 。conversation 使用了Translation Service(目录、逻辑物理映射、路由),以及建立终端之间语音路径的Connection Service 。</P>
<P>对于一个包含了大量的具有架构重要意义的类的、更大的系统来说，图 3 b 描述了空中交通管理系统的顶层类图，包含 8 个类的种类（例如，类的分组）。</P>
<P><A name=N100D8><SPAN class=atitle3>进程架构</SPAN></A><BR>过程分解 </P>
<P>进程架构考虑一些非功能性的需求，如性能和可用性。它解决并发性、分布性、系统完整性、容错性的问题，以及逻辑视图的主要抽象如何与进程结构相配合在一起－即在哪个控制线程上，对象的操作被实际执行。</P>
<P>进程架构可以在几种层次的抽象上进行描述，每个层次针对不同的问题。在最高的层次上，进程架构可以视为一组独立执行的通信程序（叫作"processes"）的逻辑网络，它们分布在整个一组硬件资源上，这些资源通过 LAN 或者 WAN 连接起来。多个逻辑网络可能同时并存，共享相同的物理资源。例如，独立的逻辑网络可能用于支持离线系统与在线系统的分离，或者支持软件的模拟版本和测试版本的共存。</P>
<P>进程是构成可执行单元任务的分组。进程代表了可以进行策略控制过程架构的层次（即：开始、恢复、重新配置及关闭）。另外，进程可以就处理负载的分布式增强或可用性的提高而不断地被重复。</P>
<P>软件被划分为一系列单独的任务。任务是独立的控制线程，可以在处理节点上单独地被调度。</P>
<P>接着，我们可以区别主要任务、次要任务。主要任务是可以唯一处理的架构元素；次要任务是由于实施原因而引入的局部附加任务（周期性活动、缓冲、暂停等等）。它们可以作为 Ada Task 或轻量线程来实施。主要任务的通讯途径是良好定义的交互任务通信机制：基于消息的同步或异步通信服务、远程过程调用、事件广播等。次要任务则以会见或共享内存来通信。在同一过程或处理节点上，主要任务不应对它们的分配做出任何假定。</P>
<P>消息流、过程负载可以基于过程蓝图来进行评估，同样可以使用哑负载来实现"中空"的进程架构，并测量在目标系统上的性能。正如 Filarey et al. 在他的 Eurocontrol 实验中描述的那样。</P>
<P>进程视图的表示法</P>
<P>我们所使用的进程视图的表示方法是从Booch最初为 Ada 任务推荐的表示方法扩展而来。同样，用来所使用的表示法关注在架构上具有重要意义的元素。(图 4) </P>
<P><A name=N100FB><B>图 4 － 过程蓝图表示法</B></A><BR><IMG height=270 alt="图 4 － 过程蓝图表示法" src="http://www-128.ibm.com/developerworks/cn/rational/r-4p1-view/images/image008.jpg" width=492 border=0 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> </P>
<P>我们曾使用来自 TRW 的 Universal Network Architechure Services（UNAS0） 产品来构建并实施过程和任务集合（包扩它们的冗余），使它们融入过程的网络中。UNAS 包含 Software Architect Lifecycle Environment(SALE)工具，它支持上述表示方法。SALE 允许以图形的形式来描述进程架构，包括对可能的交互任务通信路径的规格说明，正是从这些路径中自动生成对应的 Ada 或 C++ 源代码。使用该方法来指定和实施进程架构的优点是易于进行修改而不会对应用软件造成太多的影响。</P>
<P>进程视图的风格 </P>
<P>许多风格可以适用于进程视图。例如采用 Garlan 和 Shaw 的分类法1,我们可以得到管道和过滤器（Pipes and filters）,或客户端/服务器，以及各种多个客户端/单个服务器和多个客户端/多个服务器的变体。对于更加复杂的系统,可以采用类似于 K.Birman 所描述的ISIS系统中进程组方法以及其它的标注方法和工具。</P>
<P>进程蓝图的例子</P>
<P><A name=N10119><B>图 5 － Télic PABX 的过程蓝图（部分）</B></A><BR><IMG height=367 alt="图 5 － Télic PABX 的过程蓝图（部分）" src="http://www-128.ibm.com/developerworks/cn/rational/r-4p1-view/images/image010.jpg" width=576 border=0 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> </P>
<P>所有的终端由单个的 Termal process 处理，其中 Termal process 由输入队列中的消息进行驱动。Controller 对象在组成控制过程三个任务之中的一项任务上执行：Low cycle rate task 扫描所有的非活动终端(200 ms)，将 High cycle rate task(10 ms)扫描清单中的终端激活，其中 High cycle rate task 检测任何重要的状态变化，将它们传递给 Main controller task，由它来对状态的变更进行解释,并通过向对应的终端发送消息来通信。这里 Controller 过程中的通信通过共享内存来实现。</P>
<P><A name=N1012C><SPAN class=atitle3>开发架构</SPAN></A><BR>子系统分解</P>
<P>开发架构关注软件开发环境下实际模块的组织。软件打包成小的程序块（程序库或子系统），它们可以由一位或几位开发人员来开发。子系统可以组织成分层结构，每个层为上一层提供良好定义的接口。</P>
<P>系统的开发架构用模块和子系统图来表达，显示了"输出"和"输入"关系。完整的开发架构只有当所有软件元素被识别后才能加以描述。但是，可以列出控制开发架构的规则：分块、分组和可见性。</P>
<P>大部分情况下，开发架构考虑的内部需求与以下几项因素有关：开发难度、软件管理、重用性和通用性及由工具集、编程语言所带来的限制。开发架构视图是各种活动的基础，如：需求分配、团队工作的分配（或团队机构）、成本评估和计划、项目进度的监控、软件重用性、移植性和安全性。它是建立产品线的基础。</P>
<P>开发蓝图的表示方法</P>
<P>同样，使用 Booch 方法的变形，仅考虑具有架构意义的项。</P>
<P><A name=N10146><B>图 5 － 开发蓝图表示方法</B></A><BR><IMG height=252 alt="图 5 － 开发蓝图表示方法" src="http://www-128.ibm.com/developerworks/cn/rational/r-4p1-view/images/image012.jpg" width=492 border=0 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> </P>
<P>来自 Rational 的 Apex 开发环境支持开发架构的定义和实现、和前文描述的分层策略，以及设计规则的实施。Rational Rose 可以在模块和子系统层次上绘制开发蓝图，并支持开发源代码(Ada、C++）进程的正向和反向工程。</P>
<P><A name=N10159><SPAN class=atitle3>开发视图的风格</SPAN></A><BR>我们推荐使用分层（layered）的风格，定义 4 到 6 个子系统层。每层均具有良好定义的职责。设计规则是某层子系统依赖同一层或低一层的子系统，从而最大程度地减少了具有复杂模块依赖关系的网络的开发量，得到层次式的简单策略。</P>
<P><A name=N10164><B>图 6 － Hughes 空中交通系统（HATS）的 5 个层</B></A><BR><IMG height=312 alt="图 6 － Hughes 空中交通系统（HATS）的 5 个层" src="http://www-128.ibm.com/developerworks/cn/rational/r-4p1-view/images/image014.jpg" width=528 border=0 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> </P>
<P>开发架构的例子 </P>
<P>图 6 代表了加拿大的 Hughes Aircraft 开发的空中交通控制系统（Air Traffic Control system）产品线的 5 个分层开发组织结构。这是和图 3 b 描述的逻辑架构相对应的开发架构。</P>
<P>第一层 和第二层组成了独立于域的覆盖整个产品线的分布式基础设施，并保护其免受不同硬件平台、操作系统或市售产品（如数据库管理系统）的影响。第三层为该基础设施增加了 ATC 框架，形成一个特定领域的软件架构（domain-specific software architecture）。使用该框架,可以在第四层上构建一个功能选择板。层次 5 则非常依赖于客户和产品,包含了大多数用户接口和外部系统接口。72 个子系统分布于 5 个层次上，每层包含了 10 至 50 个模块，并可以在其他蓝图上表示。</P>
<P><A name=N1017D><SPAN class=atitle3>物理架构</SPAN></A><BR>软件至硬件的映射</P>
<P>物理架构主要关注系统非功能性的需求，如可用性、可靠性（容错性），性能（吞吐量）和可伸缩性。软件在计算机网络或处理节点上运行，被识别的各种元素（网络、过程、任务和对象），需要被映射至不同的节点；我们希望使用不同的物理配置：一些用于开发和测试，另外一些则用于不同地点和不同客户的部署。因此软件至节点的映射需要高度的灵活性及对源代码产生最小的影响。</P>
<P>物理蓝图的表示法 </P>
<P>大型系统中的物理蓝图会变得非常混乱，所以它们可以采用多种形式，有或者没有来自进程视图的映射均可。</P>
<P><A name=N10191><B>图 7 － 物理蓝图的表示法</B></A><BR><IMG height=142 alt="图 7 － 物理蓝图的表示法" src="http://www-128.ibm.com/developerworks/cn/rational/r-4p1-view/images/image016.jpg" width=316 border=0 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> </P>
<P>TRW 的 UNAS 提供了数据驱动方法将过程架构映射至物理架构，该方法允许大量的映射的变更而无需修改源代码。</P>
<P>物理蓝图的示例</P>
<P><A name=N101A9><B>图 8 － PABX 的物理蓝图</B></A><BR><IMG height=208 alt="图 8 － PABX 的物理蓝图" src="http://www-128.ibm.com/developerworks/cn/rational/r-4p1-view/images/image018.jpg" width=424 border=0 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> </P>
<P>图 8 显示了大型 PABX 可能的硬件配置,而图 9 和图 10 显示了两种不同物理架构上的进程映射，分别对应一个小型和一个大型 PABX。C、F 和 K 是三种不同容量的计算机，支持三种不同的运行要求。</P>
<P><A name=N101BE><B>图 9 － 带有过程分配的小型 PABX 物理架构</B></A><BR><IMG height=153 alt="图 9 － 带有过程分配的小型 PABX 物理架构" src="http://www-128.ibm.com/developerworks/cn/rational/r-4p1-view/images/image020.jpg" width=162 border=0 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> </P>
<P><A name=N101D0><B>图10－显示了过程分配的大型PABX物理蓝图</B></A><BR><IMG height=459 alt=图10－显示了过程分配的大型PABX物理蓝图 src="http://www-128.ibm.com/developerworks/cn/rational/r-4p1-view/images/image022.jpg" width=480 border=0 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> </P>
<P><A name=N101E0><SPAN class=atitle3>场景</SPAN></A><BR>综合所有的视图 </P>
<P>四种视图的元素通过数量比较少的一组重要场景（更常见的是用例）进行无缝协同工作，我们为场景描述相应的脚本（对象之间和过程之间的交互序列）。正如 Rubin 和 Goldberg 所描述的那样6。</P>
<P>在某种意义上场景是最重要的需求抽象，它们的设计使用对象场景图和对象交互图来表示4。 </P>
<P>该视图是其他视图的冗余（因此"＋1"），但它起到了两个作用：</P>
<UL xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<LI>作为一项驱动因素来发现架构设计过程中的架构元素，这一点将在下文中讨论。 
<LI>作为架构设计结束后的一项验证和说明功能，既以视图的角度来说明又作为架构原型测试的出发点。 </LI></UL>
<P>场景的表示法 </P>
<P>场景表示法与组件逻辑视图非常相似（请对照图 2），但它使用过程视图的连接符来表示对象之间的交互（请对照图 4），注意对象实例使用实线来表达。至于逻辑蓝图，我们使用 Rational Rose 来捕获并管理对象场景。</P>
<P>场景的例子</P>
<P>图 11 显示了小型 PABX 的场景片段。相应的脚本是：</P>
<P>1. Joe的电话控制器检测和校验摘机状态的变换,并发送消息唤醒相应的终端对象。</P>
<P>2. 终端分配一些资源，并要求控制器发出拨号音。</P>
<P>3. 控制器接受拨号并传递给终端。</P>
<P>4. 终端使用拨号方案来分析数字流。</P>
<P>5. 有效的数字序列被键入,终端开始会话。</P>
<P><A name=N10218><B>图 11 － 本地呼叫的初期场景――阶段选择</B></A><BR><IMG height=198 alt="图 11 － 本地呼叫的初期场景――阶段选择" src="http://www-128.ibm.com/developerworks/cn/rational/r-4p1-view/images/image024.jpg" width=480 border=0 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> </P>
<P><A name=N10228><SPAN class=atitle3>视图之间的对应性 </SPAN></A><BR>各种视图并不是完全是正交的或独立的。视图的元素根据某种设计规则和启发式方法与其他视图中的元素相关联。</P>
<P>从逻辑视图到过程视图 </P>
<P>我们发现逻辑视架构有几项重要特性：</P>
<UL xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<LI>自主性：对象是主动的、被动的还是被保护的？ 
<UL>
<LI>主动对象享有调用其他对象或其自身操作的主动权，并且当其他对象对其进行调用时，具有对其自身操作的完全控制权。 
<LI>被动对象不能主动调用任何操作，对其他对象调用自身的操作没有控制。 
<LI>被保护对象不能主动调用任何操作。但对自身的操作有一定的控制功能。 </LI></UL>
<LI>持久化：对象是暂时的还是持久化的？它们是否会导致过程或处理器的终止？ 
<LI>依赖性：对象的存在或持久化是否依赖于另一个对象？ 
<LI>分布性：对象的状态或操作是否能被物理架构中的许多节点所访问？或是被进程架构中的几个进程所访问？ </LI></UL>
<P>在逻辑视图中，我们认为每个对象均是主动的，具有潜在的"并发性"，即与其他对象具有"平行的"行为，我们并不考虑所要达到的确切并发程度。因此，逻辑结构所考虑的仅是需求的功能性方面。</P>
<P>然而，当我们定义进程架构时，由于巨大的开销，为每个对象实施各自的控制线程（例如，Unix 进程或 Ada 任务），在目前的技术状况下是不现实的。此外，如果对象是并发的，那么必须以某种抽象形式来调用它们的操作。</P>
<P>另一方面，由于以下几种原因需要多个控制线程。</P>
<UL xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<LI>为了快速响应某类外部触发，包括与时间相关的事件。 
<LI>为了在一个节点中利用多个 CPU，或者在一个分布式系统中利用多个节点。 
<LI>为了提高 CPU 的利用率，在某些控制线程被挂起，等待其他活动结束的时候（例如，访问外部对象其他活动对象时），为其他的活动分配 CPU。 
<LI>为了划分活动的优先级（提高潜在的响应能力）。 
<LI>为了支持系统的可伸缩性（借助于共享负载的其他过程）。 
<LI>为了在软件的不同领域分离关注点。 
<LI>为了提高系统的可用性（通过 Backup 过程）。 </LI></UL>
<P>我们同时使用两种策略来决定并发的程度和定义所需的过程集合。考虑一系列潜在的物理目标架构。以下两种形式我们可以任选其一：</P>
<UL xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<LI>从内至外: <BR><BR>由逻辑架构开始：定义代理任务，该任务将控制一个类的多个活动对象的单个线程进行多元化处理；同一代理任务还执行持久化处理那些依赖于一个主动对象的对象；需要相互进行操作的几个类或仅需要少量处理的类共享单个代理。这种聚合会一直进行，直到我们将过程减少到合理的较少数量，而仍允许分布性和对物理资源的使用。 
<LI>由外至内: <BR><BR>从物理结构开始：识别系统的外部触发；定义处理触发的客户过程和仅提供服务（而非初始化它们）的服务器进程；使用数据完整性和问题的串行化（serialization）约束来定义正确的服务器设置，并且为客户机与服务器代理分配对象；识别出必须分布哪些对象。 </LI></UL>
<P>其结果是将类（和它们的对象）映射至一个任务集合和进程架构中的进程。通常，活动类具有代理任务，也存在一些变形：对于给定的类，使用多个代理以提高吞吐量，或者多个类映射至单个代理，因为它们的操作并不是频繁地被调用，或者是为了保证执行序列。</P>
<P>注意这并不是产生最佳过程架构的线性的、决定性的进程；它需要若干个迭代来得到可接受的折衷。还存在许多其他方法，例如 Birman 等人5 或 Witt 等人7提出的方法。 确切的实施映射的方法不在本文的讨论范围，但我们以一个小的例子来说明一下。</P>
<P>图 12 显示了一个小的类集合如何从假想的空中交通控制系统映射至进程。</P>
<P>flight 类映射至一个 flight 代理集合：有许多航班等待处理，外部触发的频率很高，响应时间很关键，负载必须分布于多个 CPU。并且，航班处理的持久化和分布性方面都取决于 flight server，为了满足可用性，还是使用 flight server 的一台备份服务器。</P>
<P>航班的 profile 和 clearance 总是从属于某个航班,尽管它们是复杂的类,但它们共享 flight 类的进程。航班分布于若干其他进程，特别是对于显示和外部接口。</P>
<P>sectorization 类，为 controller 的权限分配建立了空域划分。由于完整性约束，仅能被一个代理处理，但可以与 flight 类共享服务器过程：更新得并不频繁。</P>
<P>location 和 arispace 及其他的静态航空信息是受到保护的对象，在几个类中共享，很少被更新；它们被映射至各自的服务器，分布于其他过程。</P>
<P><A name=N1029E><B>图 12 － 从逻辑视图到过程视图的映射</B></A><BR><IMG height=471 alt="图 12 － 从逻辑视图到过程视图的映射" src="http://www-128.ibm.com/developerworks/cn/rational/r-4p1-view/images/image026.jpg" width=540 border=0 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> </P>
<P>从逻辑视图到开发视图 </P>
<P>类通常作为一个模块来实现，例如 Ada 包中可视部分的一个类型。密切相关的类（类的种类）的集合组合到子系统中。子系统的定义必须考虑额外的约束，如团队组织、期望的代码规模（通常每个子系统为 5 K 或 20 K SLOC）、可重用性和通用性的程度以及严格的分层依据（可视性问题），发布策略和配置管理。所以，通常最后得到的不是与逻辑视图逐一对应的视图。</P>
<P>逻辑视图和开发视图非常接近，但具有不同的关注点。我们发现项目规模越大，视图间的差距也越大。例如，如果比较图 3 b 和图 6，则会发现并不存在逐一对应的类的不同种类到层的映射。而如果我们考虑类的种类的"外部接口"－网关种类时，它的实现遍布若干层：通讯协议在第 1 层或以下的层，通用网关机制在第 2 层，而特定的网关在第 5 层子系统。</P>
<P>从进程视图到物理视图 </P>
<P>进程和进程组以不同的测试和部署配置映射至可用的物理硬件。Birman 在 ISIS 项目中描述了详细的映射模式5。</P>
<P>场景主要以所使用类的形式与逻辑视图相关联；而与进程视图的关联则是考虑了一个或多个控制线程的、对象间的交互形式。</P>
<P><A name=N102C0><SPAN class=atitle3>模型的剪裁</SPAN></A><BR>并不是所有的软件架构都需要"4＋1"视图。无用的视图可以从架构描述中省略，比如：只有一个处理器，则可以省略物理视图；而如果仅有一个进程或程序，则可以省略过程视图。 对于非常小型的系统，甚至可能逻辑视图与开发视图非常相似，而不需要分开的描述。场景对于所有的情况均适用。</P>
<P><A name=N102C9><SPAN class=atitle3>迭代过程 </SPAN></A><BR>Witt 等人为设计和架构指出了 4 个阶段：勾画草图、组织、具体化和优化，分成了 12 个步骤7。他们还指出需要某种程度的反向工程。而我们认为对于大型的项目，该方法太"线性化"了。在 4 个阶段的末尾，可用于验证架构的内容太少。我们提倡一种更具有迭代性质的方法，即架构先被原形化、测试、估量、分析，然后在一系列的迭代过程中被细化。该方法除了减少与架构相关的风险之外，对于项目而言还有其他优点：团队合作、培训，加深对架构的理解，深入程序和工具等等（此处提及的是演进的原形，逐渐发展成为系统，而不是一次性的试验性的原形）。这种迭代方法还能够使需求被细化、成熟化并能够被更好地理解。</P>
<P>场景驱动（scenario-driven）的方法</P>
<P>系统大多数关键的功能以场景（或 use cases）的形式被捕获。关键意味着：最重要的功能，系统存在的理由，或使用频率最高的功能，或体现了必须减轻的一些重要的技术风险。</P>
<P>开始阶段:</P>
<UL xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<LI>基于风险和重要性为某次迭代选择一些场景。场景可能被归纳为对若干用户需求的抽象。 
<LI>形成"稻草人式的架构"。然后对场景进行"描述"，以识别主要的抽象（类、机制、过程、子系统），如 Rubin 与 Goldberg6 所指出的 ―― 分解成为序列对（对象、操作）。 
<LI>所发现的架构元素被分布到 4 个蓝图中：逻辑蓝图、进程蓝图、开发蓝图和物理蓝图。 
<LI>然后实施、测试、度量该架构，这项分析可能检测到一些缺点或潜在的增强要求。 
<LI>捕获经验教训。 </LI></UL>
<P>循环阶段:</P>
<P>下一个迭代过程开始进行：</P>
<UL xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<LI>重新评估风险， 
<LI>扩展考虑的场景选择板。 
<LI>选择能减轻风险或提高结构覆盖的额外的少量场景， </LI></UL>
<P>然后:</P>
<UL xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<LI>试着在原先的架构中描述这些场景。 
<LI>发现额外的架构元素，或有时还需要找出适应这些场景所需的重要架构变更。 
<LI>更新4个主要视图：逻辑视图、进程视图、开发视图和物理视图。 
<LI>根据变更修订现有的场景。 
<LI>升级实现工具（架构原型）来支持新的、扩展了的场景集合。 
<LI>测试。如果可能的话，在实际的目标环境和负载下进行测试。 
<LI>然后评审这五个视图来检测简洁性、可重用性和通用性的潜在问题。 
<LI>更新设计准则和基本原理。 
<LI>捕获经验教训。 </LI></UL>
<P>终止循环</P>
<P>为了实际的系统，初始的架构原型需要进行演进 。较好的情况是在经过 2 次或 3 次迭代之后，结构变得稳定：主要的抽象都已被找到。子系统和过程都已经完成，以及所有的接口都已经实现。接下来则是软件设计的范畴，这个阶段可能也会用到相似的方法和过程。</P>
<P>这些迭代过程的持续时间参差不齐，原因在于：所实施项目的规模，参与项目人员的数量、他们对本领域和方法的熟悉程度，以及该系统和开发组织的熟悉程度等等。因而较小的项目迭代过程可能持续 2-3 周（例如，10 K SLOC），而大型的项目可能为 6-9 个月（例如，700 K SLOC）。 </P>
<P><A name=N10329><SPAN class=atitle3>架构的文档化</SPAN></A><BR>架构设计中产生的文档可以归结为两种：</P>
<UL xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<LI>软件架构文档，其结构遵循"4+1"视图（请对照图 13，一个典型的提纲） 
<LI>软件设计准则，捕获了最重要的设计决策。这些决策必须被遵守，以保持系统架构的完整性。 
<P><A name=N1033B><B>图 13 － 软件架构文档提纲</B></A><BR><IMG height=360 alt="图 13 － 软件架构文档提纲" src="http://www-128.ibm.com/developerworks/cn/rational/r-4p1-view/images/image027.gif" width=174 border=0> </P></LI></UL>
<P><A name=N1034D><SPAN class=atitle2>结束语 </SPAN></A><BR>无论是否经过一次本地定制的和技术上的调整，"4＋1"视图都能在许多大型项目中成功运用。事实上，它允许不同的"风险承担人"找出他们就软件架构所关心的问题。系统工程师首先接触物理视图，然后转向进程视图；最终用户、顾客、数据分析专家从逻辑视图入手；项目经理、软件配置人员则从开发视图来看待"4＋1"视图。在 Rational 和其他地方，提出并讨论了其他系列视图，例如 Meszaros(BNR)、Hofmeister。Nord 和 Soni(Siemenms)、Emery 和 Hilliard（Mitre），但我们发现其他视图通常可以归入我们所描述的 4 个视图中的一个。例如 Cost&amp;Schedule 视图可以归入开发视图，将一个数据视图归入一个逻辑视图，以及将一个执行视图归入进程视图和物理视图的组合。</P>
<P><A name=N10358><B>表 1 － "4＋1"视图模型一览表</B></A><BR><IMG height=255 alt='表 1 － "4＋1"视图模型一览表' src="http://www-128.ibm.com/developerworks/cn/rational/r-4p1-view/images/table.gif" width=601 border=0 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> </P>
<P><A name=N10368><SPAN class=atitle2>致谢</SPAN></A><BR>"4+1" 视图的诞生要归功于在Rational、加拿大的 Hughes Aircraft、Alcatel 以及其他地方工作的同事。笔者特别感谢下面这些人的贡献： Ch. Thompson、A. Bell、M.Devlin、G. Booch、W. Royce、J. Marasco、R. Reitman、V. Ohnjec、E. Schonberg。</P>
<P><A name=resources><SPAN class=atitle2>参考资料 </SPAN></A>
<OL xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<LI>您可以参阅本文在 developerWorks 全球站点上的 <A href="http://www.software.ibm.com/ibmdl/pub/software/rational/web/whitepapers/2003/Pbk4p1.pdf" target=_blank>英文原文</A>。 
<LI>D. Garlan &amp; M. Shaw, "An Introduction to Software Architecture," Advances in Software Engineering and Knowledge Engineering, Vol. 1, World Scientific Publishing Co. (1993). 
<LI>D. E. Perry &amp; A. L. Wolf, "Foundations for the Study of Software Architecture," ACM Software Engineering Notes, 17, 4, October 1992, 40-52. 
<LI>Ph. Kruchten &amp; Ch. Thompson, "An Object-Oriented, Distributed Architecture for Large Scale Ada Systems," Proceedings of the TRI-Ada '94 Conference, Baltimore, November 6-11, 1994, ACM,p.262-271. 
<LI>G. Booch: Object-Oriented Analysis and Design with Applications, 2nd. edition, Benjamin-Cummings Pub. Co., Redwood City, California, 1993, 589p. 
<LI>K. P. Birman, and R. Van Renesse, Reliable Distributed Computing with the Isis Toolkit, IEEE Computer Society Press, Los Alamitos CA, 1994. 
<LI>K. Rubin &amp; A. Goldberg, "Object Behavior Analysis," CACM, 35, 9 (Sept. 1992) 48-62 
<LI>B. I. Witt, F. T. Baker and E. W. Merritt, Software Architecture and Design-Principles, Models, and Methods, Van Nostrand Reinhold, New-York (1994) 324p. 
<LI>D. Garlan (ed.), Proceedings of the First Internal Workshop on Architectures for Software Systems, CMU-CS-TR-95-151, CMU, Pittsburgh, 1995. </LI></OL>
<P></P>
<TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD><A name=author1></A><SPAN class=atitle2>关于作者</SPAN><BR>Philippe Kruchten </TD></TR></TBODY></TABLE><BR clear=all><IMG height=10 alt="" src="http://www.ibm.com/i/c.gif" width=100 border=0></TD></TR></TBODY></TABLE><img src ="http://www.blogjava.net/kapok/aggbug/13574.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/kapok/" target="_blank">笨笨</a> 2005-09-20 21:14 <a href="http://www.blogjava.net/kapok/archive/2005/09/20/13574.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Profile,Stereotype,TaggedValue与OCL漫谈</title><link>http://www.blogjava.net/kapok/archive/2005/09/12/12784.html</link><dc:creator>笨笨</dc:creator><author>笨笨</author><pubDate>Mon, 12 Sep 2005 14:13:00 GMT</pubDate><guid>http://www.blogjava.net/kapok/archive/2005/09/12/12784.html</guid><wfw:comment>http://www.blogjava.net/kapok/comments/12784.html</wfw:comment><comments>http://www.blogjava.net/kapok/archive/2005/09/12/12784.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/kapok/comments/commentRss/12784.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/kapok/services/trackbacks/12784.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: Profile,Stereotype,TaggedValue与OCL漫谈http://www.blogjava.net/wxb_nudt/archive/2005/09/12/12718.html起因事情的起因是由于我需要在一篇文章中使用一个UML Profile for Design Pattern，就是在上一篇blog中提到的那个Profile。但是当我使用OCL来描述一些约束时，...&nbsp;&nbsp;<a href='http://www.blogjava.net/kapok/archive/2005/09/12/12784.html'>阅读全文</a><img src ="http://www.blogjava.net/kapok/aggbug/12784.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/kapok/" target="_blank">笨笨</a> 2005-09-12 22:13 <a href="http://www.blogjava.net/kapok/archive/2005/09/12/12784.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title> 把用例应用到实时系统中的实践 </title><link>http://www.blogjava.net/kapok/archive/2005/09/07/12275.html</link><dc:creator>笨笨</dc:creator><author>笨笨</author><pubDate>Tue, 06 Sep 2005 16:23:00 GMT</pubDate><guid>http://www.blogjava.net/kapok/archive/2005/09/07/12275.html</guid><wfw:comment>http://www.blogjava.net/kapok/comments/12275.html</wfw:comment><comments>http://www.blogjava.net/kapok/archive/2005/09/07/12275.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/kapok/comments/commentRss/12275.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/kapok/services/trackbacks/12275.html</trackback:ping><description><![CDATA[<TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR vAlign=top>
<TD width=2></TD>
<TD><SPAN class=atitle>把用例应用到实时系统中的实践<BR><A href="http://www-128.ibm.com/developerworks/cn/rational/r-uc-rt/">http://www-128.ibm.com/developerworks/cn/rational/r-uc-rt/</A></SPAN></TD>
<TD width=8><IMG height=1 alt="" src="http://www.ibm.com/i/c.gif" width=8 border=0></TD>
<TD align=right width=180><NOBR>
<TABLE cellSpacing=0 cellPadding=0>
<TBODY>
<TR vAlign=top>
<TD align=right></TD>
<TD width=46>
<FORM action=https://www-130.ibm.com/developerworks/secure/email-it.jsp><INPUT type=hidden value=本文介绍了一个真实的范例，然后讨论了在把用例用来定义实时系统的规格时遇到的问题，以及相关的经验学习。 name=body><INPUT type=hidden value=把用例应用到实时系统中的实践 name=subject><INPUT type=hidden value=cn name=lang><INPUT type=image src="http://www-128.ibm.com/developerworks/cn/i/icon-email.gif" border=0 name=email></FORM></TD></TR></TBODY></TABLE></NOBR></TD>
<TD width=6><IMG height=1 alt="" src="http://www.ibm.com/i/c.gif" width=6 border=0></TD></TR>
<TR vAlign=top>
<TD bgColor=#000000 colSpan=5><IMG height=1 alt="" src="http://www.ibm.com/i/c.gif" width=100 border=0></TD></TR>
<TR vAlign=top>
<TD bgColor=#ffffff colSpan=5><IMG height=8 alt="" src="http://www.ibm.com/i/c.gif" width=100 border=0></TD></TR></TBODY></TABLE>
<TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR vAlign=top>
<TD width=5><IMG height=1 alt="" src="http://www.ibm.com/i/c.gif" width=5 border=0></TD>
<TD width="100%">
<TABLE cellSpacing=0 cellPadding=0 width=168 align=right border=0>
<TBODY>
<TR>
<TD width=8><IMG height=21 alt="" src="http://www.ibm.com/i/c.gif" width=5></TD>
<TD width=160>
<TABLE cellSpacing=0 cellPadding=0 width=160 border=0>
<TBODY>
<TR>
<TD width=160 bgColor=#000000 height=1><IMG height=1 alt="" src="http://www.ibm.com/i/c.gif" width=160></TD></TR>
<TR>
<TD align=middle background=/developerworks/cn/i/bg-gold.gif height=5><B>内容：</B></TD></TR>
<TR>
<TD width=160 bgColor=#666666 height=1><IMG height=1 alt="" src="http://www.ibm.com/i/c.gif" width=160></TD></TR>
<TR>
<TD>
<TABLE cellSpacing=0 cellPadding=0 width=160 border=0>
<TBODY>
<TR>
<TD><A href="http://www-128.ibm.com/developerworks/cn/rational/r-uc-rt/#N10038">概述</A></TD></TR>
<TR>
<TD height=1><IMG height=5 alt="" src="http://www.ibm.com/i/c.gif" width=160></TD></TR>
<TR>
<TD><A href="http://www-128.ibm.com/developerworks/cn/rational/r-uc-rt/#N1004C">为什么我们需要这篇文章？</A></TD></TR>
<TR>
<TD height=1><IMG height=5 alt="" src="http://www.ibm.com/i/c.gif" width=160></TD></TR>
<TR>
<TD><A href="http://www-128.ibm.com/developerworks/cn/rational/r-uc-rt/#N1005A">什么是实时系统的特点？</A></TD></TR>
<TR>
<TD height=1><IMG height=5 alt="" src="http://www.ibm.com/i/c.gif" width=160></TD></TR>
<TR>
<TD><A href="http://www-128.ibm.com/developerworks/cn/rational/r-uc-rt/#N1006B">产品传送系统(PT)项目</A></TD></TR>
<TR>
<TD height=1><IMG height=5 alt="" src="http://www.ibm.com/i/c.gif" width=160></TD></TR>
<TR>
<TD><A href="http://www-128.ibm.com/developerworks/cn/rational/r-uc-rt/#N10099">PT系统的用例模型</A></TD></TR>
<TR>
<TD height=1><IMG height=5 alt="" src="http://www.ibm.com/i/c.gif" width=160></TD></TR>
<TR>
<TD><A href="http://www-128.ibm.com/developerworks/cn/rational/r-uc-rt/#N10161">结构化用例</A></TD></TR>
<TR>
<TD height=1><IMG height=5 alt="" src="http://www.ibm.com/i/c.gif" width=160></TD></TR>
<TR>
<TD><A href="http://www-128.ibm.com/developerworks/cn/rational/r-uc-rt/#N10190">补充需求</A></TD></TR>
<TR>
<TD height=1><IMG height=5 alt="" src="http://www.ibm.com/i/c.gif" width=160></TD></TR>
<TR>
<TD><A href="http://www-128.ibm.com/developerworks/cn/rational/r-uc-rt/#N101D7">用例的益处</A></TD></TR>
<TR>
<TD height=1><IMG height=5 alt="" src="http://www.ibm.com/i/c.gif" width=160></TD></TR>
<TR>
<TD><A href="http://www-128.ibm.com/developerworks/cn/rational/r-uc-rt/#N101F7">用例贯穿整个项目</A></TD></TR>
<TR>
<TD height=1><IMG height=5 alt="" src="http://www.ibm.com/i/c.gif" width=160></TD></TR>
<TR>
<TD><A href="http://www-128.ibm.com/developerworks/cn/rational/r-uc-rt/#N1026C">经验学习</A></TD></TR>
<TR>
<TD height=1><IMG height=5 alt="" src="http://www.ibm.com/i/c.gif" width=160></TD></TR>
<TR>
<TD><A href="http://www-128.ibm.com/developerworks/cn/rational/r-uc-rt/#N102BC">总结</A></TD></TR>
<TR>
<TD height=1><IMG height=5 alt="" src="http://www.ibm.com/i/c.gif" width=160></TD></TR><!--Standard links for every dw-article-->
<TR>
<TD><A href="http://www-128.ibm.com/developerworks/cn/rational/r-uc-rt/#rating">对本文的评价</A></TD></TR>
<TR>
<TD><IMG height=10 alt="" src="http://www.ibm.com/i/c.gif" width=160></TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE>
<TABLE cellSpacing=0 cellPadding=0 width=160 border=0>
<TBODY>
<TR>
<TD width=160 bgColor=#000000 height=1><IMG height=1 alt="" src="http://www.ibm.com/i/c.gif" width=160></TD></TR>
<TR>
<TD align=middle background=/developerworks/cn/i/bg-gold.gif height=5><B>订阅:</B></TD></TR>
<TR>
<TD width=160 bgColor=#666666 height=1><IMG height=1 alt="" src="http://www.ibm.com/i/c.gif" width=160></TD></TR>
<TR>
<TD>
<TABLE cellSpacing=0 cellPadding=1 width=160 border=0>
<TBODY>
<TR>
<TD><A href="http://www-128.ibm.com/developerworks/cn/newsletter/">developerWorks 时事通讯</A></TD></TR>
<TR>
<TD height=1><IMG height=5 alt="" src="http://www.ibm.com/i/c.gif" width=160></TD></TR>
<TR>
<TD><A href="http://www-128.ibm.com/developerworks/cn/rational/rationaledge/">The Rational Edge</A></TD></TR>
<TR>
<TD height=1><IMG height=5 alt="" src="http://www.ibm.com/i/c.gif" width=160></TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE>
<TABLE cellSpacing=0 cellPadding=0 width=160 border=0>
<TBODY>
<TR>
<TD width=150 bgColor=#000000 colSpan=2 height=2><IMG height=2 alt="" src="http://www.ibm.com/i/c.gif" width=160></TD></TR>
<TR>
<TD width=150 bgColor=#ffffff colSpan=2 height=2><IMG height=2 alt="" src="http://www.ibm.com/i/c.gif" width=160></TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE>
<P><NAME>Kerry</NAME><BR><BR>2004 年 11 月 </P>
<BLOCKQUOTE>本文介绍了一个真实的范例，然后讨论了在把用例用来定义实时系统的规格时遇到的问题，以及相关的经验学习。</BLOCKQUOTE>
<P><A name=N10038><SPAN class=atitle2>概述</SPAN></A><BR>本文基于我去年为客户开发一个实时控制系统的工作。</P>
<P>本文的目标是：第一，重点描述实时系统规格的确定和用例之间的关系；第二，描述我们如何开发用例模型以及应用用例给我们带来了哪些益处。</P>
<P>要说明的第一件事情是为什么我们需要类似这样的一篇文章，然后我们再说明用用例来描述实时系统有哪些特殊之处。</P>
<P>在叙述为什么需要本文之后，我将描述一个具体项目和它的用例模型。我将重点描述用例模型的一些有趣的和有意义的特性，然后看看它们是如何有益于项目的。最后，我将讨论一些经验学习，并给出一些建议。</P>
<P><A name=N1004C><SPAN class=atitle2>为什么我们需要这篇文章？</SPAN></A><BR>有一种看法认为用例只对你描述高度交互的系统有用，这些系统以IT系统为代表，如银行系统。例如，在银行中你可能需要处理一个抵押应用，它会有大量的用户交互。对于实时系统来说，并不存在那么多的用户交互。但是，如果实时系统具有有意义的外部可视的行为，用用例描述仍然对定义它们的规格是有用的，即使在一些用例中用户只是选择一些设置以及告诉系统完成一些功能。</P>
<P>在为客户工作了这么多年来，我发现用例被广泛地误解。尽管有很多与之相关的书籍、文章和培训课程。可能这些书籍、文章和培训课程都只关注于问题，因此它们提供大量的不同的方法。在这些著作中经常提到的一个例子是自动柜员机(ATM)。类似这样的例子对于说明一些问题是有用的，但在处理很大而且很复杂的实际系统时却通常没有明显的帮助。在实时系统中你将怎样处理出现的问题？有一些实际的例子可以对你有所帮助，本文恰恰可以给你提供这样一个实际的例子。</P>
<P><A name=N1005A><SPAN class=atitle2>什么是实时系统的特点？</SPAN></A><BR>实时系统就是时间是最关键因素的系统。如果一个系统不理会它的时间需求，将可能导致生命危险，例如造成飞机失事。简单来说，对于这样的系统，对于时间需求处理的失败将可能导致产品的损害和上百万美元的损失。</P>
<P>实时系统也有最小限度的用户交互，对于这类系统怎么样定义它的用例是一件值得考虑的事情。实时系统通常都是高度算法化的，用例可能并不是最好的描述算法的文档方法。典型地，一个用例将引用在其它地方描述的算法。</P>
<P>如果你的系统具有有效的外部可视行为，那么用例能够极大地帮助你文档化你的系统需求。下面我描述的系统就有大量外部可视行为。在IT系统中应用用例的规则在这里仍然适用。</P>
<P><A name=N1006B><SPAN class=atitle2>产品传送系统(PT)项目</SPAN></A><BR>用户是一个全球最大的铁矿生产商，它在澳大利亚西北的Headland港拥有一套铁矿传送工厂。铁矿从传送带网络传送到火车车厢，然后分类，称重，保存在仓库。最后铁矿从仓库中运出，再通过传送带运送到船上。</P>
<P>这个系统中每个东西都很大。有的传送带有7公里长，需要15分钟才能启动。运行传送带网络需要一个复杂的控制系统。对控制系统的一个需求是减少运行系统需要的人数。另一个需求是降低对运行系统的人的培训需求。图1是工厂的航拍图。</P><IMG alt="" src="http://www-128.ibm.com/developerworks/cn/rational/r-uc-rt/3095_fig1.jpg" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <BR xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">图1：</B> Hedland港工厂的航拍图 
<P>在左上角有一个船泊位。你可以看到有铁路线从右边连过去。卸货场在接近于中间的垂直线附近。在这个线的顶端是粉碎机。你可以在北面和南面的院子里看到仓库。传送带运行在卸货场和粉碎机，以及粉碎机和仓库之间。 你可以看到运输机从仓库装上铁矿，把它运到船上。运输机的容量非常大。在这个系统中，传送带可以在一小时内传送10000吨的铁矿！</P>
<P>有一些能够增加系统复杂度的需求非常值得关注。控制系统在避免溢出的情况下要达到最大的生产能力。出口容量在2004年从每年67M（百万）吨增加到81M吨，到2011年将扩大到90M吨。</P>
<P><A name=N10088><SPAN class=atitle3>基本概念：作业(route)</SPAN></A><BR>一个作业(route)由一系列传送带、定位和反馈设备组成，这些设备被选择和调配以便把铁矿从源位置运送到目标位置。作业可以是单独的，也可以共享设备以便允许把铁矿分开运输，从一个源位置运送到多个目标位置，或者组合运输，从多个源位置运送到一个目标位置。这些作业由操作员创建、维护和删除。一旦操作员启动作业，系统就开始工作，按照正确的顺序启动每个工作，以及处理一些异常状态例如有不合适的产品已经在传送带上。</P>
<P>为了达到生产力的需求，控制系统采用激进的启动和错误处理策略。尽管已经存在的系统在一个时间点一个作业只能启动一条传送带，当它达到最大速度后，再启动下一条，依此类推。 新的控制系统在一个作业中将同时启动所有的传送带－－注意我们的传送带的长度不同，启动时间和容量也不同。在出现问题时，新的系统试图尽可能关闭最少数量的设备以避免溢出，因为启动一个长的传送带需要15分钟。无论什么可能情况，设备都将保持运行，直到铁矿有可能溢出为止。系统需要同时运行作业，以便矿石能够传送到多个目标位置或者把矿石从多个源位置组合到一个位置。</P>
<P>设备失败的处理是全自动的。当一个传送带一小时可以传送超过10000吨矿石时，你可以想象出现问题时不能很快停下传送带的后果。这个结果并不是你可以用独轮车能够清理干净的！你将不得不使用一些重型设备来清理那些溢出的矿石，而且需要花费很长的时间。甚至有更坏的结果，比如一个错误导致矿石已经倒进了船的甲板上。</P>
<P><A name=N10099><SPAN class=atitle2>PT系统的用例模型</SPAN></A><BR>本文的工作基于IBM(r) Rational Unified Process(r) (RUP(r))和一本名为“用例建模”的书，这本书由Kurt Bittner和Ian Spence合著。用例是一个可供选择的写需求的方法。在过去，我们基于一个词"shall"来书写这些声明。在几年前我曾经在一个国防项目工作，它包括22卷需求文档，没有人能够真正全部理解它们。确认所有的需求描述是正确的和一致的是一件非常困难的事情。用例可以帮助我们处理这类问题。用例把需求放在系统提供给用户和有关人员的上下文中。 按照顺序描述每个用例以消除上下文的冗余，这些冗余在用传统的基于"shall"的需求描述方法中是必然包括的。</P>
<P>这里仅仅描述用例模型的一些特点，因为全部模型太大，也太复杂。用例的规范非常长，也非常细致。</P>
<P><A name=N100A7><SPAN class=atitle3>识别角色(actor)</SPAN></A><BR>在整个操作开始前主要工作集中在识别角色是非常重要的，因为它可以确定系统的边界，清楚地指示哪些是在系统范围内，哪些在系统范围外。我们不想开发那些我们没有必要付钱的东西。在PT系统中，运输机是一个我们需要交互的系统。这里我们只需要知道运输机干什么工作，并不需要控制它如何工作，我们也不需要修改它。既然我们不控制运输机，它就在我们的系统范围之外，作为一个角色模型存在。我们有Ship-Hatch Loaders, Stackers, Sampling Stations 和Dust Control Systems - 所有这些外部系统都作为角色模型。图2显示部分这个系统的角色。</P><IMG alt="" src="http://www-128.ibm.com/developerworks/cn/rational/r-uc-rt/3095_fig2.jpg" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <BR xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">图 2:</B> PT系统角色 
<P>在图2中，角色使用UML 包分组。在左边是角色包。最重要的一个在左上角。CRO 就是Control Room Operator，中央控制室操作员。其它重要的还有在左下角的RSMT(Root System Maintenance Technician，根系统维护技术员)。</P>
<P>其它的包包括所有不同的设备角色。一些用例提到我们管理的通用设备，另一些将提到特定的不同类型的设备。</P>
<P>在图的下方有一些与我们交互的外部设备。左边的一个是PMAC，一个已经存在的系统用来处理我们的用户界面。如果它仅仅是与我们的系统相关的用户界面，那么我们不需要把它看作角色，因为实际上角色是CRO。但是它实际上是我们相关的角色，因为我们给它传递信息，并且从它那里收集信息。</P>
<P>电力负荷管理系统Power Load Management System (PLMS)是值得关注的。在Headland港，港口工厂有自己的电站。当你启动7KM长的传送带，并在上面运行数千吨的矿石是，它需要大量的电力供应。因此，传送带的启动实际上是错开的，以便降低电站的负荷。只要你想启动传送带，PT系统都将询问电站并得到电站的许可。</P>
<P><A name=N100C7><SPAN class=atitle3>确定用例</SPAN></A><BR>用例是一种简单的可选择的定义需求的方法。首先，让我们再次回顾一下用例的定义：</P>
<P>用例定义一个由系统完成的操作序列，它给操作者和相关人员提供 <B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">可观察到的有价值的结果</B>。 </P>
<P>在识别IT系统的用例时，牢记“可观察到的有价值的结果”是非常重要的，这一点在这里仍然适用。我们将看到系统提供给操作者和相关人员的值。在我们的例子中，中央控制室操作员是一个角色，但是整个公司实际上都可以看到系统把矿石从一个地方移动到另外的地方。“由系统完成的操作序列”声明了在用例中系统怎么做的描述。这些每个都是我们系统的需求。最后，用例是一个完整的有意义的事件流。把“完整的有意义的事件流”和“可观察到的有价值的结果”这两个概念组合起来可以帮助避免识别出不完整的功能片断并把它称为用例。</P>
<P>用例和角色在用例图中以图形化的方式描述。图3显示了 PT系统的顶层用例图。你很快就能看到 PT系统的用例分为4组：Operation, Administration, Configuration 和System Startup。</P><IMG alt="" src="http://www-128.ibm.com/developerworks/cn/rational/r-uc-rt/3095_fig3.jpg" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <BR xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">图 3:</B> 顶层用例图 
<P>PT系统中用例相关的操作在图4中显示:</P><IMG alt="" src="http://www-128.ibm.com/developerworks/cn/rational/r-uc-rt/3095_fig4.jpg" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <BR xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">图 4:</B> PT系统的用例 
<P>PT的主要用例是“传送产品”。正如这个用例的名字那样，你可以看到在这里系统提供给用户和有关人员的价值是把产品从一个地方运送到另一个地方的能力。这个软件也能够用来运送其它物品，不仅仅是铁矿。例如它能够用来在制药厂传送药片。传送产品是一个很大的用例，但它抓住了最根本的因素，即我们的系统存在的原因，即给我们的操作者和相关人员提供的价值。</P>
<P>在图4中我们看到与电源管理系统(PLMS)的交互，请求启动设备，我们也看到了用例与我们控制的设备的交互。我们可以显示每个设备角色，但那样的话，图就显得太混乱了。</P>
<P>在图4中，从CRO到传送产品的箭头，表示这个操作员发起或者启动这个用例。用例到设备和PLMS操作者的箭头表示这个用例或者系统与设备和PLMS交谈。从船舱装载系统(SHLS)的箭头表示SHLS发起与系统的交互－－特别地，SHLS可以请求铁矿流暂时中断以便装载机移动到另一个舱室。</P>
<P>有关管理、配置和系统启动的用例在图5中描述。</P><IMG alt="" src="http://www-128.ibm.com/developerworks/cn/rational/r-uc-rt/3095_fig5.jpg" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <BR xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">图 5:</B> 有关管理、配置和启动的用例 
<P>在这里我们可以做的一件事情是在对系统的操作影响最小的情况下更新系统软件。因此我们有"Perform Software Upgrade" 用例。我们也有"Start System" 用例 -这个用例经常被忘掉。系统有人身安全优先的规则，Start System 用例包括在系统启动时进行的所有安全检查的规格说明。你一定不想在服务人员在传送带上工作时偶然地启动它！</P>
<P>Route System Maintenance Technologist (RSMT)是一个负责创建作业或者预定义作业的人，预定义的作业稍后由CRO使用。我们可以在系统中添加新的设备，定义新设备的种类以及定义系统传送产品的特点。港口工厂处理来自不同矿山的不同类型的铁矿，它们有不同的颗粒大小、不同的矿石成分等级。我们要非常小心的一件事情是避免把错误的矿石装到船上去。</P>
<P>关于用例图这里要警告一下：用例图只是冰山的一角。直到你开始写用例规格之前不要去重新分解、重组和调整用例模型。用例的规格大约95％来自用例模型。用例图仅仅给你一个模型的总体、全面的概要描述。</P>
<P>正如我前面提到的，用例描述“事件流”。图6显示不同种类的事件流和它们是如何在用例规格中描述的。</P><IMG alt="" src="http://www-128.ibm.com/developerworks/cn/rational/r-uc-rt/3095_fig6.jpg" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <BR xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">图 6:</B>主事件流和分支流 
<P>从顶部到底端底蓝色粗线条表示主事件流(Basic Flow)。它表示每件事情都按照正确的方式发生。有很多种分支流(Alternate Flow)。描述处理设备故障的分支是一个很好的分支流的例子。另一个例子是描述操作员取消了前面请求的动作。</P>
<P>这里一个非常重要的结构是子事件流(Subflow)。子事件流就象子程序调用。我们试图保持主事件流简单易读，没有子事件流是很难做到这一点的。例如，我们使用子事件流来描述我们启动或者安放设备位置时发生的细节。这些过程每个都相当复杂，如果我们都在主事件流上描述，那么它将变得很长并且很难理解。</P>
<P>图7显示一个主事件流的片断：</P><IMG alt="" src="http://www-128.ibm.com/developerworks/cn/rational/r-uc-rt/3095_fig7.jpg" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <BR xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">图 7:</B> 描述启动一个作业的主事件流示例 
<P>在第二步，系统检查作业是否有效。如果系统确认作业无效时会发生什么？这在分支流中描述。在用例规格中我们使用脚注来指示分支流，脚注文本包括指向相关文档章节的交叉引用。这将减少描述事件流的混乱，使得它更容易读。在这里我使用 "§" 符号指示存在一个分支流。我也用高亮的红色表示这是项目术语表－－一份很重要的文档－－中的定义。</P>
<P>在第3步，系统检查选择的作业的启动策略。"Starting/Positioning Stragegy 2.1"表示交错启动，它需要在启动作业前所有的设备都到位。这个启动策略在分支流中描述。最后系统向PLMS询问是否允许启动作业。如果不允许时发生的事情也在分支流中描述。</P>
<P>在图8中，我们将看到分支流和子事件流的例子。</P><IMG alt="" src="http://www-128.ibm.com/developerworks/cn/rational/r-uc-rt/3095_fig8.jpg" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <BR xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">图 8:</B> 分支流和子事件流示例 
<P>分支流定义当基于某种原因设备不到位，因而这个作业不能启动时应该发生什么。系统给操作者发一个消息，建议在我们实际启动作业前把设备移动到相应的位置。在这个点上，用例就结束了。</P>
<P>子事件流的例子提供我们实际上如何启动作业的更详细的信息。系统检查全部作业设备是否畅通（传送带上没有其它物品）。如果正常，系统同时移动所有需要定位的设备到相应的位置，包括作业自己需要的设备和要与其它作业共享的设备，然后我们交错启动所有的设备以避免电力过载。当全部设备都运行起来后，我们告诉操作员作业已经启动，然后用例结束。第16步的 "a", "b" 和 "c" 也涉及了子事件流。</P>
<P><A name=N10147><SPAN class=atitle3>特殊需求</SPAN></A><BR>有很多需求，特别在实时系统中，不能归结到用例的事件流中。通常它们是非功能需求如性能、可用性等等。那些与给定用例相关的特殊需求可以归结到与用例规格定义相关联的"特殊需求"一节中。有时为了方便，甚至功能需求也可以放到这一节中。图9即为一个示例。</P><IMG alt="" src="http://www-128.ibm.com/developerworks/cn/rational/r-uc-rt/3095_fig9.jpg" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <BR xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">图 9:</B> 特殊需求 
<P>第一个例子可以作为一个分支流，但是为了使主事件流基于阅读，我们可以简单地说：“系统检查是否有特殊需求的xyz节中规定的不能启动的状况发生”。在这个特定用例中，如果我们在码头传送带上还有东西，而传送带由于完成了往甲板上卸矿石已经停止工作，那么我们将给操作员发出一个警告。</P>
<P>第二个例子是一个算法的详细描述，这个算法用来调整传送带的传输量和传送速度。这里，主事件流可以简单地描述：“传输量和传送速度按照特殊需求中的uvw节进行调整。”</P>
<P><A name=N10161><SPAN class=atitle2>结构化用例</SPAN></A><BR>用例的结构化是一个高级课题。你也可以不使用这项技术来完成一个系统的需求文档。用例的结构化可以让你避免冗余信息，保证用例文本只存在一个单独的可维护的位置。关于结构化的重要的一点是，你必须避免让用例模型和用例变得难以理解。</P>
<P>结构化技术在图10中显示。</P><IMG alt="" src="http://www-128.ibm.com/developerworks/cn/rational/r-uc-rt/3095_fig10.jpg" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <BR xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">图 10:</B> 结构化用例 
<P>在图的左边，我们有一个用例，它有一个主事件流，一个分支流和一个子事件流。子事件流和分支流都可以作为单独的用例分出来。分支流变成一个新的用例，扩展了原始的用例。子事件流也变成一个新的用例，它包含在原始的用例中。一般来说，包含关系仅仅用于一个分支流共用于多个用例的情况。这就是我们如何确保仅仅写一个分支流，仅仅有一个维护地点的方法。通常，当需要在已经存在的用例上增加新功能而且你又不想修改原始用例时，可以创建一个扩展流</P>
<P>把这些结构化技术用到我们的产品传送系统后，改变后的用例如图11所示：</P><IMG alt="" src="http://www-128.ibm.com/developerworks/cn/rational/r-uc-rt/3095_fig11.jpg" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <BR xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">图 11:</B> 用例模型的修改 
<P>这些新的用例称为“抽象用例”，因为它们没有操作者，你不能直接调用它们。如果我把这些抽象用例隐藏起来，你仍然可以相当清楚地看到系统的主要功能。</P>
<P>一系列的错误处理用例都以这样的声明开始：“当系统检测到设备故障”或者“当系统检测到超载”等。然后用例继续描述系统在这些情况的响应。</P>
<P>在图11的顶部，我提炼出了两个抽象用例：一个是启动作业，另一个是停止作业。从技术角度来说，我在这里破坏了规则：包含用例应当被多于一个的用例共享。我之所以这么做是因为，如果我在“传送产品”用例中写出所有的内容，文档将超过300页。把它分开可以让很多人同时在系统的不同部分描述需求。</P>
<P><A name=N10190><SPAN class=atitle2>补充需求</SPAN></A><BR>我们有很多补充的需求，它们不适合放在任何用例中。因为特定的需求与具体的用例相关，这些都是典型的非功能性需求。在你在用例中的需求和补充的需求之间存在一个平衡。当你进行实时系统工作时，你可能发现会比你进行IT系统开发时有更多的补充需求。这是由于在实时系统中有更多的有时间要求的需求，它们都在补充需求中描述。</P>
<P>下面是放在补充需求中的非功能需求的例子：</P>
<UL xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<LI>The PT System shall, upon notification of fault requiring upstream interlocks to be set to "False", set Upstream interlocks to False within 0.60 second. 
<LI>The PT System annual Availability (refer Glossary) shall exceed 99.954%. 
<LI>The PT System Maintenance Procedures shall comply with the Client's maintenance strategy for real-time PLC control systems. 
<LI>The PT System shall use the existing PMAC System for the CRO, PCO, and viewer interface. 
<LI>The portion of the PT System controlling route interlocking and directly connected to route equipment and interconnected systems shall be PLC based and, in the event of failure of higher level control within the PT System, shall be capable of safely operating any route currently starting, running, or stopping. </LI></UL>
<P>功能需求也可以包括在补充需求中。当有些功能用用例写还不如用补充需求描述时，可以把这些需求放在补充需求中，而不用写一个完整地用例规格定义。下面是一些这样的例子:</P>
<UL xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<LI>The System shall advise the Operator if the sum of the source feed setpoints for a route is more than 10% less than the minimum capacity for the route. 
<LI>If a feed source has been enabled for a route with a cleanup destination, the System shall: 
<UL>
<LI>Raise an alarm 
<LI>Re-raise the alarm every 10 minutes while the condition persists </LI></UL>
<LI>If during a ship hatch change, burden is on the wharf conveyor at or within the gross stopping distance of the shiploader, the System shall: 
<UL>
<LI>Raise an alarm 
<LI>Issue a message to the operator 
<LI>Stop the wharf conveyor 
<LI>Issue a request to the SHLS to stop the shiploader boom conveyor </LI></UL></LI></UL>
<P><A name=N101D7><SPAN class=atitle2>用例的益处</SPAN></A><BR>用例有以下益处：</P>
<UL xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<LI>给出需求的上下文，清楚显示为什么需要系统。 
<LI>把需求按照时间顺序排列，使需求比传统方式更加容易读，更容易理解。 
<LI>更容易得到客户的认同，因为他们能更容易地阅读和理解。 
<LI>可以用作项目计划、分析、设计、测试和文档的基础。 </LI></UL>
<P>另一方面，关于用例有很多不正确的观点。第一个是，象当前多种书籍和文章中指出的，传统的书写需求的方法能够更严谨和精确。实际上并不是这样的，我们在这个项目中也能写出非常严谨而精确的用例。</P>
<P>另一个看法是任何没有经过专业培训的人都可以写用例。写传统需求文档的原则在这里仍然适用。你需要从外部视角来看系统做什么。你不需要写出系统是怎样做的。象传统的需求一样，你写的用例需求也应该是可测试的。新手经常继续使用老的诸如功能分解的习惯。有开发背景的人经常倾向于从系统内部而不是用外部视角描述。</P>
<P><A name=N101F7><SPAN class=atitle2>用例贯穿整个项目</SPAN></A><BR>我前面提到，用例在整个项目中都有用。</P>
<P><A name=N10202><SPAN class=atitle3>项目计划</SPAN></A><BR>在这里我们没有足够的空间讨论分配用例迭代的准则。只能简单说，这些准则基于RUP的风险评估。下面是分配的迭代：</P>
<TABLE width="60%" border=1>
<TBODY>
<TR>
<TD><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">迭代1</B> </TD>
<TD>启动、停止和处理一个独立作业上的一个设备故障。 <BR xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">维护设备和作业。 </TD></TR>
<TR>
<TD><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">迭代2</B> </TD>
<TD>启动、停止和处理覆盖作业和作业组上的设备故障。 <BR xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">维护计划和约束。 <BR xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">维护产品。 </TD></TR>
<TR>
<TD><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">迭代3</B> </TD>
<TD>创建产品产品差距。 <BR xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">改变作业所有权。 <BR xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">直接命令设备 <BR xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">删除作业。 <BR xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">修改负载数据。 </TD></TR></TBODY></TABLE>
<P><A name=N10244><SPAN class=atitle3>用例分析</SPAN></A><BR>用例分析是一个用来识别对象、类、类属性和类方法的过程。 由于这个项目的实现方法是非面向对象的，我们使用一个映射把面向对象的分析模型转换到过程设计模型。图12显示对启动作业用例进行分析的部分结果：</P><IMG alt="" src="http://www-128.ibm.com/developerworks/cn/rational/r-uc-rt/3095_fig12.jpg" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <BR xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">图 12:</B> 从启动作业用例导出的序列图 
<P><A name=N10258><SPAN class=atitle3>测试计划</SPAN></A><BR>我极力推荐下面的一篇文章：June 2001 Rational Edge，Jim Heumann，"Generating Test Cases from Use Cases"。在我们的PT系统中使用这种方法识别测试用例。图13显示启动作业用例的迭代2的测试用例。注意在测试用例和用例需求之间的连接。它可以帮助保证需求都被测试，以及测试用例随着需求变更而更新。</P><IMG alt="" src="http://www-128.ibm.com/developerworks/cn/rational/r-uc-rt/3095_fig13.jpg" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <BR xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">图 13:</B> 从启动作业用例导出的测试用例 
<P><A name=N1026C><SPAN class=atitle2>经验学习</SPAN></A><BR>1. 集中在外部可视的行为上。这一点怎么强调都不过分，这就是我为什么这里再次重复的原因。在这个项目中，我经常告诉那些需求分析人员，让他们想象它们是飞翔在港口工厂的用户，让他们问自己他们想要看见发生的事情。如果你写的描述一些事情的需求不可见，那么你将不能对它进行测试。</P>
<P>2. 不要引入设计。这与经验1相关。下面是一个例子</P>
<P>每个作业都拥有一个使能信号，这个信号来自于作业的运送源。使能信号在操作间内部驱动作业运送来源的物理信号。(用例在这里描述了系统内部信号。)</P>
<P>有很多原因使你不应该这么做。首先，它使得测试很困难，因为描述的行为在外部不可见。第二，如果你把设计信息放到用例中，你就需要照着这些信息实现，因为那是需求，因此你不仅必须照着它来进行演示说明，而且它也限制你的设计人员的实现方式。</P>
<P>3. 不要为内部监控过程写用例。在这个系统中，由于是实时系统，有很多在系统内部运行的过程用来检查、监控和轮询其它设备。你不应该在你的用例中描述这些，因为它是设计，它仅仅是一种可能的实现方式。</P>
<P>除非过程与系统的目标相关，例如在建筑监控中的“监控建筑”用例中，你应该把它们写在补充需求规格中。例如</P>
<UL xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<LI>系统应该每200毫秒或者更短的时间内检查所有设备的状态。 
<LI>系统应该在设备失败的200毫秒内开始响应。 
<LI>系统应该保证产品混合率在设定值的+/-5%范围内。 </LI></UL>
<P>在用例的分支流或者扩展用例中，都可以描述如果系统检测到问题时发生什么事情。这些需求可以使你设计诸如轮询设备或者设备产生中断等的过程，然是它们属于设计应该考虑的事情，不属于需求的范围。</P>
<P>4. 不要太早"冻结"用例。在项目中太早冻结用例将会导致很多问题，因为在你和你的客户更好地理解需求时，你可以找到机会重新组织用例，或者你将引出新的用例，或者你要修改现有的用例。需求变更会发生，但这需要在一个迭代过程的管理和限制下进行，以便进行适当的影响评估，以及合适的预算和计划日程的变更。如果你使用迭代过程，你至少有在后面的迭代中改正的机会。</P>
<P>5. 不要过于追求完美的用例模型而超出项目计划日程。这是经验4的必然结论。你从来都不可能得到一个完美的用例模型。在某个点上，你将不得不停下修补完善用例模型的工作，开始实际的系统开发工作。即使用例模型并不完美，你也可能开发出符合用户需求的系统。最后，图14显示PT用例模型的实际样子。</P><IMG alt="" src="http://www-128.ibm.com/developerworks/cn/rational/r-uc-rt/3095_fig14.jpg" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <BR xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">图 14:</B> 不完善的用例模型 
<P>你将看到选择作业、启动作业和停止作业是主要的用例。这里并没有围绕着传送产品用例把所有其它用例联系在一起，我们不得不在附加需求中描述其它的需求。来自操作员和相关者的选择、启动和停止作业的需求并没有进行评估。用例模型不完善的主要原因在于，需求必须在某个点冻结，以便开发者不会频繁地面对不确定的开发目标，系统应当被实际开发测试和部署。</P>
<P>6. 不要害怕收集细节信息。用例假定容易被每个人阅读，但是这并不意味着你在大街上随便找一个人，给他一个描述复杂系统的用例，就能够期望他能够理解。</P>
<P>需要问你自己的问题是：你的客户需要多大程度的细节？你想给你的开发者多大的范围？如果你在用例中没有给出很多细节，你就让你的开发者自行作出决定。你想这样做吗？你的开发者可能有丰富的经验而你也很高兴这么做。另一方面，如果你正在进行实际的开发，没有充分的细节不一定是可以接受的。你需要给开发者和测试者描述以足够的细节信息，说明什么对于客户是重要的。</P>
<P>如果有大量的细节信息，可以考虑把它们放到特殊需求或者附加需求中，或者用活动框图(Activity Diagram)来补充用例。(参见经验9)</P>
<P>7. 不要引入用例间的直接交互。用例不能相互交互。它们可以相互影响，但是只能通过操作系统状态来影响。</P>
<P>8. 不要把有关解决资源争夺问题的架构决策放到用例中。这一点与第2课有关，例如，当操作员使能一个作业的来源时，同时第二个作业共享同一个来源因此得到一个来源不可用的错误时，会发生什么情况？</P>
<P>这些状况应该在不同的用例中描述。在每个用例，你只需要简单描述在给定环境下你想要系统做什么。在这个例子中，系统内部如何工作，什么信号发到设备，这些都属于架构或者设计问题。系统架构需要解决这些问题，诸如保证信号在非常接近情况下接收、不同顺序接受或者高频率地接收。</P>
<P>9. 使用活动框图以便使得复杂的用例能够易于理解。活动框图可以作为用例的规格创建。</P>
<P><A name=N102BC><SPAN class=atitle2>总结</SPAN></A><BR>在PT系统中使用用例给项目带来很大的价值。只要有外部可见的系统行为，就应该使用用例来定义需求规格。</P>
<P>对任何系统来说，在确定用例时，要集中在系统的目标上以及系统给相关人员提供的价值。在写用例时要维护一个系统的外部视图。</P>
<P>对于实时系统，附加需求在整个系统需求中占有更大的百分比。</P>
<TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD><A name=author1></A><SPAN class=atitle2>关于作者</SPAN><BR>kerry 软件开发咨询顾问, 主要从事软件开发过程的咨询和指导工作，是 Rational 产品的热衷者，同时对 J2EE 技术有着丰富的经验。可以通过 <A href="mailto:kerrylike@163.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dw="http://www.ibm.com/developerworks/">kerrylike@163.com</A> 联系作者</TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE><img src ="http://www.blogjava.net/kapok/aggbug/12275.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/kapok/" target="_blank">笨笨</a> 2005-09-07 00:23 <a href="http://www.blogjava.net/kapok/archive/2005/09/07/12275.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>EA</title><link>http://www.blogjava.net/kapok/archive/2005/08/03/9153.html</link><dc:creator>笨笨</dc:creator><author>笨笨</author><pubDate>Wed, 03 Aug 2005 13:41:00 GMT</pubDate><guid>http://www.blogjava.net/kapok/archive/2005/08/03/9153.html</guid><wfw:comment>http://www.blogjava.net/kapok/comments/9153.html</wfw:comment><comments>http://www.blogjava.net/kapok/archive/2005/08/03/9153.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/kapok/comments/commentRss/9153.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/kapok/services/trackbacks/9153.html</trackback:ping><description><![CDATA[<A href="http://www.ttdown.com/SoftView/SoftView_25145.html">http://www.ttdown.com/SoftView/SoftView_25145.html</A><BR><BR><A href="http://www.sparxsystems.com.au/">http://www.sparxsystems.com.au/</A><img src ="http://www.blogjava.net/kapok/aggbug/9153.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/kapok/" target="_blank">笨笨</a> 2005-08-03 21:41 <a href="http://www.blogjava.net/kapok/archive/2005/08/03/9153.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>UMLTools</title><link>http://www.blogjava.net/kapok/archive/2005/07/20/8029.html</link><dc:creator>笨笨</dc:creator><author>笨笨</author><pubDate>Wed, 20 Jul 2005 02:18:00 GMT</pubDate><guid>http://www.blogjava.net/kapok/archive/2005/07/20/8029.html</guid><wfw:comment>http://www.blogjava.net/kapok/comments/8029.html</wfw:comment><comments>http://www.blogjava.net/kapok/archive/2005/07/20/8029.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/kapok/comments/commentRss/8029.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/kapok/services/trackbacks/8029.html</trackback:ping><description><![CDATA[<A href="http://www.uml.org.cn/UMLTools/umlTools.asp">http://www.uml.org.cn/UMLTools/umlTools.asp</A><BR><BR><A href="http://www.uml.org.cn/UMLTools/200507193.htm">http://www.uml.org.cn/UMLTools/200507193.htm</A><BR><BR><A href="http://www.uml.org.cn/j2ee/200507154.htm">http://www.uml.org.cn/j2ee/200507154.htm</A><img src ="http://www.blogjava.net/kapok/aggbug/8029.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/kapok/" target="_blank">笨笨</a> 2005-07-20 10:18 <a href="http://www.blogjava.net/kapok/archive/2005/07/20/8029.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>http://www.rational-club.org</title><link>http://www.blogjava.net/kapok/archive/2005/06/12/5932.html</link><dc:creator>笨笨</dc:creator><author>笨笨</author><pubDate>Sun, 12 Jun 2005 02:01:00 GMT</pubDate><guid>http://www.blogjava.net/kapok/archive/2005/06/12/5932.html</guid><wfw:comment>http://www.blogjava.net/kapok/comments/5932.html</wfw:comment><comments>http://www.blogjava.net/kapok/archive/2005/06/12/5932.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/kapok/comments/commentRss/5932.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/kapok/services/trackbacks/5932.html</trackback:ping><description><![CDATA[<A href="http://www.rational-club.org">http://www.rational-club.org</A><BR><BR><BR><A href="http://www.uml.org.cn/rational/">http://www.uml.org.cn/rational/</A><img src ="http://www.blogjava.net/kapok/aggbug/5932.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/kapok/" target="_blank">笨笨</a> 2005-06-12 10:01 <a href="http://www.blogjava.net/kapok/archive/2005/06/12/5932.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>UML2：十三般武艺 </title><link>http://www.blogjava.net/kapok/archive/2005/06/11/5903.html</link><dc:creator>笨笨</dc:creator><author>笨笨</author><pubDate>Sat, 11 Jun 2005 03:42:00 GMT</pubDate><guid>http://www.blogjava.net/kapok/archive/2005/06/11/5903.html</guid><wfw:comment>http://www.blogjava.net/kapok/comments/5903.html</wfw:comment><comments>http://www.blogjava.net/kapok/archive/2005/06/11/5903.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/kapok/comments/commentRss/5903.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/kapok/services/trackbacks/5903.html</trackback:ping><description><![CDATA[<A href="http://blog.csdn.net/yuandafeng/archive/2005/01/23/265098.aspx">http://blog.csdn.net/yuandafeng/archive/2005/01/23/265098.aspx</A><BR>UML2中的十三种图：<A href="http://blog.csdn.net/images/blog_csdn_net/yuandafeng/78618/r_UML2.GIF"><BR></A><IMG height=399 alt="" hspace=0 src="http://blog.csdn.net/images/blog_csdn_net/yuandafeng/78618/r_UML2.GIF" width=657 align=baseline border=0><BR><BR><STRONG>结构图：Structure Diagram</STRONG><BR>（又称静态图）<BR>包括Class, Composite structure,Component, Deployment, Object和Package六种图<BR><BR><STRONG>行为图：Behavior Diagram</STRONG><BR>（又称动态图）<BR>包括Activity, State machine, Use Case Diagrams及<BR>四种Interaction图：Communication, Interaction,Overview, Sequence and Timing图。<BR><BR><BR>该有的还都有，“不该有的”也有了。难怪三友齐齐摇头：这已经不是我们当年可以决定的小玩意了。 <BR><img src ="http://www.blogjava.net/kapok/aggbug/5903.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/kapok/" target="_blank">笨笨</a> 2005-06-11 11:42 <a href="http://www.blogjava.net/kapok/archive/2005/06/11/5903.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>功能驱动开发模式FDD</title><link>http://www.blogjava.net/kapok/archive/2005/06/10/5890.html</link><dc:creator>笨笨</dc:creator><author>笨笨</author><pubDate>Fri, 10 Jun 2005 10:07:00 GMT</pubDate><guid>http://www.blogjava.net/kapok/archive/2005/06/10/5890.html</guid><wfw:comment>http://www.blogjava.net/kapok/comments/5890.html</wfw:comment><comments>http://www.blogjava.net/kapok/archive/2005/06/10/5890.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/kapok/comments/commentRss/5890.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/kapok/services/trackbacks/5890.html</trackback:ping><description><![CDATA[<DIV style="LAYOUT-GRID:  15.6pt none">
<P style="TEXT-ALIGN: center" align=center><B><SPAN style="FONT-SIZE: 16pt; FONT-FAMILY: 黑体; LETTER-SPACING: 2pt"><A href="http://www.huihoo.com/development/fdd.html">http://www.huihoo.com/development/fdd.html</A><BR><BR>功能驱动开发模式<SPAN lang=EN-US>FDD</SPAN></SPAN></B></P>
<P><SPAN lang=EN-US>FDD</SPAN><SPAN style="FONT-FAMILY: 宋体">（</SPAN><SPAN lang=EN-US>Feature-Driven Development</SPAN><SPAN style="FONT-FAMILY: 宋体">）是由</SPAN><SPAN lang=EN-US>Peter Coad</SPAN><SPAN style="FONT-FAMILY: 宋体">、</SPAN><SPAN lang=EN-US>Jeff de Luca </SPAN><SPAN style="FONT-FAMILY: 宋体">、</SPAN><SPAN lang=EN-US>Eric Lefebvre</SPAN><SPAN style="FONT-FAMILY: 宋体">共同开发的一套针对中小型软件开发项目的开发模式。</SPAN></P>
<P><SPAN lang=EN-US>FDD</SPAN><SPAN style="FONT-FAMILY: 宋体">是一个模型驱动的快速迭代开发过程，它强调的是简化、实用、</SPAN> <SPAN style="FONT-FAMILY: 宋体">易于被开发团队接受，适用于需求经常变动的项目。简单地说，</SPAN><SPAN lang=EN-US>FDD</SPAN><SPAN style="FONT-FAMILY: 宋体">“是一个以</SPAN><SPAN lang=EN-US>Architecture</SPAN><SPAN style="FONT-FAMILY: 宋体">为中心的，采用短迭代期，目期驱动的开发过程。它首先对整个项目建立起一个整体的模型，然后通过两周一次‘设计功能</SPAN><SPAN lang=EN-US>-</SPAN><SPAN style="FONT-FAMILY: 宋体">实现功能’的迭代完成项目开发”。此处的“功能”是指“用户眼中最小的有用的功能”，它是可理解的、可度量的，并且可以在有限的时间内（两周）实现。在开发过程中，开发计划的制定、报告的生成、开发进度的跟踪均是以上述“功能”为单位进行的。在</SPAN><SPAN lang=EN-US>FDD</SPAN><SPAN style="FONT-FAMILY: 宋体">中，它认为：<B>只有良好定义的并且简单的过程才能被很好地执行</B>。另外，由于在</SPAN><SPAN lang=EN-US>FDD</SPAN><SPAN style="FONT-FAMILY: 宋体">中采用了短周期的迭代，最小化的功能划分法，所以可以对项目的开发进程进行精确及时地监控。</SPAN></P>
<P><SPAN lang=EN-US>FDD</SPAN><SPAN style="FONT-FAMILY: 宋体">的使用需要有相应工具的支持，</SPAN><SPAN lang=EN-US>Peter Coad</SPAN><SPAN style="FONT-FAMILY: 宋体">等人开发出了一套扩展的</SPAN><SPAN lang=EN-US>UML</SPAN><SPAN style="FONT-FAMILY: 宋体">（</SPAN><SPAN lang=EN-US>FDD UML Extensions</SPAN><SPAN style="FONT-FAMILY: 宋体">），并在</SPAN><SPAN lang=EN-US>Together</SPAN><SPAN style="FONT-FAMILY: 宋体">中实现有关的功能，详细内容可参见后文。</SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体">在</SPAN><SPAN lang=EN-US>FDD</SPAN><SPAN style="FONT-FAMILY: 宋体">中，存在“主要功能集”、“功能集”、“功能”等概念，它们之间的关系及示例如下所示：</SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体">主要功能集</SPAN><SPAN lang=EN-US> = </SPAN><SPAN style="FONT-FAMILY: 宋体">功能集</SPAN><SPAN lang=EN-US>1 + </SPAN><SPAN style="FONT-FAMILY: 宋体">功能集</SPAN><SPAN lang=EN-US>2 + …</SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体">功能集</SPAN><SPAN lang=EN-US> = </SPAN><SPAN style="FONT-FAMILY: 宋体">功能</SPAN><SPAN lang=EN-US>1 + </SPAN><SPAN style="FONT-FAMILY: 宋体">功能</SPAN><SPAN lang=EN-US>2 + …</SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体">其中，主要功能集是在初始阶段根据用户的需求所制定出来的比较粗的，有待于细化的对开发项目所需要功能的描述；功能是在开发过程细化的结果，在每个迭代期中需要实现若一干个功能，这些功能的集合被称之为功能集。</SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体">在</SPAN><SPAN lang=EN-US>FDD</SPAN><SPAN style="FONT-FAMILY: 宋体">中，它将开发过程划分为如下五个阶段：</SPAN></P>
<P><SPAN lang=EN-US style="FONT-FAMILY: Wingdings">l<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体">制定整体的模型</SPAN></P>
<P><SPAN lang=EN-US style="FONT-FAMILY: Wingdings">l<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体">根据优先级列出功能的详细列表</SPAN></P>
<P><SPAN lang=EN-US style="FONT-FAMILY: Wingdings">l<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体">依据功能制定计划</SPAN></P>
<P><SPAN lang=EN-US style="FONT-FAMILY: Wingdings">l<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体">依据功能进行设计</SPAN></P>
<P><SPAN lang=EN-US style="FONT-FAMILY: Wingdings">l<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体">实现功能</SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体">每个阶段的定义又是通过被称之为：</SPAN><SPAN lang=EN-US>ETVX</SPAN><SPAN style="FONT-FAMILY: 宋体">的方法从下面四个方面加以描述的：</SPAN></P>
<P><SPAN lang=EN-US style="FONT-FAMILY: Wingdings">l<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN lang=EN-US>Entry</SPAN><SPAN style="FONT-FAMILY: 宋体">：</SPAN><SPAN lang=EN-US>Specify clear and well defined entry criteria for the process</SPAN><SPAN style="FONT-FAMILY: 宋体">；</SPAN></P>
<P><SPAN lang=EN-US style="FONT-FAMILY: Wingdings">l<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN lang=EN-US>Task</SPAN><SPAN style="FONT-FAMILY: 宋体">：列出所有要实现的任务列表，名称，是否需要实现，任务描述；</SPAN></P>
<P><SPAN lang=EN-US style="FONT-FAMILY: Wingdings">l<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN lang=EN-US>Verification</SPAN><SPAN style="FONT-FAMILY: 宋体">：；制定对过程结果的评批标准；</SPAN></P>
<P><SPAN lang=EN-US style="FONT-FAMILY: Wingdings">l<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN lang=EN-US>eXit</SPAN><SPAN style="FONT-FAMILY: 宋体">：过程结束时所需的结果；</SPAN></P>
<P style="TEXT-ALIGN: center" align=center><SPAN lang=EN-US><IMG height=137 src="http://www.huihoo.com/development/i/i08.jpg" width=487 v:shapes="_x0000_i1025"> </SPAN></P>
<P style="TEXT-ALIGN: center" align=center><SPAN lang=EN-US>FDD</SPAN><SPAN style="FONT-FAMILY: 宋体">过程示意图</SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体">在</SPAN><SPAN lang=EN-US>FDD</SPAN><SPAN style="FONT-FAMILY: 宋体">中主要存在三类人员：主要开发人员、类的所有者、功能团队，它们各自的含义如下：</SPAN></P>
<P><SPAN lang=EN-US style="FONT-FAMILY: Wingdings">l<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体">主要开发人员：用于领导其它开发人员进行</SPAN><SPAN lang=EN-US>DBF/BBF</SPAN><SPAN style="FONT-FAMILY: 宋体">的开发，对开发工作进行监督（例如对设计及代码进行审查）。主要开发人员的数量由项目整体的大小所决定，如果需要加快开发进度则可以再培养新的主要开发人员。与其它开发人员相比，主要开发人员具有更高的开发效率。</SPAN><SPAN lang=EN-US>Fred Brooks</SPAN><SPAN style="FONT-FAMILY: 宋体">在几十年前就提出了：增加开发人员数量只会降低开发效率。但对于小型的，以用户功能驱动的轻量及的开发过程此原则并不适用。在此过程中采用增加人员的方法可以提高开发的并行效率。</SPAN></P>
<P><SPAN lang=EN-US style="FONT-FAMILY: Wingdings">l<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体">类的所有者：一个类有且只有一个所有者，即一个类只能由一名开发人员进行设计及编码。采用这种方式是十分有效的，因为开发人员会感觉他拥有了部分属于自已的代码，他会以此为荣；此外，它还可以保证相关代码的一致性。如果此类中包含有复杂的算法，那么可以再增加一名专门负责算法的开发人员。虽然</SPAN><SPAN lang=EN-US>FDD</SPAN><SPAN style="FONT-FAMILY: 宋体">是面向用户功能的，而不是面向类的，但用户最终关心的是那些他们需的功能，而并不关心在开发时采用何种框架模式，所以在此以类为单位进行人员分配与开发的宗旨并不矛盾。</SPAN></P>
<P><SPAN lang=EN-US style="FONT-FAMILY: Wingdings">l<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体">功能团队：开发时功能会被分配给主要开发人员，再由主要开发人员根据实现此功能所需类的所有关系找到有关的开发人员从而构成一个临时的（最多两周）的团队。一名开发人员可以同时负责多个类的开发工作，即他可以在同一时刻处于多个功能团队中。因此在每个</SPAN><SPAN lang=EN-US>DBF/BBF</SPAN><SPAN style="FONT-FAMILY: 宋体">中功能团队的人员均可能发生变化。在此团队中主要开发人员处于核心地位，团队内部的交流也是经及为中心的。采用这种方法可以加速开发进度，并且主要开发人员还可以对过程进行必要的监控，保证设计与实现的一致性。从更高的角度来看，主要的系统设计师又负责监控各功能团队中的主要开发人员。</SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体">采用</SPAN><SPAN lang=EN-US>FDD</SPAN><SPAN style="FONT-FAMILY: 宋体">方式进行开发时，各阶段时间的分配关系大致如下所示：</SPAN></P>
<P><SPAN lang=EN-US style="FONT-FAMILY: Wingdings">l<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN>Develop an overall model&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 10% initial, 4% on-going</P>
<P><SPAN lang=EN-US style="FONT-FAMILY: Wingdings">l<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN>Build a features list&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 4% initial, 1% on-going</P>
<P><SPAN lang=EN-US style="FONT-FAMILY: Wingdings">l<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN>Plan by feature&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2% initial, 2% on-going</P>
<P><SPAN lang=EN-US style="FONT-FAMILY: Wingdings">l<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN>Design by feature, build by feature&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 77%<SPAN style="FONT-FAMILY: 宋体">（两周一个迭代期）</SPAN></P>
<P style="TEXT-ALIGN: center" align=center><SPAN lang=EN-US><IMG height=216 src="http://www.huihoo.com/development/i/i10.jpg" width=615 v:shapes="_x0000_i1026"> </SPAN></P>
<P><SPAN lang=EN-US>DBF/BBF</SPAN><SPAN style="FONT-FAMILY: 宋体">中各阶段时间分配关系：</SPAN></P>
<P><SPAN lang=EN-US style="FONT-FAMILY: Wingdings">l<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN lang=EN-US>DBF</SPAN></P>
<P><SPAN lang=EN-US style="FONT-FAMILY: Wingdings">²<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN>Walk through the domain&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1%</P>
<P><SPAN lang=EN-US style="FONT-FAMILY: Wingdings">²<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN>Design&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 40%</P>
<P><SPAN lang=EN-US style="FONT-FAMILY: Wingdings">²<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN>Inspect the design&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3%</P>
<P><SPAN lang=EN-US style="FONT-FAMILY: Wingdings">l<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN lang=EN-US>BBF</SPAN></P>
<P><SPAN lang=EN-US style="FONT-FAMILY: Wingdings">²<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN>Code/test&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 45%</P>
<P><SPAN lang=EN-US style="FONT-FAMILY: Wingdings">²<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN>Inspect the code&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 10%</P>
<P><SPAN lang=EN-US style="FONT-FAMILY: Wingdings">²<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN>Promote to build&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1%</P>
<P style="TEXT-ALIGN: center" align=center><SPAN lang=EN-US><IMG height=150 src="http://www.huihoo.com/development/i/i12.jpg" width=595 v:shapes="_x0000_i1027"> </SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体">需要注意的是：上述</SPAN><SPAN lang=EN-US>Coding</SPAN><SPAN style="FONT-FAMILY: 宋体">的过程中还包含有单元测试的内容。此外单从</SPAN><SPAN lang=EN-US>DBF/BBF</SPAN><SPAN style="FONT-FAMILY: 宋体">的过程来看，设计所有的时间要比编码的时间长（</SPAN><SPAN lang=EN-US>40% : 45%</SPAN><SPAN style="FONT-FAMILY: 宋体">），但考虑到</SPAN><SPAN lang=EN-US>FDD</SPAN><SPAN style="FONT-FAMILY: 宋体">的整个实施过程（包括前期的建模过程），设计的时间还是比编码的时间要长的（</SPAN><SPAN lang=EN-US>45% : 35%</SPAN><SPAN style="FONT-FAMILY: 宋体">）。</SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体">在</SPAN><SPAN lang=EN-US>FDD</SPAN><SPAN style="FONT-FAMILY: 宋体">中另一个重要的，并且也是十分有特色的部分就是它的报告功能。每周</SPAN><SPAN lang=EN-US>Release</SPAN><SPAN style="FONT-FAMILY: 宋体">经理要召开一次会议，会议一般限定于</SPAN><SPAN lang=EN-US>30</SPAN><SPAN style="FONT-FAMILY: 宋体">分钟以内，在会上每个主要的开发人员全面地介绍其所做的工作，并标识出相应的项目状态图。通过这种口头上的交流，可以确保各主要开发人员能对项目的其它部分有一个充分的了解。会后，</SPAN><SPAN lang=EN-US>Release</SPAN><SPAN style="FONT-FAMILY: 宋体">经理还要根据有关内容更新数据库中的信息并生成相应的报告，这个报告将发送给项目团队、用户以及主要的管理人员。</SPAN></P>
<P><SPAN lang=EN-US><IMG height=148 src="http://www.huihoo.com/development/i/i14.jpg" width=680 v:shapes="_x0000_i1028"> </SPAN></P>
<P style="TEXT-ALIGN: center" align=center><SPAN lang=EN-US><IMG height=237 src="http://www.huihoo.com/development/i/i15.gif" width=449 v:shapes="_x0000_i1029"> </SPAN></P>
<P style="TEXT-ALIGN: center" align=center><SPAN lang=EN-US><IMG height=333 src="http://www.huihoo.com/development/i/i16.gif" width=593 v:shapes="_x0000_i1030"> </SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体">为跟踪项目开发状态需要使用数据库对有关内容加以保存，在数据库中应保存如下信息：</SPAN></P>
<P><SPAN lang=EN-US style="FONT-FAMILY: Wingdings">l<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体">类型（问题域、人的交互活动、系统交互活动）</SPAN></P>
<P><SPAN lang=EN-US style="FONT-FAMILY: Wingdings">l<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体">标识（功能集前缀</SPAN><SPAN lang=EN-US>+</SPAN><SPAN style="FONT-FAMILY: 宋体">序列号）</SPAN></P>
<P><SPAN lang=EN-US style="FONT-FAMILY: Wingdings">l<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体">状态（正在处理、不再需要、正常）</SPAN></P>
<P><SPAN lang=EN-US style="FONT-FAMILY: Wingdings">l<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体">主要功能集</SPAN></P>
<P><SPAN lang=EN-US style="FONT-FAMILY: Wingdings">l<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体">功能集</SPAN></P>
<P><SPAN lang=EN-US style="FONT-FAMILY: Wingdings">l<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体">文档引用信息</SPAN></P>
<P><SPAN lang=EN-US style="FONT-FAMILY: Wingdings">l<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体">活动事件</SPAN></P>
<P><SPAN lang=EN-US style="FONT-FAMILY: Wingdings">l<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体">主要开发人员</SPAN></P>
<P><SPAN lang=EN-US style="FONT-FAMILY: Wingdings">l<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体">问题域分析时的计划日期，实际日期</SPAN></P>
<P><SPAN lang=EN-US style="FONT-FAMILY: Wingdings">l<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体">设计时的计划日期，实际日期</SPAN></P>
<P><SPAN lang=EN-US style="FONT-FAMILY: Wingdings">l<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体">设计复查时的计划日期，实际日期</SPAN></P>
<P><SPAN lang=EN-US style="FONT-FAMILY: Wingdings">l<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体">编码时的计划日期，实际日期</SPAN></P>
<P><SPAN lang=EN-US style="FONT-FAMILY: Wingdings">l<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体">编码复查时的计划日期，实际日期</SPAN></P>
<P><SPAN lang=EN-US style="FONT-FAMILY: Wingdings">l<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体">提交构造时的计划日期，实际日期</SPAN></P>
<P><SPAN lang=EN-US style="FONT-FAMILY: Wingdings">l<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体">备注</SPAN></P>
<P style="TEXT-ALIGN: center" align=center><SPAN lang=EN-US><IMG height=329 src="http://www.huihoo.com/development/i/i17.gif" width=595 v:shapes="_x0000_i1031"> </SPAN></P>
<P style="TEXT-ALIGN: center" align=center><SPAN style="FONT-FAMILY: 宋体">项目计划表</SPAN></P>
<P style="TEXT-ALIGN: center" align=center><SPAN lang=EN-US><IMG height=243 src="http://www.huihoo.com/development/i/i18.gif" width=495 v:shapes="_x0000_i1032"> </SPAN></P>
<P style="TEXT-ALIGN: center" align=center><SPAN style="FONT-FAMILY: 宋体">功能详细列表</SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体">另外，有关类及类的所有者的信息保存在其它的表中。根据数据库可自动生成有关报告。</SPAN></P>
<P style="TEXT-ALIGN: center" align=center><SPAN lang=EN-US><IMG height=205 src="http://www.huihoo.com/development/i/i19.jpg" width=372 v:shapes="_x0000_i1033"> </SPAN></P>
<P style="TEXT-ALIGN: center" align=center><SPAN style="FONT-FAMILY: 宋体">项目已完成功能统计表</SPAN></P>
<P style="TEXT-ALIGN: center" align=center><SPAN lang=EN-US><IMG height=193 src="http://www.huihoo.com/development/i/i20.gif" width=327 v:shapes="_x0000_i1034"> </SPAN></P>
<P style="TEXT-ALIGN: center" align=center><SPAN lang=EN-US>FDD</SPAN><SPAN style="FONT-FAMILY: 宋体">中扩展的</SPAN><SPAN lang=EN-US>UML<BR style="PAGE-BREAK-BEFORE: always" clear=all></SPAN></P>
<H1><SPAN lang=EN-US style="FONT-SIZE: 16pt; COLOR: blue; FONT-FAMILY: 黑体">FDD 过程 #1: 开发总体模型</SPAN></H1>
<P><B><SPAN lang=EN-US style="COLOR: blue">Entry Criteria:</SPAN></B></P>
<P class=MsoBodyTextIndent><SPAN style="FONT-FAMILY: 楷体_GB2312">客户已准备好建立一个系统。他已经有采用某种形式保存的需求列表。此时用户可能还不能完全分清楚什么是他“必面要的”，什么是他“想要的，最好有的”，但这没有关系。</SPAN></P>
<P><B><SPAN lang=EN-US style="COLOR: blue">Tasks:</SPAN></B></P>
<TABLE cellSpacing=0 cellPadding=0 border=1>
<TBODY>
<TR>
<TD class=Normal vAlign=top width=212 bgColor=#d9d9d9>
<P><SPAN style="FONT-FAMILY: 黑体">组建建模团队</SPAN><SPAN lang=EN-US></SPAN></P></TD>
<TD class=Normal vAlign=top width=212 bgColor=#d9d9d9>
<P><SPAN style="FONT-FAMILY: 黑体">项目管理</SPAN><SPAN lang=EN-US></SPAN></P></TD>
<TD class=Normal vAlign=top width=212 bgColor=#d9d9d9>
<P><SPAN style="FONT-FAMILY: 黑体">必须</SPAN><SPAN lang=EN-US></SPAN></P></TD></TR>
<TR>
<TD class=Normal vAlign=top width=637 colSpan=3>
<P><SPAN style="FONT-FAMILY: 楷体_GB2312">建模团队是由来自于领域以及开发方面的永久性人员组成。在建模的过程中也可以从其它项目中人员以便有更多的人可以参与并对模型进行评估。</SPAN><SPAN lang=EN-US></SPAN></P></TD></TR>
<TR>
<TD class=Normal vAlign=top width=212 bgColor=#d9d9d9>
<P><SPAN style="FONT-FAMILY: 黑体">领域分析</SPAN><SPAN lang=EN-US></SPAN></P></TD>
<TD class=Normal vAlign=top width=212 bgColor=#d9d9d9>
<P><SPAN style="FONT-FAMILY: 黑体">建模团队</SPAN><SPAN lang=EN-US></SPAN></P></TD>
<TD class=Normal vAlign=top width=212 bgColor=#d9d9d9>
<P><SPAN style="FONT-FAMILY: 黑体">必须</SPAN><SPAN lang=EN-US></SPAN></P></TD></TR>
<TR>
<TD class=Normal vAlign=top width=637 colSpan=3>
<P><SPAN style="FONT-FAMILY: 楷体_GB2312">领域专家对问题域进行介绍，此过程可能是</SPAN><SPAN lang=EN-US>20</SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312">分钟也可能是几个小时，需根据具体的问题域情况决定。在介绍时所涉及的内容应比问题域稍大一些。</SPAN><SPAN lang=EN-US></SPAN></P></TD></TR>
<TR>
<TD class=Normal vAlign=top width=212 bgColor=#d9d9d9>
<P><SPAN style="FONT-FAMILY: 黑体">学习资料</SPAN><SPAN lang=EN-US></SPAN></P></TD>
<TD class=Normal vAlign=top width=212 bgColor=#d9d9d9>
<P><SPAN style="FONT-FAMILY: 黑体">建模团队</SPAN><SPAN lang=EN-US></SPAN></P></TD>
<TD class=Normal vAlign=top width=212 bgColor=#d9d9d9>
<P><SPAN style="FONT-FAMILY: 黑体">可选</SPAN><SPAN lang=EN-US></SPAN></P></TD></TR>
<TR>
<TD class=Normal vAlign=top width=637 colSpan=3>
<P><SPAN style="FONT-FAMILY: 楷体_GB2312">学习各种资料，包括：组件模型、传统的或者是采用</SPAN><SPAN lang=EN-US>use-case</SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312">方式描述的功能需求书、数据模型以及用记手册。</SPAN><SPAN lang=EN-US></SPAN></P></TD></TR>
<TR>
<TD class=Normal vAlign=top width=212 bgColor=#d9d9d9>
<P><SPAN style="FONT-FAMILY: 黑体">生成非正式的功能列表</SPAN><SPAN lang=EN-US></SPAN></P></TD>
<TD class=Normal vAlign=top width=212 bgColor=#d9d9d9>
<P><SPAN style="FONT-FAMILY: 黑体">系统设计师</SPAN> <SPAN style="FONT-FAMILY: 黑体">主要程序员</SPAN><SPAN lang=EN-US></SPAN></P></TD>
<TD class=Normal vAlign=top width=212 bgColor=#d9d9d9>
<P><SPAN style="FONT-FAMILY: 黑体">必须</SPAN><SPAN lang=EN-US></SPAN></P></TD></TR>
<TR>
<TD class=Normal vAlign=top width=637 colSpan=3>
<P><SPAN style="FONT-FAMILY: 楷体_GB2312">建模团队生成非正式的功能列表，至于具体的细化和完善留到下一阶段进行。如果需要的话，应将有关的参考资料一并注明。</SPAN><SPAN lang=EN-US></SPAN></P></TD></TR>
<TR>
<TD class=Normal vAlign=top width=212 bgColor=#d9d9d9>
<P><SPAN style="FONT-FAMILY: 黑体">开发子模型</SPAN><SPAN lang=EN-US></SPAN></P></TD>
<TD class=Normal vAlign=top width=212 bgColor=#d9d9d9>
<P><SPAN style="FONT-FAMILY: 黑体">划分为小组形式的建模团队</SPAN><SPAN lang=EN-US></SPAN></P></TD>
<TD class=Normal vAlign=top width=212 bgColor=#d9d9d9>
<P><SPAN style="FONT-FAMILY: 黑体">必须</SPAN></P></TD></TR>
<TR>
<TD class=Normal vAlign=top width=637 colSpan=3>
<P><SPAN style="FONT-FAMILY: 楷体_GB2312">系统设计师提出最初的组件或者是入手点。根据对问题域的理解，小组使用原型及组件创建出类图。创建过程如下：首要关心的是类以及它们之间的关系，然后是类所包含的函数，最后才是类所具有的属性。在寻找类的函数的过程中可以参考对问题域的理解，最初的功能列表，以及原型中所建议的函数等方法。同时还需要生成一个或多个非正式的序列图。</SPAN><SPAN lang=EN-US></SPAN></P></TD></TR>
<TR>
<TD class=Normal vAlign=top width=212 bgColor=#d9d9d9>
<P><SPAN style="FONT-FAMILY: 黑体">开发模型</SPAN><SPAN lang=EN-US></SPAN></P></TD>
<TD class=Normal vAlign=top width=212 bgColor=#d9d9d9>
<P><SPAN style="FONT-FAMILY: 黑体">系统设计师</SPAN> <SPAN style="FONT-FAMILY: 黑体">建模团队</SPAN><SPAN lang=EN-US></SPAN></P></TD>
<TD class=Normal vAlign=top width=212 bgColor=#d9d9d9>
<P><SPAN style="FONT-FAMILY: 黑体">必须</SPAN></P></TD></TR>
<TR>
<TD class=Normal vAlign=top width=637 colSpan=3>&nbsp; </TD></TR>
<TR>
<TD class=Normal vAlign=top width=212 bgColor=#d9d9d9>
<P><SPAN style="FONT-FAMILY: 黑体">记录候选模型</SPAN><SPAN lang=EN-US></SPAN></P></TD>
<TD class=Normal vAlign=top width=212 bgColor=#d9d9d9>
<P><SPAN style="FONT-FAMILY: 黑体">系统设计师</SPAN> <SPAN style="FONT-FAMILY: 黑体">主要程序员</SPAN><SPAN lang=EN-US></SPAN></P></TD>
<TD class=Normal vAlign=top width=212 bgColor=#d9d9d9>
<P><SPAN style="FONT-FAMILY: 黑体">必须</SPAN></P></TD></TR>
<TR>
<TD class=Normal vAlign=top width=637 colSpan=3>
<P><SPAN style="FONT-FAMILY: 楷体_GB2312">记录员（可以由团队人员分别担任）记录下来工作中所评估过的比较重要的但未被采用的模型，以便于将来在项目中参考。</SPAN><SPAN lang=EN-US></SPAN></P></TD></TR></TBODY></TABLE>
<P><B><SPAN lang=EN-US style="COLOR: blue">Verification:</SPAN></B></P>
<TABLE cellSpacing=0 cellPadding=0 border=1>
<TBODY>
<TR>
<TD class=Normal vAlign=top width=212 bgColor=#d9d9d9>
<P><SPAN style="FONT-FAMILY: 黑体">内部及外部的评审</SPAN><SPAN lang=EN-US></SPAN></P></TD>
<TD class=Normal vAlign=top width=212 bgColor=#d9d9d9>
<P><SPAN style="FONT-FAMILY: 黑体">建模团队</SPAN><SPAN lang=EN-US></SPAN></P></TD>
<TD class=Normal vAlign=top width=212 bgColor=#d9d9d9>
<P><SPAN style="FONT-FAMILY: 黑体">必须</SPAN></P></TD></TR>
<TR>
<TD class=Normal vAlign=top width=637 colSpan=3>
<P><SPAN style="FONT-FAMILY: 楷体_GB2312">参与此项目的领域专家进行内部自评，外部评审是必须的，以便判断对问题域的理解是否正确，功能是否是必须的，范围是否合理。</SPAN><SPAN lang=EN-US></SPAN></P></TD></TR></TBODY></TABLE>
<P><B><SPAN lang=EN-US style="COLOR: blue">Exit:</SPAN></B></P>
<P><SPAN style="FONT-FAMILY: 楷体_GB2312">结束过程时，团队必须提交如下内容，并且这些内容已经过开发经理以及系统设计师的审阅及批准：</SPAN><SPAN lang=EN-US></SPAN></P>
<P><SPAN lang=EN-US style="FONT-FAMILY: Symbol">-<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312">类图，包括：类、类间关系、类的函数以及属性。类及类间关系建立起了模型的大致轮廓。根据最初的功能有列表以及非正式的序列图而来的函数展现出系统的功能，并且是后续开发过程中建立详细功能列表的前提。此外还应有非正式的序列图。</SPAN><SPAN lang=EN-US></SPAN></P>
<P><SPAN lang=EN-US style="FONT-FAMILY: Symbol">-<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312">非正式的功能列表。</SPAN><SPAN lang=EN-US></SPAN></P>
<P><SPAN lang=EN-US style="FONT-FAMILY: Symbol">-<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312">其它可供选择的模型信息。</SPAN><SPAN lang=EN-US></SPAN></P><B><SPAN lang=EN-US style="FONT-SIZE: 10.5pt; FONT-FAMILY: 'Times New Roman'"><BR style="PAGE-BREAK-BEFORE: always" clear=all></SPAN></B>
<H1><SPAN lang=EN-US style="FONT-SIZE: 16pt; COLOR: blue; FONT-FAMILY: 黑体">FDD 过程 #2: 创建功能列表</SPAN></H1>
<P><SPAN style="FONT-FAMILY: 宋体">在此阶段，团队标识出所有的功能，对其加以分组，为其设定优先级，并设置相应的权重。</SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体">在下面的活动中，小组工作的重点在于功能，因此领域专家可以不再需要。</SPAN></P>
<P><B><SPAN lang=EN-US style="COLOR: blue">Entry Criteria:</SPAN></B></P>
<P><SPAN style="FONT-FAMILY: 宋体">建模团队已成功地完成了</SPAN><SPAN lang=EN-US>FDD</SPAN><SPAN style="FONT-FAMILY: 宋体">第一阶段的工作，开发出了系统的整体模型。</SPAN><SPAN lang=EN-US style="FONT-FAMILY: 楷体_GB2312"></SPAN></P>
<P><B><SPAN lang=EN-US style="COLOR: blue">Tasks:</SPAN></B></P>
<TABLE cellSpacing=0 cellPadding=0 border=1>
<TBODY>
<TR>
<TD class=Normal vAlign=top width=212 bgColor=#d9d9d9>
<P><SPAN style="FONT-FAMILY: 黑体">组建功能列表团队</SPAN><SPAN lang=EN-US></SPAN></P></TD>
<TD class=Normal vAlign=top width=212 bgColor=#d9d9d9>
<P><SPAN style="FONT-FAMILY: 黑体">项目经理</SPAN> <SPAN style="FONT-FAMILY: 黑体">开发经理</SPAN><SPAN lang=EN-US></SPAN></P></TD>
<TD class=Normal vAlign=top width=212 bgColor=#d9d9d9>
<P><SPAN style="FONT-FAMILY: 黑体">必须</SPAN><SPAN lang=EN-US></SPAN></P></TD></TR>
<TR>
<TD class=Normal vAlign=top width=637 colSpan=3>
<P><SPAN style="FONT-FAMILY: 楷体_GB2312">功能列表团队是由来自于领域专家以及开发方面的固定人员构成的。</SPAN><SPAN lang=EN-US></SPAN></P></TD></TR>
<TR>
<TD class=Normal vAlign=top width=212 bgColor=#d9d9d9>
<P><SPAN style="FONT-FAMILY: 黑体">标识功能</SPAN> <SPAN style="FONT-FAMILY: 黑体">创建功能集</SPAN><SPAN lang=EN-US></SPAN></P></TD>
<TD class=Normal vAlign=top width=212 bgColor=#d9d9d9>
<P><SPAN style="FONT-FAMILY: 黑体">功能列表团队</SPAN><SPAN lang=EN-US></SPAN></P></TD>
<TD class=Normal vAlign=top width=212 bgColor=#d9d9d9>
<P><SPAN style="FONT-FAMILY: 黑体">必须</SPAN><SPAN lang=EN-US></SPAN></P></TD></TR>
<TR>
<TD class=Normal vAlign=top width=637 colSpan=3>
<P><SPAN style="FONT-FAMILY: 楷体_GB2312">团队首先从上一阶段得到的非正式的功能列表入手，接着：</SPAN><SPAN lang=EN-US></SPAN></P>
<P><SPAN lang=EN-US style="FONT-FAMILY: Symbol">-<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312">将模型中的函数转换为功能</SPAN><SPAN lang=EN-US></SPAN></P>
<P><SPAN lang=EN-US style="FONT-FAMILY: Symbol">-<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312">将模型中的</SPAN><SPAN lang=EN-US>moment-intervals</SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312">转换为功能集（并将功能集再组织成主功能集），头脑风暴，选择，添加功能以便实现用户所要的以及所想的。</SPAN><SPAN lang=EN-US></SPAN></P>
<P><SPAN style="FONT-FAMILY: 楷体_GB2312">在此采用下述格式进行描述：</SPAN><SPAN lang=EN-US></SPAN></P>
<P><SPAN lang=EN-US style="FONT-FAMILY: Symbol">-<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312">针对功能：</SPAN><SPAN lang=EN-US> &lt;action&gt;the&lt;result&gt;&lt;by | for | of | to&gt;a(n)&lt;object&gt;</SPAN></P>
<P><SPAN lang=EN-US style="FONT-FAMILY: Symbol">-<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312">针对功能集：</SPAN><SPAN lang=EN-US>&lt;action&gt;&lt;-ing&gt;a(n)&lt;object&gt;</SPAN></P>
<P><SPAN lang=EN-US style="FONT-FAMILY: Symbol">-<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312">针对主功能集：</SPAN><SPAN lang=EN-US>&lt;object&gt;management</SPAN></P>
<P><SPAN style="FONT-FAMILY: 楷体_GB2312">此处的</SPAN><SPAN lang=EN-US>object</SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312">可以指一个人、一个地点或者一件事（包括：角色、某一时刻、某一时间段或者是描述）</SPAN><SPAN lang=EN-US></SPAN></P></TD></TR>
<TR>
<TD class=Normal vAlign=top width=212 bgColor=#d9d9d9>
<P><SPAN style="FONT-FAMILY: 黑体">为功能集以及功能设置优先级</SPAN><SPAN lang=EN-US></SPAN></P></TD>
<TD class=Normal vAlign=top width=212 bgColor=#d9d9d9>
<P><SPAN style="FONT-FAMILY: 黑体">功能列表团队</SPAN><SPAN lang=EN-US></SPAN></P></TD>
<TD class=Normal vAlign=top width=212 bgColor=#d9d9d9>
<P><SPAN style="FONT-FAMILY: 黑体">必须</SPAN><SPAN lang=EN-US></SPAN></P></TD></TR>
<TR>
<TD class=Normal vAlign=top width=637 colSpan=3>
<P><SPAN style="FONT-FAMILY: 楷体_GB2312">通过“</SPAN><SPAN lang=EN-US>Feature Board</SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312">”为功能集以及功能设置优先级。优先级的划分：</SPAN><SPAN lang=EN-US>A</SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312">（必须实现），</SPAN><SPAN lang=EN-US>B</SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312">（最好能实现），</SPAN><SPAN lang=EN-US>C</SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312">（如果可能则实现），</SPAN><SPAN lang=EN-US>D</SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312">（以后再实现）。设置时是依据用户的满意程序所定的。</SPAN><SPAN lang=EN-US></SPAN></P></TD></TR>
<TR>
<TD class=Normal vAlign=top width=212 bgColor=#d9d9d9>
<P><SPAN style="FONT-FAMILY: 黑体">分解复杂功能</SPAN><SPAN lang=EN-US></SPAN></P></TD>
<TD class=Normal vAlign=top width=212 bgColor=#d9d9d9>
<P><SPAN style="FONT-FAMILY: 黑体">功能列表团队</SPAN><SPAN lang=EN-US></SPAN></P></TD>
<TD class=Normal vAlign=top width=212 bgColor=#d9d9d9>
<P><SPAN style="FONT-FAMILY: 黑体">必须</SPAN><SPAN lang=EN-US></SPAN></P></TD></TR>
<TR>
<TD class=Normal vAlign=top width=637 colSpan=3>
<P><SPAN style="FONT-FAMILY: 楷体_GB2312">在系统设计师的带领下开发人员对功能进行查开，以便找到那些无法在两周之内完成的功能，对此类功能应将其细分为更小的功能或步骤。</SPAN><SPAN lang=EN-US></SPAN></P></TD></TR></TBODY></TABLE>
<P><B><SPAN lang=EN-US style="COLOR: blue">Verification:</SPAN></B></P>
<TABLE cellSpacing=0 cellPadding=0 border=1>
<TBODY>
<TR>
<TD class=Normal vAlign=top width=212 bgColor=#d9d9d9>
<P><SPAN style="FONT-FAMILY: 黑体">内部及外部的评审</SPAN><SPAN lang=EN-US></SPAN></P></TD>
<TD class=Normal vAlign=top width=212 bgColor=#d9d9d9>
<P><SPAN style="FONT-FAMILY: 黑体">功能列表团队</SPAN><SPAN lang=EN-US></SPAN></P></TD>
<TD class=Normal vAlign=top width=212 bgColor=#d9d9d9>
<P><SPAN style="FONT-FAMILY: 黑体">必须</SPAN></P></TD></TR>
<TR>
<TD class=Normal vAlign=top width=637 colSpan=3>
<P><SPAN style="FONT-FAMILY: 楷体_GB2312">参与此项目的领域专家进行内部自评，外部评审是必须的，以便判断对问题域的理解是否正确，功能是否是必须的，范围是否合理。</SPAN><SPAN lang=EN-US></SPAN></P></TD></TR></TBODY></TABLE>
<P><B><SPAN lang=EN-US style="COLOR: blue">Exit Criteria:</SPAN></B></P>
<P><SPAN>&nbsp;&nbsp;&nbsp; </SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312">本阶段结束时，详细的功能列表必需已经产生了，并且将功能进行分组形成主功能集以及功能集，此外这些内容已经过开发经理以及系统设计师的审阅及批准。</SPAN></P><B><SPAN lang=EN-US style="FONT-SIZE: 10.5pt; FONT-FAMILY: 'Times New Roman'"><BR style="PAGE-BREAK-BEFORE: always" clear=all></SPAN></B>
<H1><SPAN lang=EN-US style="FONT-SIZE: 16pt; COLOR: blue; FONT-FAMILY: 黑体">FDD 过程 #3: 根据功能制定计划</SPAN></H1>
<P><SPAN style="FONT-FAMILY: 宋体">根据已制定的层次化的、具有优先级以及权重的功能列表，项目经理、开发经理以及主要开发人员一起制定出</SPAN><SPAN lang=EN-US>DBF/BBF</SPAN><SPAN style="FONT-FAMILY: 宋体">阶段的里程碑。</SPAN></P>
<P><B><SPAN lang=EN-US style="COLOR: blue">Entry Criteria:</SPAN></B></P>
<P><SPAN style="FONT-FAMILY: 宋体">功能列表团队已成功地完成了</SPAN><SPAN lang=EN-US>FDD</SPAN><SPAN style="FONT-FAMILY: 宋体">第二阶段的工作，并已形成详细的功能列表。</SPAN><SPAN lang=EN-US style="FONT-FAMILY: 楷体_GB2312"></SPAN></P>
<P><B><SPAN lang=EN-US style="COLOR: blue">Tasks:</SPAN></B></P>
<TABLE cellSpacing=0 cellPadding=0 border=1>
<TBODY>
<TR>
<TD class=Normal vAlign=top width=212 bgColor=#d9d9d9>
<P><SPAN style="FONT-FAMILY: 黑体">计划制定团队</SPAN><SPAN lang=EN-US></SPAN></P></TD>
<TD class=Normal vAlign=top width=212 bgColor=#d9d9d9>
<P><SPAN style="FONT-FAMILY: 黑体">项目经理</SPAN><SPAN lang=EN-US></SPAN></P></TD>
<TD class=Normal vAlign=top width=212 bgColor=#d9d9d9>
<P><SPAN style="FONT-FAMILY: 黑体">必须</SPAN><SPAN lang=EN-US></SPAN></P></TD></TR>
<TR>
<TD class=Normal vAlign=top width=637 colSpan=3>
<P><SPAN style="FONT-FAMILY: 楷体_GB2312">计划制定团队由项目经理、开发经理以及主要开发人员给成。</SPAN><SPAN lang=EN-US></SPAN></P></TD></TR>
<TR>
<TD class=Normal vAlign=top width=212 bgColor=#d9d9d9>
<P><SPAN style="FONT-FAMILY: 黑体">制定功能以及功能集的开发顺序</SPAN><SPAN lang=EN-US></SPAN></P></TD>
<TD class=Normal vAlign=top width=212 bgColor=#d9d9d9>
<P><SPAN style="FONT-FAMILY: 黑体">计划制定团队</SPAN><SPAN lang=EN-US></SPAN></P></TD>
<TD class=Normal vAlign=top width=212 bgColor=#d9d9d9>
<P><SPAN style="FONT-FAMILY: 黑体">必须</SPAN><SPAN lang=EN-US></SPAN></P></TD></TR>
<TR>
<TD class=Normal vAlign=top width=637 colSpan=3>
<P><SPAN style="FONT-FAMILY: 楷体_GB2312">计划制定团队设置开发的先后顺序，并制定出最初的针对功能集或者主要功能集的完成日期。</SPAN><SPAN lang=EN-US></SPAN></P></TD></TR>
<TR>
<TD class=Normal vAlign=top width=212 bgColor=#d9d9d9>
<P><SPAN style="FONT-FAMILY: 黑体">为类指定实现人</SPAN><SPAN lang=EN-US></SPAN></P></TD>
<TD class=Normal vAlign=top width=212 bgColor=#d9d9d9>
<P><SPAN style="FONT-FAMILY: 黑体">计划制定团队</SPAN><SPAN lang=EN-US></SPAN></P></TD>
<TD class=Normal vAlign=top width=212 bgColor=#d9d9d9>
<P><SPAN style="FONT-FAMILY: 黑体">必须</SPAN><SPAN lang=EN-US></SPAN></P></TD></TR>
<TR>
<TD class=Normal vAlign=top width=637 colSpan=3>
<P><SPAN style="FONT-FAMILY: 楷体_GB2312">根据开发顺序以及功能的重要性为每个类指定特定的实现人。</SPAN><SPAN lang=EN-US></SPAN></P></TD></TR>
<TR>
<TD class=Normal vAlign=top width=212 bgColor=#d9d9d9>
<P><SPAN style="FONT-FAMILY: 黑体">为主要功能集以及功能集指定相应负责的主要设计人员</SPAN><SPAN lang=EN-US></SPAN></P></TD>
<TD class=Normal vAlign=top width=212 bgColor=#d9d9d9>
<P><SPAN style="FONT-FAMILY: 黑体">计划制定团队</SPAN><SPAN lang=EN-US></SPAN></P></TD>
<TD class=Normal vAlign=top width=212 bgColor=#d9d9d9>
<P><SPAN style="FONT-FAMILY: 黑体">必须</SPAN><SPAN lang=EN-US></SPAN></P></TD></TR>
<TR>
<TD class=Normal vAlign=top width=637 colSpan=3>
<P><SPAN style="FONT-FAMILY: 楷体_GB2312">根据开发顺序以及功能的重要性为每个主要功能集或者是功能集指定相应负责的主要开发人员。</SPAN><SPAN lang=EN-US></SPAN></P></TD></TR></TBODY></TABLE>
<P><B><SPAN lang=EN-US style="COLOR: blue">Verification:</SPAN></B></P>
<TABLE cellSpacing=0 cellPadding=0 border=1>
<TBODY>
<TR>
<TD class=Normal vAlign=top width=212 bgColor=#d9d9d9>
<P><SPAN style="FONT-FAMILY: 黑体">内部及外部的评审</SPAN><SPAN lang=EN-US></SPAN></P></TD>
<TD class=Normal vAlign=top width=212 bgColor=#d9d9d9>
<P><SPAN style="FONT-FAMILY: 黑体">计划制定团队</SPAN><SPAN lang=EN-US></SPAN></P></TD>
<TD class=Normal vAlign=top width=212 bgColor=#d9d9d9>
<P><SPAN style="FONT-FAMILY: 黑体">必须</SPAN></P></TD></TR>
<TR>
<TD class=Normal vAlign=top width=637 colSpan=3>
<P><SPAN style="FONT-FAMILY: 楷体_GB2312">参与此项目的计划制定人员进行内部自评，外部评审是必须的，并且是由更高一级的管理人员进行。采用“由顶向下”的方式让所有的开发人员均对此计划进行评估。通常一些开发人员由于过分保守会希望延长开发时间。但另一方面，项目经理或者是开发组长又会觉得“每个人都具有与我相同的能力”从而认为可以提前完成开发。在此应进行相应的平衡。</SPAN><SPAN lang=EN-US></SPAN></P></TD></TR></TBODY></TABLE>
<P><B><SPAN lang=EN-US style="COLOR: blue">Exit Criteria:</SPAN></B></P>
<P><SPAN style="FONT-FAMILY: 楷体_GB2312">本阶段结束时，开发计划已经产生了，并且这些内容已经过开发经理以及主要设计师的审阅及批准。计划中应包括以下内容：</SPAN><SPAN lang=EN-US></SPAN></P>
<P><SPAN lang=EN-US style="FONT-FAMILY: Symbol">-<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312">一个整体的开发日期</SPAN><SPAN lang=EN-US></SPAN></P>
<P><SPAN lang=EN-US style="FONT-FAMILY: Symbol">-<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312">针对每个主要功能集、功能集、功能指定有关负责人（</SPAN><SPAN lang=EN-US>CP</SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312">）以及完成时间</SPAN><SPAN lang=EN-US></SPAN></P>
<P><SPAN lang=EN-US style="FONT-FAMILY: Symbol">-<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312">针对每个类，指定负责其完成的开发人</SPAN><SPAN lang=EN-US></SPAN></P>
<P><SPAN style="FONT-FAMILY: 黑体">注意：</SPAN><SPAN lang=EN-US></SPAN></P>
<P><SPAN>&nbsp;&nbsp;&nbsp; </SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312">为便于为功能设置优先级，可以创建一个称之为</SPAN><SPAN lang=EN-US>FFB</SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312">（待实现功能板）。</SPAN><SPAN lang=EN-US></SPAN></P><B><SPAN lang=EN-US style="FONT-SIZE: 10.5pt; FONT-FAMILY: 'Times New Roman'"><BR style="PAGE-BREAK-BEFORE: always" clear=all></SPAN></B>
<H1><SPAN lang=EN-US style="FONT-SIZE: 16pt; COLOR: blue; FONT-FAMILY: 黑体">FDD 过程 #4: 根据功能进行设计（DBF）</SPAN></H1>
<P><SPAN style="FONT-FAMILY: 宋体">根据已制定的层次化的、具有优先级以及权重的功能列表，项目经理、开发经理以及主要开发人员一起制定出</SPAN><SPAN lang=EN-US>DBF/BBF</SPAN><SPAN style="FONT-FAMILY: 宋体">阶段的里程碑。</SPAN></P>
<P><B><SPAN lang=EN-US style="COLOR: blue">Entry Criteria:</SPAN></B></P>
<P><SPAN style="FONT-FAMILY: 宋体">计划制定团队已成功地完成了</SPAN><SPAN lang=EN-US>FDD</SPAN><SPAN style="FONT-FAMILY: 宋体">第三阶段的工作。</SPAN><SPAN lang=EN-US style="FONT-FAMILY: 楷体_GB2312"></SPAN></P>
<P><B><SPAN lang=EN-US style="COLOR: blue">Tasks:</SPAN></B></P>
<TABLE cellSpacing=0 cellPadding=0 border=1>
<TBODY>
<TR>
<TD class=Normal vAlign=top width=212 bgColor=#d9d9d9>
<P><SPAN style="FONT-FAMILY: 黑体">组建</SPAN><SPAN lang=EN-US>DBF</SPAN><SPAN style="FONT-FAMILY: 黑体">团队</SPAN><SPAN lang=EN-US></SPAN></P></TD>
<TD class=Normal vAlign=top width=212 bgColor=#d9d9d9>
<P><SPAN style="FONT-FAMILY: 黑体">主要程序员</SPAN><SPAN lang=EN-US></SPAN></P></TD>
<TD class=Normal vAlign=top width=212 bgColor=#d9d9d9>
<P><SPAN style="FONT-FAMILY: 黑体">必须</SPAN><SPAN lang=EN-US></SPAN></P></TD></TR>
<TR>
<TD class=Normal vAlign=top width=637 colSpan=3>
<P><SPAN style="FONT-FAMILY: 楷体_GB2312">主要开发人员从已有的类中找与可能与特点功能有关的类，然后找到负责实现这些类的开发人员并将他们组建成功能实现团队。开始进行功能的设计，如果需要的话，还可以请领域专家加入。</SPAN><SPAN lang=EN-US></SPAN></P></TD></TR>
<TR>
<TD class=Normal vAlign=top width=212 bgColor=#d9d9d9>
<P><SPAN style="FONT-FAMILY: 黑体">问题域学习</SPAN><SPAN lang=EN-US></SPAN></P></TD>
<TD class=Normal vAlign=top width=212 bgColor=#d9d9d9>
<P><SPAN style="FONT-FAMILY: 黑体">功能实现团队</SPAN> <SPAN style="FONT-FAMILY: 黑体">领域专家</SPAN><SPAN lang=EN-US></SPAN></P></TD>
<TD class=Normal vAlign=top width=212 bgColor=#d9d9d9>
<P><SPAN style="FONT-FAMILY: 黑体">可选</SPAN><SPAN lang=EN-US></SPAN></P></TD></TR>
<TR>
<TD class=Normal vAlign=top width=637 colSpan=3>
<P><SPAN style="FONT-FAMILY: 楷体_GB2312">（本步骤是可选的，主要依赖于功能的复杂性而定）领域专家将对问题域进行一个一般性的介绍，他只介绍与功能有关的内容，但这并不是为理解与功能有关的上下文所必须的工作。</SPAN><SPAN lang=EN-US></SPAN></P></TD></TR>
<TR>
<TD class=Normal vAlign=top width=212 bgColor=#d9d9d9>
<P><SPAN style="FONT-FAMILY: 黑体">学习有关参考资料</SPAN><SPAN lang=EN-US></SPAN></P></TD>
<TD class=Normal vAlign=top width=212 bgColor=#d9d9d9>
<P><SPAN style="FONT-FAMILY: 黑体">功能实现团队</SPAN><SPAN lang=EN-US></SPAN></P></TD>
<TD class=Normal vAlign=top width=212 bgColor=#d9d9d9>
<P><SPAN style="FONT-FAMILY: 黑体">可选</SPAN><SPAN lang=EN-US></SPAN></P></TD></TR>
<TR>
<TD class=Normal vAlign=top width=637 colSpan=3>
<P><SPAN style="FONT-FAMILY: 楷体_GB2312">（本步骤是可选的，主要依赖于功能的复杂性而定）根据功能列表中所列的参考书目以及其它的可拿到的资料，功能实现团队的成员进行学习，以便获得与功能相关的详细的信息。</SPAN><SPAN lang=EN-US></SPAN></P></TD></TR>
<TR>
<TD class=Normal vAlign=top width=212 bgColor=#d9d9d9>
<P><SPAN style="FONT-FAMILY: 黑体">创建序列图</SPAN><SPAN lang=EN-US></SPAN></P></TD>
<TD class=Normal vAlign=top width=212 bgColor=#d9d9d9>
<P><SPAN style="FONT-FAMILY: 黑体">功能实现团队</SPAN><SPAN lang=EN-US></SPAN></P></TD>
<TD class=Normal vAlign=top width=212 bgColor=#d9d9d9>
<P><SPAN style="FONT-FAMILY: 黑体">必须</SPAN><SPAN lang=EN-US></SPAN></P></TD></TR>
<TR>
<TD class=Normal vAlign=top width=637 colSpan=3>
<P><SPAN style="FONT-FAMILY: 楷体_GB2312">根据对功能的理解以及原有的非正式的序列图和组件，功能实现团队创建一正式的，详细的序列图。同时应记录下可选择的其它方案、决定以及注释。主要的开发人员将序列图添加至项目模型中（同时也要更新相应的类图）。</SPAN><SPAN lang=EN-US></SPAN></P></TD></TR>
<TR>
<TD class=Normal vAlign=top width=212 bgColor=#d9d9d9>
<P><SPAN style="FONT-FAMILY: 黑体">实现类及其方法的原型</SPAN><SPAN lang=EN-US></SPAN></P></TD>
<TD class=Normal vAlign=top width=212 bgColor=#d9d9d9>
<P><SPAN style="FONT-FAMILY: 黑体">功能实现团队</SPAN><SPAN lang=EN-US></SPAN></P></TD>
<TD class=Normal vAlign=top width=212 bgColor=#d9d9d9>
<P><SPAN style="FONT-FAMILY: 黑体">必须</SPAN><SPAN lang=EN-US></SPAN></P></TD></TR>
<TR>
<TD class=Normal vAlign=top width=637 colSpan=3>
<P><SPAN style="FONT-FAMILY: 楷体_GB2312">每位类的实现人员根据序列图更新有关类及类中的方法，这包括：方法的参数、返回值、错误处理以及消息的发送。</SPAN><SPAN lang=EN-US></SPAN></P></TD></TR>
<TR>
<TD class=Normal vAlign=top width=212 bgColor=#d9d9d9>
<P><SPAN style="FONT-FAMILY: 黑体">设计复查</SPAN><SPAN lang=EN-US></SPAN></P></TD>
<TD class=Normal vAlign=top width=212 bgColor=#d9d9d9>
<P><SPAN style="FONT-FAMILY: 黑体">功能实现团队</SPAN><SPAN lang=EN-US></SPAN></P></TD>
<TD class=Normal vAlign=top width=212 bgColor=#d9d9d9>
<P><SPAN style="FONT-FAMILY: 黑体">必须</SPAN><SPAN lang=EN-US></SPAN></P></TD></TR>
<TR>
<TD class=Normal vAlign=top width=637 colSpan=3>
<P><SPAN style="FONT-FAMILY: 楷体_GB2312">功能实现团队完成对设计的复查。如果主要开发人员认为有关功能的设计比较复杂并对其有所担心的话，他可以从别的地方请若干人员一起进行复查。</SPAN><SPAN lang=EN-US></SPAN></P></TD></TR>
<TR>
<TD class=Normal vAlign=top width=212 bgColor=#d9d9d9>
<P><SPAN style="FONT-FAMILY: 黑体">记录设计复查活动</SPAN><SPAN lang=EN-US></SPAN></P></TD>
<TD class=Normal vAlign=top width=212 bgColor=#d9d9d9>
<P><SPAN style="FONT-FAMILY: 黑体">文档人员</SPAN><SPAN lang=EN-US></SPAN></P></TD>
<TD class=Normal vAlign=top width=212 bgColor=#d9d9d9>
<P><SPAN style="FONT-FAMILY: 黑体">必须</SPAN><SPAN lang=EN-US></SPAN></P></TD></TR>
<TR>
<TD class=Normal vAlign=top width=637 colSpan=3>
<P><SPAN style="FONT-FAMILY: 楷体_GB2312">团队中的文档人员针对类的实现人按顺序将有关设计复查的活动记录下来。</SPAN><SPAN lang=EN-US></SPAN></P></TD></TR></TBODY></TABLE>
<P><B><SPAN lang=EN-US style="COLOR: blue">Verification:</SPAN></B></P>
<TABLE cellSpacing=0 cellPadding=0 border=1>
<TBODY>
<TR>
<TD class=Normal vAlign=top width=212 bgColor=#d9d9d9>
<P><SPAN style="FONT-FAMILY: 黑体">设计复查</SPAN><SPAN lang=EN-US></SPAN></P></TD>
<TD class=Normal vAlign=top width=212 bgColor=#d9d9d9>
<P><SPAN style="FONT-FAMILY: 黑体">功能实现团队</SPAN><SPAN lang=EN-US></SPAN></P></TD>
<TD class=Normal vAlign=top width=212 bgColor=#d9d9d9>
<P><SPAN style="FONT-FAMILY: 黑体">必须</SPAN></P></TD></TR>
<TR>
<TD class=Normal vAlign=top width=637 colSpan=3>
<P><SPAN style="FONT-FAMILY: 楷体_GB2312">功能设计团队通过对序列图的“走查“实现内部的复查。外部评审是必须的，以确保存有关功能均以实现。</SPAN><SPAN lang=EN-US></SPAN></P></TD></TR></TBODY></TABLE>
<P><B><SPAN lang=EN-US style="COLOR: blue">Exit Criteria:</SPAN></B></P>
<P><SPAN style="FONT-FAMILY: 楷体_GB2312">本阶段结束时，应已完成如下工作，并且这些工作已经过主要设计师的审阅及批准。计划中应包括以下内容：</SPAN><SPAN lang=EN-US></SPAN></P>
<P><SPAN lang=EN-US style="FONT-FAMILY: Symbol">-<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312">功能及其相关参考资料（如果有的话）</SPAN><SPAN lang=EN-US></SPAN></P>
<P><SPAN lang=EN-US style="FONT-FAMILY: Symbol">-<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312">详细的序列图</SPAN><SPAN lang=EN-US></SPAN></P>
<P><SPAN lang=EN-US style="FONT-FAMILY: Symbol">-<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312">更新后的类图</SPAN><SPAN lang=EN-US></SPAN></P>
<P><SPAN lang=EN-US style="FONT-FAMILY: Symbol">-<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312">更新后的类及其方法原型</SPAN><SPAN lang=EN-US></SPAN></P>
<P><SPAN lang=EN-US style="FONT-FAMILY: Symbol">-<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312">开发团队认为有价值的其它实现方案</SPAN><SPAN lang=EN-US></SPAN></P><B><SPAN lang=EN-US style="FONT-SIZE: 10.5pt; FONT-FAMILY: 'Times New Roman'"><BR style="PAGE-BREAK-BEFORE: always" clear=all></SPAN></B>
<H1><SPAN lang=EN-US style="FONT-SIZE: 16pt; COLOR: blue; FONT-FAMILY: 黑体">FDD 过程 #5: 根据功能进行设计（BBF）</SPAN></H1>
<P><SPAN style="FONT-FAMILY: 宋体">在</SPAN><SPAN lang=EN-US>DBF</SPAN><SPAN style="FONT-FAMILY: 宋体">工作的基础上，每个类的实现者完成类的各个方法。此外他还需完善基于类的测试方案并实现类一级的单元测试。根据主要开发人员的意见，功能实现团队可能还需在进行单元测试之前先进行源代码检查。当代码编写并检查后开发人员就将其放入配置管理系统中。在所有的类均已完成并</SPAN><SPAN lang=EN-US>Check-In</SPAN><SPAN style="FONT-FAMILY: 宋体">之后，主要开发人员将代码提升以便进行构造。</SPAN></P>
<P><B><SPAN lang=EN-US style="COLOR: blue">Entry Criteria:</SPAN></B></P>
<P><SPAN style="FONT-FAMILY: 宋体">功能实现团队已成功地完成了</SPAN><SPAN lang=EN-US>FDD</SPAN><SPAN style="FONT-FAMILY: 宋体">第四阶段的工作。</SPAN><SPAN lang=EN-US style="FONT-FAMILY: 楷体_GB2312"></SPAN></P>
<P><B><SPAN lang=EN-US style="COLOR: blue">Tasks:</SPAN></B></P>
<TABLE cellSpacing=0 cellPadding=0 border=1>
<TBODY>
<TR>
<TD class=Normal vAlign=top width=212 bgColor=#d9d9d9>
<P><SPAN style="FONT-FAMILY: 黑体">实现类及其方法</SPAN><SPAN lang=EN-US></SPAN></P></TD>
<TD class=Normal vAlign=top width=212 bgColor=#d9d9d9>
<P><SPAN style="FONT-FAMILY: 黑体">功能实现团队</SPAN><SPAN lang=EN-US></SPAN></P></TD>
<TD class=Normal vAlign=top width=212 bgColor=#d9d9d9>
<P><SPAN style="FONT-FAMILY: 黑体">必须</SPAN><SPAN lang=EN-US></SPAN></P></TD></TR>
<TR>
<TD class=Normal vAlign=top width=637 colSpan=3>
<P><SPAN style="FONT-FAMILY: 楷体_GB2312">根据</SPAN><SPAN lang=EN-US>DBF</SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312">中的详细的序列图类的实现人员完成类的方法的实现。此外他也要为测试实现有关的测试方法。主要开发人员则需添加针对功能的测试方法。</SPAN><SPAN lang=EN-US></SPAN></P></TD></TR>
<TR>
<TD class=Normal vAlign=top width=212 bgColor=#d9d9d9>
<P><SPAN style="FONT-FAMILY: 黑体">代码检查</SPAN><SPAN lang=EN-US></SPAN></P></TD>
<TD class=Normal vAlign=top width=212 bgColor=#d9d9d9>
<P><SPAN style="FONT-FAMILY: 黑体">功能实现团队</SPAN><SPAN lang=EN-US></SPAN></P></TD>
<TD class=Normal vAlign=top width=212 bgColor=#d9d9d9>
<P><SPAN style="FONT-FAMILY: 黑体">必须</SPAN><SPAN lang=EN-US></SPAN></P></TD></TR>
<TR>
<TD class=Normal vAlign=top width=637 colSpan=3>
<P><SPAN style="FONT-FAMILY: 楷体_GB2312">主要开发人员负责安排一次针对</SPAN><SPAN lang=EN-US>BBF</SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312">的代码检查，检查可以在单元测试之前也可以在其后。一般检查是由功能实现团队成员加以完成的，如果主要开发人员认为需要的话，也可以请团队以外的人进行检查。</SPAN><SPAN lang=EN-US></SPAN></P></TD></TR>
<TR>
<TD class=Normal vAlign=top width=212 bgColor=#d9d9d9>
<P><SPAN style="FONT-FAMILY: 黑体">代码检查记录</SPAN><SPAN lang=EN-US></SPAN></P></TD>
<TD class=Normal vAlign=top width=212 bgColor=#d9d9d9>
<P><SPAN style="FONT-FAMILY: 黑体">文档人员</SPAN><SPAN lang=EN-US></SPAN></P></TD>
<TD class=Normal vAlign=top width=212 bgColor=#d9d9d9>
<P><SPAN style="FONT-FAMILY: 黑体">必须</SPAN><SPAN lang=EN-US></SPAN></P></TD></TR>
<TR>
<TD class=Normal vAlign=top width=637 colSpan=3>
<P><SPAN style="FONT-FAMILY: 楷体_GB2312">团队中的文档人员针对每个类的实现人将有关的代码检查活动记录下来。</SPAN><SPAN lang=EN-US></SPAN></P></TD></TR>
<TR>
<TD class=Normal vAlign=top width=212 bgColor=#d9d9d9>
<P><SPAN style="FONT-FAMILY: 黑体">单元测试</SPAN><SPAN lang=EN-US></SPAN></P></TD>
<TD class=Normal vAlign=top width=212 bgColor=#d9d9d9>
<P><SPAN style="FONT-FAMILY: 黑体">功能实现团队</SPAN><SPAN lang=EN-US></SPAN></P></TD>
<TD class=Normal vAlign=top width=212 bgColor=#d9d9d9>
<P><SPAN style="FONT-FAMILY: 黑体">必须</SPAN><SPAN lang=EN-US></SPAN></P></TD></TR>
<TR>
<TD class=Normal vAlign=top width=637 colSpan=3>
<P><SPAN style="FONT-FAMILY: 楷体_GB2312">每个类的实现人员均需测试相应的类的代码以及此类所支持的功能。作为所有功能的集成者，主要开发人员对整个功能进行测试。</SPAN><SPAN lang=EN-US></SPAN></P></TD></TR>
<TR>
<TD class=Normal vAlign=top width=212 bgColor=#d9d9d9>
<P><SPAN lang=EN-US>Check-In</SPAN><SPAN style="FONT-FAMILY: 黑体">代码并对其进行构造</SPAN><SPAN lang=EN-US></SPAN></P></TD>
<TD class=Normal vAlign=top width=212 bgColor=#d9d9d9>
<P><SPAN style="FONT-FAMILY: 黑体">功能实现团队</SPAN><SPAN lang=EN-US></SPAN></P></TD>
<TD class=Normal vAlign=top width=212 bgColor=#d9d9d9>
<P><SPAN style="FONT-FAMILY: 黑体">必须</SPAN><SPAN lang=EN-US></SPAN></P></TD></TR>
<TR>
<TD class=Normal vAlign=top width=637 colSpan=3>
<P><SPAN style="FONT-FAMILY: 楷体_GB2312">代码一旦编写完成并经过检查和测试，类的实现人就可以将其放入配置管理系统中。当所有的类均已完成</SPAN><SPAN lang=EN-US>Check-In</SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312">并且可以正常工作时，主要开发人员将提升代码以便进行构造，同时更新在功能列表中的有关功能的状态信息。</SPAN><SPAN lang=EN-US></SPAN></P></TD></TR></TBODY></TABLE>
<P><B><SPAN lang=EN-US style="COLOR: blue">Verification:</SPAN></B></P>
<TABLE cellSpacing=0 cellPadding=0 border=1>
<TBODY>
<TR>
<TD class=Normal vAlign=top width=212 bgColor=#d9d9d9>
<P><SPAN style="FONT-FAMILY: 黑体">代码检查及单元测试</SPAN><SPAN lang=EN-US></SPAN></P></TD>
<TD class=Normal vAlign=top width=212 bgColor=#d9d9d9>
<P><SPAN style="FONT-FAMILY: 黑体">功能实现团队</SPAN><SPAN lang=EN-US></SPAN></P></TD>
<TD class=Normal vAlign=top width=212 bgColor=#d9d9d9>
<P><SPAN style="FONT-FAMILY: 黑体">必须</SPAN></P></TD></TR>
<TR>
<TD class=Normal vAlign=top width=637 colSpan=3>
<P><SPAN style="FONT-FAMILY: 楷体_GB2312">功能实现团队必须进行代码检查。文档人员应记录有关活动。</SPAN><SPAN lang=EN-US></SPAN></P></TD></TR></TBODY></TABLE>
<P><B><SPAN lang=EN-US style="COLOR: blue">Exit Criteria:</SPAN></B></P>
<P><SPAN style="FONT-FAMILY: 楷体_GB2312">本阶段结束时，应已完成如下工作，并且这些工作已经过主要设计师的审阅及批准。计划中应包括以下内容：</SPAN><SPAN lang=EN-US></SPAN></P>
<P><SPAN lang=EN-US style="FONT-FAMILY: Symbol">-<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312">实现了类的方法并对代码进行了检查和单元测试</SPAN><SPAN lang=EN-US></SPAN></P>
<P><SPAN lang=EN-US style="FONT-FAMILY: Symbol">-<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312">按顺序针对每个类的方法的单元测试记录</SPAN><SPAN lang=EN-US></SPAN></P>
<P><SPAN lang=EN-US style="FONT-FAMILY: Symbol">-<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312">类已被开发人员</SPAN><SPAN lang=EN-US>Check-In</SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312">，主要开发人员已提升代码进行构造并同步更新功能状态。</SPAN><SPAN lang=EN-US></SPAN></P></DIV><img src ="http://www.blogjava.net/kapok/aggbug/5890.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/kapok/" target="_blank">笨笨</a> 2005-06-10 18:07 <a href="http://www.blogjava.net/kapok/archive/2005/06/10/5890.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JUDE 还不错的免费的UML工具</title><link>http://www.blogjava.net/kapok/archive/2005/06/10/5862.html</link><dc:creator>笨笨</dc:creator><author>笨笨</author><pubDate>Fri, 10 Jun 2005 05:40:00 GMT</pubDate><guid>http://www.blogjava.net/kapok/archive/2005/06/10/5862.html</guid><wfw:comment>http://www.blogjava.net/kapok/comments/5862.html</wfw:comment><comments>http://www.blogjava.net/kapok/archive/2005/06/10/5862.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/kapok/comments/commentRss/5862.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/kapok/services/trackbacks/5862.html</trackback:ping><description><![CDATA[<P>JUDE</P><img src ="http://www.blogjava.net/kapok/aggbug/5862.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/kapok/" target="_blank">笨笨</a> 2005-06-10 13:40 <a href="http://www.blogjava.net/kapok/archive/2005/06/10/5862.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>UML的StereoType的解释</title><link>http://www.blogjava.net/kapok/archive/2005/06/10/5846.html</link><dc:creator>笨笨</dc:creator><author>笨笨</author><pubDate>Fri, 10 Jun 2005 03:00:00 GMT</pubDate><guid>http://www.blogjava.net/kapok/archive/2005/06/10/5846.html</guid><wfw:comment>http://www.blogjava.net/kapok/comments/5846.html</wfw:comment><comments>http://www.blogjava.net/kapok/archive/2005/06/10/5846.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/kapok/comments/commentRss/5846.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/kapok/services/trackbacks/5846.html</trackback:ping><description><![CDATA[UML 2.0 Superstructure Specification<BR><A href="http://www.uml.org/">http://www.uml.org/</A><BR>附录部分不错。<BR><BR><A href="http://www.uml.org.cn/oobject/200504115.htm">http://www.uml.org.cn/oobject/200504115.htm</A><BR>
<P class=MsoNormal><SPAN class=content lang=EN-US>UML</SPAN><SPAN class=content style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">中的四种机制使地它简单和更易于使用，你可以在</SPAN><SPAN class=content lang=EN-US>UML</SPAN><SPAN class=content style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">语言的任何时候用同样的方法来使用，这四种机制是：</SPAN></P>
<P class=MsoNormal style="MARGIN-LEFT: 21.25pt; TEXT-INDENT: -21.25pt; mso-list: l4 level1 lfo3; tab-stops: list 21.25pt"><SPAN class=content lang=EN-US style="FONT-FAMILY: Wingdings">l<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN class=content lang=EN-US>specifications</SPAN></P>
<P class=MsoNormal style="MARGIN-LEFT: 21.25pt; TEXT-INDENT: -21.25pt; mso-list: l4 level1 lfo3; tab-stops: list 21.25pt"><SPAN class=content lang=EN-US style="FONT-FAMILY: Wingdings">l<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN class=content lang=EN-US>adornments</SPAN></P>
<P class=MsoNormal style="MARGIN-LEFT: 21.25pt; TEXT-INDENT: -21.25pt; mso-list: l4 level1 lfo3; tab-stops: list 21.25pt"><SPAN class=content lang=EN-US style="FONT-FAMILY: Wingdings">l<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN class=content lang=EN-US>common divisions</SPAN></P>
<P class=MsoNormal style="MARGIN-LEFT: 21.25pt; TEXT-INDENT: -21.25pt; mso-list: l4 level1 lfo3; tab-stops: list 21.25pt"><SPAN class=content lang=EN-US style="FONT-FAMILY: Wingdings">l<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN class=content lang=EN-US>extensibility</SPAN></P>
<P class=MsoNormal><SPAN class=content style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">本章讨论</SPAN><SPAN class=content lang=EN-US>adornments</SPAN><SPAN class=content style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">和</SPAN><SPAN class=content lang=EN-US>extensibility</SPAN><SPAN class=content style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">这两种机制。</SPAN><SPAN class=content lang=EN-US><?XML:NAMESPACE PREFIX = O /><O:P></O:P> </SPAN></P>
<P class=MsoNormal><SPAN class=content style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">注释是最重要的一种修饰。一个注释在</SPAN><SPAN class=content lang=EN-US>UML</SPAN><SPAN class=content style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">中是一个图形符号，描述了和它相关联的元素或一组元素的限制或注释语。</SPAN></P>
<P class=content><?XML:NAMESPACE PREFIX = V /><V:SHAPETYPE id=_x0000_t75 stroked="f" filled="f" path="m@4@5l@4@11@9@11@9@5xe" o:preferrelative="t" o:spt="75" coordsize="21600,21600"><V:STROKE joinstyle="miter"></V:STROKE><V:FORMULAS><V:F eqn="if lineDrawn pixelLineWidth 0"></V:F><V:F eqn="sum @0 1 0"></V:F><V:F eqn="sum 0 0 @1"></V:F><V:F eqn="prod @2 1 2"></V:F><V:F eqn="prod @3 21600 pixelWidth"></V:F><V:F eqn="prod @3 21600 pixelHeight"></V:F><V:F eqn="sum @0 0 1"></V:F><V:F eqn="prod @6 1 2"></V:F><V:F eqn="prod @7 21600 pixelWidth"></V:F><V:F eqn="sum @8 21600 0"></V:F><V:F eqn="prod @7 21600 pixelHeight"></V:F><V:F eqn="sum @10 21600 0"></V:F></V:FORMULAS><V:PATH o:connecttype="rect" gradientshapeok="t" o:extrusionok="f"></V:PATH><O:LOCK aspectratio="t" v:ext="edit"></O:LOCK></V:SHAPETYPE>
<TABLE cellSpacing=0 cellPadding=0 align=left>
<TBODY>
<TR>
<TD width=168 height=20></TD></TR>
<TR>
<TD></TD>
<TD class=content><IMG height=46 src="http://www.uml.org.cn/oobject/images/umlcon27.gif" width=208 v:shapes="_x0000_s1026"></TD></TR></TBODY></TABLE><SPAN class=content lang=EN-US>&nbsp;<O:P> </O:P></SPAN>
<P class=content>&nbsp;<O:P> </O:P></P>
<P class=content>&nbsp;<O:P> </O:P></P>
<P class=MsoNormal><SPAN class=content lang=EN-US>&nbsp;<O:P> </O:P></SPAN><SPAN class=content style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">上图就是一个使用注释的例子，图中右边的为注释符号。</SPAN></P>
<P class=MsoNormal><SPAN class=content lang=EN-US>&nbsp;<O:P> </O:P>UML</SPAN><SPAN class=content style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的扩充性机制允许你在控制的方式下扩充</SPAN><SPAN class=content lang=EN-US>UML</SPAN><SPAN class=content style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">语言。这一类的机制包括：</SPAN><SPAN class=content lang=EN-US>stereotype</SPAN><SPAN class=content style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，标记值、约束。</SPAN><SPAN class=content lang=EN-US>Stereotype</SPAN><SPAN class=content style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">扩充了</SPAN><SPAN class=content lang=EN-US>UML</SPAN><SPAN class=content style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的词汇表，允许你创建新的建筑块，这些建筑块从已有的继承而来，但特别针对你的问题。标记值扩充了</SPAN><SPAN class=content lang=EN-US>UML</SPAN><SPAN class=content style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的建筑块的属性，允许你在元素的规格中创建新的信息。约束扩充了</SPAN><SPAN class=content lang=EN-US>UML</SPAN><SPAN class=content style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">建筑块的语义，允许你添加新的规则或修改已有的。你将使用这些机制来让</SPAN><SPAN class=content lang=EN-US>UML</SPAN><SPAN class=content style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">满足你的领域和开发的特别需要。</SPAN></P>
<P class=content>&nbsp; 
<TABLE cellSpacing=0 cellPadding=0 align=left>
<TBODY>
<TR>
<TD width=220 height=28></TD></TR>
<TR>
<TD></TD>
<TD class=content><IMG height=83 src="http://www.uml.org.cn/oobject/images/umlcon28.gif" width=113 v:shapes="_x0000_s1027"></TD></TR></TBODY></TABLE><SPAN class=content lang=EN-US>&nbsp;<O:P> </O:P></SPAN>
<P class=content>&nbsp;<O:P> </O:P></P>
<P class=content>&nbsp;<O:P> </O:P></P>
<P class=MsoNormal><SPAN class=content lang=EN-US>&nbsp;<O:P> </O:P><O:P></O:P><O:P></O:P></SPAN><SPAN class=content><BR style="mso-ignore: vglayout" clear=all><SPAN style="FONT-FAMILY: 宋体"><BR></SPAN></SPAN><SPAN class=content style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">上面是一个使用扩充机制的例子。</SPAN><SPAN class=content lang=EN-US>&lt;&lt;subsystem&gt;&gt;</SPAN><SPAN class=content style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">是</SPAN><SPAN class=content lang=EN-US>stereotype</SPAN><SPAN class=content style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，</SPAN><SPAN class=content lang=EN-US>{version = 3.2}</SPAN><SPAN class=content style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">是标记值</SPAN></P>
<P class=content>&nbsp;<O:P> </O:P></P>
<P class=content><O:P></O:P></P>
<H3 class=content>术语和概念</H3>
<P class=MsoNormalIndent><SPAN class=content><I style="mso-bidi-font-style: normal"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;注释</SPAN></I><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">是一种图形符号用来限制或给一个元素或一组元素加上注解。<I style="mso-bidi-font-style: normal">注释</I>画成一个带折角的矩形，在矩形中加上文字或图形的注解，</SPAN></SPAN><SPAN class=content lang=EN-US><O:P></O:P></SPAN><SPAN class=content><I style="mso-bidi-font-style: normal"><SPAN lang=EN-US>stereotype</SPAN></I><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">是</SPAN></SPAN><SPAN class=content lang=EN-US>UML</SPAN><SPAN class=content style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">词汇的扩充，允许你创建新的</SPAN><SPAN class=content lang=EN-US>UML</SPAN><SPAN class=content style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">建筑块，这些新的建筑块和原有的类似，但特别针对你自己的问题。通常</SPAN><SPAN class=content lang=EN-US>stereotype</SPAN><SPAN class=content style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">画成用</SPAN><SPAN class=content lang=EN-US>&lt;&lt;</SPAN><SPAN class=content style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">和</SPAN><SPAN class=content lang=EN-US>&gt;&gt;</SPAN><SPAN class=content style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">包围起来的一个名字，通常放在另一个元素的名字之上。作为可选，</SPAN><SPAN class=content lang=EN-US>stereotype</SPAN><SPAN class=content style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">可以画成加一个图标。</SPAN></P>
<P class=MsoNormalIndent><SPAN class=content>&nbsp;&nbsp;&nbsp;&nbsp;<SPAN lang=EN-US><O:P></O:P></SPAN><I style="mso-bidi-font-style: normal"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">标记值</SPAN></I><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">是</SPAN></SPAN><SPAN class=content lang=EN-US>UML</SPAN><SPAN class=content style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">元素特性的扩充，允许你创建元素规格的新的信息。在</SPAN><SPAN class=content lang=EN-US>UML</SPAN><SPAN class=content style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">中标记值画成</SPAN><SPAN class=content lang=EN-US>{}</SPAN><SPAN class=content style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">内的字符串，跟在元素名后面。</SPAN><SPAN class=content lang=EN-US><O:P></O:P> </SPAN></P>
<P class=MsoNormalIndent><SPAN class=content><I style="mso-bidi-font-style: normal"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;限制</SPAN></I><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">是</SPAN></SPAN><SPAN class=content lang=EN-US>UML</SPAN><SPAN class=content style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">元素语义的扩充，允许你对一个</SPAN><SPAN class=content lang=EN-US>UML</SPAN><SPAN class=content style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">元素添加新规则或修改存在的规则。限制通常画成</SPAN><SPAN class=content lang=EN-US>{}</SPAN><SPAN class=content style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">内的字符串，放在关系附近。当然，你也可以把限制用注释来表示。</SPAN><SPAN class=content lang=EN-US><O:P></O:P></SPAN></P>
<H3 class=content>通用建模技术</H3>
<P class=MsoNormalIndent style="MARGIN-LEFT: 42.25pt; TEXT-INDENT: -21.25pt; mso-list: l2 level1 lfo4; tab-stops: list 42.25pt"><SPAN class=content lang=EN-US>1.<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN class=content style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">建模注解</SPAN></P>
<P class=content style="MARGIN-LEFT: 21pt; TEXT-INDENT: 0cm">使用注释的目的是为了让模型更清晰，下面是使用注释的一些技巧：</P>
<P class=MsoNormalIndent style="MARGIN-LEFT: 42.25pt; TEXT-INDENT: -21.25pt; mso-list: l5 level1 lfo5; tab-stops: list 42.25pt"><SPAN class=content lang=EN-US style="FONT-FAMILY: Wingdings">l<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN class=content style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">将注释放在你要注解的元素边上，写下注解的文字。用依赖关系的线将注释和被注释的元素连起来会让人更明白。</SPAN></P>
<P class=MsoNormalIndent style="MARGIN-LEFT: 42.25pt; TEXT-INDENT: -21.25pt; mso-list: l5 level1 lfo5; tab-stops: list 42.25pt"><SPAN class=content lang=EN-US style="FONT-FAMILY: Wingdings">l<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN class=content style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">记住，你可以隐藏元素或使隐藏的元素可见。这就意味着你可以将注释不隐藏起来，而她注释的元素是可见的，这样会使你的模型图简洁，在必要的地方让注释可见。</SPAN></P>
<P class=MsoNormalIndent style="MARGIN-LEFT: 42.25pt; TEXT-INDENT: -21.25pt; mso-list: l5 level1 lfo5; tab-stops: list 42.25pt"><SPAN class=content lang=EN-US style="FONT-FAMILY: Wingdings">l<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN class=content style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">如果你的注释很长或不仅仅是普通文本，你可以将你的注解放到一个独立的外部文件中（如</SPAN><SPAN class=content lang=EN-US>WORD</SPAN><SPAN class=content style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">文档）然后链接或嵌入到你的模型中。</SPAN></P>
<P class=content>下面是一个使用注解的例子：</P>
<P class=content style="TEXT-INDENT: 0cm">&nbsp; 
<TABLE cellSpacing=0 cellPadding=0 align=left>
<TBODY>
<TR>
<TD width=0 height=7></TD></TR>
<TR>
<TD></TD>
<TD class=content><IMG height=257 src="http://www.uml.org.cn/oobject/images/umlcon29.gif" width=574 v:shapes="_x0000_s1028"></TD></TR></TBODY></TABLE><SPAN class=content lang=EN-US>&nbsp;<O:P> </O:P></SPAN>
<P class=content style="TEXT-INDENT: 0cm">&nbsp;<O:P> </O:P></P>
<P class=content style="TEXT-INDENT: 0cm">&nbsp;<O:P> </O:P></P>
<P class=content style="TEXT-INDENT: 0cm">&nbsp;<O:P> </O:P></P>
<P class=content style="TEXT-INDENT: 0cm">&nbsp;<O:P> </O:P></P>
<P class=content style="TEXT-INDENT: 0cm">&nbsp;<O:P> </O:P></P>
<P class=content style="TEXT-INDENT: 0cm">&nbsp;<O:P> </O:P></P>
<P class=content style="TEXT-INDENT: 0cm">&nbsp;<O:P> </O:P></P>
<P class=content style="TEXT-INDENT: 0cm">&nbsp;<O:P> </O:P><O:P></O:P><O:P></O:P><O:P></O:P><O:P></O:P><O:P></O:P></P>
<H3 class=content>建立新的建筑块</H3>
<P class=MsoNormalIndent><SPAN class=content lang=EN-US>&nbsp;&nbsp;&nbsp;&nbsp;UML</SPAN><SPAN class=content style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的建筑块如：类、接口、合作、组件、注释、关系等等，都在为具体问题建模的时候基本上是够用了。然而，如果你想扩展你的模型的词汇，如用来表示你的特定的问题领域，你需要</SPAN><SPAN class=content lang=EN-US>stereotypes</SPAN><SPAN class=content style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">。</SPAN></P>
<P class=content>&nbsp;&nbsp;&nbsp;&nbsp;建立新的建筑块有如下的技巧：</P>
<P class=MsoNormalIndent style="MARGIN-LEFT: 42.25pt; TEXT-INDENT: -21.25pt; mso-list: l3 level1 lfo6; tab-stops: list 42.25pt"><SPAN class=content lang=EN-US style="FONT-FAMILY: Wingdings">l<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN class=content style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">确定没有现成的基本的</SPAN><SPAN class=content lang=EN-US>UML</SPAN><SPAN class=content style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">方法可以表达你的需要。如果你碰到一个普通的建模问题，很有可能已经有某种标准的</SPAN><SPAN class=content lang=EN-US>stereotype</SPAN><SPAN class=content style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">是你想要的。</SPAN></P>
<P class=MsoNormalIndent style="MARGIN-LEFT: 42.25pt; TEXT-INDENT: -21.25pt; mso-list: l3 level1 lfo6; tab-stops: list 42.25pt"><SPAN class=content lang=EN-US style="FONT-FAMILY: Wingdings">l<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN class=content style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">如果你确信没有现成的东西可以表达这些语义，首先找到一个</SPAN><SPAN class=content lang=EN-US>UML</SPAN><SPAN class=content style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">中的最接近你要建立的模型的元素（例如：类、接口、组件、注释、关系等等）然后为她定义一个</SPAN><SPAN class=content lang=EN-US>stereotype</SPAN><SPAN class=content style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">。值得一提的是你可以定义</SPAN><SPAN class=content lang=EN-US>stereotypes</SPAN><SPAN class=content style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的层次从而得到一般的</SPAN><SPAN class=content lang=EN-US>stereotypes</SPAN><SPAN class=content style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">和为它定义的特别的特性。这种方法尽量少用。</SPAN></P>
<P class=MsoNormalIndent style="MARGIN-LEFT: 42.25pt; TEXT-INDENT: -21.25pt; mso-list: l3 level1 lfo6; tab-stops: list 42.25pt"><SPAN class=content lang=EN-US style="FONT-FAMILY: Wingdings">l<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN class=content style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">通过对普通的</SPAN><SPAN class=content lang=EN-US>stereotype</SPAN><SPAN class=content style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">定义一组标记值和对</SPAN><SPAN class=content lang=EN-US>stereotype</SPAN><SPAN class=content style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">进行限制可以实现普通</SPAN><SPAN class=content lang=EN-US>stereotype</SPAN><SPAN class=content style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">不能实现的功能。</SPAN></P>
<P class=MsoNormalIndent style="MARGIN-LEFT: 42.25pt; TEXT-INDENT: -21.25pt; mso-list: l3 level1 lfo6; tab-stops: list 42.25pt"><SPAN class=content lang=EN-US style="FONT-FAMILY: Wingdings">l<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN class=content style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">如果你希望这些</SPAN><SPAN class=content lang=EN-US>stereotype</SPAN><SPAN class=content style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">具有不同的视觉效果，为他们定义一个特别的图标。</SPAN></P>
<P class=content style="MARGIN-LEFT: 21pt; TEXT-INDENT: 0cm"><V:SHAPE id=_x0000_i1026 style="WIDTH: 414.75pt; HEIGHT: 4in" type="#_x0000_t75" fillcolor="window" o:ole=""><V:IMAGEDATA o:title="" src="file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/msoclip1/01/clip_image007.wmz"></V:IMAGEDATA></V:SHAPE><IMG height=384 src="http://www.uml.org.cn/oobject/images/umlcon30.gif" width=553 v:shapes="_x0000_i1026"></P>
<P class=MsoNormalIndent style="MARGIN-LEFT: 21pt; TEXT-INDENT: 0cm"><SPAN class=content style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">上面是一个例子。假如你用活动图来为一个涉及到教练工作流和队员工作流的体育活动建模。在这里，区别教练和运动员以及与其他的本领域的对象是有意义的。上面的图中有两个事物是很突出的，教练对象和队员对象。这里不仅仅是普通的类，更确切地说，他们现在是两个新的建筑块。因为定义了教练和员</SPAN><SPAN class=content lang=EN-US>stereotype</SPAN><SPAN class=content style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，并且运用到了</SPAN><SPAN class=content lang=EN-US>UML</SPAN><SPAN class=content style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的类上。在这个图上，被标记为</SPAN><SPAN class=content lang=EN-US>:Coach</SPAN><SPAN class=content style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">和</SPAN><SPAN class=content lang=EN-US>:Team</SPAN><SPAN class=content style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的匿名实例，后者显示了不同的状态。</SPAN></P>
<H3 class=content>建模新属性</H3>
<P class=MsoNormalIndent style="MARGIN-LEFT: 21pt; TEXT-INDENT: 0cm"><SPAN class=content lang=EN-US>UML</SPAN><SPAN class=content style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">建筑块的基本属性如：类的属性和操作，包的内容等等，都足够描述清楚你要建立的模型。然而，如果你想扩展这些基本建筑块（或者用</SPAN><SPAN class=content lang=EN-US>stereotype</SPAN><SPAN class=content style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">建立的新的建筑块）的属性，你就需要使用标记值。</SPAN></P>
<P class=content style="MARGIN-LEFT: 21pt; TEXT-INDENT: 0cm">下面是一些技巧：</P>
<P class=MsoNormalIndent style="MARGIN-LEFT: 42.25pt; TEXT-INDENT: -21.25pt; mso-list: l0 level1 lfo7; tab-stops: list 42.25pt"><SPAN class=content lang=EN-US style="FONT-FAMILY: Wingdings">l<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN class=content style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">首先要确定的是你的需要无法用基本的</SPAN><SPAN class=content lang=EN-US>UML</SPAN><SPAN class=content style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">表达。如果你碰到一个普通的建模问题，很有可能已经有某种标准的标记值是你想要的</SPAN></P>
<P class=MsoNormalIndent style="MARGIN-LEFT: 42.25pt; TEXT-INDENT: -21.25pt; mso-list: l0 level1 lfo7; tab-stops: list 42.25pt"><SPAN class=content lang=EN-US style="FONT-FAMILY: Wingdings">l<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN class=content style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">如果你确定没有其他的方法可以表达你需要的语义，添加新的属性到一个单独的元素或一个</SPAN><SPAN class=content lang=EN-US>stereotype</SPAN><SPAN class=content style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">。继承的规则是适用的，也就是说对父亲定义的标记值对儿子也具有。</SPAN><SPAN class=content lang=EN-US><V:SHAPE id=_x0000_i1027 style="WIDTH: 249pt; HEIGHT: 200.25pt" type="#_x0000_t75" fillcolor="window"><V:IMAGEDATA o:title="" src="file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/msoclip1/01/clip_image009.wmz"></V:IMAGEDATA> </V:SHAPE><IMG height=267 src="http://www.uml.org.cn/oobject/images/umlcon31.gif" width=332 v:shapes="_x0000_i1027"></SPAN></P>
<H3 class=content>建立新的语义</H3>
<P class=MsoNormalIndent><SPAN class=content style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">&nbsp;&nbsp;&nbsp;当你用</SPAN><SPAN class=content lang=EN-US>UML</SPAN><SPAN class=content style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">建立模型的时候，你总是使用</SPAN><SPAN class=content lang=EN-US>UML</SPAN><SPAN class=content style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">定义的规则，这实在是件好事，因为别的懂得如何读</SPAN><SPAN class=content lang=EN-US>UML</SPAN><SPAN class=content style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的人可以毫无偏差地读懂你想要表达的东西。然而，如果你发现你需要表达的语义是</SPAN><SPAN class=content lang=EN-US>UML</SPAN><SPAN class=content style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">无法表达的或你想要修改</SPAN><SPAN class=content lang=EN-US>UML</SPAN><SPAN class=content style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的规则，这时你就需要使用限制了。下面是使用限制的一些技巧：</SPAN></P>
<P class=MsoNormalIndent style="MARGIN-LEFT: 42.25pt; TEXT-INDENT: -21.25pt; mso-list: l1 level1 lfo8; tab-stops: list 42.25pt"><SPAN class=content lang=EN-US style="FONT-FAMILY: Wingdings">l<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN class=content style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">首先要确定的是你的需要无法用基本的</SPAN><SPAN class=content lang=EN-US>UML</SPAN><SPAN class=content style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">表达。如果你碰到一个普通的建模问题，很有可能已经有某种标准的限制是你想要的。</SPAN></P>
<P class=MsoNormalIndent style="MARGIN-LEFT: 42.25pt; TEXT-INDENT: -21.25pt; mso-list: l1 level1 lfo8; tab-stops: list 42.25pt"><SPAN class=content lang=EN-US style="FONT-FAMILY: Wingdings">l<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN class=content style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">如果你确定没有其他的方法可以表达你需要的语义，用文本的形式在限制中写下你的新语义，并且将他放在他涉及的元素附近。你可以使用依赖关系来明确地表示限制和他涉及的元素之间的关联。</SPAN></P>
<P class=MsoNormalIndent style="MARGIN-LEFT: 42.25pt; TEXT-INDENT: -21.25pt; mso-list: l1 level1 lfo8; tab-stops: list 42.25pt"><SPAN class=content lang=EN-US style="FONT-FAMILY: Wingdings">l<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN class=content style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">如果你需要详细说明你的语义，你可以用使用</SPAN><SPAN class=content lang=EN-US>OCL</SPAN><SPAN class=content style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">把它写下来。</SPAN></P>
<P class=content style="MARGIN-LEFT: 21pt; TEXT-INDENT: 0cm">下面的图是一个公司人力资源系统的一小部分：</P>
<P class=content style="MARGIN-LEFT: 21pt; TEXT-INDENT: 0cm; TEXT-ALIGN: center" align=center><V:SHAPE id=_x0000_i1025 style="WIDTH: 212.25pt; HEIGHT: 159.75pt" type="#_x0000_t75" fillcolor="window" o:ole=""><V:IMAGEDATA o:title="" src="file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/msoclip1/01/clip_image011.wmz"></V:IMAGEDATA></V:SHAPE><IMG height=213 src="http://www.uml.org.cn/oobject/images/umlcon32.gif" width=283 v:shapes="_x0000_i1025"></P>
<P class=MsoNormalIndent style="MARGIN-LEFT: 21pt; TEXT-INDENT: 0cm"><SPAN class=content style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">这副图显示了每个</SPAN><SPAN class=content lang=EN-US>Person</SPAN><SPAN class=content style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">可能是</SPAN><SPAN class=content lang=EN-US>0</SPAN><SPAN class=content style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">个或多个</SPAN><SPAN class=content lang=EN-US>Department</SPAN><SPAN class=content style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的成员。每个</SPAN><SPAN class=content lang=EN-US>Department</SPAN><SPAN class=content style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">至少要有一个</SPAN><SPAN class=content lang=EN-US>Person</SPAN><SPAN class=content style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">成员。这副图进一步说明每个</SPAN><SPAN class=content lang=EN-US>Department</SPAN><SPAN class=content style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">严格地有一个</SPAN><SPAN class=content lang=EN-US>Person</SPAN><SPAN class=content style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">作为管理者，每个</SPAN><SPAN class=content lang=EN-US>Person</SPAN><SPAN class=content style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">可以是</SPAN><SPAN class=content lang=EN-US>0</SPAN><SPAN class=content style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">个或多个</SPAN><SPAN class=content lang=EN-US>Department</SPAN><SPAN class=content style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的被管理人员。所有的这些语义可以被简单的</SPAN><SPAN class=content lang=EN-US>UML</SPAN><SPAN class=content style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">表达。然而，为了指出一个管理者必须也是</SPAN><SPAN class=content lang=EN-US>Department</SPAN><SPAN class=content style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的成员是多员关系所忽略的，也是简单的</SPAN><SPAN class=content lang=EN-US>UML</SPAN><SPAN class=content style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">无法表达的。为了表达这种关系，你必须写下一个限制指出管理者是</SPAN><SPAN class=content lang=EN-US>Department</SPAN><SPAN class=content style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">成员的一个子集。从子集到超集用依赖关系将两个关系联系起来。<BR><BR><BR><BR><BR><BR><A href="http://www.uml.org.cn/UMLApplication/UMLApplication30.htm"><FONT face="Times New Roman">http://www.uml.org.cn/UMLApplication/UMLApplication30.htm</FONT></A><BR><BR>
<TABLE cellSpacing=0 cellPadding=0 width=760 align=center border=0>
<TBODY>
<TR>
<TD class=title vAlign=center align=middle height=56><B><FONT color=#ff0000 size=3><SPAN class=p16>在Java中保留Stereotype</SPAN><!-- #EndEditable --></FONT></B></TD></TR>
<TR>
<TD class=formtitle align=middle height=40><!-- #BeginEditable "2" -->作者：仙人掌工作室 &nbsp;&nbsp;&nbsp;本文选自：赛迪网<!-- #EndEditable --></TD></TR></TBODY></TABLE>
<TABLE height=65 cellSpacing=0 cellPadding=0 width=760 align=center border=0>
<TBODY>
<TR>
<TD class=content height=65><!-- #BeginEditable "3" -->
<TABLE width="85%" align=center border=0>
<TBODY>
<TR><FONT size=2>在前面两篇文章中（<A href="http://www.uml.org.cn/UMLApplication/UMLApplication28.htm?columnID=294&amp;articleID=28875&amp;pageNO=1" target=_blank><FONT color=#002c99>《用UML描述Java类》</FONT></A>和<A href="http://www.uml.org.cn/UMLApplication/UMLApplication29.htm?columnID=294&amp;articleID=28877&amp;pageNO=1" target=_blank><FONT color=#002c99>《在UML中表示Java继承和接口》</FONT></A>），我们比较了在Java编程语言以及UML建模语言这两种环境中，类以及类之间关系在表达方式以及概念方面的差异。下面我们要来看看UML Stereotype机制对于编写Java代码的影响。<BR><BR>
<CENTER><FONT color=#000099><STRONG>在Java程序中保留Stereotype</STRONG></FONT></CENTER><BR><BR>UML拥有一系列可用来扩展其核心概念的机制，但最为人们熟知的也许就是Stereotype。Stereotype一般译作“构造型”，它是一种扩展元模型语义的建模元素。构造型必须基于元模型中特定的现有类型或类。构造型可扩展已有类型和类的语义，但不能改动它们的结构。构造型默认的表示方法是在关键词周围加上尖角双括号，这种双括号在某些欧洲语言中自然存在，因为它很象两个尖括号，所以用两个尖括号也是一种被认可的表示方式。<BR><BR>构造型几乎适用于UML中的任何元素，包括类、属性、操作以及关联等。例如，我们可以用构造型来显示UML图中一个类别的类。图一显示了用构造型来表示State设计模式中一个类扮演的角色，改编自《Design Patterns》一书。UML定义了大量的标准构造型，我们既可以使用这些标准构造型，也可以定义自己的构造型。<BR><BR>
<CENTER><IMG height=289 src="http://www.uml.org.cn/UMLApplication/images/38606.gif" width=496></CENTER><BR><BR>
<CENTER>图一：UML构造型用于表示类在设计模式中的角色</CENTER><BR><BR>图一中的MessageStatus接口本来应该让interface这个词位于尖括号之内。但是，为了把接口和其他构造型区分出来，用来制作本文UML图的Together ControlCenter工具已予以省略。这是因为接口与其他构造型不同，“在UML元模型中接口也具有与类相似的特性”。<BR><BR>直到UML1.4之前（20001年9月），UML中的一个图形元素只能有一个构造型。但在UML 1.4中，OMG（对象管理组织）取消了这个限制，现在一个图形元素可以有多个构造型。许多UML工具由于未能跟上这一变化，所以仍没有提供这方面的支持。<BR><BR>那么，构造型对于我们的Java代码又有何影响呢？从某种意义上讲，答案是“完全没有”，因为Java没有提供任何让我们按照这种方式对类进行分类的手段（前面几篇文章已经讨论了接口和继承，在UML中它们都有自己特定的表示方法）。但是，另一方面，我们可以利用构造型更清楚、明白地说明Java代码的含义：首先约定构造型的具体意义，然后在源代码注释中以一个新的javadoc标记的形式包含构造型，有效地减少为了说明Java代码含义而需要手工编写的说明文字数量。下面的代码片断就是图一Sent类的骨架代码，构造型以一个定制javadoc标记的形式加入到了注释之中：<BR><BR><CCID_NOBR></FONT></TR></TBODY></TABLE>
<TABLE cellSpacing=0 borderColorDark=#ffffff cellPadding=2 width=550 align=center borderColorLight=black border=1>
<TBODY>
<TR>
<TD class=code bgColor=#e6e6e6><PRE><FONT size=2><CCID_CODE>
/**
 * @Stereotype concreteState
 * @author AuthorName
 * @version 0.0001
 */
public class Sent implements MessageStatus {
}</CCID_CODE>
</FONT></PRE></TD></TR></TBODY></TABLE><FONT size=2></CCID_NOBR><BR><BR>在UML中，并非只有类可以通过指定构造型而约束其定义。图二显示了两个类之间的依赖关系，用构造型来表示这种依赖关系的类型。在这个例子中，Factory类的对象负责创建Item类的对象。Factory类的代码显示了定制的javadoc标记如何用构造型来简洁明了地说明这种依赖关系。<BR><BR>
<CENTER><IMG height=135 src="http://www.uml.org.cn/UMLApplication/images/38608.gif" width=375></CENTER><BR><BR>
<CENTER>图二：加注instantiate构造型的UML依赖关系</CENTER><BR><BR>符号说明：在前面的文章中，我们看到了三种类之间的关系，这里出现的是第四种。关联关系用一根实线加上开叉的箭头表示（如果关联关系是单向的话），一般化关系用实线加上封闭的箭头（从子类指向超类）表示，Realization关系用虚线加上封闭的箭头（从实现接口的类指向接口）表示。现在我们看到了第四种箭头与线型的组合：虚线加上开叉箭头表示的依赖关系。<BR><BR><CCID_NOBR></FONT>
<TABLE cellSpacing=0 borderColorDark=#ffffff cellPadding=2 width=550 align=center borderColorLight=black border=1>
<TBODY>
<TR>
<TD class=code bgColor=#e6e6e6><PRE><FONT size=2><CCID_CODE>
public class Factory
{
  /**
   * @dependency &lt;&lt;instantiate&gt;&gt; Item 
   * @return a new Item
   */
  public Item createItem() {
        return new Item();
  }
}</CCID_CODE>
</FONT></PRE></TD></TR></TBODY></TABLE><FONT size=2></CCID_NOBR><BR><BR>操作和属性同样可以指定构造型。如图三所示，两个操作被加注了构造型，用来表示它们是否会修改属性的值。与图三对应的源代码同样利用定制的javadoc标记说明该方法的构造型信息。<BR><BR>
<CENTER><IMG height=154 src="http://www.uml.org.cn/UMLApplication/images/38615.gif" width=158></CENTER><BR><BR>
<CENTER>图三：为类的操作加注UML构造型</CENTER><BR><BR><CCID_NOBR></FONT>
<TABLE cellSpacing=0 borderColorDark=#ffffff cellPadding=2 width=550 align=center borderColorLight=black border=1>
<TBODY>
<TR>
<TD class=code bgColor=#e6e6e6><PRE><FONT size=2><CCID_CODE>
public class Sale
{
    ...
  /**
   * @Stereotype query
   * @return total price of sale
   */
  public BigDecimal calcTotal() {
  }
    ...
}</CCID_CODE>
</FONT></PRE></TD></TR></TBODY></TABLE><FONT size=2></CCID_NOBR><BR><BR>在java源代码中加上了描述构造型信息的定制javadoc标记之后，好处不仅仅在于减少了需要手工编写的注释，而且使得UML工具有可能处理这些标记并完成下面这类任务：<BR><BR>从Java源代码重新生成（比没有定制javadoc标记的情况下）更加完整的UML图。<BR><BR>在Javadoc生成的文档中增加额外的信息。<BR><BR>例如，本文所用的建模工具TogetherSoft的Together ControlCentre，就是用这种方法来保留各种无法直接在Java源代码中保留的UML类图语义信息。<BR><BR>
<CENTER><FONT color=#000099><STRONG>其他表示方法</STRONG></FONT></CENTER><BR><BR>本文开头提到，尖括号是显示构造型的默认方式。实际上，构造型还可以用改变图形符号或形状的方式表示。图四的例子显示了两个带有<CCID_CODE> &lt;&lt;actor&gt;&gt;</CCID_CODE> 构造型的类。Cashier利用&lt;<ACTOR> &gt;构造型的替代符号画出，Manager类用默认的矩形画出。在使用替代符号时，很难再列出类的各种属性和操作，所以通常省略。还有第三种表示方法，即在常规的矩形符号内的类名称右边放上一个很小的替代符号，但现在这种表示方法已经不太见到了。<BR><BR>
<CENTER><IMG height=119 src="http://www.uml.org.cn/UMLApplication/images/38610.gif" width=204></CENTER><BR><BR>
<CENTER><CCID_CODE>图四：&lt;&lt;actor&gt;&gt;构造型的替代符号</CCID_CODE> </CENTER><BR><BR>在类图中使用替代符号表示构造型有一个很大的缺点，如果有些人不熟悉类图用到的符号，要理解类图表达的是什么意思就很困难了。另外，多一种符号，理解图形的负担就增加一分。在这个系列的文章中，我们只关注那些最常见的UML类图符号。<BR><BR>除了用改变符号形状的方法来表示已经指定了某种构造型之外，我们还可以通过改变图形元素的颜色或纹理来表达同样的信息。运用色彩意味着我们可以保留常规的图形形状和符号，同时又能表达出与改变形状同样多的视觉信息（如果不是更多的话）。另外，与抽象的形状相比，简单的配色方案一般更容易掌握一些。<BR><BR>
<CENTER><IMG height=655 src="http://www.uml.org.cn/UMLApplication/images/38612.gif" width=521></CENTER><BR><BR>
<CENTER>图五：在类图中运用色彩</CENTER><BR><BR>图五的彩色类图运用了Peter Coad等人的四色原型（Archetype）组合来定义类。<BR><BR>粉红色的<CCID_CODE> &lt;&lt;moment-interval&gt;&gt;</CCID_CODE> 类表示在一个系统中，由于业务或者合法性的原因必须跟踪的事件或活动。CarSale和CarRental就是两个粉红色类的例子。<BR><BR>黄色的<CCID_CODE> &lt;&lt;role&gt;&gt;</CCID_CODE> 类代表参与事件或活动的方式，例如，CarSalesperson和Customer都是黄色类的例子。<BR><BR>绿色的类可进一步分成<CCID_CODE> &lt;&lt;party&gt;&gt;（通常是一个人或组织）、&lt;&lt;place&gt;&gt;（事件或活动发生的地点）以及&lt;thing&gt;&gt;（实际涉及事件或活动的物体）</CCID_CODE> 。<BR><BR>第四种原型是蓝色的catalog-entry-like-description（简称<CCID_CODE> &lt;&lt;description&gt;&gt;</CCID_CODE> ），表示的是诸如现实当中的汽车与展览目录中的描述之间的差异：汽车型号属于蓝色的类，它包含一系列的值和取值范围描述所有属于该类别的车，而每一辆现实中的车则由绿色的<CCID_CODE> &lt;&lt;thing&gt;&gt;</CCID_CODE> 来表示。<BR><BR>属于特定原型的类具有或多或少相似的属性和行为，属于同一原型的类还会倾向于以通常而言可预测的方式与其他原型的类交互。这些特征和行为模式可以帮助我们快速构造出健壮的、可扩展的对象模型，迅速掌握有可能被忽略的属性和操作，增强我们对代码结构的信心。图五显示了我们可能在各种原型的类中找到的属性和操作，以及各种原型之间的典型关系。<BR><BR>结束语：在这篇文章中，我们了解了对于UML中一些很有用的概念，如果它在Java语言中没有直接的等价概念，如何在Java代码中利用UML的这些概念来保留高层次的设计思想。在<A href="http://www.uml.org.cn/UMLApplication/UMLApplication31.htm?columnID=294&amp;articleID=28873&amp;pageNO=1" target=_blank><FONT color=#002c99>下一篇文章</FONT></A>中，我们将告别UML类图，转而讨论UML另一种重要的图形——交互图，包括序列图和协作图。</FONT> </TD></TR></TBODY></TABLE><BR><BR></SPAN></P><img src ="http://www.blogjava.net/kapok/aggbug/5846.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/kapok/" target="_blank">笨笨</a> 2005-06-10 11:00 <a href="http://www.blogjava.net/kapok/archive/2005/06/10/5846.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>UML 基础: 组件图</title><link>http://www.blogjava.net/kapok/archive/2005/06/08/5764.html</link><dc:creator>笨笨</dc:creator><author>笨笨</author><pubDate>Wed, 08 Jun 2005 10:31:00 GMT</pubDate><guid>http://www.blogjava.net/kapok/archive/2005/06/08/5764.html</guid><wfw:comment>http://www.blogjava.net/kapok/comments/5764.html</wfw:comment><comments>http://www.blogjava.net/kapok/archive/2005/06/08/5764.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/kapok/comments/commentRss/5764.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/kapok/services/trackbacks/5764.html</trackback:ping><description><![CDATA[<A href="http://www-128.ibm.com/developerworks/cn/rational/rationaledge/content/feb05/bell/bell.html#notes">http://www-128.ibm.com/developerworks/cn/rational/rationaledge/content/feb05/bell/bell.html#notes</A><BR><BR>
<TABLE cellSpacing=0 cellPadding=0 border=0>
<TBODY>
<TR vAlign=top align=left>
<TD>
<P>级别: 初级</P></TD></TR></TBODY></TABLE>
<P><A href="http://www-128.ibm.com/developerworks/cn/rational/rationaledge/content/feb05/bell/bell.html#author1"><NAME>Donald Bell</NAME></A><BR>IBM 全球服务, IBM<BR>2005 年 2 月 15 日</P>
<BLOCKQUOTE>来自 Rational Edge：这篇文章介绍组件图，一个在新的统一建模语言 2.0中规定的结构图。</BLOCKQUOTE>
<P><IMG alt=Illustration hspace=8 src="http://www-128.ibm.com/developerworks/cn/rational/rationaledge/content/feb05/bell/bell-illustr.jpg" align=right border=0 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">该文是关于在统一建模语言 2.0或UML中使用的基本图的一系列文章中的一部分。在以前关于 <A href="http://www-128.ibm.com/developerworks/cn/rational/rationaledge/content/feb05/bell/index.html">UML 类图</A>中，我描述了类图的标记集如何作为所有UML 2结构图的基础。随着UML 2的轨迹，本文介绍组件图。</I> </P>
<P></P>
<P><A name=N1004C><SPAN class=atitle2>图的目的</SPAN></A><BR>组件图的主要目的是显示系统组件间的结构关系。在 UML 1.1 中，一个组件表现了实施项目，如文件和可运行的程序。不幸地，这与组件这个术语更为普遍的用法、指象COM组件这样的东西相冲突。随着时间的推移及UML的连续版本发布， UML 组件已经失去了最初的绝大部分含义。UML 2 正式改变了组件概念的本质意思；在 UML 2 中，组件被认为是独立的，在一个系统或子系统中的封装单位，提供一个或多个接口。虽然 UML 2 规范没有严格地声明它，但是组件是呈现事物的更大的设计单元，这些事物一般将使用可更换的组件来实现。但是，并不象在 UML 1. x中，现在，组件必须有严格的逻辑，设计时构造。主要思想是，你能容易地在你的设计中重用及/或替换一个不同的组件实现，因为一个组件封装了行为，实现了特定接口。<A href="http://www-128.ibm.com/developerworks/cn/rational/rationaledge/content/feb05/bell/bell.html#notes" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <SUP>1</SUP> </A></P>
<P>在以组件为基础的开发（CBD）中，组件图为架构师提供一个开始为解决方案建模的自然形式。组件图允许一个架构师验证系统的必需功能是由组件实现的，这样确保了最终系统将会被接受。</P>
<P>除此之外，组件图对于不同的小组是有用的交流工具。图可以呈现给关键项目发起人及实现人员。通常，当组件图将系统的实现人员连接起来的时候，组件图通常可以使项目发起人感到轻松，因为图展示了对将要被建立的整个系统的早期理解。</P>
<P>开发者发现组件图是有用的，因为组件图给他们提供了将要建立的系统的高层次的架构视图，这将帮助开发者开始建立实现的路标，并决定关于任务分配及（或）增进需求技能。系统管理员发现组件图是有用的，因为他们可以获得将运行于他们系统上的逻辑软件组件的早期视图。虽然系统管理员将无法从图上确定物理设备或物理的可执行程序，但是，他们仍然欢迎组件图，因为它较早地提供了关于组件及其关系的信息（这允许系统管理员轻松地计划后面的工作）。</P>
<P><A name=N10066><SPAN class=atitle2>符号</SPAN></A><BR>在现在，组件图符号集使它成为最容易画的 UML 图之一。图 1 显示了一个使用前 UML 1.4 符号的简单的组件图；这个例子显示两个组件之间的关系：一个使用了Inventory System组件的Order System组件。正如你所能见到的，在UML 1.4 中，用一个大方块，并且在它的左边有两个凸出的小方块，来表示组件。</P><IMG height=264 alt="图 1：这个简单的组件图使用 UML 1.4 符号显示Order System的一般性依赖关系" src="http://www-128.ibm.com/developerworks/cn/rational/rationaledge/content/feb05/bell/Bell-Fig1.gif" width=224 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
<P><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">图 1：这个简单的组件图使用 UML 1.4 符号显示Order System的一般性依赖关系</B> </P>
<P>上述的 UML 1.4 符号在 UML 2 中仍然被支持。然而，UML 1.4 符号集在较大的系统中不能很好地调节。关于这一点的理由是，如同我们在这篇文章的其余部分将会见到一样，UML 2 显著地增强了组件图的符号集。在维持它易于理解的条件下，UML 2 符号能够调节得更好，并且符号集也具有更多的信息。 </P>
<P>让我们依照 UML 2 规范一步步建立组件图。</P>
<P><A name=N10082><SPAN class=atitle2>基础</SPAN></A><BR>现在，在 UML 2 中画一个组件很类似于在一个类图上画一个类。事实上，在 UML 2 中，一个组件仅仅是类概念的一个特殊版本。这意味着适用于类分类器的符号规则也适用于组件分类器。（如果你已经读了并理解了我以前的关于大体上的结构图和类图细节的文章 [http:// www. ibm.com/developerworks/cn/rational/rationaledge/content/feb05/bell/index.html]，你就会很易理解组件图）。</P>
<P>在 UML 2 中，一个组件被画成堆积着可选择小块的一个立着的长方形。UML 2 中，组件的一个高层次的抽象视图，可以用一个长方形建模，包括组件的名字和组件原型的文字和/或图标。组件原型的文本是“«component»”，而组件原型图标是在左边有两个凸出的小长方形的一个大长方形（UML 1.4 中组件的符号元素）。图 2 显示，组件可以用UML 2规范中的三种不同方法表示。</P><IMG height=110 alt="图 2：画组件名字区的不同方法" src="http://www-128.ibm.com/developerworks/cn/rational/rationaledge/content/feb05/bell/Bell-Fig2.gif" width=504 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
<P><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">图 2：画组件名字区的不同方法</B> </P>
<P>当在图上画一个组件时，重要的是，你总要包括组件原型文本（在双重尖括号中的那个component，如图 2 所示）和/或图标。理由呢？在 UML 中，没有任何原型分类器的一个长方形被解释为一个类组件。组件原型和/或图标用来区别作为组件元素的长方形。</P>
<P><A name=N1009E><SPAN class=atitle3>为组件提供/要求接口建模</SPAN></A><BR>在图 2 中所画的Order组件表现了所有有效的符号元素；然而，一个典型的组件图包括更多的信息。一个组件元素可以在名字区下面附加额外的区。如前面所提到的，一个组件是提供一个或更多公共接口的独立单元。提供的接口代表了组件提供给它的用户/客户的服务的正式契约。图 3 显示了Order组件有第二个区，用来表示Order组件提供和要求的接口。<A href="http://www-128.ibm.com/developerworks/cn/rational/rationaledge/content/feb05/bell/bell.html#notes" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <SUP>2</SUP> </A></P><IMG height=187 alt="图 3：这里额外的区显示Order组件提供和要求的接口。" src="http://www-128.ibm.com/developerworks/cn/rational/rationaledge/content/feb05/bell/Bell-Fig3.gif" width=197 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
<P><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">图 3：这里额外的区显示Order组件提供和要求的接口。</B> </P>
<P>在图 3 中的Order组件例子中，组件提供了名为 OrderEntry 和 AccountPayable 的接口。此外，组件也要求另外一个组件提供Person接口。<A href="http://www-128.ibm.com/developerworks/cn/rational/rationaledge/content/feb05/bell/bell.html#notes" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <SUP>3</SUP> </A></P>
<P><A name=N100C4><SPAN class=atitle3>组件接口建模的其它方法</SPAN></A><BR>UML 2 也引入另外一种方法来显示组件提供并要求的接口。这个方法是建立一个里面有组件名的大长方形，并在长方形的外面放置在 UML 2 规范中称为接口符号的东西。这第二种方法在图 4 中举例说明。</P><IMG height=177 alt="图 4: 一种可选择的方法（与图3相比）：使用接口符号显示组件提供/要求的接口" src="http://www-128.ibm.com/developerworks/cn/rational/rationaledge/content/feb05/bell/Bell-Fig4.gif" width=455 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
<P><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">图 4: 一种可选择的方法（与图3相比）：使用接口符号显示组件提供/要求的接口</B> </P>
<P>在这第二种方法中，在末端有一个完整的圆周的接口符号代表组件提供的接口 -- “棒棒糖”是这个接口分类器实现关系符号的速记法。在末端只有半个圆的接口（又称插座）符号代表组件要求的接口（在两种情况下，接口的名字被放置在接口符号本身的附近）。即使图 4 看起来与图 3 有很大的不同，但两个图都提供了相同的信息 -- 例如，Order组件提供两个接口：OrderEntry 和 AccountPayable，而且Order组件 <I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">要求</I> Person接口。</P>
<P><A name=N100DF><SPAN class=atitle3>组件关系的建模</SPAN></A><BR>当表现组件与其他的组件的关系时，棒棒糖和插座符号也必须包括一支依存箭头（如类图中所用的）。在有棒棒糖和插座的组件图上，注意，依存箭从强烈的（要求的）插座引出，并且它的箭头指向供应者的棒棒糖，如图 5 所示。</P><IMG height=266 alt="图 5：显示Order系统组件如何依赖于其他组件的组件图" src="http://www-128.ibm.com/developerworks/cn/rational/rationaledge/content/feb05/bell/Bell-Fig5.gif" width=468 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
<P><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">图 5：显示Order系统组件如何依赖于其他组件的组件图</B> </P>
<P>图 5 显示，Order系统组件依赖于客户资源库和库存系统组件。注意在图 5 中复制出的接口名 CustomerLookup 和 ProductAccessor。 在这个例子中，这看起来可能是不必要的重复，不过符号确实允许在每个依赖于实现差别的组件中有不同的接口（和不同的名字）（举例来说，一个组件提供一个较小的必需的接口子类）。</P>
<P><A name=N100F7><SPAN class=atitle3>子系统</SPAN></A><BR>在 UML 2 中，子系统分类器是组件分类器的一个特别版本。因为这一点，子系统符号元素象组件符号元素一样继承所有的组件符号集规则。唯一的差别是，一个子系统符号元素由subsystem关键字代替了component，如图 6 所示。</P><IMG height=89 alt="图 6：子系统元素的一个例子" src="http://www-128.ibm.com/developerworks/cn/rational/rationaledge/content/feb05/bell/Bell-Fig6.gif" width=140 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
<P><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">图 6：子系统元素的一个例子</B> </P>
<P>UML 2 规范在如何区别子系统与组件方面相当含糊。从建模的观点，规范并不认为组件与子系统有任何区别。与 UML 1. x 相比较，这个 UML 2 模型歧义是新的。但是有一个理由。在 UML 1. x 中，一个子系统被认为是一个软件包，而且这个软件包符号正对许多 UML 实践者造成困惑；因此，UML 2中把子系统作为特殊的组件，因为这是最多的 UML 1. x 使用者了解它的方式。这一改变确实把模糊引入图中，但是这一模糊更多的是 UML 2 规范中对抗错误的一个现实反射。</P>
<P>到这里，你可能正在抓着头皮并感到疑惑，什么时候该用组件元素，什么时候又该用子系统元素。相当坦率地说，我没有一个直接的答案给你。我可以告诉你，UML 2 规范中说，何时该使用组件或子系统决定于建模者的方法论。我个人很喜欢这个答案，因为它帮助确保UML与方法论相互独立，这在软件开发中将帮助保持它的普遍可使用。</P>
<P><A name=N10112><SPAN class=atitle2>超越基础</SPAN></A><BR>组件图是比较容易理解的图之一，因此没有很多超越基础的内容。然而，有一个方面你可以认为是略微困难的。</P>
<P><A name=N1011C><SPAN class=atitle3>显示组件的内部结构</SPAN></A><BR>有时候显示组件的内部结构是有意义的。在关于类图的我的前面的文章中，我显示了该如何为类的内部结构建模；这里，当它由其他组件组成的时候，我将会关注如何为组件的内部结构建模。</P>
<P>为了显示组件的内部结构，你只需把组件画得比平常大一些并在名字区内放置内部的部分。图 7 显示Store组件的内部结构。</P><IMG height=370 alt="图 7: 这个组件的内部结构由其他组件组成。" src="http://www-128.ibm.com/developerworks/cn/rational/rationaledge/content/feb05/bell/Bell-Fig7.gif" width=689 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
<P><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">图 7: 这个组件的内部结构由其他组件组成。</B> </P>
<P>使用在图 7 中显示的例子，Store组件提供了 OrderEntry 接口并要求Account接口。Store组件由三个组件组成：Order，Customer和Product组件。注意Store的 OrderEntry 和Account接口符号在组件的边缘上为何有一个方块。这一个方块被称为一个端口。单纯感觉来说，端口提供一种方法，它显示建模组件所 <I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">提供/要求</I> 的接口如何与它里面的部分相关联。<A href="http://www-128.ibm.com/developerworks/cn/rational/rationaledge/content/feb05/bell/bell.html#notes" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <SUP>4</SUP> </A>通过使用端口，我们可以从外部实例中分离出Store组件的内部部件。在图 7 中，对于过程而言，OrderEntry 端口代表Order组件的 OrderEntry 接口。同时，内部的Customer组件要求的Account接口被分配到Store组件的必需的Account端口。通过连接Account端口，Store组件内部部件（例如Customer组件）可以有代表执行端口接口的未知外部实体的本地特征。必需的Account接口将会由Store组件的外部组件实现。<A href="http://www-128.ibm.com/developerworks/cn/rational/rationaledge/content/feb05/bell/bell.html#notes" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <SUP>5</SUP> </A></P>
<P>在图 7 中，你可能也注意到了，在内部的组件之间的内部连接与图 5 中显示的那些不同。这是因为内部结构的这些描绘事实是嵌套在分类器（在我们的例子中是一个组件)里的协作图，因为协作图显示分类器中的实体或角色。在内部的组件之间建模的关系以 UML 称为的一个组合连接器表示。一个组合连接器绑定一个组件 <I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">提供</I> 的接口到另外的一个组件的 <I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">必需</I> 接口。组合连接器用紧紧相连的棒棒糖和插座符号表示。以这种方式画这些组合连接器使棒棒糖和插座成为很容易理解的符号。</P>
<P><A name=N10151><SPAN class=atitle2>结论</SPAN></A><BR>组件图经常是一个架构师在项目的初期就建立的非常重要的图。然而，组件图的有用性跨越了系统的寿命。组件图是无价的，因为它们模型化和文档化了一个系统的架构。因为组件图文档化了系统的架构，开发者和系统可能的系统管理员会发现这一工作的关键产品有助于他们理解系统。</P>
<P>组件图也视为软件系统配置图的输入，这将会是本系列后面的文章主题。 </P><A name=notes xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"></A>
<P><A name=N10161><SPAN class=atitle2>脚注</SPAN></A><BR><SUP xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">1</SUP>在UML1.x 中称为组件的实际项目，在 UML 2 中称为产物。一个产物是一个物理单位，象一个文件，可运行的程序，脚本，数据库等等。只有一种产物依赖于实际的节点；类和组件没有“位置”。然而，一个产物可能显示组件和其他的分类器（例如类）。一个单一的组件可能通过多重产物显示，它们可能是在相同的或不同的节点上，因此，一个单一的组件可以间接地在多重节点上被实现。</P>
<P><SUP xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">2</SUP>即使组件是独立的单元，它们仍然可能依赖于其他组件提供的服务。由于这一点，文档化一个组件的必需接口是很有用的。</P>
<P><SUP xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">3</SUP>图3并不显示Order组件完整的上下文。在一个真实的模型中，OrderEntry，AccountPayable 和Person接口会呈现在系统的模型中。</P>
<P><SUP xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">4</SUP>事实上，端口适用于任何类型的分类器（例如，一个类或者你的模型中可能会有的其他分类器）。为了使本文简洁，我在组件分类器及它们的使用中提及端口。</P>
<P><SUP xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">5</SUP>一般来说，当你画一个端口和一个接口之间的依存关系时，依赖方（要求）的接口将会在运行时间内处理所有的处理逻辑。然而，这并不是一种硬性的规定 -- 对于周围的组件（举例来说，我们例子中的Store组件），使用自己的进程逻辑，而不是仅把进程委托给依赖接口，是完全可以接受的。</P>
<P><A name=resources><SPAN class=atitle2>参考资料 </SPAN></A>
<OL xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<LI>您可以参阅本文在 developerWorks 全球站点上的 <A href="http://www.ibm.com/developerworks/rational/library/dec04/bell/index.html" target=_blank>英文原文</A>。 </LI></OL>
<P></P>
<TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD><A name=author1></A><SPAN class=atitle2>关于作者</SPAN><BR><IMG height=80 alt="Author photo" src="http://www.ibm.com/developerworks/rational/library/content/Authors/A-F/donaldBell.jpg" width=64 align=left xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Donald Bell是IBM全球服务的一个IT专家，在那儿他和IBM的客户一起致力于设计和开发基于软件解决方案的J2EE。 </TD></TR></TBODY></TABLE><img src ="http://www.blogjava.net/kapok/aggbug/5764.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/kapok/" target="_blank">笨笨</a> 2005-06-08 18:31 <a href="http://www.blogjava.net/kapok/archive/2005/06/08/5764.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>UML 序列图</title><link>http://www.blogjava.net/kapok/archive/2005/06/08/5763.html</link><dc:creator>笨笨</dc:creator><author>笨笨</author><pubDate>Wed, 08 Jun 2005 10:28:00 GMT</pubDate><guid>http://www.blogjava.net/kapok/archive/2005/06/08/5763.html</guid><wfw:comment>http://www.blogjava.net/kapok/comments/5763.html</wfw:comment><comments>http://www.blogjava.net/kapok/archive/2005/06/08/5763.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/kapok/comments/commentRss/5763.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/kapok/services/trackbacks/5763.html</trackback:ping><description><![CDATA[<A href="http://www-128.ibm.com/developerworks/cn/rational/rationaledge/content/feb05/bell/3101.html">http://www-128.ibm.com/developerworks/cn/rational/rationaledge/content/feb05/bell/3101.html</A><BR>IBM<BR>2005 年 2 月 15 日
<BLOCKQUOTE>来自Rational Edge：本文作为UML 基础的、关于统一建模语言的基础图的一系列文章的一部分，提供对序列图的详细介绍。它也介绍了最近的 UML 2.0 规范的几个新符号元件。</BLOCKQUOTE>
<P>
<TABLE width="100%">
<TBODY>
<TR>
<TD width="30%"></TD></TR></TBODY></TABLE></P>
<P><IMG alt=Illustration hspace=5 src="http://www-128.ibm.com/developerworks/cn/rational/rationaledge/content/feb05/bell/ill_3101.gif" border=0 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> </P><BR xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<P><I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">现在是二月，而且到如今你或许已经读到、或听到人们谈论UML 2.0 —— 包括若干进步的 UML 的新规范，所做的变化。考虑到新规范的重要性，我们也正在修改这个文章系列的基础，把我们的注意力从 OMG 的 UML 1.4 规范，转移到 OMG 的已采纳 UML 2.0草案规范（又名 UML 2）。我不喜欢在一系列文章的中间，把重点从 1.4 变为 2.0 ，但是 UML 2.0 草案规范是前进的重要一步，我感觉需要扩充文字。</I> </P>
<P><I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">由于一些理由，OMG 改良了 UML 。主要的理由是，他们希望 UML 模型能够表达模型驱动架构（MDA），这意味着 UML 必须支持更多的模型驱动的符号。同时， UML 1.x 符号集合有时难以适用于较大的应用程序。此外,为了要使图变成更容易阅读，需要改良符号元件。（举例来说，UML 1.x 的模型逻辑流程太复杂，有时不可能完成。对UML 2 中的序列图的符号集合的改变，已经在序列化逻辑建模方面取得巨大的进步)。</I> </P>
<P><I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">注意我上面所述的文字：“已采纳UML2.0草案规范。”确实，规范仍然处于草案状态，但是关键是草案规范已经被 OMG 采用，OMG是一个直到新标准相当可靠，才会采用它们的组织。 在 UML 2 完全地被采用之前，规范将会有一些修改，但是这些改变应该是极小的。主要的改变将会是在 UML 的内部 —— 包括通常被实施 UML 工具的软件公司使用的功能。</I> </P>
<P><I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">本文的主要目的是继续把我们的重点放在基础UML图上；这个月，我们进一步了解序列图。再次请注意，下面提供的例子正是以新的 UML 2 规范为基础。</I> </P>
<P><A name=N1006E><SPAN class=atitle2>图的目的</SPAN></A><BR>序列图主要用于按照交互发生的一系列顺序，显示对象之间的这些交互。很象类图，开发者一般认为序列图只对他们有意义。然而，一个组织的业务人员会发现，序列图显示不同的业务对象如何交互，对于交流当前业务如何进行很有用。除记录组织的当前事件外，一个业务级的序列图能被当作一个需求文件使用，为实现一个未来系统传递需求。在项目的需求阶段，分析师能通过提供一个更加正式层次的表达，把用例带入下一层次。那种情况下，用例常常被细化为一个或者更多的序列图。</P>
<P>组织的技术人员能发现，序列图在记录一个未来系统的行为应该如何表现中，非常有用。在设计阶段，架构师和开发者能使用图，挖掘出系统对象间的交互，这样充实整个系统设计。</P>
<P>序列图的主要用途之一，是把用例表达的需求，转化为进一步、更加正式层次的精细表达。用例常常被细化为一个或者更多的序列图。序列图除了在设计新系统方面的用途外，它们还能用来记录一个存在系统（称它为“遗产”）的对象现在如何交互。当把这个系统移交给另一个人或组织时，这个文档很有用。</P>
<P><A name=N1007F><SPAN class=atitle2>符号 </SPAN></A><BR>既然这是我基于 UML 2的 UML 图系列文章的第一篇，我们需要首先讨论对 UML 2 图符号的一个补充，即一个叫做框架的符号元件。在 UML 2中，框架元件用于作为许多其他的图元件的一个基础，但是大多数人第一次接触框架元件的情况，是作为图的图形化边界。当为图提供图形化边界时，一个框架元件为图的标签提供一致的位置。在 UML 图中框架元件是可选择的；就如你能在图 1 和 2 中见到的，图的标签被放在左上角，在我将调用框架的“namebox”中，一种卷角长方形，而且实际的 UML 图在较大的封闭长方形内部定义。</P><IMG height=222 alt="图 1: 空的 UML 2 框架元件" src="http://www-128.ibm.com/developerworks/cn/rational/rationaledge/content/feb05/bell/3101_figure1.jpg" width=385 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
<P><A name=N10093><SPAN class=atitle3>图 1: 空的 UML 2 框架元件</SPAN></A><BR></P>
<P>除了提供一个图形化边框之外，用于图中的框架元件也有描述交互的重要的功能, 例如序列图。在序列图上一个序列接收和发送消息（又称交互），能通过连接消息和框架元件边界，建立模型（如图 2 所见到）。这将会在后面“超越基础”的段落中被更详细地介绍。</P>
<P><IMG alt="图 2: 一个接收和发送消息的序列图" src="http://www-128.ibm.com/developerworks/cn/rational/rationaledge/content/feb05/bell/3101_figure2.jpg" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> </P>
<P><A name=N100A7><SPAN class=atitle3>图 2: 一个接收和发送消息的序列图</SPAN></A><BR></P>
<P>注意在图 2 中，对于序列图，图的标签由文字“sd”开始。当使用一个框架元件封闭一个图时，图的标签需要按照以下的格式:</P>
<BLOCKQUOTE xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>图类型 图名称</CODE></PRE></TD></TR></TBODY></TABLE></BLOCKQUOTE>
<P>UML 规范给图类型提供特定的文本值。（举例来说，sd代表序列图，activity代表活动图，use case代表用例图）。</P>
<P><A name=N100BE><SPAN class=atitle2>基础 </SPAN></A><BR>序列图的主要目的是定义事件序列，产生一些希望的输出。重点不是消息本身，而是消息产生的顺序；不过，大多数序列图会表示一个系统的对象之间传递的什么消息，以及它们发生的顺序。图按照水平和垂直的维度传递信息：垂直维度从上而下表示消息/调用发生的时间序列，而且水平维度从左到右表示消息发送到的对象实例。</P>
<P><A name=N100CC><SPAN class=atitle3>生命线</SPAN></A><BR>当画一个序列图的时候，放置生命线符号元件，横跨图的顶部。生命线表示序列中，建模的角色或对象实例。<A href="http://www-128.ibm.com/developerworks/cn/rational/rationaledge/content/feb05/bell/3101.html#notes" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"></A> <SUP xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">1 </SUP>生命线画作一个方格，一条虚线从上而下，通过底部边界的中心（图 3）。生命线名字放置在方格里。</P>
<P><IMG height=209 alt="图 3: 用于一个实体名为freshman的生命线的Student类的一个例子" src="http://www-128.ibm.com/developerworks/cn/rational/rationaledge/content/feb05/bell/3101_figure3.jpg" width=141 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> </P>
<P><A name=N100E6><SPAN class=atitle3>图 3: 用于一个实体名为freshman的生命线的Student类的一个例子</SPAN></A><BR></P>
<P>UML 的生命线命名标准按照如下格式:</P>
<BLOCKQUOTE xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>实体名 : 类名</CODE></PRE></TD></TR></TBODY></TABLE></BLOCKQUOTE>
<P>在如图3所示的例子中，生命线表示类Student的实体，它的实体名称是freshman。这里注意一点，生命线名称带下划线。当使用下划线时，意味着序列图中的生命线代表一个类的特定实体，不是特定种类的实体（例如，角色）。在将来的一篇文章中，我们将会了解结构化建模。现在，仅仅评述序列图，可能包含角色（例如<I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">买方</I>和<I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">卖方</I>），而不需要叙述谁扮演那些角色（例如<B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Bill</B>和<B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Fred</B>）。这准许不同语境的图重复使用。简单拖放，序列图的实例名称有下划线，而角色名称没有。</P>
<P>图 3 中我们生命线例子是一个命名的对象，但是不是所有的生命线都代表命名的对象。相反的，一个生命线能用来表现一个匿名的或未命名的实体。当在一个序列图上，为一个未命名的实例建模时，生命线的名字采用和一个命名实例相同的模式；但是生命线名字的位置留下空白，而不是提供一个例图名字。再次参考图 3，如果生命线正在表现Student类的一个匿名例图，生命线会是: “Student”。同时, 因为序列图在项目设计阶段中使用，有一个未指定的对象是完全合法: 举例来说，“freshman”。</P>
<P><A name=N1010C><SPAN class=atitle3>消息</SPAN></A><BR>为了可读性，序列图的第一个消息总是从顶端开始，并且一般位于图的左边。然后继发的消息加入图中，稍微比前面的消息低些。</P>
<P>为了显示一个对象（例如，生命线）传递一个消息给另外一个对象，你画一条线指向接收对象，包括一个实心箭头（如果是一个同步调用操作）或一个棍形箭头（如果是一个异步讯号）。消息/方法名字放置在带箭头的线上面。正在被传递给接收对象的消息，表示接收对象的类实现的一个操作/方法。在图 4 的例子中，analyst对象调用ReportingSystem 类的一个实例的系统对象。analyst对象在调用系统对象的 getAvailableReports 方法。系统对象然后调用secSystem 对象上的、包括参数userId的getSecurityClearance 方法，secSystem的类的类型是 SecuritySystem。<A href="http://www-128.ibm.com/developerworks/cn/rational/rationaledge/content/feb05/bell/3101.html#notes" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"></A> <SUP xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">2 </SUP></P>
<P><IMG alt="图 4: 一个在对象之间传递消息的实例" src="http://www-128.ibm.com/developerworks/cn/rational/rationaledge/content/feb05/bell/3101_figure4.jpg" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> </P>
<P><A name=N10127><SPAN class=atitle3>图 4: 一个在对象之间传递消息的实例</SPAN></A><BR></P>
<P>除了仅仅显示序列图上的消息调用外，图 4 中的图还包括返回消息。这些返回消息是可选择的；一个返回消息画作一个带开放箭头的虚线，向后指向来源的生命线，在这条虚线上面，你放置操作的返回值。在图 4 中，当 getSecurityClearance 方法被调用时，secSystem 对象返回 userClearance 给系统对象。当 getAvailableReports 方法被调用时，系统对象返回 availableReports。</P>
<P>此外，返回消息是序列图的一个可选择部分。返回消息的使用依赖建模的具体/抽象程度。如果需要较好的具体化，返回消息是有用的；否则，主动消息就足够了。我个人喜欢，无论什么时候返回一个值，都包括一个返回消息，因为我发现额外的细节使一个序列图变得更容易阅读。</P>
<P>当序列图建模时，有时候，一个对象将会需要传递一个消息给它本身。一个对象何时称它本身？一个纯化论者会争辩一个对象应该永不传递一个消息给它本身。然而，为传递一个消息给它本身的对象建模，在一些情境中可能是有用的。举例来说，图 5 是图 4 的一个改良版本。 图 5 版本显示调用它的 determineAvailableReports 方法的系统对象。通过表示系统传递消息“determineAvailableReports”给它本身，模型把注意力集中到过程的事实上，而不是系统对象。</P>
<P>为了要画一个调用本身的对象，如你平时所作的，画一条消息，但是不是连接它到另外的一个对象，而是你把消息连接回对象本身。</P>
<P><IMG alt="图 5: 系统对象调用它的 determineAvailableReports 方法" src="http://www-128.ibm.com/developerworks/cn/rational/rationaledge/content/feb05/bell/3101_figure5.jpg" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> </P>
<P><A name=N10144><SPAN class=atitle3>图 5: 系统对象调用它的 determineAvailableReports 方法</SPAN></A><BR></P>
<P>图 5 中的消息实例显示同步消息；然而，在序列图中，你也能为异步消息建模。一个异步消息和一个同步的画法类似，但是消息画的线带一个棍形矛头，如图 6 所示。</P>
<P><IMG height=208 alt="图 6: 表示传递到实体2的异步消息的序列图片段" src="http://www-128.ibm.com/developerworks/cn/rational/rationaledge/content/feb05/bell/3101_figure6.jpg" width=364 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> </P>
<P><A name=N1015A><SPAN class=atitle3>图 6: 表示传递到实体2的异步消息的序列图片段</SPAN></A><BR></P>
<P><A name=N10164><SPAN class=atitle3>约束</SPAN></A><BR>当为对象的交互建模时，有时候，必须满足一个条件，消息才会传递给对象。约束在 UML 图各处中，用于控制流。在这里，我将会讨论UML 1.x 及UML 2.0两者的约束。在 UML 1.x 中，一个约束只可能被分配到一个单一消息。UML 1.x中，为了在一个序列图上画一个约束，你把约束元件放在约束的消息线上，消息名字之前。图 7 显示序列图的一个片段，消息addStudent 方法上有一个约束。</P>
<P><IMG height=252 alt="图 7:UML 1.x 序列图的一个片段，其中addStudent 消息有一个约束" src="http://www-128.ibm.com/developerworks/cn/rational/rationaledge/content/feb05/bell/3101_figure7.jpg" width=614 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> </P>
<P><A name=N10178><SPAN class=atitle3>图 7:UML 1.x 序列图的一个片段，其中addStudent 消息有一个约束</SPAN></A><BR></P>
<P>在图 7 中，约束是文本“[ pastDueBalance=0]”。通过这个消息上的约束，如果应收帐系统返回一个零点的逾期平衡，addStudent 消息才将会被传递。约束的符号很简单；格式是: </P>
<BLOCKQUOTE xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>[Boolean Test]</CODE></PRE></TD></TR></TBODY></TABLE></BLOCKQUOTE>
<P>举例来说，</P>
<BLOCKQUOTE xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>[pastDueBalance = 0]</CODE></PRE></TD></TR></TBODY></TABLE></BLOCKQUOTE>
<P><A name=N10196><SPAN class=atitle3>组合碎片(变体方案，选择项，和循环)</SPAN></A><BR>然而，在大多数的序列图中，UML 1.x“in-line”约束不足以处理一个建模序列的必需逻辑。这个功能缺失是 UML 1.x 的一个问题。UML 2 已经通过去掉“in-line”约束，增加一个叫做组合碎片的符号元件，解决了这一个问题。一个组合碎片用来把一套消息组合在一起，在一个序列图中显示条件分支。UML 2 规范指明了组合碎片的 11 种交互类型。十一种中的三种将会在“基础”段落中介绍，另外两种类型将会在“超越基础”中介绍，而那剩余的六种我将会留在另一篇文章中介绍。（嗨，这是一篇文章而不是一本书。我希望你在一天中看完这部分！）</P>
<P><A name=N101A1><SPAN class=atitle3>变体</SPAN></A><BR>变体用来指明在两个或更多的消息序列之间的、互斥的选择。<A href="http://www-128.ibm.com/developerworks/cn/rational/rationaledge/content/feb05/bell/3101.html#notes" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"></A> <SUP xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">3 </SUP>变体支持经典的“if then else”逻辑的建模（举例来说，<B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">如果</B> 我买三个，<B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">然后</B> 我得到 我购买的20% 折扣；<B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">否则</B> 我得到我购买的 10% 折扣）。</P>
<P>就如你将会在图 8 中注意到的，一个变体的组合碎片元件使用框架来画。单词“alt”放置在框架的namebox里。然后较大的长方形分为 UML 2 所称的操作元。<A href="http://www-128.ibm.com/developerworks/cn/rational/rationaledge/content/feb05/bell/3101.html#notes" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"></A> <SUP xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">4 </SUP>操作元被虚线分开。每个操作元有一个约束进行测试，而这个约束被放置在生命线顶端的操作元的左上部。<A href="http://www-128.ibm.com/developerworks/cn/rational/rationaledge/content/feb05/bell/3101.html#notes" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"></A> <SUP xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">5 </SUP>如果操作元的约束等于“true”，然后那个操作元是要执行的操作元。</P>
<P><IMG height=766 alt="图 8：包含变体组合碎片的一个序列图片段" src="http://www-128.ibm.com/developerworks/cn/rational/rationaledge/content/feb05/bell/3101_figure8.jpg" width=507 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> </P>
<P><A name=N101D3><SPAN class=atitle3>图 8：包含变体组合碎片的一个序列图片段</SPAN></A><BR></P>
<P>图 8作为一个变体的组合碎片如何阅读的例子，显示序列从顶部开始，即bank对象获取支票金额和帐户结余。此时，序列图中的变体组合碎片接管。因为约束“[balance &gt;= amount]”，如果余额超过或等于金额，然后顺序进行bank对象传递 addDebitTransaction 和 storePhotoOfCheck 消息给account对象。然而，如果余额不是超过或等于金额，然后顺序的过程就是bank传递addInsuffientFundFee 和 noteReturnedCheck 消息给account对象，returnCheck 消息给它自身。因为“else”约束，当余额不大于或者等于金额时，第二个序列被调用。在变体的组合碎片中，不需要“else”约束；而如果一个操作元，在它上面没有一个明确的约束，那么将假定“else”约束。</P>变体的组合碎片没被限制在简单的“if then else”验证。可能需要大量的变体路径。 如果需要较多的变体方案，你一定要做的全部工作就是把一个操作元加入有序列约束和消息的长方形中。 
<P><A name=N101E0><SPAN class=atitle3>选择项</SPAN></A><BR>选择项组合碎片用来为序列建模，这些序列给予一个特定条件，将会发生的；或者，序列不发生。一个选择项用来为简单的“if then”表达式建模。（例如，如果架上的圈饼少于五个，那么另外做两打圈饼）。</P>
<P>选择项组合碎片符号与变体组合碎片类似，除了它只有一个操作元并且永不能有“else”约束以外（它就是如此，没有理由）。要画选择项组合，你画一个框架。文字“opt”是被放置在框架的 namebox 里的文本，在框架的内容区，选择项的约束被放置在生命线顶端上的左上角。 然后选择项的消息序列被放在框架的内容区的其余位置内。这些元件如图 9 所示。</P>
<P><IMG height=527 alt="图 9：包括选择项组合碎片的一个序列图片段" src="http://www-128.ibm.com/developerworks/cn/rational/rationaledge/content/feb05/bell/3101_figure9.jpg" width=626 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> </P>
<P><A name=N101F7><SPAN class=atitle3>图 9：包括选择项组合碎片的一个序列图片段</SPAN></A><BR></P>
<P>阅读选择项组合碎片很容易。图 9 是图 7 的序列图片段的再加工，但是这次它使用一个选择项组合碎片，因为如果Student的逾期平衡等于0，需要传递更多的消息。按照图 9 的序列图，如果Student的逾期平衡等于零，然后传递addStudent，getCostOfClass和chargeForClass消息。如果Student的逾期平衡不等于零，那么在选择项组合碎片中，序列不传递任何一个消息。</P>
<P>例子图 9的序列图片段包括一个选择项约束；然而，约束不是一个必需的元件。在高层次、抽象的序列图中，你可能不想叙述选择项的条件。你可能只是想要指出片段是可选择的。</P>
<P><A name=N10207><SPAN class=atitle3>循环</SPAN></A><BR>有时候你将会需要为一个重复的序列建模。在 UML 2 中，为一个重复的序列建模已经改良，附加了循环组合碎片。</P>
<P>循环组合碎片表面非常类似选择项组合碎片。你画一个框架，在框架的 namebox 中放置文本“loop”。在框架的内容区中，一个生命线的顶部，循环约束<A href="http://www-128.ibm.com/developerworks/cn/rational/rationaledge/content/feb05/bell/3101.html#notes" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"></A> <SUP xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">6 </SUP>被放置在左上角。然后循环的消息序列被放在框架内容区的其余部分中。在一个循环中，除了标准的布尔测试外，一个约束能测试二个特定的条件式。特定的约束条件式是写作“minint = [the number]”（例如，“minint = 1”）的最小循环次数，和写作“maxint = [the number]”（例如，“maxint = 5”）的最大循环次数。通过最小循环检验，循环必须运行至少指定次数，而循环执行次数不能达到约束指定的最大循环次数。</P>
<P><IMG alt="图 10：循环组合碎片的一个序列图例子" src="http://www-128.ibm.com/developerworks/cn/rational/rationaledge/content/feb05/bell/3101_figure10_small.jpg" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> </P>
<P><A name=N10222><SPAN class=atitle3>图 10：循环组合碎片的一个序列图例子 （单击放大）</SPAN></A><BR></P>
<P>在图 10 中显示的循环运行，直到 reportsEnu 对象的 hasAnotherReport 消息返回false。如果循环序列应该运行，这个序列图的循环使用一个布尔测试确认。为了阅读这个图，你和平常一样，从顶部开始。当你到达循环组合碎片，做一个测试，看看值 hasAnotherReport 是否等于true。如果 hasAnotherReport 值等于true，于是序列进入循环片断。然后你能和正常情况一样，在序列图中跟踪循环的消息。</P>
<P><A name=N10235><SPAN class=atitle2>超越基础 </SPAN></A><BR></P>我已经介绍了序列图的基础，应该使你可以为将会在系统中通常发生的大部份交互建模。下面段落将会介绍用于序列图的比较高阶的符号元件。 
<P><A name=N10240><SPAN class=atitle3>引用另外一个序列图</SPAN></A><BR>当做序列图的时候，开发者爱在他们的序列图中，重用存在的序列图。<A href="http://www-128.ibm.com/developerworks/cn/rational/rationaledge/content/feb05/bell/3101.html#notes" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"></A> <SUP xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">7 </SUP>在 UML 2 中开始，引进“交互进行”元件。追加交互进行的可以说是 UML 2 交互建模中的最重要的创新。交互进行增加了功能，把原始的序列图组织成为复杂的序列图。由于这些，你能组合（重用）较简单的序列，生成比较复杂的序列。这意味你能把完整的、可能比较复杂的序列，抽象为一个单一的概念单位。</P>
<P>一个交互进行元件使用一个框架绘制。文字“ref”放置在框架的 namebox 中，引用的序列图名字放置在框架的内容区里，连同序列图的任何参数一起。引用序列图的名字符号如下模式:</P>
<BLOCKQUOTE xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>序列图名[(参数)] [: 返回值]</CODE></PRE></TD></TR></TBODY></TABLE></BLOCKQUOTE>
<P>两个例子:</P>
<BLOCKQUOTE xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">1. <CODE>Retrieve Borrower Credit Report(ssn) : borrowerCreditReport</CODE> </BLOCKQUOTE>
<P>或者</P>
<BLOCKQUOTE xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">2. <CODE>Process Credit Card(name, number, expirationDate, amount : 100)</CODE> </BLOCKQUOTE>
<P>在例子 1 中，语法调用叫做Retrieve Borrower Credit Report的序列图，传递给它参数 ssn。序列Retreive Borrower Credit Report返回变量 borrowerCreditReport 。</P>
<P>在实例 2 中，语法调用叫做Process Credit Card的序列图，传递给它参数name，number，expiration date，和 amount。然而，在例子 2 中，amount参数将会是值100。因为例子2没有返回值标签，序列不返回值（假设，建模的序列不需要返回值）。</P>
<P><IMG alt="图 11: 一个引用两个不同序列图的序列图" src="http://www-128.ibm.com/developerworks/cn/rational/rationaledge/content/feb05/bell/3101_figure11.jpg" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> </P>
<P><A name=N1027C><SPAN class=atitle3>图 11: 一个引用两个不同序列图的序列图</SPAN></A><BR></P>
<P>图 11 显示一个序列图，它引用了序列图“Balance Lookup”和“Debit Account”。序列从左上角开始，客户传递一个消息给teller对象。teller对象传递一个消息给 theirBank 对象。那时，调用Balance Lookup序列图，而 accountNumber作为一个参数传递。Balance Lookup序列图返回balance变量。然后检验选择项组合碎片的约束条件，确认余额大于金额变量。在余额比金额更大的情况下，调用Debit Account序列图，给它传递参数accountNumber 和amount。在那个序列完成后，withdrawCash 消息为客户返回cash。</P>
<P>重要的是，注意在图 11 中，theirBank 的生命线被交互进行Balance Lookup隐藏了。因为交互进行隐藏生命线，意味着theirBank 生命线在“Balance Lookup”序列图中被引用。除了隐藏交互进行的生命线之外，UML 2 也指明，生命线在它自己的“Balance Lookup”序列中，一定有相同的 theirBank 。</P>
<P>有时候，你为一个序列图建模，其中交互进行会重叠<I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">没有</I> 在交互进行中引用的生命线。在那种情况下，生命线和正常的生命线一样显示，不会被重叠的交互进行隐藏。</P>
<P>在图 11 中，序列引用“Balance Lookup”序列图。“Balance Lookup”序列图在图 12 中显示。因为例子序列有参数和一个返回值，它的标签 —— 位于图的 namebox 中 —— 按照一个特定模式:</P>
<BLOCKQUOTE xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>图类型 图名 [参数类型:参数名]</CODE></PRE></TD></TR></TBODY></TABLE></BLOCKQUOTE>
<BLOCKQUOTE xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>[: 返回值类型]</CODE></PRE></TD></TR></TBODY></TABLE></BLOCKQUOTE>
<P>两个例子:</P>
<BLOCKQUOTE xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">1. <CODE>SD Balance Lookup(Integer : accountNumber) : Real</CODE> </BLOCKQUOTE>
<P>或</P>
<BLOCKQUOTE xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">2. <CODE>SD Available Reports(Financial Analyst : analyst) : Reports</CODE> </BLOCKQUOTE>
<P>图 12 举例说明例子 1，在里面，Balance Lookup序列把参数 accountNumber 作为序列中的变量使用，序列图显示返回的Real对象。在类似这种情况下，返回的对象采用序列图实体名。</P>
<P><IMG alt="图 12: 一个使用 accountNumber 参数并返回一个Real对象的序列图" src="http://www-128.ibm.com/developerworks/cn/rational/rationaledge/content/feb05/bell/3101_figure12.jpg" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> </P>
<P><A name=N102C1><SPAN class=atitle3>图 12: 一个使用 accountNumber 参数并返回一个Real对象的序列图</SPAN></A><BR></P>
<P>图 13 举例说明例子 2，在里面，一个序列图获取一个参数，返回一个对象。然而，在图 13 中参数在序列的交互中使用。</P>
<P><IMG alt="图 13: 一个在它的交互中使用参数、返回一个Reports对象的序列图" src="http://www-128.ibm.com/developerworks/cn/rational/rationaledge/content/feb05/bell/3101_figure13.jpg" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> </P>
<P><A name=N102D5><SPAN class=atitle3>图 13: 一个在它的交互中使用参数、返回一个Reports对象的序列图</SPAN></A><BR></P>
<P><A name=N102DF><SPAN class=atitle3>门</SPAN></A><BR>前面的段落展示如何通过参数和返回值传递信息，引用另一个序列图。然而，有另一个方法在序列图之间传递消息。门可能是一个容易的方法，为在序列图和它的上下文之间的传递消息建模。一个门只是一个消息，图形表示为一端连接序列图的框架边缘，另一端连接到生命线。使用门的图 11 和 12 ，在图 14 和 15 中可以被看到重构。图 15 的例图有一个叫做getBalance的入口门，获取参数 accountNumber。因为是箭头的线连接到图的框架，而箭头连接到生命线，所以 getBalance 消息是一个入口门。序列图也有一个出囗门，返回balance变量。出口门同理可知，因为它是一个返回消息，连接从一个生命线到图的框架，箭头连接框架。</P>
<P><IMG alt="图 14: 图 11 的重构，这次使用门" src="http://www-128.ibm.com/developerworks/cn/rational/rationaledge/content/feb05/bell/3101_figure14.jpg" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> </P>
<P><A name=N102F1><SPAN class=atitle3>图 14: 图 11 的重构，这次使用门</SPAN></A><BR></P>
<P><IMG alt="图 15: 图 12 的重构，这次使用门" src="http://www-128.ibm.com/developerworks/cn/rational/rationaledge/content/feb05/bell/3101_figure15.jpg" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> </P>
<P><A name=N10302><SPAN class=atitle3>图 15: 图 12 的重构，这次使用门</SPAN></A><BR></P>
<P><A name=N1030C><SPAN class=atitle3>组合碎片（跳转和并行）</SPAN></A><BR>在本文前面“基础”的段落中呈现的，我介绍了“变体”，“选择项”，和“循环”的组合碎片。这些三个组合碎片是大多数人将会使用最多的。然而，有二个其他的组合碎片，大量共享的人将会发现有用——跳转和并行。</P>
<P><A name=N10317><SPAN class=atitle3>跳转</SPAN></A><BR>跳转组合碎片几乎在每个方面都和选择项组合碎片一致，除了两个例外。首先，跳转的框架namebox的文本“break”代替了“option”。其次, 当一个跳转组合碎片的消息运行时，封闭的交互作用的其他消息将不会执行，因为序列打破了封闭的交互。这样，跳转组合碎片非常象 C++ 或 Java 的编程语言中的break关键字。</P>
<P><IMG alt="图 16: 来自图 8 的序列图片段的重构，片段使用跳转代替变体" src="http://www-128.ibm.com/developerworks/cn/rational/rationaledge/content/feb05/bell/3101_figure16.jpg" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> </P>
<P><A name=N10329><SPAN class=atitle3>图 16: 来自图 8 的序列图片段的重构，片段使用跳转代替变体</SPAN></A><BR></P>
<P>跳转最常用来做模型异常处理。图 16 是图 8 的重构，但是这次图16使用跳转组合碎片，因为它把balance &lt; amount的情况作为一个异常对待，而不是一个变体流。要阅读图 16，你从序列的左上角开始，向下读。当序列到达返回值“balance”的时候，它检查看看是否余额比金额更少。如果余额不少于金额，被传递的下一个消息是 addDebitTransaction 消息，而且序列正常继续。然而，在余额比金额更少的情况下，然后序列进入跳转组合碎片，它的消息被传递。一旦跳转组合的消息的已经被传递，序列不发送任何其它消息就退出（举例来说，addDebitTransaction）。</P>
<P>注意有关跳转的一件重要的事是，它们只引起一个封闭交互的序列退出，不必完成图中描述的序列。在这种情况下，跳转组合是变体或者循环的一部分，然后只是变体或循环被退出。</P>
<P><A name=N10339><SPAN class=atitle3>并行</SPAN></A><BR>今天的现代计算机系统在复杂性和有时执行并发任务方面不断进步。当完成一个复杂任务需要的处理时间比希望的长的时候，一些系统采用并行处理进程的各部分。当创造一个序列图，显示并行处理活动的时候，需要使用并行组合碎片元件。</P>
<P>并行组合碎片使用一个框架来画，你把文本“par”放在框架的 namebox 中。然后你把框架的内容段用虚线分为水平操作元。框架的每个操作元表示一个在并行运行的线程。 </P>
<P><IMG alt="图 17: oven 是并行做两个任务的对象实例" src="http://www-128.ibm.com/developerworks/cn/rational/rationaledge/content/feb05/bell/3101_figure17.jpg" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> </P>
<P><A name=N1034E><SPAN class=atitle3>图 17: oven 是并行做两个任务的对象实例</SPAN></A><BR></P>
<P>图 17 可能没有举例说明做并行活动的对象的最好的计算机系统实例，不过提供了一个容易理解的并行活动序列的例子。序列如这样进行：hungryPerson 传递 cookFood 消息给oven 对象。当oven 对象接收那个消息时，它同时发送两个消息（nukeFood 和 rotateFood）给它本身。这些消息都处理后，hungryPerson 对象从oven 对象返回 yummyFood 。</P>
<P><A name=N1035B><SPAN class=atitle2>总结</SPAN></A><BR>序列图是一个用来记录系统需求，和整理系统设计的好图。序列图是如此好用的理由是，因为它按照交互发生的时间顺序，显示了系统中对象间的交互逻辑。</P>
<P><A name=N10366><SPAN class=atitle2>参考</SPAN></A><BR></P>
<UL xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<LI>UML 2.0 Superstructure Final Adopted Specification (第8章部分) <A href="http://www.omg.org/cgi-bin/doc?ptc/2003-08-02" target=_blank>http://www.omg.org/cgi-bin/doc?ptc/2003-08-02</A> 
<LI>UML 2 Sequence Diagram Overview <A href="http://www.agilemodeling.com/artifacts/sequenceDiagram.htm" target=_blank>http://www.agilemodeling.com/artifacts/sequenceDiagram.htm</A> 
<LI>UML 2 Tutorial <A href="http://www.omg.org/news/meetings/workshops/UML%202003%20Manual/Tutorial7-Hogg.pdf" target=_blank>http://www.omg.org/news/meetings/workshops/UML%202003%20Manual/Tutorial7-Hogg.pdf</A> </LI></UL><A name=notes xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"></A>
<P><A name=N1038C><SPAN class=atitle2>脚注 </SPAN></A><BR>1 在完全建模系统中，对象（类的实例）也将会在系统的类图中建模。</P>
<P>2 当阅读这个序列图时，假定分析师登录进入系统之内。</P>
<P>3 请注意，附着在不同的变体操作元上的、两个或更多的约束条件式的确可能同时是真，但是实际最多只有一个操作元将会在运行时发生（那种情况下变体的“wins”没有按照 UML 标准定义)。</P>
<P>4 虽然操作元看起来非常象公路上的小路，但是我特别不叫它们小路。泳道是在活动图上使用的 UML 符号。请参考<I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">The Rational Edge</I> 早期关于 <A href="http://www-128.ibm.com/developerworks/cn/rational/rationaledge/content/feb05/bell/content/RationalEdge/sep03/f_umlbasics_db.pdf" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">活动图</A>的文章。</P>
<P>5 通常，附上约束的生命线是拥有包含在约束表达式中的变量的生命线。</P>
<P>6 关于选择项组合碎片，循环组合碎片不需要在它上放置一个约束条件。</P>
<P>7 可能重用任何类型的序列图（举例来说，程序或业务）。我只是发现开发者更喜欢按功能分解他们的图。</P>
<P><A name=resources><SPAN class=atitle2>参考资料 </SPAN></A>
<UL>
<LI>您可以参阅本文在 developerWorks 全球站点上的 <A href="http://www.ibm.com/developerworks/rational/library/3101.html" target=_blank xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">英文原文</A>。<BR></LI></UL>
<P></P>
<TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD><A name=author1></A><SPAN class=atitle2>关于作者</SPAN><BR><IMG height=80 alt="Donald Bell" src="http://www-128.ibm.com/developerworks/cn/rational/rationaledge/content/feb05/bell/donaldBell.jpg" width=64 align=left border=0 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Donald Bell是IBM全球服务的一个IT专家，在那儿他和IBM的客户一起致力于设计和开发基于软件解决方案的J2EE。 </TD></TR></TBODY></TABLE><BR clear=all><img src ="http://www.blogjava.net/kapok/aggbug/5763.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/kapok/" target="_blank">笨笨</a> 2005-06-08 18:28 <a href="http://www.blogjava.net/kapok/archive/2005/06/08/5763.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于UML 2中结构图的介绍</title><link>http://www.blogjava.net/kapok/archive/2005/06/08/5762.html</link><dc:creator>笨笨</dc:creator><author>笨笨</author><pubDate>Wed, 08 Jun 2005 10:24:00 GMT</pubDate><guid>http://www.blogjava.net/kapok/archive/2005/06/08/5762.html</guid><wfw:comment>http://www.blogjava.net/kapok/comments/5762.html</wfw:comment><comments>http://www.blogjava.net/kapok/archive/2005/06/08/5762.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/kapok/comments/commentRss/5762.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/kapok/services/trackbacks/5762.html</trackback:ping><description><![CDATA[<TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR vAlign=top>
<TD width=5></TD>
<TD width="100%"><A href="http://www-128.ibm.com/developerworks/cn/rational/rationaledge/content/feb05/bell/index.html">http://www-128.ibm.com/developerworks/cn/rational/rationaledge/content/feb05/bell/index.html</A><BR><BR>
<TABLE cellSpacing=0 cellPadding=0 width=168 align=right border=0>
<TBODY>
<TR>
<TD width=8><IMG height=21 alt="" src="http://www.ibm.com/i/c.gif" width=5></TD>
<TD width=160>
<TABLE cellSpacing=0 cellPadding=0 width=160 border=0>
<TBODY>
<TR>
<TD width=160 bgColor=#000000 height=1><IMG height=1 alt="" src="http://www.ibm.com/i/c.gif" width=160></TD></TR>
<TR>
<TD align=middle background=/developerworks/cn/i/bg-gold.gif height=5><B>内容：</B></TD></TR>
<TR>
<TD width=160 bgColor=#666666 height=1><IMG height=1 alt="" src="http://www.ibm.com/i/c.gif" width=160></TD></TR>
<TR>
<TD>
<TABLE cellSpacing=0 cellPadding=0 width=160 border=0>
<TBODY>
<TR>
<TD><A href="http://www-128.ibm.com/developerworks/cn/rational/rationaledge/content/feb05/bell/index.html#N1007D">UML 2 中的阴和阳</A></TD></TR>
<TR>
<TD height=1><IMG height=5 alt="" src="http://www.ibm.com/i/c.gif" width=160></TD></TR>
<TR>
<TD><A href="http://www-128.ibm.com/developerworks/cn/rational/rationaledge/content/feb05/bell/index.html#N10088">大体上的结构图</A></TD></TR>
<TR>
<TD height=1><IMG height=5 alt="" src="http://www.ibm.com/i/c.gif" width=160></TD></TR>
<TR>
<TD><A href="http://www-128.ibm.com/developerworks/cn/rational/rationaledge/content/feb05/bell/index.html#N1009C">基础</A></TD></TR>
<TR>
<TD height=1><IMG height=5 alt="" src="http://www.ibm.com/i/c.gif" width=160></TD></TR>
<TR>
<TD><A href="http://www-128.ibm.com/developerworks/cn/rational/rationaledge/content/feb05/bell/index.html#N10356">超过基础</A></TD></TR>
<TR>
<TD height=1><IMG height=5 alt="" src="http://www.ibm.com/i/c.gif" width=160></TD></TR>
<TR>
<TD><A href="http://www-128.ibm.com/developerworks/cn/rational/rationaledge/content/feb05/bell/index.html#N10496">UML 2 补充</A></TD></TR>
<TR>
<TD height=1><IMG height=5 alt="" src="http://www.ibm.com/i/c.gif" width=160></TD></TR>
<TR>
<TD><A href="http://www-128.ibm.com/developerworks/cn/rational/rationaledge/content/feb05/bell/index.html#N10536">结论</A></TD></TR>
<TR>
<TD height=1><IMG height=5 alt="" src="http://www.ibm.com/i/c.gif" width=160></TD></TR>
<TR>
<TD><A href="http://www-128.ibm.com/developerworks/cn/rational/rationaledge/content/feb05/bell/index.html#N10547">脚注</A></TD></TR>
<TR>
<TD height=1><IMG height=5 alt="" src="http://www.ibm.com/i/c.gif" width=160></TD></TR><!--Standard links for every dw-article-->
<TR>
<TD><A href="http://www-128.ibm.com/developerworks/cn/rational/rationaledge/content/feb05/bell/index.html#resources">参考资料 </A></TD></TR>
<TR>
<TD height=1><IMG height=5 alt="" src="http://www.ibm.com/i/c.gif" width=160></TD></TR>
<TR>
<TD><A href="http://www-128.ibm.com/developerworks/cn/rational/rationaledge/content/feb05/bell/index.html#author1">关于作者</A></TD></TR>
<TR>
<TD height=1><IMG height=5 alt="" src="http://www.ibm.com/i/c.gif" width=160></TD></TR>
<TR>
<TD><A href="http://www-128.ibm.com/developerworks/cn/rational/rationaledge/content/feb05/bell/index.html#rating">对本文的评价</A></TD></TR>
<TR>
<TD><IMG height=10 alt="" src="http://www.ibm.com/i/c.gif" width=160></TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE>
<TABLE cellSpacing=0 cellPadding=0 width=160 border=0>
<TBODY>
<TR>
<TD width=160 bgColor=#000000 height=1><IMG height=1 alt="" src="http://www.ibm.com/i/c.gif" width=160></TD></TR>
<TR>
<TD align=middle background=/developerworks/cn/i/bg-gold.gif height=5><B>相关内容：</B></TD></TR>
<TR>
<TD width=160 bgColor=#666666 height=1><IMG height=1 alt="" src="http://www.ibm.com/i/c.gif" width=160></TD></TR>
<TR>
<TD>
<TABLE cellSpacing=0 cellPadding=1 width=160 border=0>
<TBODY>
<TR>
<TD><A href="http://www.ibm.com/developerworks/rational/library/769.html" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">UML basics: Part I: An introduction to the Unified Modeling Language</A></TD></TR>
<TR>
<TD height=1><IMG height=5 alt="" src="http://www.ibm.com/i/c.gif" width=160></TD></TR>
<TR>
<TD><A href="http://www.ibm.com/developerworks/rational/library/content/RationalEdge/sep03/f_umlbasics_db.pdf" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">UML basics: Part II: The activity diagram</A></TD></TR>
<TR>
<TD height=1><IMG height=5 alt="" src="http://www.ibm.com/i/c.gif" width=160></TD></TR>
<TR>
<TD><A href="http://www.ibm.com/developerworks/rational/library/content/RationalEdge/nov03/t_modelinguml_db.pdf" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">UML basics: Part III: The class diagram</A></TD></TR>
<TR>
<TD height=1><IMG height=5 alt="" src="http://www.ibm.com/i/c.gif" width=160></TD></TR>
<TR>
<TD><A href="http://www-128.ibm.com/developerworks/cn/rational/rationaledge/content/feb05/bell/3101.html" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">UML 时序图</A></TD></TR>
<TR>
<TD height=1><IMG height=5 alt="" src="http://www.ibm.com/i/c.gif" width=160></TD></TR>
<TR>
<TD height=1><IMG height=5 alt="" src="http://www.ibm.com/i/c.gif" width=160></TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE>
<TABLE cellSpacing=0 cellPadding=0 width=160 border=0>
<TBODY>
<TR>
<TD width=160 bgColor=#000000 height=1><IMG height=1 alt="" src="http://www.ibm.com/i/c.gif" width=160></TD></TR>
<TR>
<TD align=middle background=/developerworks/cn/i/bg-gold.gif height=5><B>订阅:</B></TD></TR>
<TR>
<TD width=160 bgColor=#666666 height=1><IMG height=1 alt="" src="http://www.ibm.com/i/c.gif" width=160></TD></TR>
<TR>
<TD>
<TABLE cellSpacing=0 cellPadding=1 width=160 border=0>
<TBODY>
<TR>
<TD><A href="http://www-128.ibm.com/developerworks/cn/newsletter/">developerWorks 时事通讯</A></TD></TR>
<TR>
<TD height=1><IMG height=5 alt="" src="http://www.ibm.com/i/c.gif" width=160></TD></TR>
<TR>
<TD><A href="http://www-128.ibm.com/developerworks/cn/rational/rationaledge/">The Rational Edge</A></TD></TR>
<TR>
<TD height=1><IMG height=5 alt="" src="http://www.ibm.com/i/c.gif" width=160></TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE>
<TABLE cellSpacing=0 cellPadding=0 width=160 border=0>
<TBODY>
<TR>
<TD width=150 bgColor=#000000 colSpan=2 height=2><IMG height=2 alt="" src="http://www.ibm.com/i/c.gif" width=160></TD></TR>
<TR>
<TD width=150 bgColor=#ffffff colSpan=2 height=2><IMG height=2 alt="" src="http://www.ibm.com/i/c.gif" width=160></TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE><SPAN class=atitle2>关于UML 2中结构图的介绍</SPAN><BR>
<TABLE cellSpacing=0 cellPadding=0 border=0>
<TBODY>
<TR vAlign=top align=left>
<TD>
<P>级别: 高级</P></TD></TR></TBODY></TABLE>
<P><A href="http://www-128.ibm.com/developerworks/cn/rational/rationaledge/content/feb05/bell/index.html#author1"><NAME>Donald Bell</NAME></A><BR>IBM 全球服务, IBM<BR>2005 年 2 月 15 日</P>
<BLOCKQUOTE>来自Rational Edge：在 UML 2 中，作为新结构图类型的最重要实例，类图可以在整个软件开发生命周期中，被分析师，业务建模人员，开发者和测试者使用的。本文提供了全面的介绍。</BLOCKQUOTE>
<P><IMG alt=Illustration hspace=5 src="http://www-128.ibm.com/developerworks/cn/rational/rationaledge/content/feb05/bell/bell_ill.jpg" align=right border=0 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">这是关于统一建模语言、即UML 里采用的基本图的一系列文章的一部分。在我 <A href="http://www-128.ibm.com/developerworks/cn/rational/rationaledge/content/feb05/bell/3101.html">先前关于序列图的文章</A> 里，我把重点从 UML 1.4 版，转移到 OMG的采用UML 2.0版草案规范（又称为UML 2）。在这篇文章中，我将会讨论结构图，这是已经在 UML 2 中提出的一种新图种类。由于本系列文章的目的是使人们了解记号元素及它们的含意，该文主要关注类图。你很快就会知道这样做的理由。随后的文章将会覆盖结构范畴中包含的其它图。</I> </P>
<P><I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">我也想提醒读者，这一系列文章是关于 UML 记号元素的，所以这些文章并不意味着为建模的最好方式提供指导方针，或是该如何决定哪些内容应该首先被建模。相反的，该文及本系列文章的目的主要是帮助大家对于记号元素 -- 语法和含义有一个基本的理解。借由这些知识，你应该可以阅读图，并使用正确的记号元素创建你自己的图。</I> </P>
<P><I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">这篇文章假定你对面向对象的设计已经有了基本的理解。你们当中如果有人需要一些面向对象概念的帮助，那么可以访问</I> <A href="http://java.sun.com/docs/books/tutorial/java/concepts/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">http://java.sun.com/docs/books/tutorial/java/concepts/</A>，来获得Sun公司关于面向对象编程的简短指导。<I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">阅读</I> “什么是类？”<I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">和</I> 什么是继承？” <I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">章节，将提供给你足够的理解，并对该文的阅读会有所帮助。另外，David Taylor的书《</I> Object-Oriented Technologies: A Manager's Guide<I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">》提供了面向对象设计的优秀，高水平的说明，而无需对计算机编程有高深的理解。</I> </P>
<P><A name=N1007D><SPAN class=atitle2>UML 2 中的阴和阳</SPAN></A><BR>在 UML 2 中有二种基本的图范畴：结构图和行为图。每个 UML 图都属于这二个图范畴。结构图的目的是显示建模系统的静态结构。它们包括类，组件和（或）对象图。另一方面，行为图显示系统中的对象的动态行为，包括如对象的方法，协作和活动之类的内容。行为图的实例是活动图，用例图和序列图。</P>
<P><A name=N10088><SPAN class=atitle2>大体上的结构图</SPAN></A><BR>如同我所说的，结构图显示建模系统的静态结构。关注系统的元件，无需考虑时间。在系统内，静态结构通过显示类型和它们的实例进行传播。除了显示系统类型和它们的实例，结构图至少也显示了这些元素间的一些关系，可能的话，甚至也显示它们的内部结构。</P>
<P>贯穿整个软件生命周期，结构图对于各种团队成员都是有用的。一般而言，这些图支持设计验证，和个体与团队间的设计交流。举例来说，业务分析师可以使用类或对象图，来为当前的资产和资源建模，例如分类账，产品或地理层次。架构师可以使用组件和部署图，来测试/确认他们的设计是否充分。开发者可以使用类图，来设计并为系统的代码（或即将成为代码的）类写文档。</P><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">特殊的类图</B> 
<P>UML 2 把结构图看成一个分类；这里并不存在称为“结构图”的图。然而，类图提供结构图类型的一个主要实例，并为我们提供一组记号元素的初始集，供所有其它结构图使用。由于类图是如此基本，本文的剩余部分将会把重点集中在类图记号集。在本文的结尾，你将对于如何画UML 2类图有所了解，而且对于理解在后面文章中将涉及的其他结构图有一个稳固的基础。</P>
<P><A name=N1009C><SPAN class=atitle2>基础</SPAN></A><BR>如先前所提到的，类图的目的是显示建模系统的类型。在大多数的 UML 模型中这些类型包括：</P>
<UL xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<LI>类<BR><BR>
<LI>接口<BR><BR>
<LI>数据类型<BR><BR>
<LI>组件 </LI></UL>
<P>UML 为这些类型起了一个特别的名字：“分类器”。通常地，你可以把分类器当做类，但在技术上，分类器是更为普遍的术语，它还是引用上面的其它三种类型为好。</P>
<P><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">类名</B> </P>
<P>类的 UML 表示是一个长方形，垂直地分为三个区，如图 1 所示。顶部区域显示类的名字。中间的区域列出类的属性。底部的区域列出类的操作。当在一个类图上画一个类元素时，你必须要有顶端的区域，下面的二个区域是可选择的（当图描述仅仅用于显示分类器间关系的高层细节时，下面的两个区域是不必要的）。图 1 显示一个航线班机如何作为 UML 类建模。正如我们所能见到的，名字是 <I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Flight</I>，我们可以在中间区域看到Flight类的3个属性：flightNumber，departureTime 和 flightDuration。在底部区域中我们可以看到Flight类有两个操作：delayFlight 和 getArrivalTime。</P><IMG height=128 alt="图 1: Flight类的类图" src="http://www-128.ibm.com/developerworks/cn/rational/rationaledge/content/feb05/bell/bell_fig1.jpg" width=288 border=0 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
<P><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">图 1: Flight类的类图</B> </P>
<P></P>
<P><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">类属性列表</B> </P>
<P>类的属性节（中部区域）在分隔线上列出每一个类的属性。属性节是可选择的，要是一用它，就包含类的列表显示的每个属性。该线用如下格式：</P>
<BLOCKQUOTE xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<TABLE cellSpacing=0 cellPadding=5 width=400 bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>name : attribute type</CODE></PRE></TD></TR></TBODY></TABLE></BLOCKQUOTE>
<BLOCKQUOTE xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<TABLE cellSpacing=0 cellPadding=5 width=400 bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>flightNumber : Integer</CODE></PRE></TD></TR></TBODY></TABLE></BLOCKQUOTE>
<P>继续我们的Flight类的例子，我们可以使用属性类型信息来描述类的属性，如表 1 所示。</P>
<P><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">表 1：具有关联类型的Flight类的属性名字</B> </P>
<TABLE width="100%" border=0>
<TBODY>
<TR>
<TD bgColor=#000000>
<TABLE width="100%" border=0>
<TBODY>
<TR bgColor=#cccccc>
<TD>属性名称</TD>
<TD>属性类型</TD></TR>
<TR bgColor=#ffff99>
<TD>flightNumber</TD>
<TD>Integer</TD></TR>
<TR bgColor=#ffff99>
<TD>departureTime</TD>
<TD>Date</TD></TR>
<TR bgColor=#ffff99>
<TD>flightDuration</TD>
<TD>Minutes</TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE>
<P>在业务类图中，属性类型通常与单位相符，这对于图的可能读者是有意义的（例如，分钟，美元，等等）。然而，用于生成代码的类图，要求类的属性类型必须限制在由程序语言提供的类型之中，或包含于在系统中实现的、模型的类型之中。</P>
<P>在类图上显示具有默认值的特定属性，有时是有用的（例如，在银行账户应用程序中，一个新的银行账户会以零为初始值）。UML 规范允许在属性列表节中，通过使用如下的记号作为默认值的标识：</P>
<BLOCKQUOTE xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<TABLE cellSpacing=0 cellPadding=5 width=400 bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>name : attribute type = default value</CODE></PRE></TD></TR></TBODY></TABLE></BLOCKQUOTE>
<P>举例来说：</P>
<BLOCKQUOTE xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<TABLE cellSpacing=0 cellPadding=5 width=400 bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>balance : Dollars = 0</CODE></PRE></TD></TR></TBODY></TABLE></BLOCKQUOTE>
<P>显示属性默认值是可选择的；图 2 显示一个银行账户类具有一个名为 <I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">balance</I>的类型，它的默认值为0。</P><IMG height=113 alt="图 2：显示默认为0美元的balance属性值的银行账户类图。" src="http://www-128.ibm.com/developerworks/cn/rational/rationaledge/content/feb05/bell/bell_fig2.jpg" width=212 border=0 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
<P><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">图 2：显示默认为0美元的balance属性值的银行账户类图。</B> </P>
<P></P>
<P><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">类操作列表</B> </P>
<P>类操作记录在类图长方形的第三个（最低的）区域中，它也是可选择的。和属性一样，类的操作以列表格式显示，每个操作在它自己线上。操作使用下列记号表现：</P>
<BLOCKQUOTE xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<TABLE cellSpacing=0 cellPadding=5 width=400 bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>	name(parameter list) : type of value returned</CODE></PRE></TD></TR></TBODY></TABLE></BLOCKQUOTE>
<P>下面的表 2 中Flight类操作的映射。</P>
<P><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">表 2：从图 2 映射的Flight类的操作</B> </P>
<TABLE width="100%" border=0>
<TBODY>
<TR>
<TD bgColor=#000000>
<TABLE width="100%" border=0>
<TBODY>
<TR vAlign=top align=left bgColor=#cccccc>
<TD><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">操作名称</B> </TD>
<TD><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">返回参数</B> </TD>
<TD><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">值类型</B> </TD></TR>
<TR vAlign=top align=left bgColor=#ffff99>
<TD>delayFlight</TD>
<TD>
<TABLE cellSpacing=2 cellPadding=5 width="100%" border=0>
<TBODY>
<TR>
<TD><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Name</B> </TD>
<TD><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Type</B> </TD></TR>
<TR>
<TD>numberOfMinutes </TD>
<TD>Minutes</TD></TR></TBODY></TABLE></TD>
<TD>N/A</TD></TR>
<TR vAlign=top align=left bgColor=#ffff99>
<TD>getArrivalTime </TD>
<TD>N/A </TD>
<TD>Date</TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE>
<P>图3显示，delayFlight 操作有一个Minutes类型的输入参数 -- numberOfMinutes。然而，delayFlight 操作没有返回值。<A href="http://www-128.ibm.com/developerworks/cn/rational/rationaledge/content/feb05/bell/index.html#notes" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <SUP>1</SUP> </A>当一个操作有参数时，参数被放在操作的括号内；每个参数都使用这样的格式：“参数名：参数类型”。</P><IMG height=129 alt="图 3：Flight类操作参数，包括可选择的“in”标识。" src="http://www-128.ibm.com/developerworks/cn/rational/rationaledge/content/feb05/bell/bell_fig3.jpg" width=279 border=0 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
<P><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">图 3：Flight类操作参数，包括可选择的“in”标识。</B> </P>
<P></P>
<P>当文档化操作参数时，你可能使用一个可选择的指示器，以显示参数到操作的输入参数、或输出参数。这个可选择的指示器以“in”或“out”出现，如图3中的操作区域所示。一般来说，除非将使用一种早期的程序编程语言，如Fortran ，这些指示器可能会有所帮助，否则它们是不必要的。然而，在 C++和Java中，所有的参数是“in”参数，而且按照UML规范，既然“in”是参数的默认类型，大多数人将会遗漏输入/输出指示器。</P>
<P><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">继承</B> </P>
<P>在面向对象的设计中一个非常重要的概念，<I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">继承</I>，指的是一个类（子类）<I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">继承</I>另外的一个类（超类）的同一功能，并增加它自己的新功能（一个非技术性的比喻，想象我继承了我母亲的一般的音乐能力，但是在我的家里，我是唯一一个玩电吉他的人）的能力。为了在一个类图上建模继承，从子类（要继承行为的类）拉出一条闭合的，单键头（或三角形）的实线指向超类。考虑银行账户的类型：图 4 显示 CheckingAccount 和 SavingsAccount 类如何从 BankAccount 类继承而来。</P><IMG height=335 alt="图 4: 继承通过指向超类的一条闭合的，单箭头的实线表示。" src="http://www-128.ibm.com/developerworks/cn/rational/rationaledge/content/feb05/bell/bell_fig4.jpg" width=563 border=0 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
<P><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">图 4: 继承通过指向超类的一条闭合的，单箭头的实线表示。</B> </P>
<P></P>
<P>在图 4 中，继承关系由每个超类的单独的线画出，这是在IBM Rational Rose和IBM Rational XDE中使用的方法。然而，有一种称为 <I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">树标记</I>的备选方法可以画出继承关系。当存在两个或更多子类时，如图 4 中所示，除了继承线象树枝一样混在一起外，你可以使用树形记号。图 5 是重绘的与图 4 一样的继承，但是这次使用了树形记号。</P><IMG height=335 alt="图 5: 一个使用树形记号的继承实例" src="http://www-128.ibm.com/developerworks/cn/rational/rationaledge/content/feb05/bell/bell_fig5.jpg" width=563 border=0 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
<P><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">图 5: 一个使用树形记号的继承实例</B> </P>
<P></P>
<P><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">抽象类及操作</B> <BR xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">细心的读者会注意到，在图 4 和 图5 中的图中,类名BankAccount和withdrawal操作使用斜体。这表示，BankAccount 类是一个抽象类，而withdrawal方法是抽象的操作。换句话说，BankAccount 类使用withdrawal规定抽象操作，并且CheckingAccount 和 SavingsAccount 两个子类都分别地执行它们各自版本的操作。</P>
<P>然而，超类（父类）不一定要是抽象类。标准类作为超类是正常的。</P>
<P><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">关联</B> <BR xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">当你系统建模时，特定的对象间将会彼此关联，而且这些关联本身需要被清晰地建模。有五种关联。在这一部分中，我将会讨论它们中的两个 -- 双向的关联和单向的关联，而且我将会在<I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Beyond the basics</I>部分讨论剩下的三种关联类型。请注意，关于何时该使用每种类型关联的详细讨论，不属于本文的范围。相反的，我将会把重点集中在每种关联的用途，并说明如何在类图上画出关联。</P>
<P><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">双向（标准）的关联</B> <BR xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">关联是两个类间的联接。关联总是被假定是双向的；这意味着，两个类彼此知道它们间的联系，除非你限定一些其它类型的关联。回顾一下Flight 的例子，图 6 显示了在Flight类和Plane类之间的一个标准类型的关联。</P><IMG height=172 alt="图 6：在一个Flight类和Plane类之间的双向关联的实例" src="http://www-128.ibm.com/developerworks/cn/rational/rationaledge/content/feb05/bell/bell_fig6.jpg" width=680 border=0 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
<P><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">图 6：在一个Flight类和Plane类之间的双向关联的实例</B> </P>
<P></P>
<P>一个双向关联用两个类间的实线表示。在线的任一端，你放置一个角色名和多重值。图 6 显示Flight与一个特定的Plane相关联，而且Flight类知道这个关联。因为角色名以Plane类表示，所以Plane承担关联中的“assignedPlane”角色。紧接于Plane类后面的多重值描述0...1表示，当一个Flight实体存在时，可以有一个或没有Plane与之关联（也就是，Plane可能还没有被分配）。图 6 也显示Plane知道它与Flight类的关联。在这个关联中，Flight承担“assignedFlights”角色；图 6 的图告诉我们，Plane实体可以不与flight关联（例如，它是一架全新的飞机）或与没有上限的flight（例如，一架已经服役5年的飞机）关联。</P>
<P>由于对那些在关联尾部可能出现的多重值描述感到疑惑，下面的表3列出了一些多重值及它们含义的例子。</P>
<P><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">表 3: 多重值和它们的表示</B> </P>
<TABLE border=0>
<TBODY>
<TR>
<TD bgColor=#000000>
<TABLE cellSpacing=2 cellPadding=5 width="100%" border=0>
<TBODY>
<TR bgColor=#cccccc>
<TD colSpan=2>可能的多重值描述</TD></TR>
<TR bgColor=#ffff99>
<TD>表示</TD>
<TD>含义</TD></TR>
<TR bgColor=#ffff99>
<TD>0..1 </TD>
<TD>0个或1个</TD></TR>
<TR bgColor=#cccccc>
<TD>1</TD>
<TD>只能1个</TD></TR>
<TR bgColor=#cccccc>
<TD>0..*</TD>
<TD>0个或多个</TD></TR>
<TR bgColor=#cccccc>
<TD>* </TD>
<TD>0个或多个</TD></TR>
<TR bgColor=#cccccc>
<TD>1..*</TD>
<TD>1个或我个</TD></TR>
<TR bgColor=#cccccc>
<TD>3</TD>
<TD>只能3个</TD></TR>
<TR bgColor=#cccccc>
<TD>0..5</TD>
<TD>0到5个</TD></TR>
<TR bgColor=#cccccc>
<TD>5..15 </TD>
<TD>5到15个</TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE>
<P><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">单向关联</B> <BR xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">在一个单向关联中，两个类是相关的，但是只有一个类知道这种联系的存在。图 7 显示单向关联的透支财务报告的一个实例。</P><IMG height=113 alt="图 7: 单向关联一个实例：OverdrawnAccountsReport 类 BankAccount 类，而 BankAccount 类则对关联一无所知。" src="http://www-128.ibm.com/developerworks/cn/rational/rationaledge/content/feb05/bell/bell_fig7.jpg" width=600 border=0 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
<P><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">图 7: 单向关联一个实例：OverdrawnAccountsReport 类 BankAccount 类，而 BankAccount 类则对关联一无所知。</B> </P>
<P></P>
<P>一个单向的关联，表示为一条带有指向已知类的开放箭头（不关闭的箭头或三角形，用于标志继承）的实线。如同标准关联，单向关联包括一个角色名和一个多重值描述，但是与标准的双向关联不同的时，单向关联只包含已知类的角色名和多重值描述。在图 7 中的例子中，OverdrawnAccountsReport 知道 BankAccount 类，而且知道 BankAccount 类扮演“overdrawnAccounts”的角色。然而，和标准关联不同，BankAccount 类并不知道它与 OverdrawnAccountsReport 相关联。<A href="http://www-128.ibm.com/developerworks/cn/rational/rationaledge/content/feb05/bell/index.html#notes" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <SUP>2</SUP> </A></P>
<P><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">软件包</B> <BR xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">不可避免，如果你正在为一个大的系统或大的业务领域建模，在你的模型中将会有许多不同的分类器。管理所有的类将是一件令人生畏的任务；所以，UML 提供一个称为 <I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">软件包</I>的组织元素。软件包使建模者能够组织模型分类器到名字空间中，这有些象文件系统中的文件夹。把一个系统分为多个软件包使系统变成容易理解，尤其是在每个软件包都表现系统的一个特定部分时。<A href="http://www-128.ibm.com/developerworks/cn/rational/rationaledge/content/feb05/bell/index.html#notes" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <SUP>3</SUP> </A></P>
<P>在图中存在两种方法表示软件包。并没有规则要求使用哪种标记，除了用你个人的判断：哪种更便于阅读你画的类图。两种方法都是由一个较小的长方形（用于定位）嵌套在一个大的长方形中开始的，如图 8 所示。但是建模者必须决定包的成员如何表示，如下：</P>
<UL xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<LI>如果建模者决定在大长方形中显示软件包的成员，则所有的那些成员<A href="http://www-128.ibm.com/developerworks/cn/rational/rationaledge/content/feb05/bell/index.html#notes"> <SUP>4</SUP> </A>需要被放置在长方形里面。另外，所有软件包的名字需要放在软件包的较小长方形之内（如图 8 的显示）。<BR><BR>
<LI>如果建模者决定在大的长方形之外显示软件包成员，则所有将会在图上显示的成员都需要被置于长方形之外。为了显示属于软件包的分类器属于，从每个分类器画一条线到里面有加号的圆周，这些圆周粘附在软件包之上（图9）。 </LI></UL><IMG height=410 alt="图 8：在软件包的长方形内显示软件包成员的软件包元素例子" src="http://www-128.ibm.com/developerworks/cn/rational/rationaledge/content/feb05/bell/bell_fig8.jpg" width=576 border=0 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
<P><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">图 8：在软件包的长方形内显示软件包成员的软件包元素例子</B> </P>
<P></P><IMG height=622 alt="图 9：一个通过连接线表现软件包成员的软件包例子" src="http://www-128.ibm.com/developerworks/cn/rational/rationaledge/content/feb05/bell/bell_fig9.jpg" width=551 border=0 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
<P><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">图 9：一个通过连接线表现软件包成员的软件包例子</B> </P>
<P></P>
<P><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">了解基础重要性</B> </P>
<P>在 UML 2 中，了解类图的基础更为重要。这是因为类图为所有的其他结构图提供基本的构建块。如组件或对象图（仅仅是举了些例子）。</P>
<P><A name=N10356><SPAN class=atitle2>超过基础</SPAN></A><BR>到此为止，我已经介绍了类图的基础，但是请继续往下读！在下面的部分中，我将会引导你到你会使用的类图的更重要的方面。这些包括UML 2 规范中的接口，其它的三种关联类型，可见性和其他补充。</P>
<P><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">接口</B> <BR xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">在本文的前面，我建议你以类来考虑<I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">分类器</I>。事实上，分类器是一个更为一般的概念，它包括数据类型和接口。</P>
<P>关于何时、以及如何高效地在系统结构图中使用数据类型和接口的完整讨论，不在本文的讨论范围之内。既然这样，我为什么要在这里提及数据类型和接口呢？你可能想在结构图上模仿这些分类器类型，在这个时候，使用正确的记号来表示，或者至少知道这些分类器类型是重要的。不正确地绘制这些分类器，很有可能将使你的结构图读者感到混乱，以后的系统将不能适应需求。</P>
<P>一个类和一个接口不同：一个类可以有它形态的真实实例，然而一个接口必须至少有一个类来实现它。在 UML 2 中，一个接口被认为是类建模元素的特殊化。因此，接口就象类那样绘制，但是长方形的顶部区域也有文本“interface”，如图 10 所示。<A href="http://www-128.ibm.com/developerworks/cn/rational/rationaledge/content/feb05/bell/index.html#notes" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <SUP>5</SUP> </A></P><IMG height=262 alt="图 10：Professor类和Student类实现Person接口的类图实例" src="http://www-128.ibm.com/developerworks/cn/rational/rationaledge/content/feb05/bell/bell_fig10.gif" width=325 border=0 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
<P><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">图 10：Professor类和Student类实现Person接口的类图实例</B> </P>
<P></P>
<P>在图 10 中显示的图中，Professor和Student类都实现了Person的接口，但并不从它继承。我们知道这一点是由于下面两个原因：1) Person对象作为接口被定义 -- 它在对象的名字区域中有“interface”文本，而且我们看到由于Professor和Student对象根据画类对象的规则（在它们的名字区域中没有额外的分类器文本）标示，所以它们是 <I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">类</I>对象。 2) 我们知道继承在这里没有被显示，因为与带箭头的线是点线而不是实线。如图 10 所示，一条带有闭合的单向箭头的<I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">点</I> 线意味着实现（或实施）；正如我们在图 4 中所见到的，一条带有闭合单向箭头的<I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">实</I>线表示继承。</P>
<P><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">更多的关联</B> <BR xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">在上面，我讨论了双向关联和单向关联。现在，我将会介绍剩下的三种类型的关联。</P>
<P><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">关联类</B> <BR xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">在关联建模中，存在一些情况下，你需要包括其它类，因为它包含了关于关联的有价值的信息。对于这种情况，你会使用 <I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">关联类</I> 来绑定你的基本关联。关联类和一般类一样表示。不同的是，主类和关联类之间用一条相交的点线连接。图 11 显示一个航空工业实例的关联类。</P><IMG height=235 alt="图 11：增加关联类 MileageCredit" src="http://www-128.ibm.com/developerworks/cn/rational/rationaledge/content/feb05/bell/bell_fig11.jpg" width=731 border=0 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
<P><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">图 11：增加关联类 MileageCredit</B> </P>
<P></P>
<P>在图 11 中显示的类图中，在Flight类和 FrequentFlyer 类之间的关联，产生了称为 MileageCredit的关联类。这意味当Flight类的一个实例关联到 FrequentFlyer 类的一个实例时，将会产生 MileageCredit 类的一个实例。</P>
<P><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">聚合</B> <BR xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">聚合是一种特别类型的关联，用于描述“总体到局部”的关系。在基本的聚合关系中， <I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">部分类</I> 的生命周期独立于 <I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">整体类</I> 的生命周期。</P>
<P>举例来说，我们可以想象，<I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">车</I> 是一个整体实体，而 <I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">车轮</I> 轮胎是整辆车的一部分。轮胎可以在安置到车时的前几个星期被制造，并放置于仓库中。在这个实例中，Wheel类实例清楚地独立地Car类实例而存在。然而，有些情况下， <I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">部分</I> 类的生命周期并 <I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">不</I> 独立于 <I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">整体</I> 类的生命周期 -- 这称为合成聚合。举例来说，考虑公司与部门的关系。 <I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">公司和部门</I> 都建模成类，在公司存在之前，部门不能存在。这里Department类的实例依赖于Company类的实例而存在。</P>
<P>让我们更进一步探讨基本聚合和组合聚合。</P>
<P><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><I>基本聚合</I> </B><BR xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">有聚合关系的关联指出，某个类是另外某个类的一部分。在一个聚合关系中，子类实例可以比父类存在更长的时间。为了表现一个聚合关系，你画一条从父类到部分类的实线，并在父类的关联末端画一个未填充棱形。图 12 显示车和轮胎间的聚合关系的例子。</P><IMG height=49 alt="图 12: 一个聚合关联的例子" src="http://www-128.ibm.com/developerworks/cn/rational/rationaledge/content/feb05/bell/bell_fig12.jpg" width=291 border=0 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
<P><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">图 12: 一个聚合关联的例子</B> </P>
<P></P>
<P><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><I>组合聚合</I> </B><BR xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">组合聚合关系是聚合关系的另一种形式，但是子类实例的生命周期依赖于父类实例的生命周期。在图13中，显示了Company类和Department类之间的组合关系，注意组合关系如聚合关系一样绘制，不过这次菱形是被填充的。</P><IMG height=47 alt="图 13: 一个组合关系的例子" src="http://www-128.ibm.com/developerworks/cn/rational/rationaledge/content/feb05/bell/bell_fig13.jpg" width=341 border=0 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
<P><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">图 13: 一个组合关系的例子</B> </P>
<P></P>
<P>在图 13 中的关系建模中，一个Company类实例至少总有一个Department类实例。因为关系是组合关系，当Company实例被移除/销毁时，Department实例也将自动地被移除/销毁。组合聚合的另一个重要功能是部分类只能与父类的实例相关（举例来说，我们例子中的Company类）。</P>
<P><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">反射关联</B> <BR xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">现在我们已经讨论了所有的关联类型。就如你可能注意到的，我们的所有例子已经显示了两个不同类之间的关系。然而，类也可以使用反射关联与它本身相关联。起先，这可能没有意义，但是记住，类是抽象的。图 14 显示一个Employee类如何通过manager / manages角色与它本身相关。当一个类关联到它本身时，这并不意味着类的实例与它本身相关，而是类的一个实例与类的另一个实例相关。</P><IMG height=114 alt="图 14：一个反射关联关系的实例" src="http://www-128.ibm.com/developerworks/cn/rational/rationaledge/content/feb05/bell/bell_fig14.gif" width=193 border=0 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
<P><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">图 14：一个反射关联关系的实例</B> </P>
<P></P>
<P>图 14 描绘的关系说明一个Employee实例可能是另外一个Employee实例的经理。然而，因为“manages”的关系角色有 0..*的多重性描述；一个雇员可能不受任何其他雇员管理。</P>
<P><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">可见性</B> <BR xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">在面向对象的设计中，存在属性及操作可见性的记号。UML 识别四种类型的可见性：public，protected，private及package。</P>
<P>UML 规范并不要求属性及操作可见性必须显示在类图上，但是它要求为每个属性及操作定义可见性。为了在类图上的显示可见性，放置可见性标志于属性或操作的名字之前。虽然 UML 指定四种可见性类型，但是实际的编程语言可能增加额外的可见性，或不支持 UML 定义的可见性。表4显示了 UML 支持的可见性类型的不同标志。</P>
<P><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">表 4：UML 支持的可见性类型的标志</B> </P>
<TABLE width="100%" border=0>
<TBODY>
<TR>
<TD bgColor=#000000>
<TABLE width="100%" border=0>
<TBODY>
<TR bgColor=#cccccc>
<TD>标志</TD>
<TD>可见性类型</TD></TR>
<TR bgColor=#ffff99>
<TD>+</TD>
<TD>Public</TD></TR>
<TR bgColor=#ffff99>
<TD># </TD>
<TD>Protected</TD></TR>
<TR bgColor=#ffff99>
<TD>- </TD>
<TD>Private</TD></TR>
<TR bgColor=#ffff99>
<TD>~</TD>
<TD>Package</TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE>
<P>现在，让我们看一个类，以说明属性及操作的可见性类型。在图 15 中，所有的属性及操作都是public，除了 updateBalance 操作。updateBalance 操作是protected。</P><IMG height=129 alt="图 15：一个 BankAccount 类说明它的属性及操作的可见性" src="http://www-128.ibm.com/developerworks/cn/rational/rationaledge/content/feb05/bell/bell_fig15.jpg" width=276 border=0 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
<P><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">图 15：一个 BankAccount 类说明它的属性及操作的可见性</B> </P>
<P></P>
<P><A name=N10496><SPAN class=atitle2>UML 2 补充</SPAN></A><BR>既然我们已经覆盖了基础和高级主题，我们将覆盖一些由UML 1. x增加的类图的新记号。</P>
<P><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">实例</B> <BR xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">当一个系统结构建模时，显示例子类实例有时候是有用的。为了这种结构建模，UML 2 提供 <I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">实例规范</I> 元素，它显示在系统中使用例子（或现实）实例的值得注意的信息。</P>
<P>实例的记号和类一样，但是取代顶端区域中仅有的类名，它的名字是经过拼接的:</P>
<BLOCKQUOTE xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<TABLE cellSpacing=0 cellPadding=5 width=400 bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>Instance Name : Class Name</CODE></PRE></TD></TR></TBODY></TABLE></BLOCKQUOTE>
<P>举例来说：</P>
<BLOCKQUOTE xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<TABLE cellSpacing=0 cellPadding=5 width=400 bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>Donald : Person</CODE></PRE></TD></TR></TBODY></TABLE></BLOCKQUOTE>
<P>因为显示实例的目的是显示值得注意的或相关的信息，没必要在你的模型中包含整个实体属性及操作。相反地，仅仅显示感兴趣的属性及其值是完全恰当的。如图16所描述。</P><IMG height=90 alt="图 16：Plane类的一个实例例子（只显示感兴趣的属性值）" src="http://www-128.ibm.com/developerworks/cn/rational/rationaledge/content/feb05/bell/bell_fig16.jpg" width=176 border=0 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
<P><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">图 16：Plane类的一个实例例子（只显示感兴趣的属性值）</B> </P>
<P></P>
<P>然而，仅仅表现一些实例而没有它们的关系不太实用；因此，UML 2 也允许在实体层的关系/关联建模。绘制关联与一般的类关系的规则一样，除了在建模关联时有一个附加的要求。附加的限制是，关联关系必须与类图的关系相一致，而且关联的角色名字也必须与类图相一致。它的一个例子显示于图 17 中。在这个例子中，实例是图 6 中类图的例子实例。</P><IMG height=247 alt="图 17：图 6 中用实例代替类的例子" src="http://www-128.ibm.com/developerworks/cn/rational/rationaledge/content/feb05/bell/bell_fig17.jpg" width=576 border=0 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
<P><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">图 17：图 6 中用实例代替类的例子</B> </P>
<P></P>
<P>图 17 有Flight类的二个实例，因为类图指出了在Plane类和Flight类之间的关系是 <I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">0或多</I>。因此，我们的例子给出了两个与NX0337 Plane实例相关的Flight实例。</P>
<P><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">角色</B> <BR xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">建模类的实例有时比期望的更为详细。有时，你可能仅仅想要在一个较多的一般层次做类关系的模型。在这种情况下，你应该使用 <I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">角色</I> 记号。角色记号类似于实例记号。为了建立类的角色模型，你画一个方格，并在内部放置类的角色名及类名，作为实体记号，但是在这情况你不能加下划线。图 18 显示一个由图 14 中图描述的雇员类扮演的角色实例。在图 18 中，我们可以认为，即使雇员类与它本身相关，关系确实是关于雇员之间扮演经理及团队成员的角色。</P><IMG height=73 alt="图 18：一个类图显示图14中扮演不同角色的类" src="http://www-128.ibm.com/developerworks/cn/rational/rationaledge/content/feb05/bell/bell_fig18.gif" width=506 border=0 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
<P><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">图 18：一个类图显示图14中扮演不同角色的类</B> </P>
<P>注意，你不能在纯粹类图中做类角色的建模，即使图 18显示你可以这么做。为了使用角色记号，你将会需要使用下面讨论的内部结构记号。</P>
<P><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">内部的结构</B> <BR xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">UML 2 结构图的更有用的功能之一是新的内部结构记号。它允许你显示一个类或另外的一个分类器如何在内部构成。这在 UML 1. x 中是不可能的，因为记号限制你只能显示一个类所拥有的聚合关系。现在，在 UML 2 中，内部的结构记号让你更清楚地显示类的各个部分如何保持关系。</P>
<P>让我们看一个实例。在图 18 中我们有一个类图以表现一个Plane类如何由四个引擎和两个控制软件对象组成。从这个图中省略的东西是显示关于飞机部件如何被装配的一些信息。从图 18 的图，你无法说明，是每个控制软件对象控制两个引擎，还是一个控制软件对象控制三个引擎，而另一个控制一个引擎。</P><IMG height=197 alt="图 19: 只显示对象之间关系的类图" src="http://www-128.ibm.com/developerworks/cn/rational/rationaledge/content/feb05/bell/bell_fig19.gif" width=415 border=0 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
<P><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">图 19: 只显示对象之间关系的类图</B> </P>
<P></P>
<P>绘制类的内在结构将会改善这种状态。开始时，你通过用二个区域画一个方格。最顶端的区域包含类名字，而较低的区域包含类的内部结构，显示在它们父类中承担不同角色的部分类，角色中的每个部分类也关系到其它类。图 19 显示了Plane类的内部结构；注意内部结构如何澄清混乱性。</P><IMG height=277 alt="图 20：Plane类的内部结构例子。" src="http://www-128.ibm.com/developerworks/cn/rational/rationaledge/content/feb05/bell/bell_fig20.gif" width=579 border=0 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
<P><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">图 20：Plane类的内部结构例子。</B> </P>
<P></P>
<P>在图 20 中Plane有两个 ControlSoftware 对象，而且每个控制二个引擎。在图左边上的 ControlSoftware（control1）控制引擎 1 和 2 。在图右边的 ControlSoftware（control2）控制引擎 3 和 4 。</P>
<P><A name=N10536><SPAN class=atitle2>结论</SPAN></A><BR>至少存在两个了解类图的重要理由。第一个是它显示系统分类器的静态结构；第二个理由是图为UML描述的其他结构图提供了基本记号。开发者将会认为类图是为他们特别建立的；但是其他的团队成员将发现它们也是有用的。业务分析师可以用类图，为系统的业务远景建模。正如我们将会在本系列关于 UML 基础的文章中见到的，其他的图 -- 包括活动图，序列图和状态图——参考类图中的类建模和文档化。</P>
<P>关于“UML 基础”的本系列的后面的元件图。</P><A name=notes xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"></A>
<P><A name=N10547><SPAN class=atitle2>脚注</SPAN></A><BR><SUP xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">1</SUP> delayFlight没有返回值，因为我作出了设计决定，不要返回值。有一点可以争论的是，延迟操作应该返回新的到达时间，而且，如果是这种情形，操作属性将显示为 <CODE>delayFlight(numberOfMinutes : Minutes) : Date。</CODE> </P>
<P><SUP xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">2</SUP>可能看起来很奇怪， BankAccount 类不知道 OverdrawnAccountsReport 类。这个建模使报表类可以知道它们报告的业务类，但是业务类不知道它们正在被报告。这解开两个对象的耦合，并因此使系统变得更能适应变化。</P>
<P><SUP xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">3</SUP> 软件包对于组织你的模型类是庞大的，但是记住重要的一点是，你的类图应该是关于建模系统的容易交流的信息。在你的软件包有许多类的情况下，最好使用多个主题类图，而不是仅仅产生一个大的类图。</P>
<P><SUP xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">4</SUP> 要理解重要一点，当我说“所有的那些成员”时，我仅仅意味着在当前图中的类将显示出来。显示一个有内容的软件包的图，不需要显示它的所有内容。它可以依照一些准则，显示包含元素的子集，这个准则就是并非所有的软件包分类器都是必需的。</P>
<P><SUP xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">5</SUP> 当画一个类图时，在 UML 规范中，全部要做的只是把类放入长方形的顶部区域，而你同理处理接口；然而，UML 规范认为，在这个区域放置“class”文本是可选的，如果类没有显示，那么它应该被假设。</P>
<P><A name=resources><SPAN class=atitle2>参考资料 </SPAN></A>
<UL>
<LI>您可以参阅本文在 developerWorks 全球站点上的 <A href="http://www.ibm.com/developerworks/rational/library/content/RationalEdge/sep04/bell/index.html" target=_blank xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">英文原文</A>。<BR></LI></UL>
<P></P>
<TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD><A name=author1></A><SPAN class=atitle2>关于作者</SPAN><BR><IMG height=80 alt="Author photo" src="http://www-128.ibm.com/developerworks/cn/rational/rationaledge/content/feb05/bell/donaldBell.jpg" width=64 align=left xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Donald Bell是IBM全球服务的</TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE><img src ="http://www.blogjava.net/kapok/aggbug/5762.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/kapok/" target="_blank">笨笨</a> 2005-06-08 18:24 <a href="http://www.blogjava.net/kapok/archive/2005/06/08/5762.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>