您可以捐助,支持我们的公益事业。

1元 10元 50元





认证码:  验证码,看不清楚?请点击刷新验证码 必填



  求知 文章 文库 Lib 视频 iPerson 课程 认证 咨询 工具 讲座 Modeler   Code  
会员   
 
   
 
 
     
   
 订阅
  捐助
需求分析与需求建模
 
作者:wsdxs0102 来源:希赛网 发布于 2016-3-22
  3966  次浏览      14
 

软件架构师的工作很辛苦,还要面对“令人不悦”的需求分析。希望本章的内容能为软件架构师更有效地工作提供一个突破口。

1 需求分析基础

1.1 什么是软件需求

什么是软件需求?简单地说,软件需求就是“这个软件到底要为用户做什么”。

IEEE的软件工程标准术语表将需求定义为:

1. 用户所需的解决某个问题或达到某个目标所要具备的条件或能力。

2. 系统或系统组件为符合合同、标准、规范或其它正式文档而必须满足的条件或必须具备的能力。

3. 上述第一项或第二项中定义的条件和能力的文档表述。

而RUP是这样定义需求的:

需求描述了系统必须满足的情况或提供的能力,它就可以是直接来自客户需要,也可以来自合同、标准、规范或其他有正规约束力的文档(A requirement describes a condition or either derived directly from user needs, or stated in a contract, standard, specification, or other formally imposed document.)。

1.2 需求捕获VS.需求分析VS.系统分析

需求捕获是获取知识的过程,只是从无到有、从少到多。需求采集者必须理解用户所从事的工作,并且了解用户和客户希望软件系统在哪些方面帮助他们。

需求分析是挖掘和整理知识的过程,它在已掌握知识的基础上进行。毕竟,初步捕获到的需求信息往往处于不同层次,也有一些主观甚至不正确的信息。而经过必要的需求分析工作之后,需求会更加系统、更加有条理、更加全面。

那么系统分析呢?如果说,需求分析致力于搞清楚软件系统要“做什么”的话,那么系统分析已经涉及“怎么做”的问题了。

需求捕获、需求分析以及系统分析之间的关系我们必须理解透彻,否则就会影响工作的有效性进行。

在实践中,需求分析和需求捕获的关系常常令人困扰。究其原因,是因为需求捕获、需求分析并不是先后进行的的两个阶段性工作,相反,它们往往是相互伴随、交叉进行的:需求工作伊始,无疑更多的是进行需求捕获工作,相伴进行的需求分析和整理工作占的比例偏少;但随着掌握的需求信息越来越多,我们需要开展的对需求的分析和整理工作也越来越多了。

同样,在实践中,需求分析和系统分析也常常被混淆。需求分析致力与搞清软件系统要“做什么”,而系统分析更关注“怎么做”的问题,比如大多数分析方法(如OOA)应该术语系统分析的范畴。

1.3 需求捕获及其工作成果

典型的需求捕获的工作成果是一摞“需求采集卡”(如表1-2所示),其中记录了需求类型、需求描述、需求背景、需求提出者和需求记录者等对进一步的需求分析非常有用的信息。

有的组织采用《需求调查报告》的形式,将采集到的需求进行归纳和汇总。

1.4 需求分析及其工作成果

通过需求采集活动,我们捕获了大量“原始需求”,而需求分析则对采集到的原始需求进行分析、整理、辨别和归纳,最终形成系统的、明确的软件需求。

何为需求分析?需求分析就是对用户需求进行分析,以得到一份明确的、规范的需求定义。

需求分析的工作成果是《软件需求规格说明书》,它精确地阐述了一个软件系统必须提供的功能、必须达到的质量属性指标以及它必须遵守的约束。《软件需求规格说明书》应尽可能完整地描述各种条件下的系统行为。

1.5 系统分析及其工作成果

需求分析致力于搞清楚软件系统要“做什么”,而系统分析已经开始关注“怎么做”的问题。

对于不同的系统分析方法,其工作成果差异大。通过结构分析方法得到的最重要的工作成果是数据流图;而面向对象的系统分析方法得到的工作成果主要是分析类图、鲁棒性、序列图等——其中分析类图描述设计的静态方面,而鲁棒图和序列图描述设计的动态方面。

1.6 需求分析在软件过程中所处的位置

本节要讨论的需求分析活动,是整个分析阶段的重要工作之一。

在分析阶段前,是概念化阶段。概念化阶段要解决项目的起源问题,主要针对项目目标主要特性、功能范围和成功要素等进行构思并达成一致。一般而言,对定制开发的软件项目来说,概念化阶段需要需方的高层领导参与,明确业务需要,由需方自行组织人员阐述业务需求;而对产品型的软件公司来说,在概念化阶段,往往是产品管理部门根据市场部门的要求,定义产品所要提供的业务功能。无论上述哪种情况,都应阐明业务需求及该需求产生的背景和理由等。

概念化阶段的工作为需求分析奠定了基础、划分了范围,接下来就可以进行需求分析了(如图1-1所示)。

图 1.1 需求分析过程在软件过程中的位置

概念化阶段明确了软件项目的意义、可行性及概括等,在概念化阶段最重要的成果《愿景与范围文档》所规定的大前提的指导下,需求分析活动要进一步完善和细化软件需求。

需求分析和领域建模是相互支持的关系。不难理解,要进行领域建模,很大程度上依赖于需求讨论会等活动。同时,领域模型作为领域建模的成果,规定了重要的领域词汇表,并且这些词汇的定义是严格的、大家共同认可的,所以可以成为团队交流的基础,自然也应当作为需求分析活动和《软件需求规格说明书》应当遵循的标准词汇。

对于后期的架构设计活动而言,需求分析活动应该提供功能需求、质量属性需求以及约束性需求等不同需求的明确定义。软件构架师将就此开展用例分析(当功能需求采用用例描述时)、质量属性分析、细化架构设计等活动。

2 软件需求的类型

以工程领域的例子做个类比吧。

比如设计一座跨江大桥:

我们会考虑“连接南北的公路交通”这个“功能需求”,从而初步设计出理想化的桥墩支撑的公路桥方案;

然后还要考虑造桥要面临的“约束条件”,这个约束条件可能是“不能影响万吨轮从桥下通过”,于是细化设计方案,规定桥墩的高度和桥墩之间的间距;

另外还要顾及“大桥的试用期质量属性”,比如为了“能在湍急的江流中保持稳固”,可以把大桥桥墩深深地建在岩石层之上,和大地浑然一体;

其实,“建造期间的质量属性”也很值得考虑,比如在大桥的设计过程中的一些考虑“施工方便性”的措施。

和工程领域的功能需求、约束条件、使用质量属性、建造期间的质量属性等类似,软件系统的需求种类也相当复杂,具体分类如图2-1所示。

图 2.1软件需求的类型

功能需求是我们最熟悉的一类需求。功能需求描述要开发的软件系统应该做什么,它可以通过“软件系统应提供的服务”的形式来定义,既包括为用户提供的服务,又包括本系统为其他系统提供的服务。

非功能需求中有一类称为约束的需求,它规定了开发系统时必须遵守的限制的条件。例如,采用何种操作系统、采用何种开发技术、需要和哪些遗留系统进行互操作等,可以视为技术性约束。而为了获得相关行业或组织的认可,或者大型企业集团处于长期整合规划的要求,软件的设计和开发可能还必须遵守相关的行业标准、企业标准等标准的约束。当然,根据具体情况的不同,还可能需要遵守相关的法律、法规、政府规章等行政或法律约束。上述情况可视为约束性需求这一大类。

功能需求强调行为,而约束不是行为。Craig Larman在《UML和模式应用(第2版)》写道:

约束不是行为,是设计或项目的某些限制条件。这些限制条件也属于需求,但通常被称为“约束”来强调其限制性。

例如:

必须使用Oracle(我们硬件签署过使用许可证了);

必须在Linux上运行(成本低)。

下面重点讨论非功能需求中的质量属性需求。

如何给众多质量属性分类,这是一个问题。McCall等人于1977年提出的软件质量属性的分类模型,影响非常广泛。如图2-2所示。它将软件的质量属性划分为三大类:产品操作、产品修改、产品改型。

图 2.2 McCall等人提出的软件质量属性的分类模型

该分类方法相当经典,但似乎缺少了“产品开发”类的质量属性——诸如易理解性、可扩展性和可重用性等。另一方面,我们也发现产品开发、产品修改和产品改型这三类质量属性有重叠(如易理解性和可扩展性对开发和维护都很重要,再如对产品改型很关键的可重用性也同样影响着产品开发)。因此,考虑到被广泛认同的迭代式开发所暗示的增量交付使开发、修改和维护之间的界限不再像以前那么明显,所以我们认为有充分的理由将产品开发、产品修改和产品改型这三类质量属性合并为一类。

可以将软件质量属性划分为运行期质量属性和开发期质量属性两大类:

开发期质量属性其实包含了和软件开发、维护和移植这三类活动相关的所有质量属性,可以说这里的“开发”是相当广义的;

开发期质量属性是开发人员、开发管理人员和维护人员都非常关心的,对最终用户而言,这些质量属性只是间接地促进用户需求的满足;

运行期质量属性是软件系统在运行期间,最终用户可以直接感受到的一类属性,这些质量属性直接影响着用户对软件产品的满意度。

表 2.1推荐的软件质量属性分类方式

运行期质量属性需求是一类非常重要的非功能需求,对客户满意度非常关键,下面一一进行说明。

性能(Performance)。性能是指软件系统及时提供相应服务的能力。

具体而言,性能包括速度、吞吐量和持续高速性三方面的要求:

吞吐量通过单位时间处理的交易数来度量;

速度往往通过平均相应时间来度量;

而持续高速性是指保持高速处理速度的能力。

持续高速性和实时系统有关,实时系统有“硬实时”和“软实时”之分,其中硬实时系统对每次系统相应时间都有严格要求,如果不能满足要求,后果将是致命的,所以把性能笼统地说成“进行典型操作性所需的时间”显然忽视了实时系统性能的内涵。

下面值得说明一下效率和性能的关系:它们反映了同一问题的“表”、“里”两面,性能为“表”,效率为“里”,如图2-3所示。所谓效率,是指软件系统对CPU处理能力和存储能力这两大类计算机资源的使用效率。

安全性(Security)。指软件系统同时兼顾向合法用户提供服务,以及阻止非授权使用的能力。高安全性意味着“同时兼顾”,这是因为有些攻击的目的是使软件系统拒绝向合法用户提供服务,而不是非法访问。

易用性(Usability)。不少文献也称之为可用性,但为了避免和持续可用性混淆,本教程采用非常流行的“易用性”的叫法。指软件系统易于使用的程度。

持续可用性(Availability)。不少文献也称之为可用性,但为了避免和易用性混淆,本教程采用“持续可用性”的叫法。持续可用性指系统长时间无故障运行的能力。

可伸缩性(Scalability)。指当用户数和数据量增加时,软件系统维持高服务质量的能力。例如当业务量较小时,软件系统运行在一台服务器上,当业务量增大时,可以通过增加服务器或增加单台服务器上所运行软件系统的个数来提高性能,而无需对软件系统本身进行编程级的修改。

互操作性(Interoperability)。指本软件系统与其他系统交换数据和相互调用服务的难以程度。

可靠性(Reliability)。软件系统在一定的时间内无故障运行的能力。

图 2.3 性能和效率的关系

鲁棒性(Robustness)。也称健壮性、容错性。鲁棒性是指软件系统在以下情况下仍然能够正常运行的能力:用户进行了非法操作;相连的软硬件系统发生了故障,以及其他非正常情况。

而开发期质量属性随着软件系统规模的日益增长,显得越来越重要了,下面一一说明。

易理解性(Understandability)。尤指设计被开发人员理解的难以程度。

可扩展性(Extensibility)。为适应新需求或需求的变化为软件增加功能的能力。我们在实际工作中,经常将可扩展性成为灵活性。

可重用性(Reusability)。重用软件系统或其一部分的能力的难以程度。

可测试性(Testability)。对软件测试以证明其满足需求规约的难以程度。在实际工作中主要指进行单元测试、插桩测试等的难以程度。

可维护性(Maintainability)。为了达到下列三种目的之一,而定位修改点并实施修改的难易程度:修改Bug、增加功能、提高质量属性。

可移植性(Portability)。将软件系统从一个运行环境转移到另一个不同的运行环境的难易程度。

务实地,我们可以将运行期质量属性和功能性一起视为“软件的外部质量”,而将开发期质量属性视为“软件的内部质量”。无疑,软件的内部质量制约着软件的外部质量;在软件开发管理本身已经十分复杂的今天,想使内部质量很差的软件具有良好的外部质量几乎是不可能的。同时,随着商业环境变化的加剧,很多企业软件出现了“建成即废弃”的尴尬情况。于是,软件系统的内部品质越来越受到重视,通过强化软件系统的可扩展性、易理解性等开发期质量属性,可以使软件有更多被改变、被重用的空间。

3 需求对架构的影响

一个成功的软件架构师,不会对所有需求“胡子眉毛一把抓”,而是分门别类梳理清楚,不同的需求对架构设计的作用方式不同。图3-1总结了各类需求与软件架构之间的关系。

图 3.1各类需求与软件架构之间的关系

功能需求影响架构,而架构必须适应功能需求。但功能并不能决定架构,这是显而易见的——因为如果仅为了满足功能需求而进行架构设计,那么设计结果几乎是毫无约束的,基于接口编程还是统统硬编码到实现都能实现功能需求,分不分层,以及如何分层似乎也无不同。

倒是质量属性需求对软件架构影响更大。例如,为了获得高可移植性,架构设计中必须考虑对硬件和平台相关特性进行封装和隔离。再例如,精心规划职责模型是获得高性能的根本,这就是为什么“将性能放在首位的软件系统”有时其架构与众不同的原因。

反过来,大部分质量属性需求能否被满足,也很大程度上依靠软件架构的设计。例如性能、可扩展性和可测试性等,虽然也受到编码质量的影响,但架构设计是否合理更为关键。再例如,微内核架构对可扩展性、可重用性和可移植性等有极大提高,适用作为生存期非常长(如20年)的软件系统的架构,以应对源源不断的变化;但微内核架构降低了软件系统的易理解性,增加了系统的复杂性。

约束性需求最为特殊,它可能产生的影响有3种:

作为架构设计时必须遵守的限制条件(如必须运行于Linux系统)

导致软件系统必须提供某些功能需求(参见表3-1的例子)

导致软件系统必须满足某些约束性需求(参见表3-1的例子)

表 3.1从约束性需求导出功能需求和质量属性需求的例子

表3-1展示了对某银行系统进行需求分析的片段。利息率是国家统一规定的,并且利率调整方案未必提前公布,所以对银行系统所有利率的调整必须能在一小时之内迅速完成。由此,银行系统应具有良好的可配置性,并提供相应的调整利率的使用功能。

总之,全面正确地对需求分类,为后续工作奠定了格局基础,是整个项目成功的第一步。

3.1 超市系统案例:领会需求类型的不同影响

例子是最好的老师。

为了更好地理解不同种类软件需求的不同影响,我们来分析一个实际的例子。在表3-2中,我们列举了一个典型的超市系统的需求子集。

表 3.2 超市系统案例:理解需求种类

从这个例子中可以清晰地看到需求可以分为两大类:功能需求和非功能需求。

简而言之,功能需求就是“软件有什么用,软件需要做什么”。同时,注意把握功能需求的层次性是软件需求的最佳实践。以该超市系统为例:

超市老板希望通过软件来“提高收银效率”;

那么,你可能需要为收银员提供一系列功能来促成这个目的,比如供收银员使用的“任意商品项可单独取消”功能有利于提高收银效率;

而具体到这个超市系统,系统分析员可能决定要提供的具体功能为:通过收银终端的按键组合,可以使收银过程从“逐项录入状态”进入“选择取消状态”,从而取消某项商品。

从上面的例子中我们还惊讶地发现,非功能需求——人们最经常忽视的一大类需求——包括的内容非常多,并且极其重要。非功能性需求又可以分为如下三类:

约束。要开发出用户满意的软件并不是件容易的事,而全面理解要设计的软件系统所面临的约束可以使你向成功迈进一步。约束性需求既包括企业级的商业考虑(例如“项目预算有限”),也包括最终用户级的实际情况(例如“用户的平均电脑操作水平偏低”);既可能包括具体技术的明确要求(例如“要求能在Linux上运行”),又可能需要考虑开发团队的真实状况(例如“开发人员分散在不同地点”)。这些约束性需求当然对架构设计影响很大,比如受到“项目预算有限”的限制,架构师就不应选择高技术成本的手段或昂贵的中间件等,而考虑到“开发人员分散在不同地点”,就更应注重软件模块职责划分的合理性和松耦合性等。

运行期质量属性。这类需求主要指软件系统在运行期间表现出的质量水平。运行期质量属性非常关键,因为它们直接影响着客户对软件系统的满意度,大多数客户也不会接收运行期质量属性拙劣的软件系统。常见的运行期质量属性包括软件系统中的易用性、性能、可伸缩性、持续可用性、鲁棒性、安全性等。在我们的超市系统的案例中,用户对高性能提出了具体要求(真正的性能需求应该量化,我们的表10-2没体现),他们不能容忍金融合计超过2s的延时;

开发期质量属性。这类非功能需求中的某些项人们倒是念念不忘,可惜很多人并没有意识到“开发期质量属性”和“运行期质量属性”对架构设计的影响到底有何不同。开发期质量属性是开发人员最为关心的,要达到怎样的目标应根据项目的具体情况而定,而过度设计会付出额外的代价。

3.2 各类需求的“易变更性”不同

需求的变更可以说“让我欢喜让我忧”——其中既蕴含了风险又包含了机遇。

之所以说需求变更蕴含有风险,是因为不存在不需要成本的需求变更。任何需求变更的都可能意味着时间和金钱的消耗,并且大量需求变更之后程序可能被搞得混乱不堪,而内部质量降低势必造成外部质量下滑,例如Bug增多等。

当然,需求变更也蕴含着机遇。对软件架构设计而言,这个机遇可能意味着设计出稳定的架构,最终这个架构能够支持业务功能在一定范围内“随需应变”。

需求为什么会变更呢?总结而言,需求变更可能有三类来源(如图3-2所示):

图 3.2软件需求信息传递链

我们要解决的问题发生了变化。商业环境变了(如行业软件)、国家政策变了(如电子政务系统)、用户兴趣变了(如游戏软件)都会引起我们要解决的问题发生变化;

我们对问题的理解发生了变化。客户和用户对他们要解决的问题的认识会改变,同样,开发团队对需求的理解也会不断加深。有些没有经验的开发人员单纯地认为客户提的需求不够确切,显然是忽视了“需求理解”其实是一个包含客户和开发方案都在内的“信息传递链”这一事实;

我们理解问题的过程有误。例如我们了解需求找错了人。例如负责采集和分析需求的需求分析员的技能拙劣。

值得庆幸的是,大量经验表明,一个软件系统的各类需求“易变化性”并不相同。或者反过来,不同种类的需求的稳定性并不相同,一刀切地认为“需求变更无所不在”并不准确,甚至导致放弃了设计更稳定的软件架构的机会。着实可惜。

关于需求变更是有规律可循的。一般而言,功能需求最易变,而质量属性需求最稳定(如图3-3所示)。

图 3.3软件需求的易变化性不同

功能需求最容易变化。但同时,任何有经验的软件架构师都必须明白,功能需求的易变性中潜伏着两类不易变性,用好这两类不易变性我们的工作将变得从容些。

一是功能需求集中存在少量长期稳定的功能。例如银行系统中的存钱和支取功能,例如票务系统中的订票功能……这些功能作为软件系统的“基本特色”,任凭软件系统如何升级都会被保留。

二是虽然功能的行为步骤常常变化,但功能点本身趋于稳定。当采用用例技术进行需求捕获和需求分析时,用例图往往是相对稳定的(它描述了功能体系),而用例规约则可能频繁变化(它以交互序列的形式描述功能执行的步骤)。

质量属性需求相对来说最为稳定。例如,但凡是银行系统,总是对安全性要求很高、对持续可用性要求很高等。

一般而言,约束性需求的稳定性则稍差,技术趋势发生变化、法律法规重新界定和用户组织调整改组等,都有可能使约束性需求变更。

4 质量属性需求与需求折衷

众多质量属性需求之间往往会有冲突,我们必须权衡。在软件实践中,人们对软件质量属性的重视不够,这已成为很多项目遭受失败的常见根源之一。但作为软件架构师,应该对质量属性需求的折衷有系统性的把握。

本章前面比较全面地介绍了14种质量属性,而经典文献中给出的是其中12种质量属性之间的关系,如表4-1所示,值得架构师研究和借鉴。

表 4.1 质量属性关系矩阵

说明:“+”代表“行属性”促进“列属性”;“-”代表的含义则相反

由表中可以看出,不同的质量属性之间可能存在3种关系:

无影响

促进

阻碍

上表略显混乱,基本无规律可循。本节运用数学中的“矩阵变换”将之变换成更有规律的矩阵表示,如表4-2所示。

表 4.2调整后的质量属性关系矩阵

说明:浅蓝色为区域1,白色为区域2,浅绿色为区域3

如前所述,开发期质量属性可以认为是软件项目的内部属性,这些指标的良莠深刻影响着开发人员、维护人员、测试人员和开发管理人员的工作。可测试性、可重用性、可维护性、可扩展性和可移植性这些开发期质量属性之间的关系总结如下(如表4-2中“区域3”所示,即不包含开发期质量属性和运行期质量属性之间的关系):

除了不存在影响关系之外,绝大多数运行期质量属性之间存在促进和被促进的关系。例如,可重用性越好,可测试性、可维护性、可扩展性和可移植性就越好;

唯一的例外是,可移植性可能对可维护性造成负面影响;

很多属性之间是“相互”促进的。例如,可测试性和可维护性是相互促进的关系;

但也有不少属性之间的促进关系是“单向”的。例如,可移植性促进可测试性,但可测试性却不能促进可移植性(也不会降低可移植性)。

相比之下,和运行期质量属性相关的制约关系就显得比较复杂。但经过仔细分析,我们还是能把握住其中较为明显的规律:

非常典型的是,性能和安全性这两个运行期质量属性和其他质量属性之间都是抵触关系(如表4-2中区域1所示)。

性能和安全性要求高,势必会为其他质量指标带来负面影响。例如,此消彼长,为了构成更加安全的系统,在系统的易用性、可测试性和可维护性方面就“可能”要做出让步;

反过来,其他质量属性指标也会对性能和安全性造成负面影响。某些嵌入式系统对性能要求非常高,但可测试性和可靠性方面也必须达到极高要求,这时就需要架构师非常高超的折衷技能,以达到总体最优的效果。

那么,性能和安全性之间呢?很简单,如表所示,极高的安全性要求将使我们不得不降低性能要求;

除了性能和安全性之外,持续可用性、可互操作性、可靠性、鲁棒性和易用性等运行期质量属性相关的制约关系比较复杂,需要更多经验。

5 领域建模基础

领域建模是建立领域模型的过程。领域建模专注于分析问题领域本身,发掘重要的业务领域概念,并建立业务领域概念之间的关系。接下来,我们来介绍一下什么是领域建模,以及常用于表达领域模型的UML图(从而带来实感)。

5.1 什么是领域模型

案例先行。图5-1展示了银行领域模型的一小部分。

图 5.1银行领域模型的凭证相关部分

这是一幅UML类图,它抽象地表示了银行领域中和凭证相关的部分领域知识:

任何一个银行“帐户”(这里没有详细分类)可能与多个“凭证”相关;

具体而言,凭证可以使银行卡、存折或存单等形式;

任何凭证都有明确的生效起始日和终止日;

但各种凭证的凭证号却不是统一的,比如存折和信用卡有不同的编号格式;

……

模型虽小,却涵盖了银行一些实际的业务情况。由此例可以看出:领域模型是对实际问题领域的抽象表示,它专注于分析问题领域本身,发掘重要的业务领域概念,并建立业务领域概念之间的关系。

Grady Booch在《面向对象项目的解决方案》中说明了“关于一般领域模型规模的经验性法则”,这一法则无疑为我们提供了更多领域模型的实感:

对于中等复杂度的项目,应该在系统的领域模型中找到大约50~100个类,它们只代表定义问题空间词汇的那些关键抽象。

5.2 领域模型相关的UML图

一般情况下,领域模型用下面两种UML图表示:

类图

状态图

类图无疑是用得最多的,但有时状态图可以用来对业务领域对象的状态变化进行有效的补充说明。仅举一例。图5-2描述了储蓄帐户的可能状态及状态转换关系。

图 5.2储蓄帐户的可能状态及状态转换关系

该状态转换图作为银行领域模型的一部分,表达了如下业务知识:

储蓄帐户有正常、挂失、冻结和销户等4种状态;

有效的储蓄帐户始于开户交易,开户交易成功后储蓄帐户处于正常状态;

开户交易的业务规则是:开户金额≥10元人民币;

用户可以凭身份证要求对自己的储蓄帐户进行挂失和解挂交易;

银行可以根据授权(例如司法授权)对储蓄帐户进行冻结和解冻;

处于正常状态的储蓄帐户可以进行存款、取款交易;

处于正常状态的储蓄帐户经销户交易后变成销户状态。

5.3 领域建模在软件过程中所处的位置

成功的项目都是相似的,失败的项目却各有各的失败之处。对于采用面向对象技术的软件项目而言,领域建模恰恰属于“都是相似的”之列——领域建模是公认的促进OO项目成功的最佳实践之一。

5.3.1 领域建模的必要性:从需求分析的两个典型困难说起

有经验的需求分析员会特别注意避免常见问题的发生,下面我们来讨论其中的两个。

第一个困难:用户的参与不够,造成需求分析成果中假设的成分太多。很典型的情况是,用户不能理解开发方为什么要投入如此多的精力进行需求捕获和需求分析,在他们看来,“需求很明白”;另一方面,在用户真正使用了软件系统一段时间之前,他们往往并不确切地知道自己需要什么。这是一个悖论,除了运用原型等方法进行需求启发之外,我们有必要和用户进行“更深一级”的沟通。

领域模型是对实际问题领域的抽象,它“穿透”用户想要的功能的表象,专注于分析问题领域本身,发掘重要的业务领域概念,并建立业务领域概念之间的关系。因此,开发方和用户在“领域模型”上达成的共识,往往比“功能需求”上达到的共识“更深一级”,从而也更加稳固。

可以这么说,“用户参与不够”其实是两个问题:用户参与不够多,或者用户参与不够深入。

需要讨论、原型评审和现场客户等方法可以比较好地解决“用户参与不够多”的问题。通过和用户一起进行领域建模的讨论、领域模型的评审,可以比较好地解决“用户参与不够深入”的问题。用户代表或领域专家深入参与领域建模活动,可以避免需求分析员对业务领域的理解一直停留在假设的层面,直到软件开发出来后才被用户发现的尴尬局面出现。

第二个困难:问题领域太复杂时,需求分析的开展会遇到困难。一个广为人知的案例来自敏捷社区,《敏捷软件开发生态环境》中记载了一个因“分析瘫痪”而惨败的案例:

新加坡贷款项目是一个巨大的失败。在Jeff没有加入该项目之前,一家知名的大型系统集成公司(在此当然不便点名)在该项目上花了两年时间,最后宣布做不下去了。……

该项目是一个设计大范围的商业、公司和消费者的贷款系统,它融合了大量的贷款凭证(从信用卡到大型跨银行的公司贷款)和广泛的贷款功能(从调查到完成到后台检测)。……

而Jeff却成功了,他的成功来自许多最佳实践,其一就是领域建模。《敏捷软件开发生态环境》中继续写道:

进入到“新”项目不到两个月时间,Jeff的团队就开始向客户提供可演示的特性。该团队花了大约一个月时间进行整体对象模型方面的工作……

类似下列情况你也许并不陌生。需求分析在进行过程中,我们可能不断地因“对关键领域问题的理解不足”而卡壳或者争论不休。例如,银行系统中客户、帐户、凭证的关系因“一本通”、“一卡通”的出现变得复杂了,需求讨论可能一而再、再而三地影响需求分析的推进。

怎么办呢?可以借助于领域建模。柳传志曾说过,做事要“撒上一层土,夯实了,在撒上一层土,在夯实了”,很有借鉴意义。对于需求分析而言,也存在一个领域知识的“夯实”问题。借而鉴之,我们在需求分析过程中不应忘记:搞清楚一部分领域知识,就将此部分只是建模并将模型在整个项目组公开,再搞清楚一部分领域知识,再建模并将模型在整个项目组公开。

通过上面“两个困难”的讨论可以看出,领域建模对需求分析起着必要的支持作用。

5.3.2 领域建模与需求分析的关系

领域模型是探索问题领域的工具,可以帮助我们探索和提炼问题领域知识。那么,它和需求分析是什么关系呢?从本质上来讲,领域建模和需求分析活动是相互伴随、相互支持的。如图5-3所示。一方面,领域模型提供的词汇表应当成为所有团队成员所使用语言的核心,在需求活动以及其他活动中起到团队交流基础的作用。另一方面,需求捕捉和而烦恼系非常关键,因为不知道客户想要什么,就无法提供让客户满意的软件。

图 5.3领域建模与需求捕获之间的关系

关于是先有领域模型还是先有需求定义的问题,在业界也可算一个颇有争议的话题了。其实,务实来讲,它们是同时产生、交叠演进的。图12-4展示了常见的项目过程是如何规划的。

图 5.4常见的项目过程是如何规划的

5.3.3 领域建模所处的位置

图5-5总结了领域模型对整个软件开发活动的重要作用:

领域模型为需求定义提供了领域知识和领域词汇。较之《词汇表》而言,领域模型更能体现各领域概念之间的关系,有较好的大局观。

软件界面的设计往往和领域模型关系密切。一方面,领域信息是所要展现内容中最重要的部分;另一方面,界面结构必须和业务内容的结构相一致,否则会使软件晦涩难用;

领域模型是否合理将影响软件系统的可扩展性。这是因为,丰富多彩的软件功能背后“藏”着的领域模型决定了软件功能可能的范围。Martin Fowler在《分析模式》一书中指出:模型的选择会影响最终产生的系统的灵活性和可重用性。此言不虚;

由于分层架构的思想被广泛接受,领域模型经过精化之后会成为业务层的核心;

领域模型是设计持久层数据模型的良好基础,在实践中直接将领域模型映射成物理数据模型的例子也屡见不鲜。

图 5.5领域模型在软件开发中的作用

5.4 领域模型对软件架构的重要作用

软件的架构设计对整个软件开发而言是举足轻重的,而领域模型对架构设计的成功与否又起着非常关键的作用。总体而言,领域模型对软件架构乃至整个软件系统开发工作的作用可以归纳为如下3点:

探索复杂问题、固化领域知识

决定功能范围、影响可扩张性

提供交流基础、促进有效沟通

下面结合案例分别进行讲解。值得说明的是,为了使没有接触过领域建模的读者尽快熟悉领域建模,我们决定引入多个实际案例——在说明领域模型的每个作用时引入一个新的案例。

6 领域建模案例

6.1 配置管理工具案例:探索复杂问题、固化领域知识

《人月神话》一书指出了软件开发的“根本问题”,所谓根本问题,就是无论如何也回避不掉的问题,首当其冲的就是“软件的复杂性”。而运用面向对象的领域模型技术,可以帮助我们驯服复杂的问题。对此,Grady Booch和Martin Fowler都不约而同地表示过,他们采用面向对象方法最大的原因是它有助于解决更为复杂的问题。领域模型本身作为辅助思维的工具,帮组我们将注意力始终保持在最为重要的业务概念及其关系上,使我们能够不断深入地、系统地整理对问题的认识。

下面举例。

软件配置管理工具的分析和设计工作。由于软件配置管理领域有不少非常专业的术语,并且配置管理和整个软件开发过程有着密切的支持和被支持的关系,因此使得配置管理领域比较复杂。在这种情况下,项目伊始,通过领域建模来探索并理清复杂的问题,是非常有实际意义的实践方法。

领域建模往往要经历一个从模糊到清晰,从零散到系统的过程。例如,图6-1展示了对软件有价值的知识:

图 6.1开始时的领域模型可能零散且不完整

软件配置管理中,被管理的对象不是抽象的概念,而是实实在在的以“工件”形式存在的工作成果;

随着软件开发和管理工作的开展,工件可能发生“变更”——或被增强、或被修改,不一而足;

“基线”和“配置项”都是软件配置管理中非常关键的概念……

软件架构师和领域专家通力合作,在稚嫩却有启发性的最初领域模型的基础上不断讨论、不断探索、不断挖掘,使领域模型不断精化,最终的领域模型变得越来越严谨、越来越系统。图6-2展示了最终软件配置管理领域模型的一部分。

任何软件工程过程,都少不了角色(role)、活动(activity)和工件(artifact)等概念(或者类似概念)。这些概念本身很好理解。角色是对个人或者作为开发团队的一组人的职责的规定;具体人和角色的关系,好比人和帽子的关系。活动就是角色执行的工作单元。工作就是工作的成品或半成品。

倒是这些概念的关系显得更加重要。角色的职责,具体体现在他执行的活动和负责的工作上。工件是由活动生产出来的——工件是活动的输出;比如制定《编码规范》。然而,活动本身也可能以工件作为输入——活动可能需求使用工作;比如编码活动要参考《编码规范》。还有一种关系,工件既是活动的输入又是它的输出——活动修改工件;比如修改《编码规范》。

建立并管理基线(baseline),为软件开发管理提供了有力的支持。基线的要点有二:一是要通过评审,而是要受配置和变更管理控制。IEEE对于基线的完整定义是:已经通过正式复审和批准的某规约或产品,它因此可以作为进一步开发的基础,并且只能通过正式的变更控制过程进行改变。

图 6.2软件配置管理领域模型(部分)

配置和变更管理完成建立并管理基线的任务。置于配置和变更管理之下的工件,被称为配置项(configuration item)——因此模型中把配置项建模为工件的子类。而基线就是由多个配置项组成的瞬时快照——因为受配置和变更管理控制是基线的必要条件。任何工件都有可能发生变更;正如并不是所有工件都是配置项一样,变更也不一定都受控,比如,用于讨论的临时设计就不必受控。只有配置项的变更,才是需要受配置和变更管理控制的。到底哪些工作应当受控,是根据实践情况决定的,应当在规范性和灵活性之间权衡考虑。

通过对案例的分析,我们看到领域建模的过程就是对复杂问题进行探索的过程,最终得到的领域模型将复杂的领域知识记录下来、“固化”下来。

领域建模活动的结果是领域模型,但是由于问题领域的复杂性,领域模型不是一蹴而就的。在领域建模过程中,前期的成果往往很不完善,我们会不断基于现有的成果进行讨论、分析和完善。因此,领域建模的过程就是探索复杂问题的过程,而领域模型的早期版本本身也成了促进进一步思维的工具。

6.2 人事管理系统案例:决定功能范围、影响可扩展性

为了说明领域模型如何决定功能范围并影响软件系统的可扩展性,我们引入一个新的案例(或许这个案例正式你熟悉的领域)。

这是一个人事管理系统的例子。

客户对最初交付的HR管理系统他们比较满意。在这个版本中,架构师根据“统计公司雇员”等需求(没有考虑可扩展性)设计了领域模型,图6-3展示了这个领域模型的一角。

图 6.3最初的人事管理系统领域模型之一角

时间流转,公司开始出现职位升迁、员工离职,甚至离职的员工又被“挖”回来等情况。这时,HR管理系统出现了问题,比如HR经理希望列出如图6-4所示的员工履历纵览,但系统却智能显示某员工的最新职位。

图 6.4最初的模型不支持此功能

毋庸置疑,必须对系统进行升级才能支持“能够反映职位变动和离职员工重新加入公司”这一特性。但这时我们发现,由于领域模型的限制,希望仅扩充应用层(相当于领域层、数据层)就增加对“查看员工履历”功能的支持是不可能的。这是因为领域层并没有提供“查看员工履历”所需的服务,而且领域层也没有能力提供出这样的服务。

没办法,领域模型必须被重新设计以增强能力,如图6-5所示。说明一下,由于建模者的习惯差异,有的人常用“关联类”而有的人不用。图6-5中,分别用两种方式表达了相同的设计思想,只不过左边的模型采用了关联类语法而已。

图 6.5升级后的模型(前者采用关联类)

不难看出,公司和雇员原来是一对多关系,现在变成了多对多关系;更深层次的,职位、所在部门、薪水这些属性从“雇员类”移到了“雇佣类”。分析如下:

雇员的姓名、性别很少改变(或者说,本HR系统不打算支持那些极端情况),而地址只需记录最新的即可,因此姓名、性别、地址作为雇员的属性;

和姓名不同,雇员的职位、部门、薪水并不是一成不变的,而是随着职业生涯的发展不断变化的。从面向对象的角度考虑,职位、部门、薪水不应作为雇员的属性;

其实,公司雇佣了某人作为雇员,那么公司和雇员之间就建立了雇佣和被雇佣的关系,而职位、部门、薪水都是对这种雇佣关系的描述。从面向对象的角度考虑,可以采用关联类来描述“雇佣”这种关系。除了职位、部门、薪水等属性之外,雇佣类还应该担负记载雇佣时间段的职责。

这样一来,为了支持“能够反映职位变动和离职员工重新加入公司”这一特性,不仅具体实现要增强、数据库要改变,而且子系统的接口也会随之发生改变,使这一变化的影响涉及到其他子系统。

下面,让我们仔细体会一下上面例子所说明的问题。

变化无所不在。一个软件系统,用户交互的方式变换花样了,持久数据的存储从文件方式变成关系数据库(甚至对象数据库)了,或许还和形形色色的其他系统“无缝集成”了……

但并非变化无常。比如,问题领域层的对象似乎在某种程度上还是“老面孔”。关于这一点,一个老于世故的例子是航空订票系统——从架在“大型主机+字符终端”之上的基于命令行的订票系统,到现在的B/S结构的分布式订票系统,“航班”、“乘客”及“优惠策略”这些领域概念似乎从未变过。

领域模型决定了软件系统功能的范围。任何模型都是对现实世界的某种程度的抽象,领域模型也不例外。抽象意味着有目的性地忽略;而忽略哪些对象和关系,保留哪些对象和关系,都和具体目的有关。最初的人事管理领域模型(见图6-3)可以支持很多有用的功能,但这个模型不能反映雇员的职位和部门等的变化历史。后来的人事管理领域模型(见图6-5)更为复杂,提供了记录历史的功能。

领域模型还影响着软件系统的可扩展性。可扩展性是软件系统的一种非功能性的质量属性,是在系统保持现有功能特性的基础上,扩展实现有一定相关性的其他功能特性的容易程度。扩展越容易则可扩展性越高。功能是软件系统能够完成的具体任务;而模型揭示了丰富多彩的功能需求背后的机构,使我们设法“驯服”复杂性时有了切中要害的“着力点”。如果说,定义系统的功能相当于“拍照片”的话,那么领域建模就相当于“做透视”:功能需求记录了系统外在的、用户可感知的“应该列表”,但它们是易变的,当商业环境急剧变化的时候需求尤其易变;而领域模型揭示并模拟问题领域的内在结构,相当与对问题领域进行了一层抽象,良好的领域模型不仅支持现有功能需求的满足,还在一定程度上支持未来可能出现的新需求,使系统需要扩展的时候仅需增加必要的“应用功能代码”,体现良好的可扩展性。

6.3 在线拍卖系统案例:提供交流基础、促进有效沟通

有人说,团队开发最重要的问题有三个:交流,交流,还是交流。

领域模型是团队交流的基础,是所有团队成员所使用语言的核心(如图6-6)所示。领域模型规定了重要的领域词汇表,并且这些词汇的定义是严格的、大家共同认可的,所以可以成为团队交流的基础。例如,当开发人员刨根问底地向用户讨教需求、和系统分析员争论需求文档、和测试人员争论那是不是Bug的问题之时,就应该用领域模型规定的“领域词汇”,进行不易产生歧义的有效沟通。任何团队开发活动,都应注意交流的问题。团队的不同成员之间共识越多,他们之间的合作就越顺畅。

图 6.6领域模型是团队交流的基础

下面,以类似淘宝网的C2C网络平台作为案例,着重讨论“在线拍卖”相关的领域模型,说明其对有效沟通的作用。

拍卖领域的规则比较复杂,图6-7和图6-8所示为其领域模型的一部分。图6-7清楚地表达了和成交相关的领域知识,界定了相关术语,有利于无歧义地进行交流。例如成交是拍卖商品、买家和卖家之间的关系的描述,并且其中的买家是“喊出”成交价的那个买家。

然而网上交易涉及到的交付流程比较复杂,图6-8对此进行了简化描述。将这些容易理解不清的关键领域知识通过建模“固定”下来,作为交流的基础,就大大降低了交流不畅发生的几率。

图 6.7领域模型的类图部分

图 6.8领域模型的状态图部分

   
3966 次浏览       14
 
相关文章

需求分析师的能力模型
基于模型的需求管理方法与工具
需求管理工具DOORS 的接口
使用Web+EA实现基于模型的需求管理
需求经过大脑的过程:需求分析评估方法
 
相关文档

需求分析与需求管理
需求分析具体要求全解
需求分析与验证
需求分析的核心线索
基于UML的需求分析方法
 
相关课程

需求分析与管理
从需求过渡到设计
业务建模与业务分析
产品需求分析与管理
需求分析最佳实践与沙盘演练
最新课程计划
信息架构建模(基于UML+EA)3-21[北京]
软件架构设计师 3-21[北京]
图数据库与知识图谱 3-25[北京]
业务架构设计 4-11[北京]
SysML和EA系统设计与建模 4-22[北京]
DoDAF规范、模型与实例 5-23[北京]
相关文章
需求分析方法—把测试流程图表化
敏捷需求分析五大关键因素
写好市场需求文档的10种技巧
需求分析中减少客户摩擦的法则
软件项目需求管理复杂性分析
EPC-事件驱动的流程链
更多...   
相关培训课程
软件需求分析与管理实践
业务建模与业务分析
软件需求分析与管理
软件需求分析师
面向产品的需求分析与管理
IT规划体系与实践
成功案例
北京 软件需求分析与管理
某知名基金 软件需求分析
联想 业务需求分析与建模
财税领域某IT服务商 测试需求分析
医疗行业 面向产品的需求管理
某知名IT服务商 测试需求分析>
某高新技术公司 测试架构、需求分析
更多...