中科院高级系统架构师培训讲义


◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 1 - 目录目录目录目录 前言前言前言前言 ............................................................................................................................................................................................................................................................................................---- 6 6 6 6 ---- 教学的思想与方法教学的思想与方法教学的思想与方法教学的思想与方法 ............................................................................................................................................................................................................................................---- 7 7 7 7 ---- 第一章第一章第一章第一章 从系统工程的角度构建架构从系统工程的角度构建架构从系统工程的角度构建架构从系统工程的角度构建架构 ............................................................................................................................................................................---- 8 8 8 8 ---- 1.1 软件架构的定义与问题 ...............................................................................................- 8 - 一、软件架构的定义 ......................................................................................................... - 8 - 二、系统架构师的职责与思维方式.................................................................................. - 8 - 三、对软件开发过程的认知 ........................................................................................... - 12 - 1.2 规范性软件开发过程与软件架构...............................................................................- 14 - 一、规范性软件开发过程 ............................................................................................... - 14 - 二、软件开发增量模型与系统架构................................................................................ - 16 - 1.3 架构设计的自顶向下结构化分解...............................................................................- 18 - 一、软件架构的结构化方法 ........................................................................................... - 18 - 二、数据流图及其分解 ................................................................................................... - 19 - 三、基于数据流的结构设计 ........................................................................................... - 23 - 四、结构图的进一步细化 ............................................................................................... - 25 - 五、结构化分解的设计原则 ........................................................................................... - 26 - 1.4 软件架构的设计过程 ..................................................................................................- 27 - 1.5 从系统工程的角度分析和设计架构...........................................................................- 30 - 一、应用系统工程帮助需求分配.................................................................................... - 30 - 二、组织复杂软硬件系统的需求.................................................................................... - 31 - 1.6 迭代的建立架构基线 ..................................................................................................- 33 - 一、成功的软件架构设计 ............................................................................................... - 33 - 二、建立弹性软件架构 ................................................................................................... - 37 - 三、建立架构基线的步骤 ............................................................................................... - 38 - 四、从质量属性及其应对策略的视角优化架构............................................................ - 39 - 五、从模块划分的视角优化架构.................................................................................... - 41 - 六、从共享分层结构的视角优化架构............................................................................ - 42 - 七、从软件复用与组件化的视角优化架构.................................................................... - 43 - 第二章第二章第二章第二章 从业务架构到产品架构从业务架构到产品架构从业务架构到产品架构从业务架构到产品架构 ........................................................................................................................................................................................---- 47 47 47 47 ---- 2.1 从问题域到业务架构概念 ..........................................................................................- 47 - 一、用创新思想设计产品概念........................................................................................ - 47 - 二、由问题分析建立业务架构概念................................................................................ - 49 - 三、通过调研明确用户目标 ........................................................................................... - 51 - 四、项目总体概念性架构的确定.................................................................................... - 52 - 2.2 从需求分析到架构设计 ..............................................................................................- 54 - 一、从系统的角度描述需求 ........................................................................................... - 54 - 二、通过用例场景建立行为模型.................................................................................... - 55 - 三、用例结构化及其文档描述........................................................................................ - 56 - 四、并发处理框架的业务模型........................................................................................ - 60 - 五、并发处理框架用例及其业务流................................................................................ - 62 - 2.3 从领域模型到数据模型 ............................................................................................- 65 - 一、领域模型的初步建立 ............................................................................................... - 65 - 二、数据模型的建立 ....................................................................................................... - 68 - ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 2 - 2.4 系统安全性设计与软件架构.....................................................................................- 68 - 一、Web 系统的不安全因素分析 ................................................................................... - 68 - 二、实现安全服务的基本措施........................................................................................ - 69 - 三、建立安全软件开发过程模型.................................................................................... - 72 - 四、安全漏洞与防护措施 ............................................................................................... - 73 - 五、传输层加密的方法 ................................................................................................... - 77 - 六、不对称加密框架的架构设计.................................................................................... - 78 - 七、传输层加解密业务流程分析.................................................................................... - 82 - 2.5 产品架构模型的分析与设计.....................................................................................- 83 - 一、总体架构模型的建立 ............................................................................................... - 83 - 二、子系统架构模型的建立 ........................................................................................... - 84 - 第三章第三章第三章第三章 软件架构的重构与优化软件架构的重构与优化软件架构的重构与优化软件架构的重构与优化 ........................................................................................................................................................................................---- 88 88 88 88 ---- 3.1 研发型项目的敏捷过程与重构...................................................................................- 88 - 一、敏捷过程的提出的原因 ........................................................................................... - 88 - 二、敏捷过程的价值观与方法论.................................................................................... - 89 - 三、敏捷过程对架构的影响 ........................................................................................... - 92 - 四、软件重构与架构优化 ............................................................................................... - 93 - 3.2 通过优先级分析澄清关键特征的价值.......................................................................- 94 - 3.3 单一职责原则(SRP).....................................................................................................- 97 - 一、职责是变化的一个轴线 ........................................................................................... - 97 - 二、分离耦合的职责 ....................................................................................................... - 98 - 三、业务规则和持久化 ................................................................................................... - 99 - 3.4 开放—封闭原则(OCP).............................................................................................. - 100 - 一、OCP 原则的基本概念............................................................................................. - 100 - 二、实现 OCP 的关键是抽象........................................................................................ - 100 - 三、预测变化和“贴切的”结构.................................................................................. - 101 - 3.5 依赖倒置原则(DIP).............................................................................................. - 102 - 一、对传统层次结构的倒置 ......................................................................................... - 102 - 二、依赖倒置原则的设计方法...................................................................................... - 103 - 三、架构、框架与业务层面的复用.............................................................................. - 105 - 3.6 接口隔离原则(ISP)....................................................................................................- 107 - 一、接口有可能被污染 ................................................................................................. - 107 - 二、分离客户就是分离接口 ......................................................................................... - 108 - 三、使用多重继承分离接口 ......................................................................................... - 109 - 3.7 包的设计与重构原则 ................................................................................................ - 110 - 一、如何进行包的设计 ..................................................................................................- 110 - 二、包的内聚性原则 ......................................................................................................- 110 - 三、包的耦合性原则(ADP).......................................................................................- 112 - 四、包的稳定依赖原则(SDO)...................................................................................- 116 - 五、包的稳定抽象原则(SAP) ...................................................................................- 117 - 3.8 封装类或者接口的变化 ............................................................................................ - 118 - 一、设计模式的基本思想 ..............................................................................................- 118 - 二、利用外观模式封装类的变化.................................................................................. - 120 - 三、利用适配器模式封装接口变化.............................................................................. - 121 - 3.9 封装业务单元的变化 ................................................................................................ - 122 - ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 3 - 一、利用模板方法封装业务单元变化.......................................................................... - 122 - 二、利用工厂模式封装对象变化.................................................................................. - 124 - 三、利用桥接模式封装业务单元变化.......................................................................... - 126 - 四、利用装饰器模式封装核心业务单元...................................................................... - 128 - 3.10 利用观察者模式处理业务单元的变化................................................................. - 129 - 3.11 代理模式在架构设计中的应用............................................................................. - 132 - 一、代理模式应用简述 ................................................................................................. - 132 - 二、在团队并行开发中使用代理模式.......................................................................... - 132 - 第四章第四章第四章第四章 平衡规范性与敏捷性的软件架构平衡规范性与敏捷性的软件架构平衡规范性与敏捷性的软件架构平衡规范性与敏捷性的软件架构........................................................................................................................................................---- 139 139 139 139 ---- 4.1 软件开发过程中规范与敏捷的融合......................................................................... - 139 - 一、两种方法论最重要的结论...................................................................................... - 139 - 二、通过评估项目特征寻求平衡方法.......................................................................... - 140 - 三、平衡敏捷与规范过程的步骤.................................................................................. - 140 - 四、在大型规范性项目中融入敏捷过程...................................................................... - 141 - 五、敏捷过程多维度扩展中的系统架构...................................................................... - 144 - 4.2 架构驱动开发中的节奏与协作................................................................................. - 147 - 一、增量发布的节拍、过程与进展.............................................................................. - 147 - 二、定期再评估、同步和调整架构.............................................................................. - 149 - 三、保持架构交付节奏建立协作关系.......................................................................... - 151 - 4.3 通过重构进一步优化架构 ........................................................................................ - 154 - 一、利用目标最小化准则发现设计重点...................................................................... - 154 - 二、软件的腐化与控制方法 ......................................................................................... - 155 - 三、发现架构的问题及其改进...................................................................................... - 157 - 第五章第五章第五章第五章 基于质量属性的架构策略基于质量属性的架构策略基于质量属性的架构策略基于质量属性的架构策略 ............................................................................................................................................................................---- 163 163 163 163 ---- 5.1 质量度量模型与质量属性场景................................................................................. - 163 - 一、三层次软件质量度量模型...................................................................................... - 163 - 二、软件架构质量属性的场景...................................................................................... - 165 - 5.2 应对质量属性的架构设计过程................................................................................. - 165 - 一、以核心功能为主进行架构设计.............................................................................. - 165 - 二、以质量属性为依据进行重构和优化...................................................................... - 166 - 三、增量式的完善架构设计 ......................................................................................... - 166 - 四、以测试驱动架构设计 ............................................................................................. - 167 - 5.3 可靠性质量解决方案 ................................................................................................ - 167 - 一、可靠性质量属性场景 ............................................................................................. - 168 - 二、健康监测 ................................................................................................................. - 169 - 三、错误恢复 ................................................................................................................. - 170 - 5.4 基于高可靠性的架构设计 ........................................................................................ - 171 - 一、进程间提升可靠性的方法...................................................................................... - 171 - 二、保证可靠性的分层结构 ......................................................................................... - 172 - 5.5 基于高可集成性的架构设计 .................................................................................... - 173 - 一、问题的陈述 ............................................................................................................. - 174 - 二、架构解决方案 ......................................................................................................... - 174 - 三、结构化模型的架构模式 ......................................................................................... - 176 - 四、子系统管理部分的模块 ......................................................................................... - 176 - 五、子系统应用模块 ..................................................................................................... - 177 - ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 4 - 六、系统设计中需要关注的问题.................................................................................. - 178 - 5.6 软件架构的恢复 ........................................................................................................ - 178 - 一、架构恢复层面的重构技术...................................................................................... - 179 - 二、反向工程和正向工程 ............................................................................................. - 179 - 三、架构和设计恢复 ..................................................................................................... - 180 - 四、架构恢复阶段的设计重构...................................................................................... - 185 - 5.7 架构评审与决策 ......................................................................................................- 186 - 一、软件架构的质量评估 ............................................................................................. - 186 - 二、ATAM 的参与人员 ................................................................................................. - 188 - 三、ATAM 的结果 ......................................................................................................... - 188 - 四、ATAM 的阶段 ......................................................................................................... - 189 - 第六章第六章第六章第六章 软件产品线架构组织与原则软件产品线架构组织与原则软件产品线架构组织与原则软件产品线架构组织与原则 ....................................................................................................................................................................---- 192 192 192 192 ---- 6.1 产品线架构的组织方法 ............................................................................................ - 192 - 一、组织产品线的需求 ................................................................................................. - 193 - 二、确定范围与变化点 ................................................................................................. - 193 - 三、产品线架构的组织原则 ......................................................................................... - 194 - 6.2 产品线架构的构思与预见 ........................................................................................ - 195 - 一、形成并统一架构的构思 ......................................................................................... - 195 - 二、阐明风险权衡后果 ................................................................................................. - 197 - 三、如何提出建设性构思 ............................................................................................. - 198 - 四、预测、验证和调整 ................................................................................................. - 199 - 五、预测产品线架构方向的改变.................................................................................. - 201 - 六、在过程中评估风险与机会...................................................................................... - 203 - 七、调整功能、预算、计划或进度.............................................................................. - 205 - 6.3 简化架构保持平衡 .................................................................................................... - 206 - 一、从组织和架构两方面思考简化.............................................................................. - 206 - 二、分别澄清组织与架构两个方面.............................................................................. - 207 - 三、确保产品线架构得到实施人员信任...................................................................... - 208 - 四、产品线架构策略的总结 ......................................................................................... - 209 - 6.4 软件架构挖掘 ..........................................................................................................- 210 - 一、架构挖掘过程 ......................................................................................................... - 210 - 二、架构挖掘的方法学问题 ..........................................................................................- 211 - 三、架构的可追踪性 ..................................................................................................... - 212 - 第七章第七章第七章第七章 业务敏捷性与面向服务的架构业务敏捷性与面向服务的架构业务敏捷性与面向服务的架构业务敏捷性与面向服务的架构................................................................................................................................................................---- 213 213 213 213 ---- 7.1 从业务的角度思考 SOA 的应用............................................................................. - 213 - 一、竞争环境中的企业变革 ......................................................................................... - 213 - 二、软件即是服务带来的挑战...................................................................................... - 214 - 三、SOA 的本质是实现业务敏捷................................................................................. - 215 - 四、SOA 一些概念的澄清............................................................................................. - 215 - 7.2 SOA 项目的路线图与规划...................................................................................... - 221 - 一、制定 SOA 项目的路线图........................................................................................ - 221 - 二、进行战略性的 SOA 规划........................................................................................ - 223 - 7.3 架构师在 SOA 设计中需要考虑的问题................................................................... - 224 - 一、全面考虑 SOA 各方面的特征................................................................................ - 224 - 二、建立服务的基础设施 ............................................................................................. - 228 - ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 5 - 三、设计企业服务总线 ................................................................................................. - 228 - 四、建立 SOA 企业软件模型........................................................................................ - 230 - 五、SOA 在信息管理领域中的应用............................................................................. - 234 - 7.4 SOA 架构设计中的 Web 服务 ................................................................................... - 236 - 一、面向服务的企业 ..................................................................................................... - 236 - 二、面向服务的开发 ..................................................................................................... - 237 - 三、SOA 的服务抽象 .................................................................................................... - 238 - 四、实现面向服务的架构 ............................................................................................. - 239 - 7.5 SOA 与业务流程管理 ............................................................................................. - 242 - 一、业务流程管理的基本概念...................................................................................... - 242 - 二、业务流程管理系统 ................................................................................................. - 243 - 三、组合 BPM、SOA 与 Web 服务.............................................................................. - 243 - 四、编制与编排规范 ..................................................................................................... - 249 - 7.6 SOA 的业务效益与误区 ............................................................................................ - 258 - 一、SOA 的业务效益 .................................................................................................... - 258 - 二、达成 SOA 的方法及需要解决的问题.................................................................... - 259 - 7.7 时代呼唤优秀的软件架构师 .................................................................................... - 262 - ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 6 - 软件架构设计的思想与模式 中科院计算所培训中心中科院计算所培训中心中科院计算所培训中心中科院计算所培训中心 谢新华谢新华谢新华谢新华 前言 在软件组织中,高水平架构师队伍的作用举足轻重,本课程针对企业开发最关注的问题深 入研讨,抓住投入产出比这个企业的核心价值,讨论软件架构组织与设计如何使这个核心价值 得以实现,其主要的思想如下: 1,软件架构设计与软件开发过程具有密切的关系。如何利用良好的架构设计,帮助项目在 良好的规范性、一致性与可靠性的过程中加入敏捷元素,以避免需求变更的风险,是目前软件 架构设计思考的热点问题。我们始终需要问自己的问题是:在两种方法论的混合模型下,如何 实现架构驱动?为此,我们必须研究不同过程下的架构设计特点,通过综合分析寻求更加良好 的设计方法。 2,在今天的企业环境下,变化就意味着胜出,因此软件开发中的需求变更不可避免,而需 求变更必然造成设计调整进而造成总体投入的增加,这会极大的影响到投资回报。统计表明, 造成软件项目失败最重要的原因是需求变更,所以我们必须研究架构设计如何更好的适应变更, 通过良好的设计确保变更、维护与升级的成本下降。在架构设计中,应用重构技术逐步优化架 构是一个重要的过程。但是,没有原则就没有方向,没有模式就没有方法,所以优化的过程需 要一系列的原则和模式来支撑。作为高级系统架构师需要对软件架构的各种优化原则有透彻的 理解。 3,随着经济全球化进程的不断推进,要增加软件产品的国际竞争力,软件质量作为企业发 展的战略问题变得越来越重要,所以,如何设计高质量的软件产品,成为软件架构设计的重要 主题。为了解决这个课题,软件架构师需要把人、组织、技术以及用户放到一个统一体中,以 一种统一协调的方式寻求最佳配合。要注意到在架构设计的时候,质量属性对于设计策略有重 大的影响,因此,架构师需要站在系统的角度思考问题。 4,为了创造高的投资回报率,产品线架构的开发与应用是一个重要的方法。产品线集中体 现了软件复用的思想。但是经验表明,单靠技术方法并不能保证产品线的成功,其中经济、组 织、管理和过程在建立和维护产品线中起到了关键作用。软件架构并不是一个纯技术范畴的问 题,我们应该站在更广阔的视角,研究构建软件产品线架构的各种问题,这就要求架构师与普 通开发人员有完全不同的思维方式。 5,为了延长软件架构的生命周期,提高已有架构资产的利用率,软件架构的恢复和重构已 经成为业内的关注点,我们必须研究如何条理化的组织架构恢复和重构工作,使架构恢复和重 构成为现实可能。 对上述一系列问题的深入思考,成为现代软件架构设计的核心思维。这需要软件架构师具 有很高的水平,需要站在全局的的视角想问题,思维层次必须脱离普通开发人员纯技术实现的 范畴,从系统的角度寻找相应的对策和解决方案,才能使设计工作变得极有主动性和想象力。 这一整套思想的实现,也为高质量软件系统提供了坚实的基础。 通过本课程学习,希望学员在今后架构设计的实践中,进一步优化架构设计,确保以低的 开发成本达到高的质量要求,从而大大提高设计水平,为企业创造更高的可度量价值。 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 7 - 教学的思想与方法 1 ,本课程属于高端培训,需要学员具备软件设计的实际工作经验,并且处于项目控制的位 置上。从国内现状看,很多技术人员长期处于某个具体开发的位置,考虑问题也局限在一个很 窄的范围,这样长久下去,对个人和公司的发展都不利。因此,课程希望能给学员提供更宽的 视野,提升站在更高的角度思考问题的能力。 2 ,课程并不准备用工匠式的方式说明问题,而是更深入的研讨现代软件系统优化设计的各 种方法和思路,旨在提升企业技术人员的整体水平。课程是站在整体的角度思考,对任何一种 语言为背景的开发这些思维方法都是适用的。 3 ,作为架构师更多的是需要对自己工作进行总结,以及在自己的领域中对于成功和失败经 验的领悟。本课程的目的是帮助学员总结和提升。学习并不一定需要从入门级再到高级一步步 进阶,这不但时间上不允许,方法上也不对头。如果我们站在更高的角度,领略这个行业众多 专家们对问题的思考,然后再俯视具体的分析与设计方法,很多东西就可以变得驾轻就熟迎刃 而解了。 4 ,案例教学是必要的,本课程的所有案例都混合在内容中。但并不是把案例作为一个死搬 硬套的模板,而是针对每个案例讨论它的背景和理念,再由理念引申出相应的价值观,为了这 个价值观形成特定的方法论,最后才是制定相应原则并总结出模式。要注意,模式不是僵硬的 规则,以为按照某种设计模式进行设计就会得到优秀的结果,那只是一个误解,相反这样很可 能是拙劣的设计。 5 ,高级系统架构师的主要任务是制订规则,这与普通技术人员主要的任务是执行规则并不 在一个层面上。不过我们也要看到,任何软件开发都是设计,每个技术人员在进行具体编码的 时候都需要有良好的、受过训练的设计思维,所以这个课程所表达的思想在各个层面上都可以 应用。更何况尽管企业中制订规则的是少数人,但是让广大技术人员早期受到这种高级训练是 很有好处的,毕竟企业是要发展和壮大,需要大批的高级技术人才。 6 ,作为高级系统架构师,创新能力是一个重要的标志。我们不希望员工成为一个墨守成规 的落伍者,而应当用开放、创造性的思维来寻求一切可能性。架构师应该充分发挥项目成员的 主动性和创造性,使开发的软件产品更具竞争力。但是,创新不是突发奇想,创新不是任意而 为更不是赶时髦,而是需要一整套方法论来支持。我们需要从技术历史知识、业务未来的走向、 当前技术现状一直到我们需要解决的根本问题入手进行深入思考,形成合适的路线图,才可能 实现有效和有用的创新,这些内容已经融合进了课程的几乎所有地方。 7 ,架构师需要站在整体考虑问题,包括业务、需求、设计、过程以及组织方法。优秀的设 计是把所有这些要素都考虑进来,从而得到最佳(或者说最合适)的解决方案。所以这个课程 学员的主体应该是企业的资深技术人员,但是除了技术人员外,诸如项目管理、业务分析、需 求分析、质量保证等方面的人员都可以从这个课程中获益,毕竟当企业有了一个共同的思维平 台以后,交流和协调就会变得比较容易。 8,再一次强调,本课程并不是一个泛泛的理论课程,也不准备过多讨论软件架构设计一般 性的方法与过程,这些问题学员完全可以通过自己的能力去解决。本课程是从实际项目要求出 发来探讨理论的应用,强调的是理论和实际相结合,从而针对问题梳理出一套行之有效的方法 论,是在思考力上下功夫,毕竟软件是一个特别强调思考力的领域。 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 8 - 第一章 从系统工程的角度构建架构 1.1 软件架构的定义与问题软件架构的定义与问题软件架构的定义与问题软件架构的定义与问题 一一一一、、、、软件架构的定义软件架构的定义软件架构的定义软件架构的定义 1))))软件架构的定义软件架构的定义软件架构的定义软件架构的定义 软件架构(software archiecture )也称之为软件体系结构,它是一组有关如下要素的重要决 策:软件系统的组织,构成系统的结构化元素,接口和它们相互协作的行为的选择,结构化元 素和行为元素组合成粒度更大的子系统的方式的选择,以及指导这一组织(元素及其接口、协 作和组合方式)的架构风格的选择。软件架构实际上是对系统整体结构设计的刻划,它关注如 下面几个问题:  一个系统的基本组织是什么样的?  系统有哪些组成组件?  组件相互之间是如何交互的?  组件和环境之间是如何交互的?  设计和演化的原则是什么? 在这中间,系统架构师是做全局的、整体的把握工作。 2))))关于架构的两个基本概念关于架构的两个基本概念关于架构的两个基本概念关于架构的两个基本概念 一直以来,对于架构的理解有两个基本概念,一个称之为组成,另一个称之为决策。  组成组成组成组成::::架构的组成概念强调“计算机及组件之间的交互”。例如在的初步设计中,“表 示层”和“业务层”是两个粗粒度的黑盒,当内部也表达了一些粒度比较细的组件的 时候,这两个黑盒变成了“灰盒”。交互的概念表现在架构描述了它们之间的关系,例 如数据如何读取、功能如何调用等。  决策决策决策决策::::架构决策不但表现了系统组织、元素、子系统的组织风格决策,还包括了非功 能性需求的决策,例如对于可扩展性的决策,对于表示逻辑与业务逻辑变化的隔离, 第三方工具包变化的隔离等,这就使架构有了弹性。 架构的组成组成组成组成与决策决策决策决策是架构设计的两个基本概念,这两个概念并不矛盾,在架构设计中,往 往是同时体现这两个概念,确保架构满足产品要求。由这两个概念出发,我们自然会提出:作 为一个高级系统架构师的核心思维到底是什么呢? 3))))架构设计是全方位的考虑问题架构设计是全方位的考虑问题架构设计是全方位的考虑问题架构设计是全方位的考虑问题 所谓架构其实并不仅仅指的是软件产品架构设计,它还包括管理架构、过程架构以及质量 保证架构等一系列问题的研究,因为高质量软件并不能只靠一个节点解决问题,而是需要有一 个全面的解决方案。 从系统的角度,我们应该看到任何软件系统都是以满足需求作为目的,而需求又是为着解 决用户的问题。所以,好的架构设计必须以全面深入的需求分析作为基础,根据需求来组织合 理的产品架构与开发模式。事实上任何模式只有针对问题才有意义。架构师必须对需求有足够 的理解,这样才能有针对性地解决问题,才可能设计出真正优秀的产品来。 二二二二、、、、系统架构师的职责与思维方式系统架构师的职责与思维方式系统架构师的职责与思维方式系统架构师的职责与思维方式 系统架构师的工作是负责设计总体解决方案以及组件的逻辑和物理布局。系统架构师的职 责和思维方式不同于纯粹的编码人员,他是站在更高的视角考虑问题,应该更加关注技术与业 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 9 - 务的对齐,下面我们对架构师的任务和思维方式作一个讨论。 1,,,,软件工程的本质与思考方式软件工程的本质与思考方式软件工程的本质与思考方式软件工程的本质与思考方式 1))))软件工程的本源软件工程的本源软件工程的本源软件工程的本源 在讨论系统架构师的职责和思维方式的时候,我们不得不思考软件工程的本源。软件工程 的目的是什么呢?从本质上,软件工程的目的就是想尽一切办法,把复杂的事情变得简单,变 得可操作。什么样的事情复杂呢?那就是大大小小的事情纠缠在一起,一个人的脑子需要记很 多事情,这就超出了人脑能够处理的能力范围。 无论是分析、设计还是组织方法,我们都是采取各种方法解决这个问题。从软件架构角度 来看我们怎么办呢?这就是模块化,就像做积木,一个个的组件,每个组件都是独立的,功能 都很单一,考虑这些积木的时候,不想别的事情,一心一意只把这些小功能做好。组件 (Component )其实就是一些积木。当我们有一大堆积木了以后就开始搭积木,搭积木的时候, 就不考虑这些积木是什么原理,而只是利用接口,从更广阔的角度把他们的功能用程序串接起 来。这就是业务流,考虑业务流的时候只考虑业务流,而不考虑功能细节。 这样就使每一件事情的考虑范围都不复杂,想大不想小,想小不想大。如果一个组织是这 样来开发软件的,那么软件开发本身就很容易。 我们还应该注意到,软件开发概念的现代化,主要是把商业的组织原则加于软件开发之上, 也就是把一个大的系统通过分工合作,经过各有所长的精细化管理,它所增加的效率,可以使 整个软件开发的效率大大提高。这就是为什么以企业化为标志的现代软件开发观念,比早期工 作环节无法分类的作坊式开发方式,显然效率要高的多原因。 软件工程还有一个要义,那就是用数目字管理,事实上如果开发模型是封闭的,而且项目 不是那么庞大,那么即使管理上有若干含糊之处应该问题并不大。但是对于一个庞大的、多个 机构协调的、充满竞争性的项目,如果不能用数目字管理,管理结构松散而懈怠,不能发挥每 个成员(或者组织)的专业长处,只是期望通过所有成员的肚量来容忍不规矩之处,那可能就 是一个致命的弱点了。 这就是软件工程,把所有的事情都分解开,一个问题一个问题解决,小问题关注细节,大 问题关注系统,这样每件事情就都不难了。我们的工作需要有成就,关键就是要学会这种思考 和处理问题的方法,这就是软件工程的本源。 2))))软件架构是软件架构是软件架构是软件架构是分析还是综合分析还是综合分析还是综合分析还是综合 在软件架构设计思维方式的讨论中,还有一个问题时时困扰着人们,那就是软件架构思考 问题的模式,是以分析为主还是以综合为主。当我们研究需求问题的时候,毫无疑义是以分析 为主(人们已经给了它一个确切的定义,那就是需求分析)。但是,在架构这个层面,似乎就没 那么简单。所谓分析,指的是当我们面对一个混沌的错综复杂的大问题的时候,我们把它一一 的按子问题分解开,这样就使复杂问题就变得简单。然后仔细研究这个孤立问题的细节,当然 还包括它和其它问题之间的关系(这称之为梳理)。这样一来,一个看似无法解决的问题,也就 变得可以理解、可以处理、而且可以细腻的解决了,从方法论来说是一种演绎法的表现。 但是这还不够,软件架构师事实上更需要一种综合能力。一个大型软件往往历经多个版本 的历史变化,每一种产品都不会凭空从天上而降,架构师思考问题的方式会受到当前其它系统 思想的感染,也会受到当前技术进步的影响,更会受到自己的历史经验、组织的管理特征、开 发团队的能力等等更高层面问题的影响。 一个系统设计,如果仅仅顾及到某个子系统或者某个模块的设计,在局部看也可能这样设 计是正确的,也可能是精良的。但是从整体上看,如果各个子功能之间杂乱丛芜、互相矛盾, 它仍然不能算作一个好的系统。这就需要有一种从整体上把握的能力,概括的说就是需要有一 种综合能力,或者是站在更高的视角看问题的能力。另一方面,一个架构师需要把自己历史的 经验,当前成功的方法和技术,各个系统之间的关系,从纵和横两方面归纳总结,把所有的问 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 10 - 题高度压缩,形成一个简明的前后连贯的纲领,使这些知识与各种其他知识体系有一个可以互 相比较的幅度与层次而得以升华,并且合理的应用到当前系统设计中去,才可能创造出更加有 效的系统,从方法论来说这是一种归纳法的表现。 一个高级系统架构师需要这两种能力,而且需要融会贯通,思维方式是需要训练的,这两 种思维模型必须在恰当的时候用在恰当的地方,所以一个系统架构师比普通技术人员有更苛刻 的要求,需要具有更多的能力。 2,,,,揭示软揭示软揭示软揭示软件架构件架构件架构件架构的概念的概念的概念的概念 1))))业务价值与架构风格业务价值与架构风格业务价值与架构风格业务价值与架构风格 针对特定的目标以及产品的业务价值,就会使软件架构具备某种特征,这称之为架构风格。 重要的是要记住,任何类型的软件架构都需要考虑产品的质量、需求和风险因素。人们通常喜 欢将“软件架构”这个词与技术内涵相关联,但是一个高级系统架构师的思考方式并不完全在 技术上,我们必须思考架构对业务的重要性,并从商业利益的角度理解软件架构。 软件架构包括对流程、技术和接口标准的投资,其目的是通过软件系统最大化与业务需求 契合和降低 IT 开发和操作的成本来改善组织的能力。软件架构可能会跨越很多项目,其中不是 所有的都能在初始投资的时候被预见。这种架构的概念有助于我们理解架构师所做的事情,以 及他们面对的众多挑战。在这里有几个概念是重要的,因为它涉及各种风格的架构思想。 2))))软件架构是一项投资软件架构是一项投资软件架构是一项投资软件架构是一项投资 架构并非一组特定的任务或技能 因为每一个组织都会以不同的方式来实现自己的架构目 标。架构师团队的目的是选择和实现最有效的对标准、程序、技术和接口的投资,以支持该组 织的业务目标和业务流程。在这些业务目标下,架构师团队的研究成果将取决于最适当的投资 类型,这需要架构师熟悉业务语言、问题和语境,以提供交流桥梁。软件架构的投资原则是: 在项目的早期就提早计划和考虑作为结果的解决方案。 3))))软件架构是一种冒险软件架构是一种冒险软件架构是一种冒险软件架构是一种冒险 软件架构是一种冒险 并不是所有的架构思想都能够如设想的那样加以实现。在难以预测的 环境下,可能会被迫修正一个已定的软件架构,从而将导致更高的成本并降低架构风格所带来 的利益。 4))))架构师无法预测未来架构师无法预测未来架构师无法预测未来架构师无法预测未来 架构师们永远无法预测将会使用他们创建的架构所有应用和系统,在现代软件系统中,越 来越多的架构目标是支持一般性的、组织化的业务方向,而不是具体的、设计好的个别项目。 因此,软件架构设计是一个冒险。 架构师们假设,如果每一个人(或者至少是一个组织的大部分人)都遵从软件架构规则, 日后将会产生好处(例如,节省生产成本、应对业务变化的敏捷性或降低进入市场的时间)。他 们希望自己的架构计划将会具有长期的价值,甚至对那些他们在建立该设计时未曾设想到的项 目。许多因素会限制一个架构师能做出的假设的数量和种类,尤其是组织对于风险的态度,以 及架构师对于未来了解或者预测的多少。 架构师希望预测未来需求的唯一方法,是他们能够充分地接触和把握业务方向。我们强调 架构师的作用,是因为理解技术问题需要与理解业务问题具有不同的思想方式。 5))))软件架构是一套约束软件架构是一套约束软件架构是一套约束软件架构是一套约束 软件架构是一套约束 它是为了实现最大多数的利益。单个的项目和程序需要遵循软件架构 的限制,以使得整个组织从中获利,而不管其任何个人的不便。没有对共同利益有着清晰认识 的组织,就不能够实现广泛使用的系统架构。 任何系统架构(一组约束)都不可能适用于整个组织,因此,如何解决冲突的流程必须是 系统架构的一部分。如果架构师不能充分参与业务管理,则冲突解决几乎是不可能的。业务需 求强加了限制和约束,同时还定义了架构师们需要设计的 IT 系统的服务级别。因此为了决定优 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 11 - 先级、可能的解决方案和折中方案。 6))))架构设计是流动的而不是静态的架构设计是流动的而不是静态的架构设计是流动的而不是静态的架构设计是流动的而不是静态的 软件架构设计的目标必须阐明 一个旨在降低成本的架构设计,和一个旨在缩短进入市场时 间的架构设计,或者与一个旨在最大化业务敏捷性的软件架构设计是不一样的。架构设计是一 个有机的流程而不是一个静态的文件,软件架构是在对组织业务目标和可行技术的不断变化的 回应中进行发展的。好的架构设计在这种变化中应该具有足够的适应力。 7))))软件架构很少具有普遍性软件架构很少具有普遍性软件架构很少具有普遍性软件架构很少具有普遍性 软件架构很少具有普通性 一个组织的不同部门会有不同的目标,可能需要不同的架构来支 持。任何一个系统架构的使用都是有范围的,“一个适用于所有应用”的系统架构很少会成功。 举例来说,一个大型机应用领域的系统架构,其共同目标是提高质量和降低成本,而一个快速 活动的业务领域的系统架构,其目标则通常是进入市场的时间及可接受的低风险。一般在系统 架构投资的深度和宽度上都需要有所取舍。 综上所述,软件架构是一个面向实际的方法,它需要适应新的、不同的实际和需求。为了 达到这个目标,就需要定义一些良好的原则和概念,使得架构师可以在大量广泛的任务里实施 设计有一个努力的方向。 3,,,,正确正确正确正确阐明架构师的任务阐明架构师的任务阐明架构师的任务阐明架构师的任务 架构师们负责多项涉及管理业务流程的工作,包括软件架构的开发、部署和维护。尽管架 构师的角色对于一个企业的成功是至关重要的,但是现实情况往往是:企业技术部门过多关注 具体的编码实现,而业务部门过多关注具体业务流程。业务人士却很少发现或注意架构师再联 系业务和 IT 技术之间的作用。架构师们需要改变并扩充自己对公司业务流程的知识,将他们转 变成为 IT 团队和业务团队之间的桥梁。 要使人们做出这些改变就需要正确阐明架构师的职责,在今天的环境下,系统架构师所关 注的已经不仅仅是技术实现方法,他需要与业务团队紧密合作,因此,与其把架构师看成技术 精湛的技术行家,还不如把架构师当作超级业务分析员。架构师的任务是为业务的成功提供解 决方案,以下架构师的任务将有助于业务成功的:  确定哪种架构投资是正确的确定哪种架构投资是正确的确定哪种架构投资是正确的确定哪种架构投资是正确的:架构师需要确定潜在的系统架构投资和证明其正确,这 需要架构师们从他们的技术和业务合作中寻找信息,以确定哪个架构投资是合适的。  需要交流需要交流需要交流需要交流架构架构架构架构原理与维护原理与维护原理与维护原理与维护方法方法方法方法:与系统架构的用户和支持者交流软件架构的原理和维 护过程,这可能涉及培训、出版物、网页、热线支持、内部咨询或资格中心等。  路线路线路线路线图图图图管理管理管理管理:很少组织在界定系统架构的时候能从一张空白的纸开始。实际上,大多 数系统架构都保持着一个路线图,记录目前的系统架构和预期的目标体系,界定其演 变路径。  业务业务业务业务冲突冲突冲突冲突的的的的解决和异常处理解决和异常处理解决和异常处理解决和异常处理:个别项目目标和组织目标之间的冲突是系统架构所固有 的。没有冲突是一个危险的信号,这可能不是忽视了架构师的存在就是没有满足规范。 异常有时候是需要的,而且应该通过一个明确的程序来加以处理。优良的软件架构往 往允许较不严格的开发,因此容易产生这些冲突,应该在项目执行的早期检测和解决 这些问题。  部署部署部署部署软件架构软件架构软件架构软件架构:大部分软件架构的部署由沟通、培训和指导的过程来实现。  监测软件架构监测软件架构监测软件架构监测软件架构的有效性的有效性的有效性的有效性:鼓励或强制遵守,为了达到业务目标,架构师定期与业务团 队成员协商是很有必要的。当企业走向更大的跨区域一体化时,某种业务、部门、系 统架构将对组织的成功越来越重要,而且将被确认为一个有价值的规范。因此对软件 架构的业务目标和角色的清晰描述是一个架构功能的必要组成部分。 4,,,,解释系统的技术解释系统的技术解释系统的技术解释系统的技术、、、、业务和功能基础业务和功能基础业务和功能基础业务和功能基础 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 12 - 为了向业务人员以及开发人员解释系统的的技术、业务和功能基础,架构师需要具备解释 设计思想的能力,解释系统大概需要从下面几个方面阐述:  从技术支撑中揭示软件架构的概念,解释必要的业务功能的现实。  阐述架构师在提供对于业务成功很关键的体系结构功能中扮演的重要角色。  解释为什么围绕业务流程来整合 IT 内容更好。  强调建立深入的 IT 与业务对话,这种对话将导致建立 IT 和公司业务单位之间有意义 的、建设性的、尊重性的和经常性的关系。  显示设计定位,以及如何使用自上而下的方式来创建业务的模式。  描述 IT 如何通过流程和度量与业务目标保持对齐。  显示 IT 如何通过增量交付保持与业务需求对齐。 4,,,,架构设计需要更广阔的视角架构设计需要更广阔的视角架构设计需要更广阔的视角架构设计需要更广阔的视角 1))))架构设计要关注质量属性架构设计要关注质量属性架构设计要关注质量属性架构设计要关注质量属性 架构师的眼光应该专注于质量属性上,根据产品质量属性的要求提出合理的架构决策。如 果我们把目光仅仅关注在流程、方法、结构原理甚至编码的本身,而不太注意架构设计最本质 的东西,很多产品即使设计出来,后期运行中就会问题百出,特别是发生变更的时候带来更大 的困难。 2))))架构与项目的组织背景相匹配架构与项目的组织背景相匹配架构与项目的组织背景相匹配架构与项目的组织背景相匹配 任何架构思想的实现,必须与具体的项目组织背景相匹配才能发挥作用。因此,架构师应 该仔细研究现代项目管理的思想和方法,吃透其中的精髓,根据具体情况,提出合适的软件工 程策略。反之,一个软件工程策略,也不可避免的也会影响到架构设计的特点。这就需要架构 师具有很宽的知识面,对整个软件工程领域都需要有透彻的理解,我们必须注意到,软件系统 设计的组织与方法不是一个僵化的规则,关键是在实践中实事求是的摸索规律,从而找出符合 实际达到要求的方案来。 3))))要理解过程对设计方案的影响要理解过程对设计方案的影响要理解过程对设计方案的影响要理解过程对设计方案的影响 在软件工程实践中,我们会发现不同的开发过程需要不同的系统架构来支撑项目成功。为 此,我们必须要仔细研究一下现代软件开发过程的演化特点。我们必须注意到:一个事情要成 功,关键是要有两个作用力,一个是思考力,另一个是执行力。其中思考力是最重要的,因为 如果思考是错误的,那么执行越坚决,最后错误就越大。架构师所处的位置主要是思考力这一 端,所以这个位置是极其重要的。设计源自于分析,分析的头脑关键在于在纷乱复杂的世界中 迅速抓住本质,迅速理出线条,迅速捕获重点。 4))))要锻炼分析和解决问题的能力要锻炼分析和解决问题的能力要锻炼分析和解决问题的能力要锻炼分析和解决问题的能力 在今天的软件工程过程中,有规范式过程和敏捷过程两种几乎完全对立的方法论,到底哪 一种是正确的?哪一种适合用的?如果存在问题,问题到底出在什么地方?这就需要分析与研 究,而分析的思路首先是对比,然后把它条理化,然后找出关键问题所在,最后得出结论总结 规律从而指导我们设计工作。所以下面的讨论,我们也可以把它作为分析方法的指导。无论从 任何一方面来说,一个优秀的人才首先应该是有思考力的人才。 三三三三、、、、对软件开发过程的认知对软件开发过程的认知对软件开发过程的认知对软件开发过程的认知 软件架构设计是需要一个方法学作为基础的,任何方法学都和它的应用背景有关。而这里 所讨论的背景是一个最根本的问题,那就是软件开发到底是什么? 1,,,,软件开发是软件开发是软件开发是软件开发是到底到底到底到底工程还是创造工程还是创造工程还是创造工程还是创造???? 软件开发到底是什么?它是一个工程实践,还是一个创造性过程呢?这是一个目前在软件 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 13 - 工程界争论不休让人倍感困惑的问题。 1))))以组织共同协调完成的项目必定是一个工程过程以组织共同协调完成的项目必定是一个工程过程以组织共同协调完成的项目必定是一个工程过程以组织共同协调完成的项目必定是一个工程过程 大型软件项目是依靠一个组织来完成的,如果这个组织在管理上是无序的,开发过程是非 正式和混乱的,计划期限和成本目标通常超限,项目的成功取决于个人英雄式的行为,在人员 发生变动时项目往往陷入灾难,那么,很难说这个项目会获得成功。从这个视点上说,软件开 发应该是一项工程,软件工程的目的是使开发过程的各个要素,以一种统一协调的方式运转, 保证时间、资金和质量这样的三角约束得以平衡,最终确保项目得以成功。 如果说我们软件开发是一项工程,那么就应该制定相应的工程标准、建立实施过程、制定 项目计划以及提供可预见可重复性的基础设施。在计划实施过程中,要尽可能减少变更以保证 计划的最终成功。 2))))软件开发需要也应该是一个创造性过程软件开发需要也应该是一个创造性过程软件开发需要也应该是一个创造性过程软件开发需要也应该是一个创造性过程 但是从另一方面来说,任何软件设计都是一个创造性过程。也就是要突破已有的思维模式 和行为模式,因为只有突破了这一点,我们的设计与产品才可能达到一个新的水准,达到从未 有过的高度,只有创新才能让自己保持领先。。 创造性过程就要视需求变更为朋友而非敌人,因为变更可以激发更多的创造力,并且可以 为客户创造更多的价值。另一方面,创造力往往更强调个人的价值,在过程中会不断修改自己 的设计。对原有的业务过程也会在开发过程中再思考,对需求的理解也会随的开发的深入产生 新的想法。如果说软件是一项创造,那么就应该更加强变化和修改。软件开发更类似一种写文 章的不断修改和涂抹的过程,而不是一种大规模的军团有序行为。也可以说软件开发并不完全 是一项工程行为。 综上所述,我们在研究软件架构之前,第一个需要突破的思想障碍就是:软件到底是什么? 如果这个问题不解决,那么一切的方法论都成为无木之本。 2,,,,软件开发既是工程又软件开发既是工程又软件开发既是工程又软件开发既是工程又是创造是创造是创造是创造 目前对软件开发方法论的尖锐对立和争论,从根本上说是一种以一概全的争论。我们认为, 软件开发既是一个工程实践又是一个创造性过程。 1))))创新的要求需要产品适应变化创新的要求需要产品适应变化创新的要求需要产品适应变化创新的要求需要产品适应变化 在软件开发的早期,我们必须强调创新,在这种创新背景下,软件不会产生可靠的结果, 每个新设计都会包含大量的没有经过测试的新思想,而这些未经测试的新思想也经常会失败。 因此,这种以创新为主的设计过程中,更加强调对变化的适应能力。 2))))以以以以工程工程工程工程为导向的产品开发为导向的产品开发为导向的产品开发为导向的产品开发需要严谨需要严谨需要严谨需要严谨的过程的过程的过程的过程 当一个工程领域成熟以后,我们就有机会对大量经受了时间考验的设计进行组合和微小的 修改,从思维方式上,就可以专注于解决良好定义的问题集合中的问题,而不是一切都从头开 始。在这个阶段,我们将更加强调稳定的、一致的以及相互协调的软件工程过程。 3))))大型软件项目的特点是工程背景中蕴含着创新大型软件项目的特点是工程背景中蕴含着创新大型软件项目的特点是工程背景中蕴含着创新大型软件项目的特点是工程背景中蕴含着创新 但是,不论软件项目多么庞大和稳固,软件的创新仍然而且必须在继续,所以我们就可以 把软件分成两的部分:  工程性过程工程性过程工程性过程工程性过程::::大量应用经过考验的模式,通过恰当的组合和微小的修改达到目的。  创造性过程创造性过程创造性过程创造性过程::::对新的各种各样的需求和设计方案进行探索。 在可行性研究阶段,软件开发大量的内容可能是属于创造性过程。而在系统开发和生产阶 段,我们所遇到的问题大部分应该属于工程性过程。这样一来问题就比较清楚了。但是这两者 是不可能截然分开的,更多的是工程性过程内蕴含着创造性过程。这样一来,我们在分析与设 计的时候就应该思路清楚,能够很好的分开这两个部分,不同的背景应用不同的方法来解决。 4))))架构师架构师架构师架构师要具备在复杂背景下思考问题的能力要具备在复杂背景下思考问题的能力要具备在复杂背景下思考问题的能力要具备在复杂背景下思考问题的能力 一个高级系统架构师的思维方式决不能死搬硬套,世界上的问题是千变万化的,但如果我 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 14 - 们已经有了大量问题家族和解决方案集合,我们的解决方案就可能受到它的启发,这种启发往 往是极其珍贵的。 3,,,,软件软件软件软件架构是工程架构是工程架构是工程架构是工程过程中发挥过程中发挥过程中发挥过程中发挥创造创造创造创造力力力力的的的的基础基础基础基础 既然软件开发的背景如此复杂,就需要有某种媒介把这两种要素很好地结合起来,从某种 意义上来说,软件架构就是这样的一种媒介。 1))))架构便于各个元素的一致性与规范性架构便于各个元素的一致性与规范性架构便于各个元素的一致性与规范性架构便于各个元素的一致性与规范性 首先,从软件架构本身的定义来看,它考虑的是软件系统的组织,构成系统的结构化元素, 接口和它们相互协作的行为的选择。这就为工程实践定义了一个框架。便于各个元素以一致的 和规范的方式进行开发,更避免了未来系统集成上的困难。 2))))接口的稳定性使创造和变更成为可能接口的稳定性使创造和变更成为可能接口的稳定性使创造和变更成为可能接口的稳定性使创造和变更成为可能 另一方面,在稳定接口下的结构化元素的设计,由接口保证了集成上的的一致性,同时又 屏蔽了内涵上的变化。这就为创造和变更打下了基础。在结构化元素的设计过程中,“为何而战” “因何而战”的问题变得更清晰,也避免了需求变更把设计引向了一个不可控制的方向。 从这个意义上说,没有合理的软件架构,也就不可能有大胆的创新。一个危危可及的组织 系统中是不可能允许创造力的,软件架构正是是工程过程中发挥创造力的基础。 3))))架构与组织方法的契合便于发挥人力架构与组织方法的契合便于发挥人力架构与组织方法的契合便于发挥人力架构与组织方法的契合便于发挥人力资源的作用资源的作用资源的作用资源的作用 软件架构的目的是加强人的作用而不是减少人的作用。一个好的架构设计,可以确保整个 项目的所有开发人员有足够的自信,确认自己所开发的那一部分是一致的、可集成的,也是符 合要求的。在各元素的范围内,是可以充分发挥自己的想象力和创造力,而这种创造又不会给 整个系统带来不必要的麻烦。 这种把人看成架构设计要素的理念非常重要,架构是要通过组织中的人去应用的,架构必 须给组织中的人带来好处,架构可以使人在开发产品的过程中不断成长。所以架构设计必须对 开发人员在软件过程的各个阶段的活动方式有清楚的认知与共识。是软件架构成为产品组织方 式的媒介,也是机构创造力的媒介。 1.2 规范性规范性规范性规范性软件开发过程与软件架构软件开发过程与软件架构软件开发过程与软件架构软件开发过程与软件架构 一一一一、、、、规范性规范性规范性规范性软件开发过程软件开发过程软件开发过程软件开发过程 软件工程过程描述的是软件构造、部署以及维护的一种方法,早在 20 世纪 70 年代,人们 就提出了规范性的瀑布式软件开发过程。以及早期一系列项目管理原则。 1,,,,规范式方法的管理原则规范式方法的管理原则规范式方法的管理原则规范式方法的管理原则 1))))基于工程规范的大型软件系统开发基于工程规范的大型软件系统开发基于工程规范的大型软件系统开发基于工程规范的大型软件系统开发 计划驱动的方法起源于系统工程和质量规范,由于大型项目的组件未必是同一个公司或者 组织生产的,所以需要建立一些系统工程原则,来协调需要精确协同工作的组件的开发。 2))))引入标准和过程规范引入标准和过程规范引入标准和过程规范引入标准和过程规范 为了解决软件开发标准的问题,首先由美国国防部开发了一系列的指导文档,为软件开发 提供符合系统工程的标准方法。随着软件工程的重要性日益增强,一些过程规范和组织化技术 被开发出来,这些规范既要反映出现有工程过程的需求和规程,也要吻合那种把软件开发看作 是数学证明过程的学院派计算机科学中的软件工程分支。经典软件过程的特征如下:  重视定义良好的工作产品重视定义良好的工作产品重视定义良好的工作产品重视定义良好的工作产品、、、、验证和确认验证和确认验证和确认验证和确认::::软件系统工程认为,从需求到代码的软件过 程中,计划驱动的方法非常精确的依赖于明确的步骤,其中每个步骤中文档的完备性 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 15 - 非常重要,这种完备性可以保证每个步骤可以验证,文档是可跟踪性的重要保证。  产品规范与过程定义和改进具有同等的联系产品规范与过程定义和改进具有同等的联系产品规范与过程定义和改进具有同等的联系产品规范与过程定义和改进具有同等的联系::::软件作为一种产品,其可塑性使过程需 要经过多次改进,正因为如此,计划驱动总是和过程改进联系在一起。过程需要进行 定义、标准化并需要逐步改进以提供对项目的有效控制。这种过程通常包括有:详细 的计划、活动、工作流程、角色和职责以及工作产品描述。执行人员应该经过应用过 程方面的培训,并且需要有一个过程监督、控制及教育的组织和支持人员。  过程过程过程过程提供可预见性提供可预见性提供可预见性提供可预见性、、、、可重复性和基础可重复性和基础可重复性和基础可重复性和基础设施的设施的设施的设施的支持来缓解人员流动问题支持来缓解人员流动问题支持来缓解人员流动问题支持来缓解人员流动问题::::计划驱动方法 的强势,在于标准化所带来的可比较和可重复性,在组织中接受过培训的人都知道在 哪里找信息,以及如何评估日常工作。这种过程的一致性可以使管理人员在项目之间 调动人员而不必要重新培训,也意味着关键人员的的流失不再是项目的厄运。 2,,,,重要重要重要重要的的的的计划驱动概念计划驱动概念计划驱动概念计划驱动概念 计划驱动的开发方法已经形成了一套有特点并证明有效的概念,主要包括:  过程改进过程改进过程改进过程改进::::改进组织过程的执行、行为规则以及这种规则的结果。  过程能力过程能力过程能力过程能力::::过程产生出计划结果的内在能力,它是可预测、可度量,而且还可能控制 和消除导致质量和生产力低下的根源。  组织成熟度组织成熟度组织成熟度组织成熟度::::一个组织可以通过持续改进其过程能力而日趋成熟。成熟度不仅包括单 个项目的能力,还包括整个组织上下标准过程的普遍适用情况。  过程小组过程小组过程小组过程小组::::帮助组织对过程进行定义、维护以及改进的一组专家。  风险管理风险管理风险管理风险管理::::一组有组织的、分析式的过程,以识别那些可能导致破坏或者损失的造成 重大破坏的风险诱因。  验证验证验证验证::::正式工作产品(例如规格说明、设计模型)是不是反映了指定的需求。  确认确认确认确认::::进一步证实工作产品对其操作任务的合适性或者价值。  软件系统架构软件系统架构软件系统架构软件系统架构::::软件系统架构定义了三点:一组系统组件、连接件以及约束;一组系 统相关人员需要的报告;一份原理说明,说明论证了如果实现了这样的系统,就会满 足项目相关人员的需要。 3,,,,线性瀑布式生命周期线性瀑布式生命周期线性瀑布式生命周期线性瀑布式生命周期 正是在上述工程学理念的指导下,人们提出了软件开发线性瀑布式生命周期模型,作为软 件工程学基础的的规范式方法论的过程表达,被称为计划驱动(或称之为规范式)的过程,如 下图所示: ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 16 - 二二二二、、、、软件开发增量模型与系统架构软件开发增量模型与系统架构软件开发增量模型与系统架构软件开发增量模型与系统架构 1,,,,现代软件过程现代软件过程现代软件过程现代软件过程原理原理原理原理 上述线性瀑布式模型往往带来了很多问题,这个模型要求在项目的第一阶段,在任何设计 和实现工作之前,尽可能的推敲,把需求完全定义清楚,并把它稳定下来,并且实际开发前冻 结需求,但历史证明这种方式是失败的,在项目很大的时候,冻结需求几乎没有可能。因此, 人们开始思考现代软件工程过程的新特征,结果就形成一系列新原则:  把过程建立在构架优先的基础之上把过程建立在构架优先的基础之上把过程建立在构架优先的基础之上把过程建立在构架优先的基础之上::::这要求在交付资源进行全面展开之前,就在需求、 构架等重大设计决策和生命周期计划之间做出权衡。  建立一个能尽早面对风险的迭代式生命周期过程建立一个能尽早面对风险的迭代式生命周期过程建立一个能尽早面对风险的迭代式生命周期过程建立一个能尽早面对风险的迭代式生命周期过程::::对于今天高度复杂的软件系统,要 按照顺序定义着那个个问题,设计整个解决方案、构造软件和测试最终产品几乎是不 可能的。这就需要使用一个迭代过程,这里的关键是定义好关键里程碑,以及最终的 目标,必须及早提出可能遇到的风险,以提高可预见性,避免昂贵的下游返工。  设计方法向强调基于设计方法向强调基于设计方法向强调基于设计方法向强调基于组组组组件件件件的开发转变的开发转变的开发转变的开发转变::::从代码行至上转为基于组件开发的思想,可以 大幅度减少开发的成本,组件是一个已经存在的代码行内聚集和,可以由原代码、也 可以由可执行文件的格式提供,并且有定义好的接口和行为。  建立一个变更管理环境建立一个变更管理环境建立一个变更管理环境建立一个变更管理环境::::迭代开发的动态特性,需要很好的变更控制环境,包括在共 享产品上工作的不同团队之间并发的工作流、客观需要的控制基线等。  用严格的用严格的用严格的用严格的、、、、基于模型的符号标记系统基于模型的符号标记系统基于模型的符号标记系统基于模型的符号标记系统::::具有严格语义的模型符号系统极其有意义,它 可以减少人之上的歧义,UML 就是一种很好的符号语言。  为过程配备工具进行客观的质量控制以及进展评估为过程配备工具进行客观的质量控制以及进展评估为过程配备工具进行客观的质量控制以及进展评估为过程配备工具进行客观的质量控制以及进展评估::::必须对所有的中间产品进行质量 评估,这些评估必须在度量的基础上进行,这些评估是在整体工程制品质量的基础上 派生出来的。  使用基于演示的方法评估中间制品使用基于演示的方法评估中间制品使用基于演示的方法评估中间制品使用基于演示的方法评估中间制品:把产品的当前状态(不论是前期原型、基线架构 或者是一个 bate 能力)转换为一个可以在相关场景下运行的演示,促使人们把注意力 更早的集中在集成上,获得对设计折衷的更加切实的理解,尽早消除构架上的缺陷。  计划在大量的使用场景中使用细节的进化等级进行中间发布计划在大量的使用场景中使用细节的进化等级进行中间发布计划在大量的使用场景中使用细节的进化等级进行中间发布计划在大量的使用场景中使用细节的进化等级进行中间发布::::必须尽早的启动软件管 理过程,项目增量迭代的进化必须与现有的对需求和构架的理解水平一致,因而采用 内聚的使用场景(该场景是针对某些相互关联的问题设置),就成为组织需求、定义迭 代内容、评估实现和组织验收测试的主要方法。  建立一个经济上具有伸缩性的可配置的过程建立一个经济上具有伸缩性的可配置的过程建立一个经济上具有伸缩性的可配置的过程建立一个经济上具有伸缩性的可配置的过程::::没有一个过程是对所有软件开发都是合 适的。一个实用的过程框架必须可以配置,以及支持更广泛的应用,这个过程必须应 用共同的过程精神、广泛的过程自动化以及共同的构架模式和组件来确保规模经济和 投资回报。 现代方法一般都要求在开发过程的前期迅速构造起一个初始版本,在这个版本中,强调的 是高风险的领域、稳定基本架构、完善获取的需求。接着,开发就以迭代序列进行下去,构建 核心的构架,直到达到期望的功能、性能和稳健性的等级。这种方法是通过不断的集成和完善 需求、构架和计划减少了风险,而不是到了系统快要交付的时候,才惊讶的发现出现的错误。 这种过程大大提高了管理上的难度,也需要管理者对问题理解的更加深刻。 2,,,,软件开发增量模型软件开发增量模型软件开发增量模型软件开发增量模型 1))))增量开发是软件增量开发是软件增量开发是软件增量开发是软件构建方法构建方法构建方法构建方法的一种改进的一种改进的一种改进的一种改进 由于在变化环境中瀑布模型对变化的响应能力非常糟糕,为了解决这个问题,出现了是所 谓增量模型。增量模型是指首先构建部分系统,再逐渐增加功能或者性能的过程。它降低了取 得初始功能之前的成本,也提高了创建可操作系统的速度。 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 17 - 2))))增量模型是软件架构驱动产品开发的产增量模型是软件架构驱动产品开发的产增量模型是软件架构驱动产品开发的产增量模型是软件架构驱动产品开发的产物物物物 增量模型是软件架构驱动产品开发的产物,它提倡以功能渐增方式开发软件,经验表明, 这种增量模型在特大型项目和小型项目中同样适用。增量模型描述了为系统需求排定优先级然 后分组实现的过程,每个后续版本都为先前版本增加了新功能。 3))))在生命周期的早期建立一个考虑了整个系统的架构在生命周期的早期建立一个考虑了整个系统的架构在生命周期的早期建立一个考虑了整个系统的架构在生命周期的早期建立一个考虑了整个系统的架构 在生命周期的早期阶段(计划、分析、设计),需要建立一个考虑了整个系统的架构,这个 架构应该是具有强的可集成性的,后续的组件方式开发,都是建立在这个架构之上。剩下的生 命周期阶段(编码、测试、交付),来实现每一个增量。 这里的架构设计包括大粒度子系统划分,最重要的业务单元接口与模块的整体设计,各个 子系统共享的数据技术服务或者基础业务的服务模块设计与实现。整个架构体系应该是完成的 经过测试和验证的系统。这就是说,首先创建的应该是一组核心的功能,或者对于项目至关重 要的最高优先级的系统,或者是能够降低风险的系统。随后基于核心功能反复扩展,逐步增加 功能以提高性能,如下图所示。 4))))增量模型的优点增量模型的优点增量模型的优点增量模型的优点  整个项目的资金不会被提前消耗,因为首先开发和交付了主要功能和高风险功能。  每个增量交付一个可操作的产品。  每次增量交付过程中获取的经验,有利于后面的改进,客户也有机会对建立好的模型 作出反应。  采用连续增量的方式,可把用户经验融入到细化的产品,这比完全重新开发要便宜得 多。  “分而治之”的策略,使问题分解成可管理的小部分,避免开发团队由于长时间的需 求任务而感到泪丧。  通过同一个团队的工作来交付每个增量,保持所有团队处于工作状态,减少了员工的 工作量,工作分布曲线通过项目中的时间阶段被拉平。  每次增量交付的结为,可以重新修订成本和进度的风险。  便于根据市场作出反应。  降低了失败和更改需求的风险。  更易于控制用户需求,因为每次曾两开发的时间很短。  由于不是一步跳到未来,所以用户能逐步适应新技术。  切实的项目进展,有利于进度控制。  风险分布到几个更小的增量中,而不是集中于一个大型开发中。  由于用户能够从早期的增量中了解系统,所以更加理解后面增量中的需求。 5))))增量开发必须注意的问题增量开发必须注意的问题增量开发必须注意的问题增量开发必须注意的问题  良好的可扩展性架构设计,是增量开发成功的基础。 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 18 -  由于一些模块必须在另一个模块之前完成,所以必须定义良好的接口。  与完整的系统相比,增量方式正式的回顾和评审更难于实现,所以必须定义可行的过 程。  要避免把难题往后推,首先完成的应该是高风险和重要的部分。  客户必须认识到总体成本不会更低。  分析阶段采用总体目标而不是完整的需求定义,可能不适应管理。  需要更加良好的计划和设计,管理必须注意动态分配工作,技术人员必须注意相关因 素的变化。 1.3 架构设计架构设计架构设计架构设计的自顶向下结构化分解的自顶向下结构化分解的自顶向下结构化分解的自顶向下结构化分解 一一一一、、、、软件架构的结构化方法软件架构的结构化方法软件架构的结构化方法软件架构的结构化方法 在计划驱动的过程中,初期的架构设计主要采用的结构化方法,自从面向对象的技术普及 以来,人们往往倾向于认为结构化方法应该让位于面向对象的方法了。这种看法是片面的,至 少在软件架构领域,自顶向下的结构划分仍然是一个重要方法,这主要是由于软件架构本身的 特点决定的。 1,,,,自顶向下逐步分解的方法自顶向下逐步分解的方法自顶向下逐步分解的方法自顶向下逐步分解的方法 在初期,当问题比较大也比较混沌的时候,采用“自顶向下逐步分解”的方法,可以使复 杂的问题变得比较简单。如果一个功能对人脑来说太大,以至于不能立刻勾画或者实现它,那 么就把它重复分解成小到足以能够处理的子功能,并且定义好它们之间的关系。用户所需求的 每个主功能都可以精确分配给一个设计元素,保证每个功能都被实现,每个设计元素都可以回 溯到需求的功能,保证设计不包括多余的元素。 这样做还有个附带的好处:不同的子功能可以分配给不同的工程师或者团队,使他们各自 处理不同的设计单元。对于一个大型系统,这样的分配是必需的,这样就有可能把一个复杂的 问题变得比较简单和可行。软件架构设计是在项目的早期开始进入,它主要表达下面几个问题:  软件架构是一种层次化的表示,其指出了由需求分析隐含地确定的某一问题的软件解 法的各个元素(称之为模块)之间的相互控制关系。  软件架构的演变从确定问题开始,当该问题的每个部分用一个或多个软件加以解决以 后,整个问题的解决方案也就有了。 这种自顶向下逐步求精的方法,也表达了人们认识事物的一般过程。 2,,,,结构化设计以数据流为核心结构化设计以数据流为核心结构化设计以数据流为核心结构化设计以数据流为核心 结构化设计的结果,需要把数据流转换成相应的模块。它使用“输入 – 处理 – 输出”这 样一个基本模型,这些模式比较适用于描述商业软件,它们中大多数依靠数据库。为什么结构 化设计以数据流为核心进行分解呢?我们先来看一下一个软件系统的本质。任何软件系统。都 可以用五类事情来完全描述系统行为: ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 19 -  系统的输入系统的输入系统的输入系统的输入:不仅仅是式输入内容,还有输入设备、形式、外观和感觉等必要的细节。 很多开发人员都发现了,在这个领域可能包括大量的细节,并且具有易变性,尤其是 GUI、多媒体或互联网的。  系统的输出系统的输出系统的输出系统的输出:对输出的描述,如语音输出或可视化显示等必需的支持,以及系统所产 生信息的协议和格式。  系统的功能系统的功能系统的功能系统的功能:把输入映射到输出,以及它们不同的组合。  系统的属性系统的属性系统的属性系统的属性:典型的非功能需求,如可靠性、可维护性、可得到性以及吞吐量等开发 人员必须考虑的问题。  系统的环境属性系统的环境属性系统的环境属性系统的环境属性:附加的非功能性需求,如系统在不同的操作系统、负载下的操作能 力等等。 这种划分方法如下图所示。 从这个图可以看出来,数据的处理和变换是软件系统的基本要素,研究数据的流动关系, 可以使结构更清楚的表达系统本质。 二二二二、、、、数据流图及其分解数据流图及其分解数据流图及其分解数据流图及其分解 结构化设计(面向过程的方法)的主要模型是数据流图(DFD),面向过程的方法在业务过 程分析等方面具有独特的优势。由于架构设计的第一步就是建议业务架构概念,而所有模块设 计的根据是所希望实现的业务流程,所以在架构设计的第一步,通过数据流图来建立产品数据 的业务流动关系是很有必要的。我们甚至可以根据数据流图来建立业务过程单元与产品结构的 某种程度的映射,这对于保证需求与设计之间的追朔关系十分有益,数据流图的特点如下:  可以表示任何一个系统(人工的、自动的、或混合的)中的数据流;  每个可以加工的过程可能需要进一步分解以求得对问题的全面理解;  着重强调的是数据流而不是控制流。 1,,,,DFD 的符号的符号的符号的符号 DFD 只用了 6 个符号来表达概念,如下图所: 2,,,,用用用用数据流图表达上下文关系数据流图表达上下文关系数据流图表达上下文关系数据流图表达上下文关系 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 20 - 在初期的业务分析中,用数据流图表达上下文关系是有一定优势的。在建立上下文关系图 的时候,系统内部在单个过程符号中概括所有处理活动,而用有向线段表示数据的流向。这种 表达可以使系统内外关系变得很清晰。这样的上下文关系也称之关联图或者为 DFD 片断。下图 是一个订单处理子系统的上下文关系图。 3,,,,基于过程划分的系统过程模型基于过程划分的系统过程模型基于过程划分的系统过程模型基于过程划分的系统过程模型 如果一个 DFD 片断包括更多的处理,可以把把每个过程逐步按层分解,以便作更详细的研 究,这称之为过程分解。例如,一个大学课程注册系统,其上下文关系(0 层图)如下: 在过程分解中,其 1 级数据流图可以作如下分解。 如果需要,可以再对过程“1”(课程安排)进行进一步分解,如下图所示。 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 21 - 这种分解的过程,将使我们对整个系统的业务模型由粗而精理解得非常清楚。 4,,,,基于事件划分的系统过程模型基于事件划分的系统过程模型基于事件划分的系统过程模型基于事件划分的系统过程模型 业务分析也可以使用事件驱动,现代过程分析也往往以事件为基础进行划分,其中每个事 件包含一套处理过程。在研究事件图的时候,往往需要了解所有的数据存储。必要的时候,数 据库分析和设计可以提到前面先来完成。要说明的是,在分析阶段并不需要数据库的详细设计, 而只是把数据存储用实体的方式从大的方面规范清楚,以此作为详细设计的一个必要的输入。 大多数事件图包括一个单一过程,并且需要说明以下内容:  输入及输入来源,来源被描述为外部代理。  输出及输出目的地,目的地被描述为外部代理。  必须读取记录的任何数据存储都应该被加入到事件图中,事件流应该加入命名。  对数据的任何增、删、改、查都应该加入到事件流中,事件流应该加入命名。 事件图的敏感性和简单性,使它成为专家和用户沟通的强有力的工具,针对我们已经讨论 过的“订单处理子系统”,可以对单个独立事件画出相应的数据流图。 5,,,,事件分解的事件分解的事件分解的事件分解的综合应用综合应用综合应用综合应用案例案例案例案例 具体到设计过程,我们到底采用过程分解还是采用事件分解要根据情况。不过一般过程分 解是静态的、先验的,比较适合预定义过程。而事件分解是动态的、更适合描述软件系统工作 的,所以适合在软件系统分析中使用。事件的取得可以对输入数据流进行分析,根据它是否触 发业务流程来判断是否是一个事件。很多情况下这两种分解方法是综合应用的,事件分解有助 于表达相互隔离的事务,而某些情况下利用过程分解有助于进一步细化事务流程,目的只有一 个,那就是把业务分析清楚。下面我们以上面讨论过的“订单处理子系统”,看综合应用事件分 解的例子。 1))))过程过程过程过程事件事件事件事件表表表表与数据流图与数据流图与数据流图与数据流图 现在我们的眼睛盯住具体的细节,为每个事件引发的事务绘制一个事件图,我们就可以建 立一个事件的上下文流图。上述“订单处理子系统”的过程事件表如下。 参与者参与者参与者参与者 事件事件事件事件 触发器触发器触发器触发器 响应响应响应响应 客户 选择产品 产品查询 生成“目录描述” 客户 发出订单 新客户订单 生成“客户订单确认”,在数据库中创建“客户订单” 和“客户订购的产品”。 客户 修改订单 客户订单修改请求 生成“客户订单确认”,修改数据库中 “客户订单”和 “客户订购的产品”。 客户 取消订单 客户订单取消 生成“客户订单确认”,在数据库中逻辑的删除 “客户 订单”和“客户订购的产品”。 据此可以画出相应的过程事件图,每一个事件应该是一个单一的过程。 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 22 - 2))))建立基于系统建立基于系统建立基于系统建立基于系统的业务模型的业务模型的业务模型的业务模型 事件图并不是孤立存在的,它们集合在一起定义了系统和子系统。我们可以把单个过程进 一步细化,构造一个或者多个系统或者子系统中所有事件的相互关系。这称之为建立基于系统 的业务模型。从本质上说,它是对业务进行形式化分解,自顶向下、逐层细化。 从某种意义上说,在绘制系统图的时候必须平衡不同详细程度的事件图,以保证一致性和 完整性,必要的时候可以扩展为多个 DFD。系统图更多的是从宏观的角度看为题,更多的考虑 相互关系,这点很重要。 3))))基本图基本图基本图基本图 系统图中的某些重要的事件过程可以扩展为一个基本的数据流图,以揭示更多的细节,这 对比较复杂的业务过程(比如订单处理特别重要),有些事件比较简单(比如报告生成),所以 不需要进一步扩展。 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 23 - 三三三三、、、、基于数据流的基于数据流的基于数据流的基于数据流的结构结构结构结构设计设计设计设计 上面的讨论告诉我们,为了把数据和业务过程的研究划分为系统的结构图,我们需要一些 划分规则,以此更清楚地研究基于数据流的系统结构化分解是有必要的。很久以来,人们已经 形成了一系列的结构化分解方法,其基本原理如下:  把信息流映射成软件结构;  信息流的类型决定了映射的方法; 下面我们分别进行讨论。 1,,,,变换流和事务流变换流和事务流变换流和事务流变换流和事务流 一般来说,信息流具有两种类型:变换流和事务流。 1))))变换流变换流变换流变换流 它的特点是:信息沿输入通路进入系统,同时由外部形式变换成内部形式。进入系统的信 息通过变换中心,经过加工处理以后再沿着输出通路变换成外部形式离开系统。 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 24 - 2))))事务流事务流事务流事务流 事务流的特点是数据沿着接收通路把外部世界的信息转换成一个事务项,然后,计算该事 务项的值,根据它的值激励起多条活动通路中的一条数据流。发出多条通路的信息流中枢被称 为“事务中心”。 2,,,,变换变换变换变换型分解型分解型分解型分解 如果数据流的特征是属于变换流,那么我们可以采用如下步骤分解: 第 1 步 复查基本系统模型。 第 2 步 复查并精化数据流图。 第 3 步 确定数据流图具有变换特性还是事务特性。 第 4 步 确定输入流和输出流的边界,从而孤立出变换中心。 第 5 步 完成“第一级分解”。 软件结构代表着对控制的自顶向下的分配,所谓分解就是分配控制的过程。 对于变换流,数据流图将被映射成一个特殊的软件结构,这个结构控制输入、变换和输出 信息等处理过程:位于软件结构最顶层的控制模块 Cm 协调下述从属的控制功能:  输入信息处理控制模块 Ca ,协调对所有输入数据的接收;  变换中心控制模块 Ct ,管理对内部形式的数据的所有操作;  输出信息控制模块 Ce ,协调输出信息的产生过程。 第 6 步 完成“第二级分解”。 把数据流图中的每一个处理映射成软件结构中一个适当的模块:  从变换中心的边界开始沿着输入通路向外移动,把输入通路中每个处理映射成软件结 构中 Ca 控制下的一个低层模块;  然后沿输出通路向外移动,把输出通路中每个处理映射成直接或间接受 Ce 控制的一个 低层模块;  最后把变换中心内的每个处理映射成受 Ct 控制的一个模块。 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 25 - 分析这张图的时候,我们需要注意到数据流程图与结构图的箭头含义是不同的,数据流程 图的箭头表达的是数据的流向,而结构图的箭头表达的是自顶向下的结构关系。当需要在结构 图中表达数据和控制的流向时,就必然的希望增加某些表示符号。 第 7 步 使用耦合性和内聚性规则对得到的软件结构进一步精化。 3,,,,事务型分解事务型分解事务型分解事务型分解 如果数据流的特征是属于事务流,那我们的分解步骤如下: 第 1 步 复查基本系统模型。 第 2 步 复查并精化数据流图。 第 3 步 确定数据流图具有变换特性还是事务特性。 第 4 步 确定事务中心和每个活动通路的流程特征。 第 5 步 把数据流图映射成一个适合于事务处理的软件结构。 第 6 步 对事务中心的结构和每个活动通路的结构进行分解、合并和改进。 第 7 步 使用耦合性和内聚性规则对得到的软件结构进一步精化。 四四四四、、、、结构图的进一步细化结构图的进一步细化结构图的进一步细化结构图的进一步细化 结构图是用来展示计算机程序模块之间的层次关系。在上面的讨论中,我们只表达了自顶 向下的结构关系,但并没有表达结构中的控制和数据的走向,为了更清楚的表达这些内容,需 要给结构图增加一些符号,目前常用的结构图主要符号如下: ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 26 - 下面是一个工资系统的部分结构图。 五五五五、、、、结构化分解的设计原则结构化分解的设计原则结构化分解的设计原则结构化分解的设计原则 我们可以把结构化分解看成一种问题分析技术,我们可以把这种技术应用在特定的环境中, 帮助我们理解在系统中运行的应用软件之上的需求。在结构化分解中,子系统是一个重要的概 念。子系统是伴随着软件复杂性的增长而日渐重要的一个概念,当软件规模越来越大,所有的 软件系统都会划分为模块或者子系统进行开发。 任何复杂系统,都可以分解成小问题也就是子系统,每个子系统子系统都是具有完整系统 架构的复杂系统组成部分,它可以合理的解释和证明、成功的设计与制造,然后在集成到整个 系统中去。子系统还可以分解成子系统,这种分解(或逐步细化)过程会一直进行下去,如下 图所示。 正确的子系统分解应该考虑下面的原则:  对功能进行分布和划分,对于以最小的成本和最大的灵活性来完成系统整体的功能来 说是最优的。  每个子系统都可以被一个小型团队所定义、设计与开发。  每个子系统都可以使用可行的制造技术制造出来。  在成功地模拟了子系统的其它子系统的接口之后,每个子系统都可以单独进行测试。  对于子系统的各个物理方面(大小、重量、位置、分布)都要进行考虑,并在整个系 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 27 - 统环境下加以优化。 子系统本身的开发也需要经过架构设计这一关。从高层来说,架构的重心主要是子系统之 间的协作,对子系统来说,架构的重心主要是模块之间的协作。如果从粒度的角度来看问题:  粒度最小的单元是“类”。  几个类紧密协作形成“模块”。  完成相对独立功能的多个模块形成“子系统”。  多个子系统相互配合满足一个完整的需求,从而构成软件“系统”。  一个大型企业往往使用多套系统,多套系统通过互操作形成“集成系统”。 从子系统的层次结构来说:  当进行高一层架构设计的时候,子系统成为一个原子单元、一个黑盒。  当进行子系统本身设计的时候,它才变成了一个结构复杂的白盒。  第三方组件可以看成一个原子单元,它是一个黑盒,我们主要应用它的服务。  当使用第三方框架的时候,需要仔细研究它的结构,这是因为这是使用的是它的结构, 而不是它的服务。 1.4 软件架构软件架构软件架构软件架构的的的的设计设计设计设计过程过程过程过程 软件架构设计需要以系统工程学的方法来开展,系统工程学是以系统论的思想和系统方法 论为基础,借助控制论、运筹学、统计学、信息处理和计算机技术,研究复杂系统的构成和子 系统的相互作用,对系统构成要素、组织结构、信息流动和控制机构进行分析,并建立相应的 数学模型和逻辑模型,系统工程学把系统的行为模式看成是系统内部的信息反馈机制决定的。 系统工程要求按照逻辑推理的路径,来解决那些原本是依靠直觉判断处理的问题。 从系统工程的角度来看,软件架构并不是一个纯技术范畴的事情,而是需要从业务需求与 技术解决方案两个方面整体考虑,需要考虑我们需要解决用户的什么问题,如果这些问题不存 在,那我们产品的价值就要打折扣了。为此,我们应该比较条理化的建立软件架构设计过程。 典型软件架构设计过程如下图所示。在图中,我们还表达出了各个子过程之间的反馈机制。 下面我们分别加以说明。 1,,,,业务架构概念业务架构概念业务架构概念业务架构概念 在构建软件架构之前,架构师需要仔细研究如下几个问题:  系统是为什么目的而构建的?  系统投运后服务于哪些利益相关者的利益?  什么角色在什么时候操作或者维护系统?  业务系统实现方法是怎样的?  整个业务系统是如何依靠系统而运转的? 在研究这些问题的时候,我们应该知道,任何项目的动因都来自于对问题的解决,而项目 的价值也来自于对问题解决的有效程度。如果一个项目所针对的问题不是十分清晰,则项目的 价值就会受到质疑,因此,在建立业务架构概念的时候,关键是明确系统需要解决什么业务问 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 28 - 题。但是我们也要认识到,并不是所有的应用都是为了解决特定问题,有些系统是为了充分利 用市场提供的机会的,比如某种游戏或者提供给喜欢智力挑战的人群。但即使这样的软件仍然 需要问题分析,或许您可以说问题是:“计算机上没有好玩的东西”、“某些人群空闲时间太多” 等等,这都需要对问题进行分析。 为了研究这些问题,我们需要仔细阅读需求分析文档中的业务模型建立、问题域及其解决 构思、产品模型的构思等等前期文档,站在系统架构的角度,全面清晰的建立业务模型,包括 组织结构关系、业务功能、业务流程、业务信息交互方法、业务地理分布、业务规则和约束条 件。这个阶段的主要活动如下:  建立产品范围、目的、最终用户、业务背景等重要的初始信息。  建立完整的业务和系统的术语字典,确保项目相关人员理解上保持一致。  建立宏观层面业务的总体概念,明确总体流程、业务功能的边界、交互与协作方式, 建立系统的概念模型。  汇总业务总的组织结构与协作职能关系。  分析业务的组成节点,以及节点间交互、协同与信息的依赖关系。  分析业务节点的事件、消息,以及由此引发的状态转换关系。  汇总业务运行的基本数据模型,以便于跟踪信息的流动与格式转换。分析业务数据的 关联关系。  理解问题域以及系统需要解决的问题。  分析业务运作层面的基本业务规则与约束条件。 这个阶段的活动非常重要,架构师只有具备了这些相互关联的业务概念以后,才可能从这 些概念中抽取恰当的架构因素。 2,,,,产品架构概念产品架构概念产品架构概念产品架构概念 在理解业务的基础上,我们需要进一步思考产品架构的概念,这个阶段从活动的层面看实 际上与建立业务架构概念是一样的,但是思维的重心转移到如下几个方面:  新系统投入运行以后,最高层面的业务会怎样运作?  新系统是如何解决原来工作系统的问题的?  新系统的投运,会对原来的组织结构划分发生什么样的影响?  由于新系统取代了原来的一些业务职能,业务节点的分布会发生怎样的变化?变化后 的节点间的信息又是怎样交换与依赖的?  变化后的业务事件传递又会发生怎样的变化?  新的系统加入以后,哪些业务流程将会发生重大变化?哪些不会发生变化?  业务的状态转换关系将会如何随着新系统地加入而改变?  业务的数据模型将会如何随着业务流程的变化而变化的?  新系统地加入,将会如何影响新的业务规则和约束? 从这些角度出发,我们会重新构建未来新系统投运以后的业务规则,相应的新规则也需要 建立,这就实现了业务过程的重构。 3 ,,,,建立建立建立建立稳定的架构基线稳定的架构基线稳定的架构基线稳定的架构基线 在对业务领域与问题域有深刻的理解以后,我们需要继续研究如下一些问题:  这个复杂系统应该分成多少和哪些子系统?  子系统是如何分布在不同的业务节点或者物理节点上的?  这些分散的子系统将提供哪些接口?这些接口如何进行交互?  各个子系统需要交互哪些数据?  每个单独的子系统,所需要实现的功能有哪些? ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 29 -  整个系统对各个子系统有哪些功能、性能和质量上的要求? “基线”这个词有两个意义:  这个阶段将会对整体架构策略做出重大的设计上的决策。一旦作出了这些决策,后续 开发没有重大情况不允许变动。  这个阶段完成的工作,本身就是架构阶段的重要成果,需要广泛认同、集体遵守以及 具备强制的约束力。 尽管在后期的演变中,这样的基线实际上还会不断的精化和优化,但最初下功夫构建稳定 的架构基线是十分必要的。这个阶段的活动如下:  校验与确认前期所有的业务架构与产品架构的信息,必要的时候补充相应的信息。  修订和增补术语字典,确保所有的相关人员对术语有相同的认知。  把整个系统功能进行拆分,并且分解到不同的运行节点上,构建不同的系统集和子系 统,在全局范围内划分接口与交互规则。  汇总系统/子系统接口信息,便于检索与浏览。  规划整个系统的通信链路、通信路径、通信网络等传输媒介。  把产品架构概念中的业务职能与系统功能相对应,从而确保满足业务要求。  分析系统/子系统在运行起动态协作需要交互的信息。  构建和模拟整个系统在业务环境下的动态特性,规划全系统内部状态变化过程、触发 的事件及约束条件。  详细汇总各个子系统间信息传递的过程、内容以及其它辅助信息。  根据初始的数据模型构建数据物理模型。  汇总质量上对系统的要求,并把这些质量要求细化分解,量化到各个子系统中去。  构建整个系统与子系统的构建和演化计划,在迭代过程中构建整体项目规划和初始的 迭代规划。  按固定时段预测技术的演化,汇总整个系统的应用技术及其演化。  分辨与汇总整个系统在不同阶段必须遵循的标准。  把业务约束映射到各个子系统,必要时附加 IT 业务约束。 4,,,,子系统架构的设计与实现子系统架构的设计与实现子系统架构的设计与实现子系统架构的设计与实现 通过上述各主要过程,我们已经实现了一个重要的总体架构基线。所有的子系统设计都是 在这个庞大的架构基线约束下展开,至此,首席架构师逐渐淡出,让位于子系统架构设计师。 子系统架构设计师的任务是继续分解、细化、设计各个子系统。在这个阶段,将会考虑更加细 节的问题,为后来的组件设计与单元设计作准备,我们需要考虑的问题如下:  规划给该子系统的功能是否可行?  在整个子系统的范围内,又能分解成什么子功能集?  在整个子系统的范围内,又能把哪些子功能合并到某些组件中去?  这些组件与子功能集是如何通过接口与子系统衔接的? 事实上子系统架构设计本身就是一个完整的系统设计,所区别的是视野集中到子系统的范 围内,这个阶段的活动如下:  校验与确认前期与该子系统相关的业务架构与产品架构的信息,必要的时候补充相应 的信息。  增补与本子系统相关的术语字典,确保所有的相关人员对术语有相同的认知。  把整个子系统功能进行拆分,并且分解到不同的组件节点上,构建不同的子功能集, 在子系统范围内划分接口与交互规则。  汇总子系统/组件接口信息,便于检索与浏览。  规划整个子系统的通信链路、通信路径、通信网络等传输媒介。 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 30 -  把产品架构概念中的子业务职能与组件功能相对应,从而确保满足业务要求。  分析子系统/组件在运行起动态协作需要交互的信息。  构建和模拟整个子系统在业务环境下的动态特性,规划子系统内部状态变化过程、触 发的事件及约束条件。  详细汇总各个组件间信息传递的过程、内容以及其它辅助信息。  根据初始的数据模型构建子系统相关的更详细的数据物理模型。  根据质量上对子系统的要求,并把这些质量要求细化分解,量化到各个组件中去。  构建整子系统的构建和演化计划,在迭代过程中构建子系统项目规划和更详细地的迭 代规划。  按固定时段预测技术的演化,汇总子系统的应用技术及其演化。  分辨与汇总子系统在不同阶段必须遵循的标准。  把业务约束映射到各个组件,必要时附加 IT 业务约束。 进入组件设计阶段也就是进入了详细设计阶段。这个阶段主要的工作就是接口与功能设计。 在迭代模型下,这个阶段很大程度上是在迭代过程中完成的,由某个设计人员带领全体开发团 队进行分析和设计。在这个过程中,我们应该考虑在小粒度架构中如何使产品需求变更不至于 对产品质量造成影响,还需要考虑业务概念模型与产品功能块有相应的追溯和回溯关系。 1.5 从系统工程的角度分析和设计从系统工程的角度分析和设计从系统工程的角度分析和设计从系统工程的角度分析和设计架构架构架构架构 一一一一、、、、应用系统工程帮助应用系统工程帮助应用系统工程帮助应用系统工程帮助需求分配需求分配需求分配需求分配 1,,,,从更广阔的角度看待分析与设计从更广阔的角度看待分析与设计从更广阔的角度看待分析与设计从更广阔的角度看待分析与设计 所谓应用系统工程帮助分析问题,是希望无论在需求分析还是在架构设计中,考虑问题的 角度要宽阔,并不仅仅在单点考虑,而是希望从多点考虑问题。例如,在大多数需求分析的资 料中,都提出来在整个需求分析的过程中,只是关注收集用户需要,而不要考虑解决方案。在 某种意义上,这对防止初期的解决方案对后期设计的影响是有一定的意义的。但是,从另一个 方面来说,把这个观念绝对化也是有害的。从架构设计的角度来看,软件架构的要求也是一种 需求,可能也是第一阶段收集需求的时候最值得关注的需求。这就需要在需求分析的时候考虑 到整体架构的因素,反过来这也会使需求过程更加趋于合理。 2,,,,把子系统作为需求实体考虑把子系统作为需求实体考虑把子系统作为需求实体考虑把子系统作为需求实体考虑 从系统工程的角度考虑需求,就需要把子系统作为一个重要的实体加以考虑。首先赋予子 系统功能描述(例如:子系统 B 将运行风速算法,并直接驱动前导显示器),然后再自上而下的 分解需求。 1))))关于派生的需求关于派生的需求关于派生的需求关于派生的需求 在这样的情况下,很可能我们会生成一个派生的需求,它们必须被赋予子系统,典型情况 下,派生需求可以分成两种:  子系统需求子系统需求子系统需求子系统需求:是子系统必须满足,但随最终用户未必有直接利益的那种需求(例如: 子系统 A 必须计算飞行器的空速)。  接口需求接口需求接口需求接口需求:是子系统为了完成整体任务,必须与另一个子系统进行通信产生的需求, 子系统创建的同时也促进了子系统之间接口的创建。 但是这些子系统需求是真的需求吗?对最终用户来说,它可能并不是重要的。但对于需求 人员来说,开发人员也是需求提供者的客户,这些需求对于开发人员是重要的,所以也是一种 至关重要的需求。 还需要注意的是,虽然这些子系统需求对项目的成功至关重要,但他们是由系统的分解得 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 31 - 来的,不同的分解方式会产生不同的派生需求。所以,在前期设计人员参加一些讨论还是非常 有意义的。重要的是要认识到,对派生需求的描述会影响最终系统完成工作的能力,以及系统 的可维护性和稳定性。 2))))子系统分包子系统分包子系统分包子系统分包 还有一种更加复杂的问题经常会发生,那就是子系统经常是由不同的团队来开发的,这也 是我们生成子系统的目的之一。在这样的情况下,子系统需求与接口,就有可能成为团队之间 的契约。更多的情况,子系统是由其它公司作为分包商开发的,这使得需求失去了其系统和技 术的环境,改变需求变得很困难,项目会被它的短处所牵制,很多大型项目就是在这个问题上 翻的船。 3))))从系统工程的角度从系统工程的角度从系统工程的角度从系统工程的角度解决问题解决问题解决问题解决问题 这就是为什么要专门讨论从系统工程的角度研究需求的原因。我们可以做什么呢?在处理 极其复杂的系统的时候,你可能需要考虑以下建议:  开发、理解和维护横跨子系统的高层需求和用例。它们描述了系统的整体功能,这些 用例提供了系统整体的工作背景,要确保你没有“只见树木,不见森林。”他们还有助 于确保系统架构设计支持最可能的使用场景。  把划分工作做得最好,并把功能限制在子系统范围内。在系统功能中使用对象技术原 则:封装和信息隐蔽。根据合同建立接口,使用消息而不是数据共享。  可能的话,把软件作为一个整体来开发,而不是一些分开的部分。避免在接口的两端, 为了双方的决策,软件都必须重构核心元素(对象)的状态。与硬件不同,软件需求 在双方的分配并不是一个清晰的划分。  当对接口进行编码的时候,在接口两端采用共同的代码。否则如果有什么变化(比如 优化)的话,两端的同步将会非常困难。另一方面,如果将来两个子系统之间的界限 消失,比如系统工程师发现两个子系统可以合并,合并将会非常困难。  最后,看看能否找到一个资深工程师来帮助你实施系统工程,如果他以前做过类似的 工作,它的经验将会对您有很大的帮助。此外这样做的副产品是,这样做有助于消除 代沟。  在多团队开发的时候,最好是其中的一个团队来开发接口代码,否则,两个团队有很 多工作是重复的。这样你将会确实的生成系统新的需求,包括接口。把接口作为正式 的需求,可以避免很多集成上的问题。 二二二二、、、、组织复杂软硬件系统的需求组织复杂软硬件系统的需求组织复杂软硬件系统的需求组织复杂软硬件系统的需求 无论需求表示成什么形式,都必须形成需求文档。一个由多人参与的工作不可避免的存在 交流问题,这就需要获取一份能够被复审和批准、大家都认可的、用来参考的文档。传统上, 利用需求规格说明这种大型文档,来获取和交流这种信息,对于大型复杂的项目,不可能没有 需求规格说明就盲目的开始项目开发,关键是这种规格说明的粒度要合理。 关于如何组织需求信息有几个要点:  对于复杂项目,必须获取需求规格说明,并把它记录在文档、数据库或工具中。  不同类型的项目,要求不同的需求组织技术。  复杂系统需要每个子系统都有需求规格说明。 在项目的前期,我们只是宏观的讨论组织需求信息的有关问题。我们必须了解到,很少有 需求能够在单个文档中定义,其原因是:  系统可能非常复杂,建档数量较大,需要有组织的和交互访问的技术。  该系统可能是相关产品系列的一个成员,没有什么文档可以包括所有的规格说明。  所构建的系统可能只是一个大型系统的子系统,仅能满足所确定需求的一个子集。 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 32 -  必须把市场和商业目标从产品的详细需求分离出来,这需要多个文档。  也可能在系统中建立制度或法规这样的需求,这些需求可以在其它地方进行建挡。 在以上例子中,都可能需要维护组成多个需求集的需求,每个需求集反映了一个特殊系统 加上若干子系统的集合的需求,下面有一些这样的例子:  一个需求集用一般术语定义系统特性,这称之为前景文档前景文档前景文档前景文档(Vision Docunment )。而另 一个需求集使用更专用的术语定义需求,这由用例模型用例模型用例模型用例模型和相关的补充需求补充需求补充需求补充需求组成。  一个“父”需求集定义整个“系统”的需求,包括硬件、软件、人员和过程,另一个 需求集只定义软件子系统的需求。  一个需求集定义产品系列的全部需求集,另一个需求集只定义特定应用和特定版本的 需求。 下面我们来看一个组织复杂软硬件系统的需求的案例。对于非常复杂的系统,唯一合理的 方法是把它创建成由多个子系统组成的系统,这些子系统有时是其它子系统构成的系统。在特 殊情况下,比如飞机控制系统,将包括上百个子系统,而每个子系统都有自己的硬件组件和软 件。 1))))创建系统级的需求规格说明创建系统级的需求规格说明创建系统级的需求规格说明创建系统级的需求规格说明 在这样的情况下,首先创建一个系统级的需求规格说明,在不了解或者不引用任何子系统 的情况下来描述系统的功能行为。例如飞机油料的装载能力、爬升速度、飞行最大高度等等。 2))))进行子系统划分进行子系统划分进行子系统划分进行子系统划分 正如讨论过的,一旦对系统级的需求达成共识,就开始系统工程活动。我们可以把系统分 解成多个子系统,描述子系统之间的接口,把系统级的需求分配到各个子系统,由此产生了系 统架构描述,定义了系统划分以及系统之间的接口。原则上是可以任意确定划分大小的,一个 可能的原则是,每个子系统可以由一个小型团队可以完成。 在分析阶段仔细考虑并稳定接口是非常必要的。系统分析师和设计师可以一直这样做下去, 直到表示出接口中所有的原始对象为止。初步的考虑可能是混乱的没有条理的,但有了这样的 矩阵就可以使自己的思维逐步的条理化,最后达到非常优秀的设计。 3 ))))开发子系统需求规格说明开发子系统需求规格说明开发子系统需求规格说明开发子系统需求规格说明 下一步,为每个子系统开发一个需求规格说明,这些规格说明应该在不引用它自己的子系 统的情况下,完整地描述它的外部行为。在这个过程中会产生一类新的需求:派生需求。这类 需求不是描述整个系统的外部行为,而是描述子系统的外部行为,因此,系统设计过程为组成 系统的子系统创建了新的需求。特别是系统之间的接口成为关键需求。本质上这是子系统与另 一个子系统之间的契约,或者是对子系统同意完成的事情的承诺。 4))))对子系统进行划分对子系统进行划分对子系统进行划分对子系统进行划分 一旦需求达成一致,再次进行系统地分析和设计,如果需要,可以进一步把子系统分解成 它自己的子系统,并且分别开发各个子系统的需求规格说明, 在每一层,都把来自上一层的需 求规格说明分配给适当的下一级需求规格说明。例如,燃料容量需求分配给燃料控制系统和燃 料储备系统,同时恰当的发现和定义新的需求。 最后,我们可以写出最底层的需求规格说明。最底层的需求规格说明指的是那些不能再分 割的需求规格说明,通常对应于仅仅是硬件或者仅仅是软件的系统,如下图所示。 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 33 - 这些需求规格说明在开发进程中还会有一个演化的过程,使细节更容易理解。 1.6 迭代的建立迭代的建立迭代的建立迭代的建立架构架构架构架构基线基线基线基线 上面应用结构化方法建立的分解结构,只是一个基本模型,当我们有了这个基本模型以后, 就要考虑进一步的调整和优化,使系统架构具有更加良好的品质。架构实现可能需要一个单一 团队,架构的功能,也可以用用户故事来说明,但是问题更集中在顶层描述,主要是框架、对 外通讯、内部框架之间的通讯,以及大的、集中在主题层面地描述。架构的成果也应该是一个 可发布的、经过测试的版本,一个架构一般也需要经过一到两次迭代完成。 一一一一、、、、成功的软件架构设计成功的软件架构设计成功的软件架构设计成功的软件架构设计 为了更好地进行架构设计,我们必须仔细研究一下,一个成功的软件架构设计应该具备什 么品质,对这种品质的深入理解,可以使我们的设计目标更加明确而有指向性,研究问题的重 点也更加突出。 1,,,,成功软件架构的品质成功软件架构的品质成功软件架构的品质成功软件架构的品质 成功的软件架构设计是高质量的,并且所花费的时间、技术决策等方面都能满足具体开发 方法的要求,具体应该有如下品质:  良好的模块化良好的模块化良好的模块化良好的模块化:每个模块职责明确,模块之间松耦合,模块内布高内聚,并且合理的 实现了信息隐蔽。  适应功能需求变化适应功能需求变化适应功能需求变化适应功能需求变化,,,,适应适应适应适应技术变化技术变化技术变化技术变化:典型情况是,应该保持具体应用的相关模块和领 域通用模块的分离,技术平台相关模块与具体技术的应用模块相分离,从而达到“隔 离变化”的效果。  对系统动态运行有良好的规划对系统动态运行有良好的规划对系统动态运行有良好的规划对系统动态运行有良好的规划:应该标识出哪些是主动模块,哪些是被动模块,明确 模块之间的调用和加锁机制,并说明关键的进程、线程、队列、消息等机制。  对数据的良好规划对数据的良好规划对数据的良好规划对数据的良好规划:不仅仅包括数据的持久化存储,还包括数据传输、数据复制与数 据同步等策略。  明确明确明确明确、、、、灵活的部署规划灵活的部署规划灵活的部署规划灵活的部署规划:这里往往牵涉到可移植性、可伸缩性、持续可用性以及互操 作性等大型企业级软件特别关注的质量属性架构策略。 好的架构并不是“好的就是成功的”,而是“适合的才是成功的”。不适当的用时间换完美, 最后会毁掉整个项目。回过头来看看我们为什么花了大量的时间讨论软件开发过程及其影响? 除了明确我们初期需要在绝大部分技术细节都不清楚的情况下定义软件架构,还要考虑初期我 们就需要搭建一个团队协作开发的基础,让不同的小组针对不同的子系统和模块深入下去,这 种团队的秉性工作也意味着可能缩短项目工程的周期。 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 34 - 架构师并没有绝对的技术选择自由,还需要考虑经济性、技术复杂性、发展趋势以及团队 水平等诸方面的因素。最终,架构师的工作成果就是为整个开发团队的工作提供足够的指导和 限制,使他们沿着正确的方向进行下去。 下面,我们来探究一下成功架构设计的关键要素是什么,这些讨论将主导着本课程内容的 演绎,是整个课程最核心的知识。 2,,,,成功架构设计的关键要素成功架构设计的关键要素成功架构设计的关键要素成功架构设计的关键要素 软件架构设计是以“需求规格说明书”为最主要的设计依据,首先勾勒出概念性的架构, 再结合具体的技术平台制定实际架构方案的。在考虑架构设计的时候,必须注意如下关键要素。 1))))是否遗漏了至关重要的非功能性需求是否遗漏了至关重要的非功能性需求是否遗漏了至关重要的非功能性需求是否遗漏了至关重要的非功能性需求 非功能需求是最重要的架构决定因素之一,所谓非功能需求主要包含两个部分:质量属性 和约束条件。质量属性是软件系统整体的质量品质,所谓整体品质,就是它往往和大多数功能 都有关系。比如易用性、可扩展、安全性、可靠性等。它们往往表现在整体上的品质,而不是 哪个功能的“内部”。 非功能需求很多情况下存在一定的相互矛盾,所以只有少数几个质量属性在架构设计中是 最重要的,它通常左右着架构风格的选择。另一方面,软件系统非功能性需求的的满足,仅凭 编程级的努力是达不到的。比如为了提供高可靠性,往往涉及错误检测、预防、修复等,这就 需要架构设计中非常重视非功能性需求。 功能是重要的,但如果仅仅盯着功能而忽视了非功能需求,则可能导致架构设计的失败。 2))))是否适应数量巨大且频繁变化的需求是否适应数量巨大且频繁变化的需求是否适应数量巨大且频繁变化的需求是否适应数量巨大且频繁变化的需求 需求的变更既蕴藏着风险又包含了机遇。之所以说是风险,是因为不存在不需要成本的需 求变更。任何变更都意味着时间和金钱的消耗,并且在大量变更以后程序可能被搞得混乱不堪, 势必引起 Bug 增多,产品质量下降。另一方面,需求变更也蕴含着机遇,对软件架构师而言, 这个机遇就意味着极力设计出更稳定的架构,最终,这个架构能够支持需求在一定范围内“随 需而变”。 从更深层次来讲,现在商业环境的特点就是频繁变化,国际化带给我们的就是对未来越来 越不可预测,技术的位置也不仅仅是服务,很多情况下技术在一定程度上还会拉动需求变更。 不考虑适应数量巨大而且频繁的需求变更,架构师就难以“从容”的进行架构设计,最终甚至 被变化拖垮而无法关注大局。 3 ))))能否从容设计架构的不同方面能否从容设计架构的不同方面能否从容设计架构的不同方面能否从容设计架构的不同方面 架构师必须具有宏观思考的能力,避免涉及太多的技术细节,但这并不意味着架构设计是 宽泛的甚至简单的。软件架构必须对开发提供足够的指导和限制,这无疑意味着软件架构的工 作是复杂的。架构师必须深入研究软件系统运行期间的情况,合理划分不同部分的职责,权衡 轻重缓急,并制定相应的并行、分时、缓存和批处理等设计决策。 架构师必须掌握系统化的方法,对复杂问题“分而治之”,分解成独立的视图。然后再综合 考虑各个视图之间的相互支持、互相影响等问题。 4))))能否及早验证架构方案并做出了调整能否及早验证架构方案并做出了调整能否及早验证架构方案并做出了调整能否及早验证架构方案并做出了调整 现代软件开发非常注意早期缓解高风险。而架构设计又是软件开发风险比较高、也是最为 关键的一环。架构设计的是否合理,将直接影响到软件项目最终是否能够得到成功。 毕竟,软件架构中包含了关于如何构建软件的一些最重要的设计决策,比如系统分为哪几 个部分?各部分之间如何交互的?等等。这些设计决策能保证最终产品满足非功能需求(比如 性能、可靠性、安全性)吗?所以,在大规模开发之前,尽早构建架构的早期版本(架构基线), 并通过对这个原型的测试评审,来评估这个架构是不是合理,这是非常重要的事情。 3,,,,软件架构设计策略软件架构设计策略软件架构设计策略软件架构设计策略 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 35 - 策略对实践提供总体上的指导,对于有难度的工程(比如软件工程),或者有竞争性目标(软 件中时间、质量、范围、成本之间存在竞争)而言,策略往往是制胜的关键。一定要注意,策 略来自于问题,没有问题的策略是无目之本。下面,我们针对成功架构设计的四个要素,以此 衍生出四个问题,作为讨论相应的策略的基础。这样的思考过程也可以成为我们研究其它架构 问题的思考范例。我们先把关键点归纳成下面的表。 编号编号编号编号 关键点关键点关键点关键点 问题问题问题问题 危害危害危害危害 策略策略策略策略 策略要点策略要点策略要点策略要点 1 是 否 遗 漏 了 至 关 重 要 的 非 功 能性需求 对需求的理解不系统、不全 面、对非功能需求不够重 视。 造成返工,项 目失败 全 面 认 识 需求 弥补非功能需求的缺失 2 是 否 适 应 数 量 巨 大 且 频 繁 变 化的需求 对于时间和质量的矛盾,办 法不足,处理草率。 耗时不少,质 量不高 关 键 需 求 决定架构 把架构理解成概要设计, 过于粗糙,不能适应实践 要求 3 能 否 从 容 设 计 架 构 的 不 同 方 面 架构设计方案覆盖范围严 重不足,许多关键决定被延 迟,或者由实现人员仓促决 定。 开发混乱,质 量不高 多 视 图 探 寻架构 架构师开展系统化团队 开发的基础,应该对不同 的涉众提供指导和限制 4 能 否 及 早 验 证 架 构 方 案 并 做 出了调整 假设架构的方案是可行的, 直到后期才发现问题,造成 大规模的返工。 造成返工,项 目失败 尽 早 验 证 架构 架构设计方案应该解决 重大技术风险,并尽早验 证架构 根据这张表,我们来讨论一下针对每个关键点的相应策略: 1))))全面认识需求全面认识需求全面认识需求全面认识需求 既然软件架构强调的是整体,而整体的设计决策必须基于对需求的全面认识,所以全面认 识需求,是软件架构的第一项需求。 但是全面认识需求并不等于“眉毛胡子一把抓”,而是需要对需求进行梳理清楚,在梳理的 过程中把需求理解清楚。全面认识需求,就需要从不同级别来考察需求,这三个级别分别为: 组织级、用户级、开发级。还需要对每个级别考虑不同类型的功能需求、质量属性、约束,如 下图所示。 一方面来说,需求是分层次的,对用户高层而言是帮助他们达到业务目标,最终用户而言, 是辅助他们完成日常工作,对开发者而言,有着更多用户没有觉察到的“需求”需要实现。 关注需求的实践意义在于在需求之间建立可跟踪性,以免由于遗漏需求使软件达不到要求, 或者一厢情愿的为用户制造没有实际意义的功能。当客户方老板说:“我希望这套软件能为我赚 更多的钱。”这恰恰是一个商业目标,并会对需求和设计产生很大的影响。 总之通过需求分类,将有助于全面认识需求、分门别类的把握需求,从而设计出高质量的 软件架构。全面认识需求还有一层含义,那就是应当在深思熟虑之后作出合适的权衡和取舍。 一方面众多质量属性往往会有冲突,我们必须权衡,另一方面,通过复杂的设计所支持的变化 可能根本不会发生,这就造成过度设计,从而造成资源浪费并增加了开发的难度。 2 ))))关键需求决定架构关键需求决定架构关键需求决定架构关键需求决定架构 软件架构师没有时间对所有的需求进行深入分析,这是现实,软件架构师没有必要对所有 的需求进行深入分析,这是策略。架构师要做的就是:接受现实,采取策略。关键需求决定架 构有两个方面的内涵:功能需求数量太多,应该控制架构设计的时候需要详细分析的用例个数。 另一方面,不同质量属性往往相互冲突,于是我们自然应该权衡那一部分质量属性是架构的重 点设计目标。 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 36 - 在实际项目中,我们往往在项目的业务目标及核心需求达成共识之后就开始架构设计了, 在这种情况下,关键需求决定架构的策略非常适合。关键需求决定架构的策略有利于集中精力 深入分析最为重要的需求。人的思维应对复杂问题的能力是有限的,当我们把问题分解、化简 和转换,最后集中精力扑在相对较少的需求上的时候,可以更为深入地分析这些需求,有利于 得到更加透彻的认识,从而设计出合理的架构。 例如一个“订单处理系统”软件项目,在全面分析需求的的基础上,下一步我们必须确定 关键需求,以把握设计的重点。在这个阶段。我们应该多问几个为什么,例如:为什么“提供 销售策略”是架构设计的关键需求呢?这是因为这个功能涉及了“订单处理系统”与外部设备 接口的模块。“人工解释细节”牵涉到采用何种技术方法:是视频?还是电话?或者是发送 E-mail ?而其它功能没有“覆盖”这一点。下表列出了“订单处理系统”项目的关键需求子集。 通过全面认识需求,我们获得了需求的广度,这个阶段特别是要关注质量和约束等非功能 性需求上。但要进行架构设计,对全面需求了然于心之后,必须抓住关键需求决定架构,这就 是需求的深度。这种策略被哲学性的潜藏在广度和深度之间。 3 ))))多视角探寻架构多视角探寻架构多视角探寻架构多视角探寻架构 利用多视角探寻架构,本质上属于分而治之的原理。当把复杂问题划分为多个相对简单的 问题的时候,就可能对每个子系统强调不同重心,而心理学的研究早就表明,“强调能使经验活 跃起来。”从而更有效地解决问题。 分而治之的策略有两种:  按问题深度分而治之按问题深度分而治之按问题深度分而治之按问题深度分而治之:先不研究那么深、那么细,按问题复杂性的层次分而治之。  按问题广度分而治之按问题广度分而治之按问题广度分而治之按问题广度分而治之:先研究问题的一个部分,分割问题,各个击破。 下图表明了这两种情况。 接口与实现分离,实际上按照问题深度分而治之的例子。表示层、业务层、数据层单独处 理,是按问题广度分而治之的例子。 4))))尽早验证架构尽早验证架构尽早验证架构尽早验证架构 应该尽早对软件架构设计方案进行开发和验证,而不仅仅向概要设计那样只是进行评审。 具体而言:  应该真正通过编码把架构实现。 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 37 -  应该实际对架构基线进行测试,测试的重点是运行时的质量属性,如性能、可维护性、 可伸缩性等。  要认真评估架构基线的实现过程,以对软件架构开发期的质量属性给出评价。  传统意义上的架构设计评审仍然是需要的,比如通过走查确保所有的功能需求能够被 支持。  要对架构的不足之处及时进行调整,并再次进行验证。 要进行实际的测试,这一点很重要,否则,软件架构能否达到质量属性要求不得而知,这 就埋下了众多技术风险。 在上述讨论的基础上,我们对软件架构的基本问题已经有了一个比较全面的了解,下面我 们对问题进行分解,针对一些具体问题进行进一步的阐述。 二二二二、、、、建立弹性软件架构建立弹性软件架构建立弹性软件架构建立弹性软件架构 对于基础架构,我还有几个观点要说明。在单一团队工作结束的时候,将建立系统早期的、 关键性的第一个版本,这是一个可执行的版本,我们称之为架构基线架构基线架构基线架构基线版本。在建立好架构基线 之前可能要花费几个迭代周期,但完成以后,将会证实你的假设、以及系统开发方法,也就可 以降低风险,基于这个架构,其它部分的开发速度将会大大加快。 一个好的架构要确保不同类型的关注点互相独立,当其中一个发生改变的时候,不至于影 响系统的其它部分。架构师应该致力于创建一个弹性架构弹性架构弹性架构弹性架构,也就是说各个不同类型的关注点保 持独立,而系统中的一部分发生变化的时候,对其余部分的影响要最小。架构设计也必须满足 性能、可靠性等系统的关注点。 好的架构必须使每个关注点互相分离,尽可能使系统一部分的改变不至于影响到其它部分, 即使有一定影响,也要清晰的识别出哪些部分需要改变,如果需要扩展架构,影响应该最小化, 已经可以工作的部分应该可以继续下去。 1,,,,分离功能性需求分离功能性需求分离功能性需求分离功能性需求 一般的希望保持功能性需求之间是分离的,功能表明了不同最终用户的关注点,并且可能 互相独立的发展,所以不希望一个功能的改变会影响到到其它。功能性需求一般是站在问题域 的高度来表达的,因此很自然的希望系统特定功能从领域中分离出来,这样,就便于把系统适 配到类似的领域中。另一方面,一些功能需求会以其它功能需求扩展的形式来定义,这样更需 要它们互相独立。 2,,,,从功能需求中分离出非功能性需求从功能需求中分离出非功能性需求从功能需求中分离出非功能性需求从功能需求中分离出非功能性需求 非功能性需求通常标识所期望的系统质量属性:安全、性能、可靠性等等,这就需要通过 一些基础结构机制来完成,比如,需要一些授权、验证以及加密机制来实现安全性;需要缓存、 负载均衡机制来满足性能要求。通常,这些基础结构机制需要在许多类中添加一小部分行为(方 法),这就意味着与基础结构机制实现的一点变动都会造成巨大的影响,因此,要使功能需求与 非功能需求之间保持分离。 3,,,,分离平台特性分离平台特性分离平台特性分离平台特性 现在的系统运行在多种技术之上,比如身份验证的基础结构机制就可能有许多可选的技术, 这些技术经常是与厂商有关的,当一个厂商把它的技术升级到一个新的、更好的版本的时候, 如果你的系统适紧密依赖于这项技术前一个版本的,那么进行升级就并不那么容易,所以要使 平台特性与系统保持独立。 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 38 - 4,,,,把测试从被测把测试从被测把测试从被测把测试从被测单元中分离出来单元中分离出来单元中分离出来单元中分离出来 作为完成一项测试的一部分工作,你必须采用一些控制措施和方法(调试、跟踪、日志等), 这些控制措施是保证系统运行流程符合测试要求的规程。这些方法是为了在系统执行的过程中 提取信息,以确认系统确实是按照预期的测试流程执行的。 这些控制措施和方法,经常需要在测试过程中向系统内插入一些与系统一起运行的代码, 在擦拭完成以后这些代码将会被删去,因此,希望把测试的实现与被测的系统分离开来。 三三三三、、、、建立架构基线的步骤建立架构基线的步骤建立架构基线的步骤建立架构基线的步骤 良好的架构必须尽早建立,技术在理论上,都没有办法通过重构等增量技术,把一个糟糕 的架构改造成一个好的架构,在实践中就更难了。事实上如果重构的成本超过了管理者所能接 受的程度,他就宁可简单的重写代码而不是重构。所以,一个良好的架构需要在建立成本很小 的时候建立起来,事实表明,优先架构会获得良好的投资回报,它减少了项目执行过程中的重 新设计和做无用功。如果已经建立了一个良好的架构,就需要持续的进行重新评估,并且做一 些必要的完善和重构。 1,,,,用例驱动的用例驱动的用例驱动的用例驱动的架构基线架构基线架构基线架构基线 1))))架构基线是一个骨架系统架构基线是一个骨架系统架构基线是一个骨架系统架构基线是一个骨架系统 架构是最终系统的一个早期版本,也称之为架构基线。架构基线是整个系统的子集,我们 称之为骨架系统骨架系统骨架系统骨架系统(skinny system )。这个骨架系统包含了项目结束时的“完整”系统所具有的模 型的一个版本,它包含了相同的子系统、组件和节点的“骨架(skeleton )”,但并非所有的“肌 肉(musculature )”都已齐全。 不管怎么说,骨架系统确实具有行为,并且是可执行的代码,可能会需要对结构和状态作 某些细微的改变,在精化阶段或者架构设计迭代结束的时候,我们就可以得到一个稳定的架构 了。 2 ))))骨架系统内包括部分最终代码骨架系统内包括部分最终代码骨架系统内包括部分最终代码骨架系统内包括部分最终代码 尽管骨架系统(架构基线)通常只包含 5%~15% 的最终代码,但他已经足够验证你所做的 关键设计了,更为重要的,你必须确认骨架系统能够成长为一个完整的系统,应该有一个书面 的架构描述文档,但现在,这个文档必须通过架构基线来验证和确认。 3 ))))重要用例确定了架构基线重要用例确定了架构基线重要用例确定了架构基线重要用例确定了架构基线 架构基线是由关键用例子集驱动建立起来的,我们称这个子集为架构重要用例,在你提取 出这些架构重要用例之前,必须尽可能收集存在的信息,以识别出系统所有的用例。这种识别 主要是对系统需要做的事情进行界定、探索和发现。当确认了与架构有关的用例以后,需要通 过讨论,确定架构的基本方案,由于架构对产品成功的重要性,大多数情况下,这个方案还需 要经过评审,然后才能进入架构设计迭代。 在这些识别出的用例中,确认哪些是最重要的,所谓“重要”,意味着它们组合在一起,可 以覆盖所有需要作出的关键决策:  演练系统的关键功能和特性。  涵盖大部分的功能性、基础结构、平台特性等方面的风险。  突出系统中一些高复杂性和高风险的部分。  是系统剩余部分的基础。 4))))对具有技术或者交互相似性的用例对具有技术或者交互相似性的用例对具有技术或者交互相似性的用例对具有技术或者交互相似性的用例,,,,可以选择一个用例作为代表可以选择一个用例作为代表可以选择一个用例作为代表可以选择一个用例作为代表 架构重要用例列表应该包含应用用例和基础结构用例,要注意对具有技术或者交互相似性 的用例,可以选择一个用例作为代表,只要解决了其中的一个用例,就可以解决其它用例了。 当挑出了架构重要用例以后,就可以分析它们当中的关键场景,通过分析用例场景,更好 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 39 - 的理解系统需要做什么以及系统的元素是如何交互的,通过对系统的理解,就可以定义和评估 架构,这个过程将不断迭代的形成一个稳定的架构。 5))))稳定的架构意稳定的架构意稳定的架构意稳定的架构意味着系统关键风险已经被解决味着系统关键风险已经被解决味着系统关键风险已经被解决味着系统关键风险已经被解决 稳定就意味着系统关键风险已经被解决,并且所做的决定可以基本上满足着手开发系统剩 余部分的需要,这个架构不仅受架构重要用例的影响,还受使用的平台、必须集成的遗留系统、 标准和方针、分布性需求、所使用的中间建和框架等等的影响。通过用例,可以评估所做的选 择是否足够,并且发现哪些方面还需要完善。 四四四四、、、、从质量属性从质量属性从质量属性从质量属性及其应对策略的视角优化及其应对策略的视角优化及其应对策略的视角优化及其应对策略的视角优化架构架构架构架构 通过从系统工程的角度分析与组织需求信息,我们已经由需求分析得到了一个框架性的架 构雏形,但那只是架构的一个大概形状,在具体进行架构设计之前,架构师必须进行架构的进 一步分析和设计,从不同的角度审视架构设计,多角度、多层次的修改架构设计方案,从而得 到一个合理的架构基线产品。 对初步的架构轮廓作第一个方面的审视,是从需求分析中仔细思考质量需求对架构的要求, 换句话说就是获取架构因素。架构分析的本质,是识别可能影响架构的因素,了解它的易变性 和优先级,并解决这些问题。其难点是,应该了解提出了什么问题,权衡这些问题,并掌握解 决影响架构重要因素的众多方法。 1,,,,架构分析需要解决的问题架构分析需要解决的问题架构分析需要解决的问题架构分析需要解决的问题 架构分析是高优先级和大影响力的活动。架构分析对如下的工作而言是有价值的:  降低遗漏系统设计核心部分的风险;  避免对低优先级的问题花费过多的精力;  为业务目标定位产品。 架构分析是在功能性需求过程中,有关识别非功能性需求的活动,这些信息对于架构设计 来说,是最值得关注的。 架构分析的一般步骤架构分析的一般步骤架构分析的一般步骤架构分析的一般步骤如下如下如下如下::::  辨识和分析影响架构的非功能性需求。  对于那些具有重要影响的需求而言,分析可选方案,并做出处理这些影响的决定,这 就是架构决策 2,,,,识别和分析架构因素识别和分析架构因素识别和分析架构因素识别和分析架构因素 1))))识别那些对架构最有影响的因素识别那些对架构最有影响的因素识别那些对架构最有影响的因素识别那些对架构最有影响的因素 任何需求对一个系统架构都有重要影响。这些影响包括可靠性、时间表、技能和成本的约 束。比如,在时间紧迫、技能有限同时资金充足的情况下,更好的办法是购买和外包,而不是 内部开发所有的组件。然而,对架构最具影响的因素,包含功能、可靠性、性能、支持性、实 现和接口。通常是非功能性属性(如可靠性和性能)决定了某个架构的独到之处,而不是功能 性需求。 2 ))))架构因素的描述架构因素的描述架构因素的描述架构因素的描述 架构分析的一个重要目标,是了解架构因素的影响、优先级和可变性(灵活性以及未来演 变的直接需要)。因此,大多数架构方法,都提倡对以下信息建立一个架构因素表。 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 40 - 因素 测量和质量场景 可变性(当前灵活性和未来演化) 因素(和其变化)对 客户的影响,架构和 其它因素 优 先 级 困难 或风 险 可靠性 --- 可恢复性 从远 程服 务失 败中 恢复。 当 远 程 服 务 失 败 的时候,侦听到远程 服务重新在线的一 分钟内,重新与之建 立联系,在产品环境 下实现正常的存储 装载。 当前灵活性:我们的 SME 认为直 到重新建立连接前,本地客户简化的 服务是可以接受的(也是可取的)。 演化:在 2 年之内,一些零售商可 能选择支付本地完全复制远程服务 的功能(如税金计算器)。可能性? 高。 对 大 规 模 设 计 影 响大。 零 售 商 确 实 不 愿 意远程服务失败,因 为这将限制或阻止 它们使用 POS 进行 销售。 高 低 …… …… …… …… 注:SME 表示主题专家。 3))))从需求文档中获取架构因素从需求文档中获取架构因素从需求文档中获取架构因素从需求文档中获取架构因素 在架构设计中,中心功能需求库就是用例,它的构想和补充规范,都是创建因素表的重要 源泉。在用例中,特殊需求、技术变化、未决问题应该被反复审核。其隐含或者清晰的架构因 素要被统一整理到补充规范里面去。 3,,,,架构因素的解析架构因素的解析架构因素的解析架构因素的解析 架构设计的技巧就是根据权衡、相互依赖关系和优先级对架构因素的解决做出合适的选择。 但这还不全面,老练的架构师具有多种领域的知识(例如:架构样式和模式、技术、产品、缺 陷和趋势),并且能把这些知识应用在它们的决定中。 1))))记录记录记录记录架构的可选方案架构的可选方案架构的可选方案架构的可选方案、、、、决定和动机决定和动机决定和动机决定和动机 几乎所有的架构方法都推荐记录,这些记录被称之为技术备忘录。包括:可选的架构方案; 决定;影响因素;显著问题;决定动机。技术备忘录描述一个重要的方面就是动机或者原理, 当架构师以后需要修改系统的时候,备忘录对理解当时的设计背后的动机极为有用。解释放弃 被选方案的理由十分重要,在将来产品进化的过程中,架构师也许需要重新考虑这些备选方案, 至少知道当初有些什么备选方案,为什么选中了其中之一。技术备忘录的格式并不重要,关键 是简单、清楚、表达信息完整。 技术备忘录技术备忘录技术备忘录技术备忘录 问题:可靠性--- 从远程服务故障中恢复 解决方案概要:通过使用查询服务实现位置透明,实现从远程到本地的故障恢复和本地服务的部分复制 架构因素架构因素架构因素架构因素::::  从远程服务中可靠恢复  从远程产品数据库的故障中可靠恢复 解决方案解决方案解决方案解决方案:::: 在服务工厂创建一个适配器…… 动机动机动机动机:::: 零售商不想停止零售活动…… 遗留问题遗留问题遗留问题遗留问题:::: 无 考虑过的备选方案考虑过的备选方案考虑过的备选方案考虑过的备选方案:::: 与远程服务厂商签订“黄金级”服务协议…… 2))))优先级优先级优先级优先级 早期要决定是否应该避免保证未来的设计,应该实事求是的考虑,哪些是将要推迟到未来 的场景,有多少代码需要改变?工作量将是多少?仔细考虑潜在的变更将有助于揭示什么是首 要考虑的重要问题。一个低耦合高内聚的产品,往往比较容易适应将来的变化,但也要仔细分 析这样付出的代价,在这个问题上,架构师的掂量往往是决定这个项目的生命线。 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 41 - 五五五五、、、、从模块划分从模块划分从模块划分从模块划分的视角优化架构的视角优化架构的视角优化架构的视角优化架构 对初步的架构轮廓作第二个方面的审视,是考虑模块化的设计问题。这也是从问题的广度 分析问题。从架构的组成单元来说,定义清楚子系统以后,下一步就是定义模块。 1,,,,模块化设计的概念模块化设计的概念模块化设计的概念模块化设计的概念 如何合理的进行模块设计呢?这里的关键是要保证模块的独立性。 模块模块模块模块::::模块是数据说明、可执行语句等程序对象的集合,是单独命名的并且可以通过名字 来访问,例如过程、函数、子程序、宏等。 模块化模块化模块化模块化::::软件被划分成独立命名和可独立访问的被称作模块的组件,每个模块完成一个子 功能,它们集成到一起可以满足问题需求。 利用模块化解决方案的注意事项利用模块化解决方案的注意事项利用模块化解决方案的注意事项利用模块化解决方案的注意事项::::  一般来说,我们倾向于每个用例定义一个模块。我们应该努力使每个模块的大小差别 在一个数量级之内。如果发现某个模块规模太大,就需要实现模块切割,然后针对这 种切割的结果,反过来修改需求分析的时候用例的表达方式。这就是由设计引发的需 求变更。  模块的大小一般以一个开发团队在一次迭代时间内能完成为好。模块切割方法与开发 成本有关。我们可以这样来思考模块化对软件工作量和成本的影响。实际的情况见下 图, 随着模块数量的增加,开发成本减低,但是系统集成的成本增加,所以最小成本 的区域在一个合适的区间。也就是说,模块并不是越多越好,只有模块数量适当的时 候,总体成本才可能下降。 2,,,,实现模块化的手段实现模块化的手段实现模块化的手段实现模块化的手段  抽象抽象抽象抽象:抽出事物的本质特性而暂时不考虑它们的细节。  信息隐蔽信息隐蔽信息隐蔽信息隐蔽:应该这样设计和确定模块,使得一个模块内包含的信息(过程和数据)对 于不需要这些信息的模块来说,是不可访问的。 模块独立性问题模块独立性问题模块独立性问题模块独立性问题::::  模块独立是指开发具有独立功能而且和其它模块之间没有过多的相互作用的模块。  模块独立的意义:功能分割,简化接口,易于多人合作开发同一软件;独立的模块易 于测试和维护。  模块独立程度的衡量标准:耦合性是对一个软件结构内不同模块间互连程度的度量。 内聚性是标志一个模块内各个处理元素彼此结合的紧密程度,理想的内聚模块只做一 件事情。 3,,,,模块化设计的一般准则模块化设计的一般准则模块化设计的一般准则模块化设计的一般准则  改进软件结构,提高模块独立性。  模块规模应该适中。大模块分解不充分;小模块使用开销大,接口复杂。 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 42 -  模块的作用范围保持在该模块的控制范围内。模块的作用范围是指该模块中一个判断 所影响的所有其它模块;模块的控制范围指该模块本身以及所有直接或间接从属于它 的模块。  力争降低模块接口的复杂程度模块接口的复杂性是引起软件错误的一个主要原因。接 口设计应该使得信息传递简单并且与模块的功能一致。  设计单入口单出口的模块,以避免内容耦合,易于理解和维护。  模块功能应该可以预测。相同的输入应该有相同的输出,否则难以理解、测试和维护。 六六六六、、、、从从从从共享共享共享共享分层结构的分层结构的分层结构的分层结构的视角优化架构视角优化架构视角优化架构视角优化架构 下面我们再从第三个方面审视架构设计,关注点在模块的缠绕缠绕缠绕缠绕和分散分散分散分散。所谓缠绕,指的是 一个模块是不是包含了多个模块不同的实现。所谓分散,一个模块的实现分散在多个不同的模 块中。解决这些缠绕和分散问题,需要使用分层结构来解决。这也是从问题的深度来分析问题 的结果。 1,,,,层模式的问题与机会层模式的问题与机会层模式的问题与机会层模式的问题与机会 在模块分割以后,就会发现有些功能块或者某些功能是共享的或者缠绕的,我们需要把这 些模块或者功能提取出来,分成若干层次,这就是层模式。层模式是构造弹性架构的基础,好 的架构几乎都是在层这个模式基础上建立起来的。分层不是目的,分层必须把分离性与易变性、 灵活性结合起来,这也是设计层模式有挑战性的问题,也是最近几年最吸引人的研究领域之一。 合理的分层也是架构师很大的一部分需要仔细设计的工作。 1))))层模式的层模式的层模式的层模式的问题问题问题问题::::  如果系统的许多部分高度的耦合,源代码的变化将波及整个系统。  如果应用逻辑与用户接口捆绑在一起,这些应用逻辑在其它不同的接口上无法重用, 也无法分布到另一个处理节点上。  如果潜在的通用技术服务或业务逻辑,与更具体的应用逻辑捆绑在一起,这些通用技 术服务或者业务逻辑无法被重用,或者分布到其它的节点,或者被不同的实现简单的 替换。  在系统的不同部分高度的耦合的情况下,难以对不同开发者清晰界定各自的工作界限。  如果高度耦合混合在系统的各个方面,则改进应用程序的功能,扩展系统,以及使用 新技术进行升级往往是艰苦和代价高昂的。 2))))解决方案解决方案解决方案解决方案: 层模式(Layers pattern )的基本思想很简单。  根据分离系统的多个具有清晰、内聚职责的设计原则,把系统大尺度的逻辑结构组织 到不同的层中,每一层都具有独立和相关的职责,使得较低的层为低级和通用的服务, 较高的层更多的为特定应用。  从较高的层到较低的层进行协作和耦合,避免从底层到高层的耦合。  层是一个大尺度的元素,通常由一些包或者子系统组装而成。层模式与逻辑架构相关, 也就是说,它描述了设计元素概念上的组织,但不是它物理上的包或者部署。层为逻 辑架构定义了一个 N 层模型,称之为分层架构(Layers Architecture ),它作为模式得 到了极为广泛的应用和引述。 3))))典型分层架构典型分层架构典型分层架构典型分层架构示例示例示例示例:::: 信息系统一般分层逻辑架构如下图所示,图中包的宽度表示的是应用范围。 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 43 - 在具体架构设计的时候,可以建立比较详细的包图,但是,并不需要面面俱到。 架构视图的核心,是展示少数值得注意的元素,或者说选择一小组有意义的元素来传达主 要的思想。 七七七七、、、、从软件复用与从软件复用与从软件复用与从软件复用与组件组件组件组件化化化化的的的的视角优化架构视角优化架构视角优化架构视角优化架构 事实上,经过从上面三个方面审视架构,我们已经建立了一个完整的而且比较良好的架构 了。但我们还需要从第四个方面在更高的层次审视我们的架构,这就是软件的复用。复用可以 大大降低后期成本,提高整个软件系统的可升级性与可维护性。我们可以考虑哪些结构可以使 用已经存在的可复用结构和产品,某些结构可以利用设计成可复用的组件已备后期使用。还需 要根据需求分析得出的易变点仔细设计产品结构,确保后期的变化不至于对产品带来太大的影 响。而复用的一个重要的手段,就是面向组件的方法。 1,,,,软件复用软件复用软件复用软件复用与系统架构与系统架构与系统架构与系统架构 1))))复用复用复用复用是指重复使用是指重复使用是指重复使用是指重复使用““““为了复用目的而设计的软件为了复用目的而设计的软件为了复用目的而设计的软件为了复用目的而设计的软件”””” 软件复用是指重复使用“为了复用目的而设计的软件”的过程。在过去的开发实践中,我 们也可能会重复使用“并非为了复用目的而设计的软件”的过程,或者在一个应用系统的不同 版本间重复使用代码的过程,这两类行为都不属于严格意义上的软件复用。 通过软件复用,在应用系统开发中可以充分地利用已有的开发成果,消除了包括分析、设 计、编码、测试等在内的许多重复劳动,从而提高了软件开发的效率,同时,通过复用高质量 的已有开发成果,避免了重新开发可能引入的错误,从而提高了软件的质量。在基于复用的软 件开发中,为复用而开发的软件架构本身就可以作为一种大粒度的、抽象级别较高的软件组件 进行复用,而且软件架构还为组件的组装提供了基础和上下文,对于成功的复用具有非常重要 的意义。 软件架构研究如何快速、可靠地用可复用组件构造系统的方式,着眼于软件系统自身的整 体结构和组件间的互联。其中主要包括:软件架构原理和风格,软件架构的描述和规范,特定 领域软件架构,组件如何向软件构架的集成机制等。 2))))从复用的角度思考系统架构从复用的角度思考系统架构从复用的角度思考系统架构从复用的角度思考系统架构 良好的软件架构提供了组件组装的基础和上下文。一个典型的软件架构是由系统中的组件、 连接和约束构成的配置格局。从这个观点看,架构决不是概要设计,架构设计本身就可以看成 一个项目,架构的结果应该是一个可执行、可验证的产品,也必须通过评审,为最终产品的复 用与可持续发展打下框架上的基础。 研究软件架构有利于发现不同系统的高层共性、保证灵活和正确的系统设计、对系统的整 体结构和全局属性进行规范约束、分析、验证和管理。将架构作为系统构造和演化的基础,可 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 44 - 以实现大规模、系统化的软件复用,这对于高效的软件工程具有非常重要的意义:  通过对软件架构的研究,有利于发现不同系统在较高级别上的共同特性;  获得正确的架构对于进行正确的系统设计非常关键;  对各种软件架构的深入了解,使得软件工程师可以根据一些原则在不同的软件架构之 间作出选择。 3 ))))软件架构是复用的基础结构软件架构是复用的基础结构软件架构是复用的基础结构软件架构是复用的基础结构 从架构的层次上表示系统,有利于系统较高级别性质的描述和分析。特别重要的是,在基 于复用的软件开发中,为复用而开发的软件架构本身就可以作为一种大粒度的、抽象级别较高 的软件组件进行复用,而且软件架构还为组件的组装提供了基础和上下文,对于成功的复用具 有非常重要的意义。 软件架构研究如何快速、可靠地用可复用组件构造系统的方式,着眼于软件系统自身的整 体结构和组件间的互联。其中主要包括:软件架构原理和风格,软件架构的描述和规范,特定 领域软件架构,组件如何向软件构架的集成机制等。 软件开发实际上是从问题域向最终解决方案逐步映射和转换的过程,而特定领域软件架构 (DSSA) 和软件架构风格(Architectural Style) 分别从问题域和软件解决方案两个方向提供了若干 经过考验的候选转换路径。 4))))特定领域软件架构特定领域软件架构特定领域软件架构特定领域软件架构((((DSSA):):):): 这是一个领域中的所有应用系统所共有的架构,是针对领域模型中的领域需求给出的解决 方案,也是识别、开发和组织特定领域可复用组件的基础。在国内外的金融、MIS、通讯和军事 等领域中都开始注意到开发特定领域的软件架构和集成框架的重要性。 5))))架构风格架构风格架构风格架构风格((((AS)))): 这是根据系统结构的组织模式确定了一组可以用于某种风格实例中的组件和连接方案,以 及它们的拓扑结构、组装规则以及局部和全局约束,从而定义了一个面向系统结构的架构家族。 软件架构风格与面向对象的设计模式或框架一样,为设计经验的复用提供了技术支持。 2,,,,面向面向面向面向组件组件组件组件的方法的方法的方法的方法 1))))组件组件组件组件需要合适的基础结构需要合适的基础结构需要合适的基础结构需要合适的基础结构 组件也称为组件,面向组件的方法包含了许多关键理论,这些关键理论解决了当今许多备 受挑剔的软件问题,这些理论包括:  组件基础设施  软件模式  软件架构  基于组件的软件开发 2))))组件组件组件组件是面向对象理念的一个变体是面向对象理念的一个变体是面向对象理念的一个变体是面向对象理念的一个变体 组件可以理解为面向对象软件技术的一种变体,它有四点原则区别于其它思想,封装、多 态、后期绑定、安全。从这个角度来说,它和面向对象是类似的。不过它取消了对于继承的强 调。在面向组件的思想里,认为继承是个紧耦合的、白盒的关系,它对大多数打包和复用来说 都是不合适的。事实上,在我们后面的讨论中,也会提到面向对象的方法中还是要优先使用组 合而不是继承,但在组件方法中则完全摒弃了继承而是调用,在组件术语里,这些调用称作“代 理”(delegation )。 3))))组件组件组件组件技术实现的关键是规范技术实现的关键是规范技术实现的关键是规范技术实现的关键是规范 实现组件技术关键是需要一个规范,这个规范应该定义封装标准,或者说是组件设计的公 共结构。理想状态这个规范应该是在行业以至全球范围内的标准,这样构建就可以在系统、企 业乃至整个软件行业中被广泛复用。组件利用组装来创建系统,在组装的过程中,可以把多个 组件结合在一起创建一个比较大的实体,如果组件之间能够匹配用户的请求和服务的规范,它 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 45 - 们就能进行交互而不需要额外的代码。 3,,,,面向面向面向面向组件组件组件组件的软件模式的软件模式的软件模式的软件模式 面向组件技术的特色在于:迅速、灵活、简洁,面向组件技术之于软件业的意义正如由生 产流水线之于工业制造,是软件业发展的必然趋势。软件业发展到今天,已经不是那种个人花 费一段时间即可完成的小软件。软件越来越复杂,时间越来越短,软件代码也从几百行到现在 的上百万行。把这些代码分解成一些组件完成,可以减少软件系统中的变化因子。 1))))面向面向面向面向组件组件组件组件方法模式方法模式方法模式方法模式 面向组件技术的思想基础在软件复用,技术基础是根据软件复用思想设计的众多组件。面 向组件将软件系统开发的重心移向如何把应用系统分解成稳定、灵活、可重用的组件和如何利 用已有组件库组装出随需而变的应用软件。 基于面向组件的架构可以描述为:系统=框架+组件+组建。框架是所有组件的支撑框架;每 个组件实现系统的每个具体功能;组建,可以视为组件的插入顺序,不同组件的组成顺序不同, 其实现的整体功能也就不同。 2))))面向面向面向面向组件组件组件组件开发的不足之开发的不足之开发的不足之开发的不足之处  系统资源耗费系统资源耗费系统资源耗费系统资源耗费::::从软件性能角度看,用面向组件技术开发的软件并不是最佳的。除了 有比较大的代码冗余外,因为它的灵活性在很大程度上是以空间和时间等为代价实现 的。  面向面向面向面向组件组件组件组件开发的风险开发的风险开发的风险开发的风险::::从细节来看,组件将组件的实现细节完全封装,如果没有好的 文档支持,有可能导致组件的使用结果不是使用者预期的。比如,组件使用者对某组 件的出错机制认识不够 4,,,,开放式系统技术开放式系统技术开放式系统技术开放式系统技术 1))))专用软件不符合统一的标准专用软件不符合统一的标准专用软件不符合统一的标准专用软件不符合统一的标准 专用软件是由单个供应商生产的不符合统一标准的产品。这些单个供应商通过版本更换来 控制软件的形式与功能。但是谁这系统越来越复杂,当一个系统建立起来以后,往往更倾向于 依赖于通用的商业软件,这种依赖往往成为内部软件复用的非常有效的形式。正是这种状态, 我们需要讨论一下开放式系统技术这个问题。 2))))通用的商业软件的质量往往超过自主开发软件通用的商业软件的质量往往超过自主开发软件通用的商业软件的质量往往超过自主开发软件通用的商业软件的质量往往超过自主开发软件 商业软件成为复用的有效形式,主要原因是规模经济的作用,通用的商业软件的质量,往往超 过终端用户自主开发能力。 3))))商业软件也可以在某个领域实现专有商业软件也可以在某个领域实现专有商业软件也可以在某个领域实现专有商业软件也可以在某个领域实现专有 商业软件也可以在某个领域内实现专有,也就是提供应用程序接口(API)为应用软件提供 服务。当软件不断升级的过程中,这些接口的复杂性可能超出用户的需要,这就需要有复杂性 的控制。 4))))由供应商组织来开发专有组件由供应商组织来开发专有组件由供应商组织来开发专有组件由供应商组织来开发专有组件,,,,由集成商实现系统集成由集成商实现系统集成由集成商实现系统集成由集成商实现系统集成 一个解决方案就是实现开放式系统技术,开放式系统技术与专有技术有根本的不同。在开 放式系统技术中,由供应商组织来开发独立于专有实现的规范,所有的供应商实现的接口都严 格的一致,并且规定了统一的术语,这样就可以是软件的生命周期得以延长,这种开放式系统 技术特别适合于面向对象的方法。 5))))配置的标准化是开放式软件的特点配置的标准化是开放式软件的特点配置的标准化是开放式软件的特点配置的标准化是开放式软件的特点 为了使商业技术能适应各种应用需求,对软件开发和安装就有一定的要求,这种要求称之为配 置(profiling ),适当的配置软件的嵌入也称为开放是软件的一个特点。 6 ))))作为集成商方面的架构师作为集成商方面的架构师作为集成商方面的架构师作为集成商方面的架构师,,,,需要专注于可扩展性需要专注于可扩展性需要专注于可扩展性需要专注于可扩展性 从架构的角度来看,不少系统结构具有大量的一对一接口和复杂的相互连接关系,这种模 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 46 - 型被称之为“烟囱”模型,当系统规模增大以后,这种关系会以平方律的速度增加,复杂性的 增加会带来相当多的问题,尤其是升级和修改越来越难以进行,而系统的可扩展性恰恰是开发 成本的重要部分。 为此,我们可以建立一个称之为对象管理器的层,用于统一协调各个对象的沟通,从可维 护性角度这是一个比较好的结构,但是在某些特别强调效率的点可以避开它。系统的架构的一 个重要原则就是对软件接口定义一个已经规划的定义,为系统集成方案提供更高的统一性,软 件的子系统部分要由应用程序接口来定义。这样,就削弱了模块之间的依赖性,这样的系统就 比较容易扩展和维护,并且支持大规模的集成。 经过从四个方面审视我们的架构,经过分析、权衡、设计和部分编码,我们就可以得到一 个稳固的架构。这个架构经过经过评审,就可以作为后期开发的基础架构。 下面我们将讨论几个专题,但讨论的时候希望研究一种思考问题的方法,从而为大家解决 更广阔的问题提供一个思维的平台。这些专题并不是独立存在,而是融合在本章所讨论的各个 阶段之中。再一次强调,方法和技术是会变化的,但优秀的思维方式是永恒的! ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 47 - 第二章 从业务架构到产品架构 软件开发需要太多的问题需要关注,当系统设计的时候,必须处理和平衡许多困难的关注 点,系统如何达到预期的功能?如何达到性能和可靠性的要求?如何处理平台特性等。为了保 证关注点的前后一致,模型驱动的开发是个很好的理念,这种理念会使整个开发变得非常有序 而且有效。 把问题分解到更小的部分,在计算机科学中被称之为关注点分离,理想情况下,希望把不 同的关注点清晰的分离到不同的模块中去,并且能够互相独立,也就说说把模块当成一个个关 注点的集合,一个个的深入研究和开发,然后再把这些软件模块组合到一起 成功的关注点分离必须尽早开始,依照涉众的关注点来收集系统的需求。软件架构设计并 不仅仅发生在项目的早期阶段,在整个项目过程中都可能迭代的考虑架构优化的问题。本章讨 论模型驱动的架构设计与恢复,我们的目标是使整个开发过程具有流畅之美,确保整个项目能 够按要求完成。为了更加清楚地表达问题,下面描述的时候利用了一个具体案例,通过这个案 例分析,我们可以更深入的理解架构设计的一些思想,而不是仅仅局限于这个案例本身。 2.1 从问题域到业务架构概念从问题域到业务架构概念从问题域到业务架构概念从问题域到业务架构概念 一一一一、、、、用创新思想构思用创新思想构思用创新思想构思用创新思想构思产品概念产品概念产品概念产品概念 我们设计任何软件产品都是为了解决客户问题,当我们面对产品设计问题的时候,我们需 要不断的问自己:为谁(Who )?解决什么问题(What )?为什么要解决这个问题(Why )? 由此可能引发一个极具创新的产品概念。对于产品创新方法,有几个观点需要我们考虑。 1,,,,把把把把软件设计的目标由输出产品转变为输出行为方式软件设计的目标由输出产品转变为输出行为方式软件设计的目标由输出产品转变为输出行为方式软件设计的目标由输出产品转变为输出行为方式 计算机科学带来了最近 30 年每十年一次的革命性变化,它颠覆了行业格局、改变了人类生 活、改变了文明历史的走向。作为这其中最重要的软件产品设计者,我们往往会问自己:到底 什么是好产品,什么是伟大的产品呢?一般认为:有 focus (专注)、能鲜明而独特地满足用户 需求的产品就是好产品,有 vision (愿景)、能引领或者创造用户需求的产品就是伟大的产品。 换句话说:仅仅满足客户需求是平庸公司所为,引导客户需求才是高手之道,因为这样才可能 构建出名垂青史的伟大产品。所以,伟大产品的设计最重要的是树立前瞻愿景,让我们的产品 能够创造或改变一种生活或者工作方式,让目标客户离不开它。为了达到这个目的,我们软件 设计的目标也应该由输出产品转变为输出行为方式。 2,,,,创新需要创新需要创新需要创新需要关注用户体验关注用户体验关注用户体验关注用户体验 我们如果仔细观察最近几年软件世界都发生了什么,就会发现人们并不是把一个又一个新 技术抛到客户面前,而是尽力的利用原有技术,反复精化优化,在应用层面提供丰富多彩的新 概念,其中一个重要的软件设计方法,就是我们要充分关注用户体验,因为用户体验是产品之 魂,也是一个伟大产品最重要的要素。 研究产品用户体验是个很复杂的问题,而且真正能做好这一点的企业并不很多。用户体验 不是靠着震撼性技术创新,而是尽可能把众多不被重视的细节做好,就是说“重要的不是你能 实现什么,而是你怎么样来实现它”。 糟糕的用户体验很重要的特点就是功能浪费。一个系统中有很多闲置的功能。例如一款手 机有的人用了一年也未必真正清楚自己的手机到底拥有哪些功能。现代手机的三大功能包括: 网页浏览和邮件、视频音频播放、电话和短信,把这三大功能整合在一起的产品比比皆是,设 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 48 - 想一下,你如何做一个和别人不一样的产品呢? 好的产品构想已经不是仅仅要实现这三大功能,而是要创作一种新的应用方式,使用户以 更简单更快乐的方式来操作这些功能?因此我们需要考虑产品能不能简化操作,产品的操作能 不能极其自然、便利、充满快感,这往往会成为优秀产品的灵魂。例如在手机市场激烈竞争的 今天,各个品牌的硬件水平差异一般不会太大,但是为什么苹果一贯保持了用户体验的领先? 诺基亚硬件水平一直并不拔尖,但其菜单设计的合理度为什么有口皆碑? 进一步研究,我们还会发现用户体验会往往成为一种品牌特征而存在。而用户体验又可以 分为三种层次,也就是说:基于物质的体验、基于情感的体验、基于环境的体验: 1))))基于物质的体验基于物质的体验基于物质的体验基于物质的体验 物质体验是基于一个产品和服务的核心功能或核心物理价值而产生,对于软件产品来说, 包括价格、开发过程的标准化、产品和服务的功能与性能优势、产品的质量属性、技术优势、 相关配套产品的成熟度、安装与售后服务等。 大部分用户将依靠这些信息做出理性的决策,所追求的是产品的物质利益。而且在这个范 畴大部分用户从价格上来说都有趋低趋势,也就是追求价格最低而质量最好的同类产品,因为 这些产品基本上都是同质化的,没有什么本质差别。也就是说物质体验决定了这个产品所必须 具备的特质,但并不会给开发方带来很大的价格优势。 2))))基于情感的体验基于情感的体验基于情感的体验基于情感的体验 情感体验是基于产品引起的精神愉悦及情感方面的价值,包括人性化需求、对员工工作方 法和工作模式的关注;对于企业客户应用这个产品所带来的附加感觉;对于企业品牌和消费层 次的表达;对于探索未知、挑战自我、追求完美的需求等。 这种对于产品带来感觉的追求,形成了用户体验的第二层次,这也是产品最具差异性的东 西,或者说这方面做得越好,产品的用户满意度就可能越高,关注这方面的用户体验就有可能 给产品带来相当大的价格优势。 3))))基于环境的体验基于环境的体验基于环境的体验基于环境的体验 环境体验是基于产品环境及外界刺激、购买时的整合体验、互动的个性化的体验功能与体 验价值,使用户产生蒙太奇般升华的兴奋感。这种体验是当一个人达到情绪、体力、智力甚至 是精神的某一特定水平时,他意识中产生的美好感觉。它是主体用户对客体环境的刺激产生的 内在反应,具有很大的个体性、主观性和不确定性。 例如我们会发现很多顾客愿意花更多的钱购买一种优雅的格调、浪漫的氛围,而并不关注 功能本身的内在价值。这种用户体验上的兴奋感,将会给产品提供无可比拟的竞争优势,关注 这方面的用户体验就有可能给产品带来巨大的价格优势。 4))))构思产品的最高境界构思产品的最高境界构思产品的最高境界构思产品的最高境界是什么是什么是什么是什么???? 所以作为一个担负构思产品的架构师,必须克服“技术钟爱”情结或是“产品偏执”情结, 不要陷到技术和产品里面去就技术谈技术、就产品谈产品的孤芳自赏。应该用“做产业”的思 维做产品,产品竞争的层次是产业价值链、企业战略和商业模式。我们需要关注行业流程,洞 察产业发展的大势,引领或创造客户需求,整合行业价值链,思维方式要达到比较高的层次。 事实上我们构思产品的最高境界,就是要用对客户充满爱的感觉来设计产品。横向的例子 是千手观音,大爱演绎、感天动地。又如工业时代的福特 T 型车(“让每一个工薪阶层都开上车”), PC 时代的 Windows (“让所有的人都能简单的使用电脑”),互联网时代 Google (“让所有的困惑 立刻解决”),正是这些光荣与梦想才创造了影响一个时代的伟大产品。 构思软件产品并不是从程序到程序的过程,而是需要对人和人性有深刻的理解。我们应该 理解人的生活需要渴望,渴望需要知识来支撑,知识需要工作来实现,而工作又会产生空虚, 除非有了爱;当带着爱来工作的时候,人们就会觉得这一切都是那么快乐。如果一个设计师对 用户没有爱,我不相信会设计出真正被用户欢迎的产品来的。 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 49 - 3,,,,关注用户体验就需要理解用户心理关注用户体验就需要理解用户心理关注用户体验就需要理解用户心理关注用户体验就需要理解用户心理 如果我们认可在新产品构思中,用户体验十分重要,那么我们就应该理解,不同的社会和 文化背景中用户需求是不一样的,也就是说我们必须理解用户心理,并且在理解用户心理的基 础上来创建伟大的产品,下面还是以我们常见的手机作为例子来思考: 手机在中国意味着什么?中国手机的核心词是“时尚”。中国的厂商,利用外来的技术,只 是改变时尚的面孔来迎合消费者就取得了成功。所以在中国消费者心目中,手机中看是非常重 要的。朋友买了一款新的手机,一定在饭桌上向你炫耀。中国的手机变成社交、炫耀的“面子” 产品,变成追求款式的东西。 但是我们发现在欧美市场,手机只是上班用的通讯工具而已。当我们看到欧美消费者手上 拿着大而土的手机时,你不要奇怪,因为下班以后人们一般不用手机的。正是在不同文化背景 下对同一种产品的不同需求,使手机在不同地域的设计重点会很不相同,这就需要在构思产品 的时候仔细思索、细细品味。 再比如我们要设计一款网游,我们就需要思考,我们到底在模拟现实中的什么状态呢?或 者我们用户的心理状态是什么呢?其实网游表面上打来打去的,实际上是在模拟一个穷光蛋白 手起家直至暴富的过程:从贫穷起家,出奇制胜,但是后来有大把金钱以后,性格上就充满好 胜、虚荣和斗富性格。如果我们认可这部分人在社会中是少数,好,那么我们的设计就着手约 束高手中有钱人的比例,也就是说即使有钱也不可能买到所有装备,除非出天价,99% 的人要 靠自己修练得到装备。但是游戏规则的背后还是金钱万能,装备价格与杀伤力成绝对正比。 当装备好到一定程度以后,则一夫当关,万夫莫开,玩家由此追求到了终极快感:将众人 踩在脚下,要做千秋万代、一统江湖。就好比那些暴发户,到一定地步花多少钱无所谓,就是 要享受这种号令四方、一呼百诺的快感,网游的用户群就定位成这样的人,在真实世界做不到 那么就在虚拟世界中体验。所以好的网游的设计需要对社会有深刻理解,需要对社会中这部分 人群的心理状态有了解,这同样是一种应用层面的创新。 4,,,,软件软件软件软件设计设计设计设计需要关注需要关注需要关注需要关注应用层面创新应用层面创新应用层面创新应用层面创新 企业的生命在于创新,谈到创新,我们现在很多时候还是把思考点放在使用什么技术上, 或者称之为技术创新,毫无疑义技术创新是重要的。但是,如果认为研发出了一种新技术就给 产品注入了新的生命,那就有失偏颇了。让我们看看周围的世界,并不是每个人要活着都需要 自己种粮食吃(小农经济思维恐怕应该过时了),也不是所有从事科学技术的人都需要研究一套 与牛顿-莱布尼兹不一样的微积分学,我们一直在使用别人的成果。所以,我们认为一个软件工 程学家充分使用人类的已有知识和经验,来进行应用层面的发明创造是一件很了不起的事情。 按照商业理论和常识,为了是产品在用户体验上做得出色,就需要对市场调查做得非常细 致。但很多情况正好相反,一些高明的设计并不特别看重用户想要什么,而是去创造那些他们 需要但表达不出来的东西,这靠的是一种思考力。 所以一说到创新,就感觉这好像是高不可攀阳春白雪的东西,但事实上我们国内目前最缺 的,就是那种在应用层面创新的能力和意识。下面我们通过一个案例,来研究在一个特定场景 下设计一个产品需要考虑哪些问题,以及相应的产品架构设计过程。 二二二二、、、、由问题分析建立业务架构概念由问题分析建立业务架构概念由问题分析建立业务架构概念由问题分析建立业务架构概念 1,,,,案例背景案例背景案例背景案例背景 在机械设计行业,PDM(产品数据管理系统 Product Data Management )是用来管理所有与 产品相关信息(包括零件信息、配置、文档、CAD 文件、结构、权限信息等)和所有与产品相 关过程(包括过程定义和管理)的技术。下面我们将在一个特定背景下研究 PDM 产品选型方法、 需求分析方法、数据模型建立方法、安全问题研究方法、数据加密实现技术方法、软件架构设 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 50 - 计方法等方面问题,特别是体验创新思维的应用方法。我们需要认识到,盲目的采用某种新技 术并不意味着创新。软件工程领域的创新应该更多的在业务方法中寻求突破,需要在新的环境 下利用信息系统给客户提供全新的行为方式。 本案例项目的用户背景是某“机械设计研究所”,该所具有悠久的传统和成就,历史上该所 在管理和设计模式上采用传统的层次化垂直结构,利用这种结构打造了一个具有固定业务、确 定交互、可以重复执行的高效企业模型,在过去情况下,这个模型是高效率的也是正确的。 但是近年以来,随着用户对产品更新换代的要求越来越快、质量要求越来越高、竞争日益 剧烈、外部压力日益增长,迫使该所在管理模型上需要重新定位,打碎长久以来形成的垂直结 构,其产品需要具有多样性、弹性和专业性,逐步相成一种趋向于水平集成的业务模型。这就 形成了企业重构的趋势。 这种趋势,造成了一种企业业务模型的解构趋势,也就是各个单位将根据自己的能力进行 业务上的专业化分工。就可以让一个企业主要专注于自己的核心业务。这一核心业务表现了其 主要的业务专长、发展方向和业务策略。核心业务以外的任务将外包给第三方来提供实际的支 援和交付,每个第三方再将重点放在提高自身的核心服务上。该所认为,这种由业务伙伴、供 应商和客户形成的更多合作与互动,将会使他们向新的业务空间发展,并以更快的速度和更高 的质量,为客户提供更加先进的设计和产品。 2,,,,合作方协同设计离不开有效的合作方协同设计离不开有效的合作方协同设计离不开有效的合作方协同设计离不开有效的 IT 系统系统系统系统 该所决定以某型产品的设计为基础进行转型试点,他们选定三家具有资质的异地设计单位 作为合作方(我们暂且简称为北京方、上海方和广州方,这种称呼主要表达的是异地,而不一 定就是这个地名),利用地域和知识优势,充分利用当地资源来设计相关部件,而“机械设计研 究所”负责项目的整体设计、系统集成、过程管理和监控等工作,其简化的工作模型如下图所 示,这个模型被称之为合作方协同设计 PCD(Partners Cooperate Design ) 但是,这个工作模型在一开始就遭遇到了很大的困难,主要表现在: 1))))设计变更设计变更设计变更设计变更造成协调工作量很大造成协调工作量很大造成协调工作量很大造成协调工作量很大 由于新产品设计过程中,设计变更和新的构思不可避免,造成机械设计研究所与合作单位 协调任务非常重,特别是在产品发生设计变更的时候,协调的难度已经超出了人能承受的范围。 2))))合作方处于异地管理难度大合作方处于异地管理难度大合作方处于异地管理难度大合作方处于异地管理难度大 由于各个合作方是处于遥远的异地,项目管理上的难度很大,里程碑的设制不可能很密, 派人到当地进行里程碑检查的成本相当高,迫使主设计方减少里程碑数目,甚至大大简化检查 内容。但是对于带有强烈创新色彩的新产品来说,设计上的不断修改是正常的,结果往往一个 问题已经非常严重了才被发现,频繁的返工造成更大的经济损失。 3))))合作方之间的协调更为困难合作方之间的协调更为困难合作方之间的协调更为困难合作方之间的协调更为困难 由于设计过程中各个合作方需要大量的协调,不但主设计方与合作方需要协调,各个合作 方相互之间也需要协调。在产品比较简单的时候这种协调问题可能问题不大,但对于如此复杂 和创新的产品,合作方之间的协调几乎不可能。 4))))驻地代表无法解决专业问题驻地代表无法解决专业问题驻地代表无法解决专业问题驻地代表无法解决专业问题 为了解决这个问题,机械设计研究决定向各个合作方派出驻地代表,但是,由于设计协调 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 51 - 需要非常专业的知识,还需要有对某些问题进行权衡和决定的权利,派出的驻地代表知识深度 广度不可能具备相应的能力,在决定上也没有相应的权限。 这些问题,在本地本单位内自上而下管理结构中并不难解决,但是在这种异地合作关系中, 特别是在过程中可能会发生设计变更的环境下,却成为这个模式得以成功的最大绊脚石。现在 的问题是,在互联网如此发达的现代社会中,如果还采用古老的人对人直接管理方法,也就是 说管理方法与业务模式是不匹配的,为了解决这个问题,首要的任务是建立一套符合目前这种 业务模式的信息系统,这成为新的合作方协同设计模式得以成功的关键。 3,,,,建立建立建立建立 PDM 信息系统要求信息系统要求信息系统要求信息系统要求 “机械设计研究所”作为一个大型设计单位,已经成功地把 PDM 用到产品设计管理中,该 系统把与产品设计相关的信息与过程集成在一起,将产品从概念设计、工程分析、结构设计、 详细设计、工艺设计、制造以及评审的整个设计生命周期内的所有数据,按一定的模式加以定 义、组织和管理,使产品数据在整个生命周期内保持一致和共享,为企业设计和生产构筑一个 并行产品开发和管理的环境。 但是,该所现有的 PDM 系统针对的是当初封闭的单位内设计管理模式,无法应用于异地的 合作方协调设计环境中,所以,该所要求把原来的系统进行扩展,在原来的系统上增加合作方 协同设计能力,搭建基于互联网的与合作方协同沟通平台,让部件设计合作方在早期就介入产 品的研发过程,以缩短主要设计部门和合作方的沟通时间,提高合作方在新产品设计中的响应 能力,实现各方共赢的局面。 三三三三、、、、通过调研明确用户目标通过调研明确用户目标通过调研明确用户目标通过调研明确用户目标 1,,,,对合作单位对合作单位对合作单位对合作单位应用信息系统应用信息系统应用信息系统应用信息系统状况状况状况状况的调研的调研的调研的调研 根据调研,我们发现“机械设计研究所”以及与它合作的三家单位,都是设计功底深厚, 在国内某一专业领域享有声誉的大单位,特别是在合作方单位,除了与“机械设计研究所”合 作的项目外,还与其他单位有很多项合作,内部管理也很严谨与先进。 四个单位在设计与生产管理上都已经不同程度实现了信息化,但是四家单位情况不同,信 息系统的概念、应用重点以及业务流程也不相同,各自系统的平台、使用语言以及数据库型号 都不一样,我们归纳出的各个单位应用信息系统的特点如下图所示。 由于各个合作方历史不同,IT 系统的演化路径不同。工作重点和企业文化也不相同,出现 这种巨大的差异是正常的。问题是在这样的背景下我们如何合理的建立设计方案,把四个完全 不同的体系整合在一起,实现异地协同设计呢? 2,,,,合作方合作方合作方合作方协同设计业务流程调研协同设计业务流程调研协同设计业务流程调研协同设计业务流程调研 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 52 - 在进行具体的 IT 产品设计之初,认真地研究一下它需要处理的业务流程是十分必要的,这 也是构思产品必要的基础。合作方协同设计(PCD)业务流程如下: 在项目的初始阶段的活动具体为: 1)企业首先定义产品开发守则 2)考查、邀请于选定合作方 3)开发进度、设计要求、监控模式提交给合作方 4)合作方接受开发进度、设计要求等信息 5)合作方提交相关部件的具体开发进度表 6)企业获取各合作方的具体开发进度表 7)企业把部分相关图纸和明细发布给相关合作方 8)合作方获取图纸和明细 在项目的监控阶段活动具体为: 1)在里程碑点,企业提出获取合作方部件相关图纸和明细要求 2)合作方把部件相关图纸和明细发布给企业 3)企业获取合作方部件相关图纸和明细 4)此后进行在线讨论 5)确认后,企业把阶段性图纸和明细检入 PDM 在发生设计变更的时候活动具体为: 1)如果发生设计变更,将启动变更流程。 2)企业把变更通知、图纸和明细通知合作方 3)合作方获取变更通知、图纸和明细 4)合作方提供反馈意见,或者确认已经发布的通知 5)企业获取合作方的反馈意见 其中关于设计变更可能是随时可能出现的子流程(但是应该争取变更点与里程碑点重合), 而其他是以此里程碑为节点,循环往复,直到最后整体设计达到要求。 由于项目的敏感性以及新产品对未来企业战略规划的重要性,虽然可以使用 Internet 系统, 但需要加强应用系统的安全性和数据传输安全性的设计,确保即使发生传输过程中的截获,也 不会造成项目核心知识的泄漏。 四四四四、、、、项目总体概念性架构的确定项目总体概念性架构的确定项目总体概念性架构的确定项目总体概念性架构的确定 1,,,,架构架构架构架构整体整体整体整体方案的选定方案的选定方案的选定方案的选定 在分析清楚业务模型的基础之上,我们力图寻找一种最合适的架构形式。目前常用的 PDM 系统架构形式包括客户/服务(C/S)架构、浏览器/服务器(B/S)架构等,但是这些架构形式无 法满足本项目的要求。本项目要求多个合作方提供与协同设计相关的设计数据服务,而本 PDM 系统需要综合所有的数据服务,形成统一的数据总线(Data Bus )。所以本项目所采用的整体架 构将采用基于 Web Services 的 PDM 系统。 Web Service 是把方法封装成单个实体且发布到网络上的功能集合。Web Service 本质上是放 置于 Web 站点上的可重用组件。Web Service 可以分散于 Web 的各个地方,通过互相调用以协 同完成业务活动。在 Web Service 的体系中,应用系统被分割为高内聚、弱耦合的单个的服务, 可以通过 Web 被调用和访问。 2,,,,基于基于基于基于 Web Services 的的的的 PDM 系统架构系统架构系统架构系统架构 1))))协调不同的服务领域间的异构数据模型协调不同的服务领域间的异构数据模型协调不同的服务领域间的异构数据模型协调不同的服务领域间的异构数据模型 PDM 系统整体采用基于 Web Services 的架构形式,有利于协调不同的服务领域间的异构数 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 53 - 据模型。本 PDM 系统的合作方协同设计是一些领域相关的服务集合。所以在这个服务领域中的 所有服务应该采用一个通用的数据模型进行通讯。 但是,由于合作方业务的复杂性,他们的数据服务将是来自不同服务领域的数据服务,由 于不同领域模型间的语义与结构之间存在巨大差异。采用基于 Web Services 的 PDM 系统,将有 利于协调不同的服务领域间的异构数据模型,使整个产品具备开放性、兼容性和互操作性。 本项目 Web Service 所提供的服务,是把各个合作方本身异构的相关数据,通过 Web Service 中的 XML 层,转换为各个系统都能理解的 XML 形式。然后由 PDM 系统进行数据集成,这样 就形成一个在项目内共享的数据总线。在这里,WSDL 在服务契约的定义担任了关键角色。通 过转换代理,在发送时,本地数据被转换为 XML 形式,而接收消息时,XML 被转换为本地数 据格式。 而由于各个合作方的数据服务是独立的而且是异构的,采用 Web Services 技术就能够提供 一种快速集成方案,项目将关注共享数据与可重用的服务。 2))))对于传输效率的考虑对于传输效率的考虑对于传输效率的考虑对于传输效率的考虑 我们有理由认为采用 XML 格式可能会有效率问题,但是该系统大量的工作是用于设计过程 控制与管理,本身的设计过程都使用基于内部的处于封闭状态的 PDM 系统,因此大部分相关数 据的传输速率应该在可接受范围内的。至于少量大型工艺文件,考虑到合作方协同设计主要是 在里程碑点上的传输,而不是日常的频繁传输,所以速率问题应该不大。 3))))总体概念性架构总体概念性架构总体概念性架构总体概念性架构 综合上面个方面的考虑,我们就可以设计出这个产品的概念性架构。在这个架构中,我们 希望合作方本身内部工作模型并不要发生改变,合作方的 Web Service 服务器只是为了建立数据 总线的通讯,与合作方相关的数据区将直接与 Web Service 服务器有关应用程序相连。其他的数 据将与这个服务器绝缘,以保护本地数据的安全。 与合作设计有关的业务,可以通过专门设计的 GUI Web 客户端程序来完成,直接应用设置 在机械设计研究所的 Web 服务器功能,而不需要在每个服务方设置过分复杂的应用程序。应用 GUI Web 客户端程序主要因为 PDM 某些应用可能比较复杂(比如工艺图纸显示,复杂业务流 程的定义与跟踪等),但是对于某些简单数据的人机交互,也可以直接使用浏览器,因此设计中 需要把这两种应用模型分开。我们设计的总体概念性架构如下图所示。 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 54 - 4))))识别需要解决的关键问题识别需要解决的关键问题识别需要解决的关键问题识别需要解决的关键问题 在设计的初始方案中,除了基本的 PDM 系统设计的内容外,还需要有四个关键问题需要解 决:第一,这个系统如何来处理以协同设计为特征的业务模型工作流呢?第二,在 PDM 处理工 艺图纸的时候,由于文件体积庞大,所以需要重点解决文件存放结构与调用方法的问题。第三, 在互联网上传输信息具有天生的不安全性,如何保护各合作单位的商业秘密呢?这是每个人都 会关心的问题,也是这个设计本身需要重点考虑的问题。第四,Web Service 技术到底如何实现 呢?实现过程中到底需要处理哪些问题呢? 对于具有合作方协同设计的 Web Services 的 PDM 系统,还提出如下基本设计要求:  加强安全机制的设计:以互联网为整个设计的基础设施,但要加强安全机制的设计。  原有的 PDM 系统互联:该系统是以机械设计研究所为中心建立 PDM 系统扩展功能, 应该与原有的 PDM 系统互联。  保证合作方远程调用数据和功能:其它合作方,设置单独的 Web Service 组件(如果原 来为 C/S 架构,则设置单独的 Web 服务器),保证对数据和功能实现远程调用。  沟通作用:合作方相互之间也可以在必要的情况下通过 Web Service 相互沟通。  保证商业秘密的安全性:各合作方的 Web Service 组件只处理与合作项目相关的数据和 文件,其它与此不相关的信息则完全绝缘,确保合作方商业秘密的安全性。  模块化:该系统是模块化的,应该很容易组合新的服务和业务模式。  不需改变原来内部的工作方式:所有传输数据协议一律采用 XML,确保跨平台跨语言 应用,不需要改变合作方内部的任何工作方式。 在选取 PDM 系统架构方案的时候,并不能盲目应用某些看似比较先进的技术,更不能认为 只要使用了某种先进的技术就一定能达到设计目的。而是需要对业务特征进行仔细评价,根据 业务需要选取合理的技术方案,并且尽可能在企业现有系统下扩充能力,制定合理的路线图, 分步骤增量式地构建系统,才能最终确保项目获得成功,并且使用户方获得最大的投资回报。 2.2 从需求分析到架构设计从需求分析到架构设计从需求分析到架构设计从需求分析到架构设计 一一一一、、、、从系统的角度描述需求从系统的角度描述需求从系统的角度描述需求从系统的角度描述需求 本项目要求在 PDM 系统的基础上,要求利用了 Web Services 技术进一步实现分布式异构环 境下合作方协同设计,因此,对项目提出了新的要求。根据需要,本产品主要需求如下。 1,,,,实现协同模式下的产品项目管理与过程管理实现协同模式下的产品项目管理与过程管理实现协同模式下的产品项目管理与过程管理实现协同模式下的产品项目管理与过程管理 本项目需要构建专门的协同设计管理模块,其基本功能需求如下: R1-1)产品应该具备项目的创建、修改、查询、审批、统计等能力。 R1-2)产品应该提供项目人员和组织机构的定义和修改,并能够对合作方进行适当的监控。 R1-3)产品应该在对项目人员和组织机构有效管理的基础上,实现对各类人员角色的指派。 R1-4)产品应该在人员角色确定后,规定其对产品数据操作权限。 R1-5)产品应该具备协同项目开发过程定义的能力。 R1-6)产品应该保证用户能够自定义过程单元,并且能够把这些单元连结成适当的工作流, 能定义工作流每个单元完成后需要提交的设计对象(部件、零件、文档等)。 R1-7)产品应该具备过程管理的手段,能够建立任务列表,并记录每个列表的执行信息。 工作流程管理的主要功能包括: R1-8)产品应该具备协同项目开发任务定义与过程监控能力。 R1-9)产品应该有效交互信息,能够根据工作进展情况,向有关人员提供相关信息和解决 方案。 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 55 - 2,,,,实现工程图档及设计文档的有效管理与检索实现工程图档及设计文档的有效管理与检索实现工程图档及设计文档的有效管理与检索实现工程图档及设计文档的有效管理与检索 R2-1)产品应该在数据库中建立合理的工程图档管理数据结构。 R2-2)产品应该组件有效的工程图档管理功能。 R2-3)产品应该根据用户定义的信息项完成图档基本信息的录入与编辑。 R2-4)产品应该建立图档基本信息与图档文件的清晰的连接关系。 R2-5)产品应该实现图档文件的批量入库和交互入库方式。 R2-6)产品对于指定的图档文件从数据库中释放,并传送到客户端进行操作,应该支持 Check-in/Check-out 功能,以保证文件的完整性和一致性。 R2-7)产品显示模块应该可以浏览和显示多种常见格式的文件。 R2-8)产品应该为用户提供快速、方便的批注功能,支持使用各种用于批注的实体(复线、 指引文字和云状线等)。批注文件可存放在独立的文件中,充分保护原始文件。 3,,,,实现产品设计与图档的配置管理实现产品设计与图档的配置管理实现产品设计与图档的配置管理实现产品设计与图档的配置管理与变更管理与变更管理与变更管理与变更管理 R3-1)产品应该建立产品结构树,该树的节点与文档对象应该有清晰的可视化关系。 R3-2)产品应该对设计文档与图档的版本演化有管理能力与可视化表达能力。 R3-3)产品应该针对设计中的不同批次或同一批次的不同阶段(如设计、工艺、制造与组 装等),生成的产品结构信息,生成不同的视图。 R3-4)产品应该能够查询与浏览品零部件之间的层次关系,并用图视方式显示产品各种配 置信息的变化,包括结构的改变、各种版本的演化。 R3-5)配置管理与变更管理应该能够对产品的各版本数据提供冻结、释放、复制等操作。 R3-6)产品对文档或图纸进行编码规则应该符合企业编码规则,这个规则在系统中应该是 可以订制的。 4 ,,,,产品的非功能需求产品的非功能需求产品的非功能需求产品的非功能需求 R4-1)产品的安全性应该保证权限控制的有效和安全。 R4-2)敏感数据在网络上传输的时候,应该保证即使发生截获也不应该被解读。 R4-3)产品的易使用性要好,尽可能不要改变各个合作单位原来的工作方式 R4-4)产品对于不属于合作伙伴协作设计的内容,不应该在系统中出现,以确保各个企业 的商业秘密的安全。 二二二二、、、、通过用例场景建立行为模型通过用例场景建立行为模型通过用例场景建立行为模型通过用例场景建立行为模型 产品用例的细化分析,首先应该从系统的角度研究外部参与者与我们将要创建的软件系统 之间如何交互。用例场景是通过一个清晰的,易被用户理解的事件流来说明一个用例的行为。 在事件流中包括用例何时开始和结束,用例何时和参与者交互,什么对象被交互以及该行为的 基本流和备选流。基本的场景描述文档的内容如下:  用例名用例名用例名用例名:这是唯一的名称,应该反映用例的主要工作。  主要参与者主要参与者主要参与者主要参与者::::请求系统提供一项服务的主要项目相关人员。  描述描述描述描述:简要描述该使用案例的作用(可以不写出)。  前置条件前置条件前置条件前置条件:开始使用该用例之前必须满足的系统和环境的状态和条件(必要条件而不 是充分条件)。  主事件主事件主事件主事件流流流流:用例的正常流程(事件流是关注系统干什么,而不是怎么干),也称为用例 的路径。可能包含有基本路径、备选路径、异常路径、成功路径和失败路径等几个方 面的内容。 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 56 -  扩展扩展扩展扩展流流流流:用例的非正常流程,如错误流程。  后置条件后置条件后置条件后置条件:用例成功结束后系统应该具备的状态和条件(但不是每个用例都有后置条 件)。 关于前置条件和后置条件,可以参考下面一些指导方针。  前置后置条件所描述的状态应该是用户能观察到的。可观察的状态例如“用户已在系 统注册”或“用户已打开文档”等。  前置条件是用例启动时候的约束,但不是用例启动时候的事件。  虽然你可以在某一个用例层次上定义前置和后置条件,但它们不是只限于一个流程。  无论执行哪个扩展流,后置条件都应该为假,它仅对主事件流成为真。比如在后置条 件中这样概括:“动作完成,或者出现错误,动作未能执行”,而不是“动作已经完成”。  后置条件对描述用例来说是重要的工具,你首先可以定义用例要获得什么后置条件, 然后再考虑如何达成这个条件(所需要的事件流程)。 下面是一个“酒店管理系统”的“预订房间”用例的简单例子。 用例名用例名用例名用例名: 预定房间 用例用例用例用例层次层次层次层次 用例用例用例用例 ID: 用户目标 主要主要主要主要参与者参与者参与者参与者: 客户 描述描述描述描述:::: 该用例描述客户如何预定一个房间 前置条件前置条件前置条件前置条件:::: 客户已经登录到系统 后置条件后置条件后置条件后置条件:::: 成功预定之后,创建一个新的一顶记录,特定时间的可用房间数将减少,如 果预定失败,数据库不会发生任何改变。 主主主主事件流事件流事件流事件流: 1, 客户选择预定一个房间。 2, 系统显示酒店拥有的房间类型,以及它们的收费标准。 3, 客户核对房间的收费(S1 )。 4, 客户对选择的房间提出预定。 5, 系统在数据库减少这个类型可预定房间的数目。 6, 系统基于提供的详细资料创建一个新的预定。 7, 系统显示预定确认号以及入住登记说明。 8, 用例结束。 扩展扩展扩展扩展流流流流:::: 5a. 重复预定重复预定重复预定重复预定 如果第 5 步存在相同的预定(同样的名字、e-mail 、入住时间、离开时间) 则系统显示原有的预定,并询问客户是否进行新的预定。 5a1,如果客户想继续,则系统开始新的预定,用例重新开始。 5a2,如果用户说明预定是重复的,用例结束。 5b…… 子事件流子事件流子事件流子事件流:::: S1 ,核定房间收费核定房间收费核定房间收费核定房间收费。 S1-1,客户选择需要的房间类型,并说明将停留的时间。 S1-2,系统根据给出的周期,计算出总的费用并告知用户。 特别需求特别需求特别需求特别需求:::: 系统必须能处理 5 个并发预定,每个预定所花时间不超过 20 秒。 三三三三、、、、用例结构化及其文用例结构化及其文用例结构化及其文用例结构化及其文档描述档描述档描述档描述 对于大多数用户和系统描述来说,上面的细化步骤再充分不过了,多数情况可以合理的确 定、精化主流程和替换流程,确定前置和后置条件,为系统提供了充分而广泛地描述。但是随 着应用的复杂性不断的增长和演变,就可能会遇到用例之间的结构化关系,下面我们来讨论有 关问题。 用例通过扩展、包含、泛化等关系作为对关注点之间进行建模的手段,称之为用例的结构 化,比如如下图所示的情况,下面讨论这种结构化用例场景的描述规则。在用例建模的时候, 不同用例之间的关系如下:  包含包含包含包含((((include )))):一个用例的实现使用另一个用例的实现。其图形表示方法为在用例图 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 57 - 上用一条从基本用例指向包含用例的虚箭线表示,并在线上标注购造型<> :  泛化泛化泛化泛化((((generalization )))):一个用例的实现从另一个抽象的用例继承。  扩展扩展扩展扩展((((extend )))):扩展关联的基本含义与泛化关联类似,但是对于扩展用例有更多的规 则,即基本的用例必须声明若干新的规则--- 扩展点(Extension Points ),扩展用例只能 在这些扩展点上增加新的行为并且基本用例不需要了解扩展用例的如何细节。它们之 间存在着扩展关系。如果特定的条件发生,扩展用例的行为才能执行。其图形表示同 样用虚箭线表示,并在线上标注购造型<> : 1,,,,包含包含包含包含((((imclude )))) 为了确保产品设计的品质,产品开发的可追踪性与回朔性要好,因此在用例设计的时候, 我们希望关注点相互独立,其重要性也不能相互比较,这就是所谓对等关注点。例如在酒店管 理系统中,预订房间(Reserve Room )、登记入住(Check In Customer )、结账离开(Check Out Customer )都是对等关注点。 随着用例的细化和精化,团队会发现某些用户行为会在多个地方重复出现,事实上,很大 一部分系统功能在多个地方重复出现时有可能的,比如输入口令进行用户确认。显然对相同的 用户行为出现冗余的文档是不合适的,这就可以使用包含关系。包含的目的是在其它用例中引 入用例。 作为分析师,我们应该注意到问题越是前期发现和解决,总的风险就越小。所以设计师希 望从分析的时候就做到使关注点相互分离。在分析的时候,对于不同用例的相似步骤,可以把 这些公共事件抽取出来,放在被包含的用例中,其它用例可以引用这些被包含用例中的事件流。 例如,“预定房间”和“登记入住”都需要参与者核对房间的可用性、以及查询有没有可用 的房间等,这可以增加一个“核对房间清单(Check Room Details )”的包含用例。 它的业务过程如下。 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 58 - 注意,大部分对子用例的调用是以包含形式表现,这使得开发团队很容易掌握,因为这类 似于软件中的子程序,如果用的合理,包含关系能简化开发和维护活动,也是很重要的一种结 构。 2,,,,扩展扩展扩展扩展((((extension )))) 1))))用例的扩展关系用例的扩展关系用例的扩展关系用例的扩展关系 随着系统随时间的不断演变,需要附加一些特性和功能来满足新的和当前的用户需要。假 定有这样的情况,一个项目范围是团队一次迭代所能完成规模的两倍,你就需要砍掉一部分功 能,把某些用例推到下一个周期完成。在第一个迭代周期完成一个主要的功能,下一个迭代周 期完成一些扩展的功能。 例如,酒店管理系统中有一个功能“待分配房间的预订人等候名单”,如果没有房间,系统 就会把客户放进这个“等候名单(Waiting list )”,因此,这个“Waiting list ”就是“预订房间(Reserve Room )”的扩展。把扩展分离出来,可以使问题容易理解,这就就不至于被过多的问题所纠缠。 下图表示了这个扩展用例的存在发生了什么。 使用扩展用例的理由有三条:  作为一个实体,扩展用例能够简化用例的维护,同时允许团队关注并细化扩展的功能, 而不需要重读基本用例本身。  把扩展看成是用例开发,扩展点可以在基本用例中给出作为“通向未来特性”的途径。  扩展用例可以表示随意性的行为,而不是一个新的基本或扩展流程。 最后一条往往是最有用的。还需要注意需求的变更,标识出哪些需求将来可能变更,尽早 提出一些解决办法,比如把可能变更的功能独立出来(至少建议这样做),这样就可以避免将来 的需求变更带来不利的影响,所以,对于产品用例的考虑,我们可以在早期注意以下几个方面:  用例对应着功能包,所以用例的大小要合适。  注意到缠绕状态,标识出并且提出建议方案。  研究并且标识出易变性,把易变的功能独立起来。 从这些角度说,产品用例是在业务用例的基础上更进一步的思考。 2))))用例扩展关系的场景描述用例扩展关系的场景描述用例扩展关系的场景描述用例扩展关系的场景描述 扩展用例包括一个或者多个扩展事件流,扩展事件流与备选事件流很相似,只不过它是在 另一个用例中添加行为,例如在“酒店管理系统”中: ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 59 - 用例名用例名用例名用例名: 预定房间 用例用例用例用例层次层次层次层次 用例用例用例用例 ID: C-2 用户目标 主要主要主要主要参与者参与者参与者参与者: 客户 描述描述描述描述:::: 该用例描述客户如何预定一个房间 前置条件前置条件前置条件前置条件:::: 客户已经登录到系统 后置条件后置条件后置条件后置条件:::: 成功预定之后,创建一个新的一顶记录,特定时间的可用房间数将减少,如 果预定失败,数据库不会发生任何改变。 主主主主事件流事件流事件流事件流: 1,客户选择预定一个房间。 2,系统显示酒店拥有的房间类型,以及它们的收费标准。 3,客户核对房间的收费(S1 )。 4,客户对选择的房间提出预定。 5,系统在数据库减少这个类型可预定房间的数目(Ea )。 6,系统基于提供的详细资料创建一个新的预定。 7,系统显示预定确认号以及入住登记说明。 8,用例结束。 扩展扩展扩展扩展流流流流:::: …… 扩展点扩展点扩展点扩展点 Ea:更新房间可用性 Ea1 ,当没有客户所选择的房间的时候,该扩展事件流发生。 扩展事件流为房间预订队列(CS-5-EF1 ) 用例名用例名用例名用例名: 处理等候列表 用例用例用例用例层次层次层次层次 用例用例用例用例 ID: CS-5 子功能 基本事件流基本事件流基本事件流基本事件流: …… 扩展事件流扩展事件流扩展事件流扩展事件流:::: EF1 ::::房间预定队列房间预定队列房间预定队列房间预定队列。。。。 1,创建一个等候预定,并根据所选择的房间类型生成一个唯一标识符。 2,把等候预定放入一个等候列表中。 3,显示这个等候预定的唯一标识符。 4,基用例结束。 3,,,,用例的泛化关系及场景描述用例的泛化关系及场景描述用例的泛化关系及场景描述用例的泛化关系及场景描述 泛化与类的泛化意义相同,表达用例之间存在“is-a-kind-of ”关系。当一组用例拥有相同的 事件流序列,或者相似的一组约束的时候,可以使用例的泛化。 一般父用例是抽象的,而子用例将继承父用例的特性。比如“预定房间”或者“预定早餐” 还可以有一套相同的其它服务的时候,可以使用泛化描述。 在“预定服务”用例中有一个抽象子事件流,所以“预定房间”是一个抽象用例,而“选 择服务”的事件实现在“预定房间”用例中。事件流执行的规则如下:实例化首先出现在子用 例中,沿着基本事件流运行,如果子用例没有定义基本事件流,则沿着父基本事件流执行,上 面的例子由于没有定义子基本事件流,所以沿着父基本事件流运行。在运行到“选择一项服务” 的时候,执行子用例定义的“选择服务”子用例,如下图所示。 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 60 - 事件流的描述如下: 用例名用例名用例名用例名: 预定服务 用例用例用例用例层次层次层次层次 用例用例用例用例 ID: C-3 用户目标 主主主主事件流事件流事件流事件流: 该用例开始于某个客户预定一个服务 1,系统显示可提供的服务。 2,客户选择一项服务(S1 )。 3,系统显示所选服务的总费用。 4,系统在数据库中减去相应服务的总数量。 5,系统为所选服务创建一个新的预定。 6,系统显示预定确定号。 7,用例结束。 扩展扩展扩展扩展流流流流:::: …… 子事件流子事件流子事件流子事件流:::: S1 :{abstract} 选择服务 用例名用例名用例名用例名: 预定房间 用例用例用例用例层次层次层次层次 用例用例用例用例 ID: C-4 用户目标 主主主主事件流事件流事件流事件流: 子事件流子事件流子事件流子事件流:::: C-3-S1 ,选择服务: 1,客户选择预定房间。 2,客户选择房间类型并说明停留时间。 3,系统根据给出的周期计算出总的费用。 要注意到的问题是,首先不要混淆泛化和扩展泛化和扩展泛化和扩展泛化和扩展,Java 中的关键字 extend 是泛化而非扩展, 而用例中的扩展与泛化是完全不同的,扩展事件流只不过是挂接到原有用例事件流的某个位置 上,以添加新的行为,而且是在同一层及解决问题。 另一个方面不能混淆泛化和包含泛化和包含泛化和包含泛化和包含,泛化和包含都是用于抽取用例的公共行为,因此容易混 淆,其实它们是实现复用的两种不同手段,泛化关系要求付用例和子用例之间拥有“is-a -kind-of” 关系,这样继承才有意义,但包含无需拥有这种关系。在使用包含的时候,当执行到使用公共 行为的步骤时,必须明确指出包含的用例,而且指明使用哪个事件流。 四四四四、、、、并发处理框架的业务模型并发处理框架的业务模型并发处理框架的业务模型并发处理框架的业务模型 为了更清楚的表达用例场景对需求分析的作用,我们描述在 PDM 系统设计中,需求(R2-6) 的详细分析,这个需求的描述为:“产品对于指定的图档文件从数据库中释放,并传送到客户 端进行操作,应该支持 Check-in/Check-out 功能,以保证文件的完整性和一致性。” 1,,,,框架的基本业务目标框架的基本业务目标框架的基本业务目标框架的基本业务目标 几乎所有的 PDM 系统都要求具有文件的检入和检出机制,这是因为在设计过程中。不可 避免地会出现关于开发进度、设计要求、监控模式、设计要求以及具体设计以及图纸的更改, 如果没有串行存取机制,当甲乙双方都修改同一个文件的时候,保存在数据库的文件到底是哪 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 61 - 一份修改稿呢? 我们定义的规则是,一个设计或者管理人员想要在一个文件上工作就要将它检出,检出操 作提供一个文件的拷贝,确保相应人员工作在该文件的最新版本之上,检出操作同时记录该动 作是由何人完成的,并且常常要求相关人员记录为什么要检出这个文件。 检出操作同时把这个文件锁定,在检入之前,避免另外一个人对其进行修改。 在完成修改以后,相关人员把文件检入回存储空间。该操作也记录谁在何时检入了该文件, 通常还要求相关人员简短说明变更了什么内容。检入动作释放了对该文件的锁定,从而允许其 他人员变更。这个动作策略,从根本上克服了并发修改的问题。 在 PDM 文件系统中,为了实现检入/检出机制,就必须对文件修改进行串行处理,由于这 个问题的困难性,我们把单独构建了一个文件并发处理框架(File Concurrent Processing Framework ,FCPF),下面我们简述一下这个框架的需求分析结果。 文件并发处理框架(FCPF)是一个提供检入/检出操作的资源锁控制的服务框架,该框架的 目标是:为了文件服务客户处理文件最新版本的时候,不至于受到并发修改的困扰,客户对象 使用 FCPF 来保护代码中的临界区域,免受因为并发修改而导致的非安全存取。 2,,,,框架的业务框架的业务框架的业务框架的业务概念概念概念概念 任何项目的需求分析,首先需要弄清楚的就是清晰的定义业务过程,为了避免文件变更活 动的互相覆盖,我们可以通过锁定避免拷贝来解决这个问题,但导致了文件修改过程变慢,现 代配置管理工具通过稍稍调整检入/检出方式来解决这个问题,也就是任何人都可以检出文件, 但是检入操作却根据不同类型的检出操作加以控制。 首先定义了两种检出操作,保留型保留型保留型保留型和非保留型非保留型非保留型非保留型,在任一点上只能有一个保留型检出,而可 以有任意多个非保留型检出。假定一个文件已经被保留型检出,其他人就没有办法做保留型检 出,只能做非保留型检出。 因此,当第一个人(文件使用客户 A)保留型检出文件以后,第二个人(文件使用客户 B) 检出将会出现一个错误信息,说明文件已经被保留型检出了,这时你可以所三件事:  等待文件使用客户 A 把文件检入。  询问文件使用客户 A 正在作何修改(一个好想法),以及会持续多久。  进行非保留型检出。 非保留检出可以访问任意文件,这就避免了不能访问独占锁定文件所带来的问题。 在检入的时候,对于文件使用客户 A 没什么问题,但对于文件使用客户 B 将出现报错信息, 除非满足一下三种情况中的一种: 第一种情况第一种情况第一种情况第一种情况::::文件使用客户文件使用客户文件使用客户文件使用客户 A 已经检入了相应文件已经检入了相应文件已经检入了相应文件已经检入了相应文件 如果 A 把文件检入,进行非保留型检出的 B 将没有办法直接检入文件,我们要求 B 首先把 A 的变更归并到自己(B)所作的变更之中,这样做的目的时避免拷贝覆盖问题,完成这种归 并之后,B 就可以检入包含归并内容的文件,下图就是这种情况的场景。 第二种情况第二种情况第二种情况第二种情况::::A 取消了相应检出操作取消了相应检出操作取消了相应检出操作取消了相应检出操作 此时,B 可以检入而无需作归并动作,因为没有需要归并的内容。 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 62 - 第三种情况第三种情况第三种情况第三种情况::::A 把保留类型由保留型转为非保留型把保留类型由保留型转为非保留型把保留类型由保留型转为非保留型把保留类型由保留型转为非保留型 当使用本系统的时候,A 能够把检出的类型从保留型转变为非保留型,在这种情况下,这 个文件拥有多个非保留型检出,但不存在保留型检出。此时,B 可以在不作任何归并的情况下 检入文件,但仅仅是第一个文件不需要做归并,其它文件,包括 A 自己的文件需要检入,都需 要归并 B 所作的更改。 五五五五、、、、并发处理框架用例及其业务流并发处理框架用例及其业务流并发处理框架用例及其业务流并发处理框架用例及其业务流 为了分析这个需求,我们首先画出该用例图结构如下。 我们可以描述出这个框架的业务流程如下图所示。 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 63 - 为了定义开发,我们写出相应的用例文档如下,在这个用例文档中强调了扩展流的写法, 并且突出了对包含关系的应用。 用例名用例名用例名用例名: 串行存取文件 用例用例用例用例层次层次层次层次 用例用例用例用例 ID: FC-1 用户目标 主要主要主要主要参与者参与者参与者参与者: 客户 范围范围范围范围:::: 文件并发处理框架(FCPF) 主主主主事件流事件流事件流事件流: 1,客户请求文件锁给予它文件存取权。 2,文件锁把控制权返回给客户以使它能够使用文件。 3,客户使用文件。 4,客户通知文件锁它对文件的使用已经完成。 5,客户结束后,文件锁处理善后事宜。 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 64 - 扩展扩展扩展扩展流流流流:::: 2a ,文件锁发现发现客户对文件已经具有存取权: 2a1 ,文件锁对请求实施文件锁转换策略(FCS-1)。 2b ,文件锁发现文件已经分配给他人使用: 2b1 ,文件锁实施兼容性策略(FCS-2) 2b2 ,使客户对文件享有非保留型存取权。 5a ,文件锁发现文件当前未被使用: 5a1 ,文件锁实施存取选择策略(FCS-3) 5a2 ,给处于挂起状态的客户赋予保留型存取权。。 用例名用例名用例名用例名: 实施文件锁转换策略 用例用例用例用例层次层次层次层次 用例用例用例用例 ID: FCS-1 子功能 主要主要主要主要参与者参与者参与者参与者: 客户 范围范围范围范围:::: 文件并发处理框架(FCPF) 主主主主事件流事件流事件流事件流: 1,文件锁验证请求的存取方式是保留型存取。 2,文件锁验证客户已经具有非保留型存取权限。 3,文件锁验证没有其他客户等待更新其存取权限。 4,文件锁验证没有其他的客户在使用文件。 5,文件锁赋予客户对文件的保留型存取权。 6,文件锁增加客户锁的个数。 扩展扩展扩展扩展流流流流:::: 1a ,文件锁发现请求的存取方式是非保留型存取: 1a1 ,文件锁增加客户锁的个数。 1a2 ,成功! 2a ,文件锁发现客户已经具有非保留型存取权限: 2a1 ,文件锁增加客户锁的个数。 2a2 ,成功! 3a ,文件锁发现有另一个客户等待更新其存取权限: 3a1 ,通知客户不能赋予它所请求的存取权限。 3a2 ,失败! 4a ,文件锁发现有另一个客户正在使用文件: 4a1 ,文件锁令客户等待获得保留型权限(FCS-4) 用例名用例名用例名用例名: 实施存取兼容性策略 用例用例用例用例层次层次层次层次 用例用例用例用例 ID: FCS-2 子功能 主要主要主要主要参与者参与者参与者参与者: 客户 范围范围范围范围:::: 文件并发处理框架(FCPF) 主主主主事件流事件流事件流事件流: 1,文件锁验证请求的存取方式是非保留型存取。 2,文件锁验证当前对文件的所有使用都是非保留型存取。 扩展扩展扩展扩展流流流流:::: 2a ,文件锁发现请求的存取方式是保留型存取: 2a1 ,文件锁令客户等待获得保留型权限(FCS-4) (进程的执行由锁服务策略恢复) 2b, 文件锁发现文件正在被其他人以保留型方式使用: 2b1 ,文件锁令客户等待获得保留型权限(FCS-4) 用例名用例名用例名用例名: 实施存取选择策略 用例用例用例用例层次层次层次层次 用例用例用例用例 ID: FCS-3 子功能 主要主要主要主要参与者参与者参与者参与者: 客户 范围范围范围范围:::: 文件并发处理框架(FCPF) 主主主主事件流事件流事件流事件流: 语境目标:文件锁必须决定哪一个等待请求(如果有的话)应该获得服务。 注意:这个策略是一个可变点。 1,文件锁选择等待时间最长的请求。 2,文件锁将保留型权限赋予被选中请求。 扩展扩展扩展扩展流流流流:::: 1a ,文件锁发现没有处于等待的请求: 1a1 ,成功! 1b ,文件锁发现有一个请求正等待从非保留型存取更新为保留型存取: 1b1 ,文件锁选中这个等待更新的请求。 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 65 - 用例名用例名用例名用例名: 令客户等待获得保留型权限 用例用例用例用例层次层次层次层次 用例用例用例用例 ID: FCS-4 子功能 主要主要主要主要参与者参与者参与者参与者: 客户 范围范围范围范围:::: 文件并发处理框架(FCPF) 主主主主事件流事件流事件流事件流: 1,文件锁将客户请求进行记录。 2,客户已非保留型方式等待直到再次被允许请求。 扩展扩展扩展扩展流流流流:::: 我们可以发现,即使这样一个简单的文件并发处理框架,在业务流上看也是相当复杂的, 所以必须把它定制成一个单独的服务框架,由专门的小组进行开发。 在需求分析的阶段,并不需要描述业务流程的实现方式,这部分内容可以在具体设计过程 中完成,在业务流程的表达上需要有一定的抽象性,只要问题的表达清楚没有歧义,这部分用 例分析就可以作为需求文档的一部分存在。我们在项目开发过程中体会到,对于具有复杂业务 流程的系统,在需求分析的时候把业务流程精确的定义下来非常必要,这样就可以为后期开发 提供强大的支持。 2.3 从领域模型到数据模型从领域模型到数据模型从领域模型到数据模型从领域模型到数据模型 为了建立正确的数据模型,我们首先需要了解 PDM 的系统在企业实施中的主要要求。如果 对这种要求不了解,是无法设计出正确的数据结构的。因此,在进行设计以前,仔细研究产品 的需求极其重要。我们构建的这个分布式数据和文裆管理功能,应该允许用户迅速无缝地访问 企业的产品信息,而不用考虑用户和过据的物理位置。这些功能包括: 1)文件的检入(Check-in )和检出(Check-out ); 2)按属性搜索机制; 3)动态浏览/导航能力; 4)分布式文件管理; 5)安全机制(记录锁定,域锁定)。 这些要求与目前流行的各种 PDM 文件系统是一致的,在这里不再重复。本项目一个特殊的 能力,是在一个合作方协同设计模式下,更好的发挥 PDM 项目管理功能,使主设计方与合作设 计方在整个过程中能够融合,以有序受控的方式,使新产品项目开发能够进行,因此,下面我 们主要介绍协同设计项目管理部分数据结构的设计过程。 一一一一、、、、领域模型的初步建立领域模型的初步建立领域模型的初步建立领域模型的初步建立 很多建立数据结构的过程是比较随意的,这样很难构建一个合理的数据模型。问题是在一 个项目中,数据模型是应该最具稳定性的,因此我们的做法是,从建立领域模型开始,通过讨 论使设计人员对业务问题慢慢理解的更透彻。边讨论、边建立模型、边使问题的研究更深入, 最后构建一个合理的数据模型,这样比直接给出设计结论风险更小。 合作方协同设计(PCD)的一个重要的内容是项目管理与过程管理,因此,我们先从项目 管理最基本的问题入手,逐步的建立静态领域模型。首先遇到的第一个领域问题,就是协同设 计项目管理到底是怎样进行的? 1))))任何项目任何项目任何项目任何项目开发特点是开发特点是开发特点是开发特点是先定义里程碑先定义里程碑先定义里程碑先定义里程碑,,,,每个里程碑包含多个任务每个里程碑包含多个任务每个里程碑包含多个任务每个里程碑包含多个任务 根据里程碑和任务之间的关系,我们用类来表示表示概念,那就是领域模型,如下图所示。 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 66 - 一个里程碑有多个任务,而且每个任务需要排定日期。 2))))每个任务可以分配多个资源每个任务可以分配多个资源每个任务可以分配多个资源每个任务可以分配多个资源,,,,而每个资源也可以提供给而每个资源也可以提供给而每个资源也可以提供给而每个资源也可以提供给多个任务多个任务多个任务多个任务 3))))在在在在 PDM 系统中系统中系统中系统中,,,,每个任务会关系到多个设计图纸和设计方案每个任务会关系到多个设计图纸和设计方案每个任务会关系到多个设计图纸和设计方案每个任务会关系到多个设计图纸和设计方案 4))))事实上事实上事实上事实上,,,,项目涉及的资源有多种项目涉及的资源有多种项目涉及的资源有多种项目涉及的资源有多种,,,,比如人比如人比如人比如人、、、、设备设备设备设备、、、、材料等材料等材料等材料等 不论资源是人员、材料还是设备,它们都需要有属于这个项目资源的基本属性,所以这是 一个父子关系。 5))))每个里程碑除了有时间每个里程碑除了有时间每个里程碑除了有时间每个里程碑除了有时间、、、、费用和质量三点控制外费用和质量三点控制外费用和质量三点控制外费用和质量三点控制外,,,,必要的时候还会有变更通知必要的时候还会有变更通知必要的时候还会有变更通知必要的时候还会有变更通知 每个里程碑可能有多个变更通知。 6))))有变更通知就需要有变更执行情况记录有变更通知就需要有变更执行情况记录有变更通知就需要有变更执行情况记录有变更通知就需要有变更执行情况记录 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 67 - 每个变更通知,可能需要有多个执行情况记录。 7))))图纸仓库应该包括图纸索引与图纸库两部分图纸仓库应该包括图纸索引与图纸库两部分图纸仓库应该包括图纸索引与图纸库两部分图纸仓库应该包括图纸索引与图纸库两部分 图纸库可以使用 PDM 系统已经存在的图纸库,任何 PDM 系统不论功能上多么不一样,这 个图纸库是必须存在的。由于图纸库一般都比较大,为了查询方便,一般都使用图纸索引。考 虑到图纸的版本演变,以及必要的 Check-in/Check-out 机制,每份图纸会有多个版本。而设计文 档也需要同样的版本控制,这都是设计文件配置管理所必需的。由于图纸的复杂性,本项目不 采用只保留变化部分的方法,而是记录整个图纸的编办变化演化过程,这样设计上比较现实, 而且也符合实际情况。为了保证串行读写机制可以实行,数据中必须记录每个版本的状态,以 识别文档当前是处于等待修改、已经在被人修改、还是正在被阅读等状态,使系统可以分配使 用文件的人为保留型、非保留型等权限。 把上面的研究结合起来,考虑到我们将使用关系型数据库,屏蔽掉项目资源的父子关系, 我们就得到了一个比较清楚的领域模型了。这里,当使用多对多关系的时候,必须添加一个关 联表,使这种关系的实际实现成为可能。 在资源部分(人员、材料、设备)使用索引与库分开的 1 对 1 关系的原因,是索引记录的 与本项目相关的信息,而库中记录的是资源本身更通用的信息。这样的数据结构便于在更广泛 的领域中使用。对于多对多关系,需要建立一个关联表,这个关联表采用“联合主键”的方式。 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 68 - 二二二二、、、、数据模型的建立数据模型的建立数据模型的建立数据模型的建立 依据我们已经建立的领域模型,再仔细思考每个领域类的属性(也就是每一张表的字段), 就可以建立一个初步的 PDM 协同设计系统关于项目管理部分的数据模型了,如下图所示,图中 只表达了各个表之间的关系,以及为建立关系有关的主键和外键,以表达图中最主要的关系。 在字段比较复杂的时候,字段的细节还是用表格表达比较合适。 通过上面的讨论我们可以知道,在面对一个复杂系统的时候,没有章法的胡乱把数据库表 结构做出来是不可取的。由于数据库结构是系统希望最为稳定的部分,所以认真研究深入体会 整个结构和概念,形成正确的设计思想十分重要。 2.4 系统安全性设计与软件架构系统安全性设计与软件架构系统安全性设计与软件架构系统安全性设计与软件架构 对于基于 Web Services 的 PDM 文件系统,系统和数据安全显得极为重要,这也是系统最重 要的非功能需求之一。本项目还有一个特殊问题,那就是 Web Service 本质上是一个基于互联网 的系统,因此所有基于 Web 的不安全因素,对本系统来说都是存在的。作为以合作方协同设计 平台系统,该平台的安全特性又对各个用户方意义特别重大,因为协同设计所牵涉到的数据大 多数具有敏感性与保密性,所以 Web 安全问题引起了用户方的极大重视是必然的,本项目对安 全性设计进行了重点和专门的考虑。 一一一一、、、、Web 系统的不安全因素分析系统的不安全因素分析系统的不安全因素分析系统的不安全因素分析 1 ,,,,Web 系统的不安全因素系统的不安全因素系统的不安全因素系统的不安全因素 一切的设计结论首先来自于对问题的分析,为了正确设计 PDM 文件系统的安全体系,我们 必须知道所有强调安全的体系结构都是需要付出代价的,其中包括系统的效率,系统的可用性 和易使用性等。因此,毫无目的处处设防并不是一个好的设计方法,因为这样可能会花费很大 的代价,还是可能在没有注意的地方出现安全漏洞。所以,正确的方法是仔细研究 Web 方式下 有哪些安全漏洞,并针对这些漏洞,寻找有效的安全设计措施。我们首先归纳一下 Web 方式的 不安全因素。 1))))Web 应用程序应用程序应用程序应用程序不安全不安全不安全不安全因素分析因素分析因素分析因素分析 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 69 - Web 应用程序使用 HTTP 作为客户端和服务器之间进行通信的媒介。它的某些很有用的特 点,反而成为安全威胁的根源。这些特点包括简单性、无状态性、文本的本质以及在 TCP 80 端 口的操作。  简单性简单性简单性简单性::::也就是通过任何一个客户端向服务器发送请求,都可以得到响应。  无状态性无状态性无状态性无状态性::::web 应用程序本身不保留有关会话的状态,为了保留会话状态需要使用诸 如 Session 等机制,而这些状态可能会存储在不安全的位置(比如 Cookes ),模拟一个 会话保持机制并不困难。  基于文本基于文本基于文本基于文本::::HTML 与 XML 都是基于文本的,任何客户都能够阅读它,不需要解密上 下文,这带来了潜在的不安全性;  运行在一个众所周知的运行在一个众所周知的运行在一个众所周知的运行在一个众所周知的 TCP 端口上端口上端口上端口上:这使得防火墙和其它网络安全设备不得不配置成 允许 TCP 80 端口上的数据包通过,使安全设备对 Web 攻击毫无抵抗能力。 2))))潜在的安全漏洞潜在的安全漏洞潜在的安全漏洞潜在的安全漏洞 Web 服务器是局域网上另一个潜在的安全漏洞。网络安全的一般目标都是禁止陌生人进入, 但 Web 站点却向外部提供了一个进入局域网的访问点。如果 Web 服务器配置不好,就会在精心 设计的防火墙系统上穿一个孔,以破坏内网安全。Web 服务器必须被配置成能够识别和认证具 有不同访问权限的用户组。 3))))可能会有恶意软件侵入可能会有恶意软件侵入可能会有恶意软件侵入可能会有恶意软件侵入 用户端的 Web 浏览器看起来很安全,但事实绝非如此。我们发现 ActiveX 控制 Web 浏览器 可能会向系统引入病毒或其它恶意软件,大部分木马病毒都是通过 ActiveX 植入的。用户的每 一个浏览动作都会留下一个历史记录,不道德的人可以由此准确地重构出用户的口味和习惯。 整个系统设计需要关注通过网络传递数据的机密性。TCP/IP 协议当初设计的时候就没有考 虑安全性,因此,极易受到网络窃听的攻击。任何数据在服务器与客户端之间传输,都可能有 人在窃听。 2 ,,,,从分析开始安全性设计从分析开始安全性设计从分析开始安全性设计从分析开始安全性设计 正是在这样的背景下,本项目对数据安全及其传输安全性提出了强烈的要求,要求 Web 服 务系统能够防范各种恶意攻击。但是从过去到现在我们见过的很多类似系统的设计中,安全问 题往往设计的比较随意,仅仅根据某些指南采取了一些基本的安全措施而已,并没有真正把消 除安全隐患和漏洞作为一个重要的任务来考虑,我们认为这种设计方法对客户是不负责任的。 正确的做法是:首先,根据项目特点,认真研究了安全漏洞的起源,分析了常用服务安全 措施特性。其次,建立基于安全的软件分析与设计过程,并把这个过程在实践中坚持了下去。 第三,针对不同的安全性问题提出了相应的安全策略。最后,针对一些特殊的要求,应该进行 了原型开发(垂直原型),以验证一些概念和方法的正确性,并把这些原型作为整个系统的技术 实现基础。在这种深入研究和试验基础上的设计,就可以实施正确的安全策略,使系统具有很 好的安全性。 Web 系统的不安全因素是比较多的,但我们也要对安全有个正确的认识,信息技术本质上 就是一个信息交流的平台,既然是交流那么绝对的安全就是不存在的。希望绝对安全最好的方 法是闭关锁国、不使用任何基于网络的信息系统,但这将会严重迟滞我们的发展。由于互联网 具有不安全性而拒绝使用更是因噎废食的方法,这个世界最安全的是老牛拉破车,但是我们能 为此拒绝坐飞机吗?所以我们需要的是恰当的安全,需要制定合适的安全策略,而不是由于恐 惧安全问题而不使用更加有效的信息技术,关键是安全控制的点要对。我们所需要做的就是仔 细研究不安全的原因,并在研究的基础上寻找合理的解决方案。 二二二二、、、、实现安全服务的基本措施实现安全服务的基本措施实现安全服务的基本措施实现安全服务的基本措施 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 70 - 在基于 Web Service 的外网传输中,我们所制定的安全策略决定着在这个区域进行通信时, 应该采用哪些安全服务。也决定着在什么条件下可以使用某种安全服务,以及对此服务的任意 一个参数施加了什么限制。我们定义,在各个相关单位内部,采用的安全机制可以使用本单位 原来已经成熟的安全机制,并不需要进行改变,这样比较现实,实现起来难度也会比较低。而 对于新构建的基于 Web Service 的系统,需要考虑合理的安全服务。 在基于服务的系统中,主要的安全防护措施称为安全服务。一般来说,在系统设计之初, 我们必须对五种通用的安全服务策略加以考虑,仔细研究每种策略将实施在什么位置上,这五 种服务包括:鉴别服务、访问控制服务、机密性服务、数据完整性服务和不可否认服务。 1,,,,鉴别服务鉴别服务鉴别服务鉴别服务 鉴别服务提供了关于某个人或事物身份的保证。这意味着当事人声称具有一个特别的身份 (例如某个特定的用户名称)时,鉴别服务需要提供某种方法来证实这一声明是正确的。我们 通常使用口令来提供鉴别方法。 鉴别是一种最重要的安全服务,因为在某种程度上所有其他安全服务都依赖于它的能力。 鉴别也是对付假冒攻击的有效方法,此攻击能够直接导致破坏任意一个基本安全目标。鉴别更 是一种特殊的通信过程,这就是说,在这个过程中需要提交人或物的身份。 鉴别又可分为以下两种情况:  身份由参与某次会话远端的一方提交的,被称之为实体鉴别。  身份由某个数据项的发送者(人或物)所提交,此身份连同数据项一起发送给接收者。 这种情况下的鉴别服务被称作数据源鉴别。 我们需要注意的是,在达到基本的安全目标方面,两种类型的鉴别服务都具有重要的作用: 数据源鉴别可以用来鉴别某一数据项真正的起源,是保证数据部分完整性目标的直接方法。而 实体鉴别则采用以下各种不同方式,以便达到安全目标。  作为访问控制服务的一种必要支持。访问控制服务的执行依赖于确知的身份,这对达 到保密性、完整性、可用性以及合法目标极其重要。  作为提供数据源鉴别的一种可能方法(当它与数据完整性机制联合起来使用时)。  作为对责任原则的一种直接支持,也就是在审计跟踪过程中做记录时,提供与某一活 动相联系的确知身份。 在 PDM 系统中,由于设计过程牵涉到各方面的人员,大量异地不同企业的人员利用本系统 达到不同的目的,所以人员的鉴别服务,以及数据的鉴别服务显得极其重要,在设计中需要专 门加以考虑。对于访问控制还有两个特殊的问题需要我们对它特别加以重视。第一个问题是在 某个终结点上,不同的人员之间容易互相替代;第二个问题是在区分个别人方面可能会采用一 些特别的技术来加以限制。 2,,,,访问控制服务访问控制服务访问控制服务访问控制服务 访问控制服务的目标是防止对任何资源进行非授权的访问。所谓非授权访问包括未经授权 的使用、泄露、修改、销毁以及颁发指令等。访问控制对保密性、完整性以及合法使用的作用 是众所周知的。访问控制是实施授权的一种方法。它既是通信安全的问题,又是计算机安全的 问题。还有一个问题通常较少受到人们注意,那就是由于必须在系统之间传输访问控制信息, 这些信息一旦被窃听,就会从根本上破坏访问控制的基础,所以对于通信的保密性提出了很高 的要求。访问控制服务的一般模型如下: 首先假定了一些主动的实体,我们称之为发起者或主体。它们试图访问一些被动的资源, 我们称作目标或客体。授权决策的控制决策需要考虑如下问题:  有哪些发起者?  他们在何种条件下? ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 71 -  为了什么目的?  他们可以访问哪些目标? 这些策略使访问请求通过某个访问控制机制而得到过滤。在 PDM 系统中,访问控制是整个 设计中应该十分重视的问题,必须由专门的设计小组制定权限设计,以及实施合适的访问控制 策略。  3,,,,机密性服务机密性服务机密性服务机密性服务 机密性服务就是保护信息不暴露给那些未授权的实体,其信息通道包括:  观察某一数据项的存在与否(不管它的内容)。  观察某一数据项的大小。  观察数据项特性(如内容、存在、大小等)的动态变化。 要达到保密的目标,必须防止信息经过这些信息通道被泄露出去。 我们需要区分两种类型的机密性服务:  数据机密性服务:攻击者想要从某个数据项中推出敏感信息十分困难。  业务流机密性服务:攻击者想要通过观察网络的业务流来获得敏感信息十分困难。  在基于 Web Services 的 PDM 系统中,由于在网络上传递的数据可能十分敏感(包括某些设 计文档和图档),因此对于数据机密性服务提出了特殊的要求,而机密性服务往往又与性能的要 求是矛盾的,这就需要综合考虑加以解决,并且对此进行了专题研究。 4,,,,数据完整性服务数据完整性服务数据完整性服务数据完整性服务 有一种威胁是以某种违反安全策略的方式,改变数据的价值和存在。所谓改变数据的价值 就是指对数据进行修改和重新排序,而改变数据的存在则意味着新增或删除它。数据完整性服 务是为了防护这样一类安全威胁。与机密性服务一样,数据完整性服务的一个重要特性是它的 具体分类,即对什么样的数据采用什么样的完整性服务。一般来说有三个重要的类型:  连接完整性服务连接完整性服务连接完整性服务连接完整性服务::::它是对某个连接上传输的所有数据进行完整性检验;  无连接完整性服务无连接完整性服务无连接完整性服务无连接完整性服务::::它是对构成一个无连接数据项的所有数据继续完整性检验;  区域完整性服务区域完整性服务区域完整性服务区域完整性服务::::它仅对某个数据单元中所指定的区域进行完整性检验 。 所有数据完整性服务都能够对付新增或修改数据的企图,但不一定能够对付复制和删除数 据。在 PDM 系统中,重要的图纸和数据传输必须提供数据完整性服务,系统应该提供“恢复” 的选择,这种情况下,当在某个连接内检测到数据完整性被破坏的时候,该服务会试图“恢复” 数据。例如,把通信将返回到某一检测点重新开始。  5,,,,不可否认服务不可否认服务不可否认服务不可否认服务 不可否认服务的主要目的,是保护通信用户免遭来自于系统其他合法用户的威胁,而不是 来自于未知攻击者的威胁。“否认”威胁在合作方协同设计管理系统中显得尤其重要,例如参与 某次通信交换的一方事后虚伪地否认曾经发生过本次交换和或交换过的内容。这会给协同双方 的信任带来极大的危机,而信任危机将极大的破坏合作方协同设计的基础。不可否认就是用来 对付此种威胁的。它能做的事情是提供无可辩驳的证据,以支持快速解决这种纠纷。 如果只考虑数据网络环境,服务否认分为两种不同的情况。  源点否认源点否认源点否认源点否认::::这是一种关于“某特定的一方是否产生了某一特定的数据项”的纠纷和/或 关于产生时间的纠纷。  递送否认递送否认递送否认递送否认::::这是一种关于“某一特定的数据项是否被递送给某特定一方”的纠纷和/或 关于递送时间的纠纷。 这两种情况会导致两种不同的不可否认服务。在基于 Web Services 的 PDM 系统中,其特点 就是对合作方协同设计的支持,因此在正确的位置实施不可否认服务是一个设计要求,也是一 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 72 - 个重要的安全策略。 三三三三、、、、建立安全软件开发过程模型建立安全软件开发过程模型建立安全软件开发过程模型建立安全软件开发过程模型 为更好地关注安全,设计出达到安全要求的系统,我们认为仅仅在某些方面任自己所好采 取一些措施是不够的,只是片面的实施某种技术手段更不是解决安全问题的办法。安全设计是 一个整体策略,它需要在整个软件设计过程中全面实施,而且是一种工程方法。他需要使每一 个团队成员都要对安全问题有足够的认知和统一的处理方法。因此,在本项目定义的软件开发 生命周期模型中,我们在安全方面增加了责任制和结构性,并且对整个开发过程进行控制,这 也可以称之为开发过程的安全改进。 经典软件开发过程模型是一种典型的基于业务的开发模型,为了开发出正确的产品,首先 需要做的就是理解业务,建立业务模型(就像本论文一开始所做的那样),然后是进行分析和设 计,这就是建立逻辑模型。最后是实现、测试、安装发布,也就是建立物理模型。这中间可能 会出现多次迭代和精化,使产品与实际要求更趋接近,如下图所示。 但是,对于安全性要求高的产品,我们就需要改进开发过程。根据本项目的特点,我们在 过程定义中加入了安全软件开发过程,强调把保障安全性的措施贯穿于整个开发周期,并以螺 旋迭代的方式对系统进行重构和优化,并在每个阶段进行安全审核。我们把就原来通用的基于 业务的开发模型,在不改变原有业务能力的基础上,增加了安全考虑,转变为基于业务和安全 两方面的模型,如下图所示。 具体的说:  建立业务模型建立业务模型建立业务模型建立业务模型::::确定业务需求(包括安全性要求和对风险、威胁的分析)和对信息的 要求。集中解决业务需求的问题,在问题分析中需要加入安全问题,而不仅仅从理论 上解决应用程序如何满足这些需求的问题。  建立逻辑模型建立逻辑模型建立逻辑模型建立逻辑模型::::需要着手了解应用程序应该如何设计才能满足业务模型提出的各个具 体要求。这时,我们需要确定应用程序的各种功能,而不是考虑建立应用程序时使用 的各种技术,这时还需要确定各种安全策略。  建立物理模型建立物理模型建立物理模型建立物理模型::::选择建立应用程序时使用的各种技术,并且进行应用程序的实际设计 工作。这是需要采取合适的安全技术,每一种技术实现需要进行原型试验,分析其特 点和陷阱,而不是盲目的把一种技术用进去。 物理模型的建立还可能重新回到当初的业务模型设想上来,这是因为项目采用的任何技术 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 73 - 都会改变目标企业的运行环境。这个模型强调了在不同的阶段思考安全问题的空间不一样,层 次也不一样,而且主要强调了以下安全步骤: 第一步:教育,我们认为这是创建安全系统最重要的部分,因为只有通过对整个开发团队 的教育,才能提高安全意识,只有全体团队成员学会如何进行威胁分析、理解和应用威胁缓解 技术,才可能避免不经意的漏洞,也才能设计和创建一个真正的安全系统。 第二步:设计阶段,利用威胁建模技术建立系统模型,采取正确的策略。 第三步:开发阶段,编码与测试并行。在编码阶段的具体措施包括:  由核心成员和同级进行新代码的安全审查并签字确认;  定义最小的安全编码准则,如应当如何处理缓冲区、如何对等不可靠的数据、应当如 何加密数据等等,并不断扩展这些准则;  审查曾经发生的安全缺陷,从过去的错误中吸取教训;  发起安全推动活动,建立安全小组,提高小组成员的安全意识,去除坏习惯,发现并 修复 bug ;记录错误,在错误跟踪数据库中记录下设计或代码中找到的安全缺陷。 第四步:发行与维护阶段,使用标准的修复机制修复安全缺陷。 四四四四、、、、安全漏洞与防护措施安全漏洞与防护措施安全漏洞与防护措施安全漏洞与防护措施 安全漏洞可能会存在于任何地方,为了使每个团对成员为安全防护有清楚的认识和策略, 我们项目组归纳了 Web 应用程序中的各种漏洞及其防护办法。我们的经验表明,只是把安全问 题变成少数人的设计点,是达不到设计一个安全系统的目的的,只有全体团队成员具有共同的 安全理念,在每个具体设计中都注意堵住漏洞,采取共同的安全防护方法,才能达到设计一个 安全系统的目的,我们要求开发组队安全性提出的策略,这些策略自然的也会成为系统的需求 存在。 1,,,,防止防止防止防止伪造输入伪造输入伪造输入伪造输入 这种攻击来自于 Web 请求在被应用使用前没有被验证,或者攻击者通过伪造 HTTP 请求的 各个部分(例如 URL、查询字符串、头、cookies 以及隐藏域等)绕过站点的安全机制,使用这 些漏洞通过 Web 应用程序来攻击后端的组件。 我们项目组采用的保护方法为: 1))))过滤恶意输入过滤恶意输入过滤恶意输入过滤恶意输入 在需要保护的位置设置数据形式的验证,包括数据类型(串,整型,实数等)、允许的字符 集、最小和最大的长度、是否允许空输入、参数是否是必须的、重复是否允许、数值范围、特 定的值(枚举型)等。 2))))合理应用客户端输入验证合理应用客户端输入验证合理应用客户端输入验证合理应用客户端输入验证 由于我们的项目确定为具有客户 GUI 应用程序的 Web Service 系统,这种 GUI 应用程序功 能强大,可以处理复杂的客户要求。在 GUI 应用程序中,恰当的利用客户端验证可以照顾到合 法用户的用户体验并减少传递给服务器的无效通信负载。所以这种方法性能和可用性方面较好。 但要注意这种方法容易被旁路,需要与服务器端验证相结合,用服务器端验证保证安全性。 本项目在客户端主要验证客户密码的组成格式是否合法,在服务端主要验证客户是否已经 得到相应的授权,对于 Web Services 系统,这里的服务端指的是分布在各个服务点的服务器。 2,,,,错误的访问控制错误的访问控制错误的访问控制错误的访问控制 访问控制通常也称为授权(通常是跟在认证之后的操作)。在本 PDM 项目中,不同的内容 或功能的访问将权授给不同的用户。这种访问控制模型与应用本身的内容和功能紧密相关,而 用户权限会很复杂,需要大量具有不同能力和特权的组与角色。 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 74 - 如果开发人员低估了实现一个可靠的访问控制机制的难度,使许多机制缺乏慎重的设计, 最终这些规则的集合就会变得杂乱而难以理解。另外,本 Web 系统为了实现更精细地管理,需 要设置多种能够通过网络对用户、数据与内容进行管理的管理员角色,这些管理员接口更是网 络内部和外部攻击者的主要目标。 为了解决这个问题,在我们的安全策略文档中要求清晰地定义访问控制策略,文档中应说 明哪种类型的用户能够访问系统,这些用户能够被允许访问哪些功能和内容。实现访问控制策 略的代码应当结构良好,模块化设计,并最好采用集中式的实现。 我们项目组采用的保护方法为: 1))))不能依靠秘密不能依靠秘密不能依靠秘密不能依靠秘密 ID 实现安全保护实现安全保护实现安全保护实现安全保护 我们发现很多 Web 站点使用某种形式的 ID、key 或索引来引用用户、角色、内容、对象或 功能,这些能可能被攻击者猜测到,在我们的项目中禁止这样做。 2))))防止暴力浏览绕过访问控制检查防止暴力浏览绕过访问控制检查防止暴力浏览绕过访问控制检查防止暴力浏览绕过访问控制检查 防止用户通过输入 url 跳过安全检查页面,设置多层防御机制。对服务端相应的应用路径, 不允许任何用户直接进入。 3))))文件许可权文件许可权文件许可权文件许可权 建立合理的人员管理模型,确保准确授权:首先建立人员的管理模型,给出各相关人员机 构表、本型号产品的开发队伍或小组表、各类人员的角色及其相应权限表,并说明设计、校对、 工艺、标检和计划等的读/写权限。然后确认用户的存取权限,即明确规定用户存取数据的范围 及可以实施的操作。最后实施存取权限控制,即对用户进行存取权限控制,监测用户的操作行 为,将用户的数据访问控制在规定的范围内。 4))))防止管理员权限过大防止管理员权限过大防止管理员权限过大防止管理员权限过大 目前大部分 PDM 系统的权限管理都由全局的系统管理员角色来担任,该系统管理员负责分 配整个 PDM 系统的权限,具有的管理功能有:项目管理、用户管理、权限管理、工作流程定义 等,这样大的权限很容易受到恶意攻击。 在本项目中,对全局系统管理员进行了约束和职责划分。设置系统管理员、数据库管理员 和安全管理员三个角色,并在操作时相互制约,从管理规范上和审计技术方面,确保管理员的 权限分级(至少 2 人在场时才能实施各种操作)。由于 Web Service 的特点,对于对于协调设计 的总体方和服务方,管理员职责是分开的。 3,,,,错误的验证错误的验证错误的验证错误的验证 Web Service 系统与一切 Web 系统一样是无状态的,当用户通过认证后,站点将会使用会话 管理(session )跟踪每个用户请求的信息流。如果在身份管理(credential management )方面存 在缺陷,例如更改密码、密码遗失、保存密码、帐户更新等管理功能不完善或出现问题的时候, 就会使认证形同虚设,攻击者很有可能劫持用户的会话,冒用他们的身份。 我们项目组采用的保护方法为: 1))))密码强度密码强度密码强度密码强度 密码应该有限制,来保障最小长度和复杂度。复杂度通常要求在用户的密码里使用最小数 目的字母,数字,和/或符号的结合,系统应该鉴别出用户设置密码是不是符合规则,如果不符 合规则,则应该提醒用户。用户应该被要求周期性的更改密码,如果更改周期时间到,应该提 醒用户。用户应该不被允许重复使用以前的密码,所以系统应该具有储存所有用户使用过的密 码的能力,并在用户设置密码的时候,查询是否重复,如遇重复应该提醒用户。 2))))密码使用密码使用密码使用密码使用 系统应该设置用户有登录次数的限制,所有的重复的登录应该被记录到日志中。失败的登 录的密码不应该被记录下来,因为这样会把用户的密码暴露给访问该日志的人。如果一个登录 失败了,系统不应该指出到底是用户名还是密码错误。用户仅应该被告知他们上次登录的日期 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 75 - 和时间,和从该时间开始,失败的登录发生的次数。 3))))密码修改控制密码修改控制密码修改控制密码修改控制 不论在什么地方允许用户修改密码,都应该使用一个密码修改机制。当修改密码时,用户 应该总是被要求提供老的和新的密码。如果忘记了的密码被用 Email 寄回给用户,当用户修改 他们的电子邮件地址时,系统应该要求用户来重新认证,否则,暂时拥有会话访问权的攻击者 可以修改他们的电子邮件地址,然后要求把“忘记了”的密码寄给非法攻击者。 4))))密码存储密码存储密码存储密码存储 不论在什么地方,所有的密码必须以加密方式存储以防止暴露。由于不可逆,这里采用哈 希算法。加密应该在明文密码使用时使用,用户密码不能被直接写在任何源程序中。解密密钥 必须被严格保护,以确保攻击者不能被获得来解密密码数据。 5))))保护传输中的认保护传输中的认保护传输中的认保护传输中的认证信息证信息证信息证信息 唯一有效的技巧是加密整个登录过程,在一般情况下可以使用 SSL。在本项目的情况下, 由于采用的是具有 GUI 的客户端,所以也可以采用自己设计的不对称加密方式。我们认识到, 传输前的在客户端的哈希不能提供有效的保护,因为被哈希的版本可能被拦截和重放。 6))))会话会话会话会话 ID 保护保护保护保护 理想情况下,用户的所有会话应该使用加密保护。这样会话 ID(cookie )就不会被从网络 上取到,杜绝了最大的会话 ID 暴露的风险。 7))))信任关系信任关系信任关系信任关系 整个 PDM 体系结构应该防止组件之间隐形的信任。每个组件应该对和它有界面的组件认证 自己,除非有充足的理由不这样做。如果需要信任的关系,应该有严格的过程和体系结构机制, 来确保随着体系结构的发展,这样的信任不会被滥用。 4,,,,注入式漏洞注入式漏洞注入式漏洞注入式漏洞 Web 应用程序在访问外部系统时会传递参数。攻击者可以把恶意代码嵌入到参数中,通过 Web 应用传递到其他系统,外部系统可能以 Web 应用的身份执行这些命令,这称之为注入式漏 洞(Injection Flaws ),例如:  通过系统调用操作系统函数,通过 shell 命令执行外部程序;  通过 SQL 注入调用后台数据库;  用 Perl ,python 或其他语言编写的脚本都可以被注入到设计不完善的 Web 应用中。 我们发现,许多 Web 应用程序利用操作系统的扩展程序实现它们的功能。例如使用 Sendmail 发送邮件。当 Web 应用程序将 HTTP 请求中的信息作为外部请求传递给这些程序的时候,必须 谨慎。否则,攻击者能够在信息中注入特殊字符、恶意命令或命令修改器,而 Web 应用程序只 会盲目地传送过去执行。 SQL 注入也是一种广泛传播的危险的注入形式。为了攻击目标数据库,攻击者必须找到由 Web 应用程序传递给数据库的参数,并通过在参数中嵌入 SQL 命令欺骗 Web 应用程序,使它把 恶意查询转发给数据库,从而获得、破坏甚至摧毁数据库内容。 我们项目组采用的保护方法为: 1))))避免使用外部解释器避免使用外部解释器避免使用外部解释器避免使用外部解释器 对于许多 shell 命令和系统调用来说,都存在完成相应功能的库函数,应尽量使用这种不需 要解释器的方式。 2))))对数据进行严格验证对数据进行严格验证对数据进行严格验证对数据进行严格验证 对于涉及到的后台数据库调用,应该对数据进行严格验证,保证其中不存在恶意内容。在 我们的系统中,要求尽量采用安全性较高的存储过程和参数化查询,但仍要保证输入内容只当 作数据使用。 3))))最小权限最小权限最小权限最小权限 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 76 - 把 Web 应用程序设置为能满足需要的最小权限运行。 4))))命令中的信息进行严格检查命令中的信息进行严格检查命令中的信息进行严格检查命令中的信息进行严格检查 当不得不使用外部命令时,任何插入到命令中的信息都必须进行严格检查,并提供相应的 机制处理可能的错误、超时或阻塞。 5,,,,不安全不安全不安全不安全的的的的存储存储存储存储 作为 PDM 系统的 Web 应用,一定需要在数据库或文件系统中保存一些敏感信息,如密码、 帐户记录等。我们已经决定使用某些加密算法来保护这些信息,但开发组还是提醒每一个成员, 下面这些方法是不恰当的:  没有加密关键数据;  密钥,证书和密码存储在不安全的位置上;  秘密内容不恰当地存储在内存中;  密钥的随机性来源不好;  加密算法选择不好;  请不要轻率的发明新的加密算法;  没有包括对加密密钥交换的支持,及其他必要的维护过程。 我们项目组采用的保护方法为: 1 ))))慎重的数据存储方法慎重的数据存储方法慎重的数据存储方法慎重的数据存储方法  除非必要,尽量少保存数据。  存储密码的摘要(例如 SHA-1)而非加密的密码。  必须使用加密算法时,尽量采用公开的密码算法库。并反复检查自己的设计,保证秘 密信息如密钥、证书、密码被妥善存储了。 2))))防止非法访问文件防止非法访问文件防止非法访问文件防止非法访问文件 为了防止非法访问,在操作系统目录下,所有文件都隐含了真实的文件名,然后将读/写控 制权全部交给操作系统的超级用户。由系统管理员建立帐号,一般用户无法找到具体所需的文 件。一且将文件交给 PDM 管理,那么就在 PDM 中生成新的、只有 PDM 才能解释的名字,并 由 PDM 控制读/写控制权。这样即使在操作系统的列表命令下,虽然在文件目录中可以列出文 件名,但无权限的用户也无法读/与和执行。本系统安全机制的层次结构如下图所示。 6,,,,关注系统配置上的不安全因素关注系统配置上的不安全因素关注系统配置上的不安全因素关注系统配置上的不安全因素 尽管上述这些策略并不能包括安全防范的全部内容,但是面面俱到的采取一切安全防范措 施也是不可取的,因为这会大大提高系统的造价,同时显著降低系统的性能。分析告诉我们, 只要肯在关键点上下功夫,把这些措施真正在设计中落实,系统的安全性将会大幅度提高,再 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 77 - 加上系统配置注意如下几点  1)注意及时为服务器打补丁; 2 )设置正确的文件和目录权限;  3)防止不必要的服务,包括内容管理和远程系统管理被运行;  4)避免缺省密码的缺省的帐号;  5)不能向客户提供包含太多信息的错误信息  6)使用经过实验验证的传输层加密方法。 那么构建一个安全性强的 PDM 系统,使系统的安全性指标达到要求应该是没有问题的。 五五五五、、、、传传传传输层加密的方法输层加密的方法输层加密的方法输层加密的方法 本 PDM 系统在采用 Web Service 模式下,由于传输信息的敏感性,必须研究合适的传输层 加密方法,以保证即使第三方截获了加密的数据,也将难以解密该数据,加密用于达到以下目 的:  保密性:防止用户的标识或数据被读取。  数据完整性:防止数据被更改。  身份验证:确保数据发自特定的一方。 尽管在 Web 领域,可以采用诸如 SSL 这一类通用方法,但是 PDM 系统往往希望传输体积 庞大的文件,SSL 对效率影响太大,可使用性也不是很好。另一方面,如果采用通用的数据加 密方式,尽管设计上可能比较简单,但加密思想容易被人理解而失去秘密。综合各种情况综合 考虑,还是需要在设计中平衡可使用性、效率、私密性等各种因素,自主构建数据加密流程。 我们可以考虑这样几种方案。 1,,,,对称加密方法对称加密方法对称加密方法对称加密方法 这也称之为私钥加密方法,其特点是使用单个私钥来加密和解密数据。由于具有密钥的任 意一方都可以使用该密钥解密数据,因此必须保护密钥不被未经授权的代理得到。私钥加密之 所以称为对称加密,是因为同一密钥既用于加密又用于解密。私钥加密算法非常快,特别适用 于对较大的数据流执行加密转换。 私钥加密的缺点是它假定双方已就密钥达成协议,但是一旦传输信息被解密,攻击者就可 以把所获得的知识延伸到其他信息中去,这将无密可保。本项目除极个别的情况外,不准备采 取这个方法。 2,,,,不对称加密不对称加密不对称加密不对称加密 不对称加密也称之为公钥加密,它使用一个必须对未经授权的用户保密的私钥和一个可以 对任何人可以公开的公钥。公钥和私钥都在数学上相关联,公钥可以被任何人使用,该密钥用 于加密要发送到私钥持有者的数据。两个密钥对于通信会话都是唯一的。公钥加密算法之所以 称为不对称算法,原因是需要用一个密钥加密数据而需要用另一个密钥来解密数据。 标准的不对称加密方法原理如下:假定有甲乙双方,乙方希望把数据传给甲方,我们可以 按照如下图的方式流程加密。 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 78 - 甲方获得乙方信息传输的请求以后,首先甲方应用程序自动生成一个公钥/私钥对,这个密 钥对从数学上是关联的,也就是说用公钥加密的数据只能用私钥解密。然后甲方把公钥传给乙 方,乙方接着使用这个密钥(公钥)加密需要传输的消息。 然后,乙方自动生成用于处理返回数据的公钥和私钥对。乙方再将这个经过加密的消息(连 同公钥(乙))发送给甲方,而甲方使用它本地私钥来解密这个消息。 此后,甲方需要把将处理完了的消息发送回乙方,它会利用上述的逆方案,使用公钥(乙) 来加密甲方的消息发送。然后,乙方使用与这个公钥相关联的私钥来解密该消息。当处理结束 以后,甲乙双方都把生的公钥私钥对删除掉,避免下一次请求使用同样的密钥。 在传输公钥期间,未经授权的代理可能截获该密钥。而且,同一代理也可能截获来自乙方 的加密消息。但是,该代理无法用公钥解密该消息。因为该消息只能用甲方的私钥来解密,而 该私钥并没有被传输。 不对称加密保密性比较好,但是效率比较低,系统结构也比较复杂,综合各种情况考虑, 我们希望研发一种传输效率能达到要求,又有一定保密性的不对称加密方法。 六六六六、、、、不对称加密框架的架构设计不对称加密框架的架构设计不对称加密框架的架构设计不对称加密框架的架构设计 1,,,,PDM 系统系统系统系统不对称加密基本思路不对称加密基本思路不对称加密基本思路不对称加密基本思路 上面的不对称加密方法虽然保密性比较好,但是对于 PDM 这样需要传输大型文件的系统, 对效率的要求比较高,需要寻求一种既有一定的保密性,效率又能达到用户需要的文件加密方 案。在安全的问题上,我们不能认为安全是高于一切的目标,而需要在安全性、可用性以及效 率之间寻求平衡。这三个非功能需求事实上是相互冲突的。假定我们有了一个非常安全的系统, 但是数据发送很慢,超过了人们忍耐的极限,那这个系统就不会有人用了。另一方面,安全性 越好的系统,一般使用起来越不方便,使用很麻烦的系统也可能就是个摆设了。讨论安全问题, 还需要注意安全是有时效性的,数据加密只要保证在相应的时效范围内不被解开就可以了,并 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 79 - 不是加密方案越复杂越好,否则对其他几个方面(效率、可用性)影响会太大反而不可取。 我们先来研究一下标准不对称加密方法产生效率问题的主要原因是:在一次请求中需要多 次往返,但是,由于一次请求实际上是属于一个完整的过程,有些密钥数据是可以重用的,所 以,我们需要研究如何在保证一定安全性的条件下,减少往返次数,就有利于提高传输效率。 首先,我们定义在正式文件传输的时候,利用 RC2 加密算法作为公钥,这种算法的特点是 加解密速度快,而且形成的加密文件体积并不会增大。我们要求,如果传输的是比较大的图纸 类文件,先要把它压缩后再加密。如果是数据库的表文件,则先把它转换成 XML 文件,然后再 进行加密。 我们再定义,所谓私钥指的是一个自定义算法,这个算法可以根据需要自己编写,因此具 有很强的私密性,而这个算法具体的计算参数,可以在运行中随机产生的,这样一来,私钥也 就是可变的了。 我们更进一步考虑,在每个约定的使用方,必须存在一个“证书”,以证明这个请求方是约 定的对象。各方面的“证书”应该是一致的,以保证所有参与数据传输的各方,都是事先约定 的成员。这个所谓“证书”实际上是一个 RSA 加密算法的密钥,它是以 XML 文件形式表现的, 在保存的时候也可以对它进行简单的加密。我们同时还用它对登录密码和公钥传输进行加密。 RSA 算法的特点是算法复杂而且加解密速度比较慢,却正适合对密码(或者密钥)这些比较小 的内容进行加解密处理。 为了避免“证书”泄露,需要定期由服务方自动生成新的“证书”,然后通过系统专门的功 能,自动安装到各个约定对象的服务器中。客户端一律使用内网,不存在与 Web 系統的直接联 系。这就保证了系统的安全性与可用性达到要求。 2,,,,传输层加密传输层加密传输层加密传输层加密框架的架构设计框架的架构设计框架的架构设计框架的架构设计 整个传输层加密框架的架构如下图所示,在这个结构中,我们力争把一些通用的处理业务 封装成独立的业务组件,以提高系统的可理解与可维护性。 下面我们将沿着处理组件和业务方法的思路来讨论这个方案的设计原理。为了减少开发难 度,提高系统的可维护性,本项目传输层加解密体系结构采用了业务组件服务的模型,这些业 务服务组件包括一个在服务方和客户方通用的加解密处理组件(EncDec.dll ),一个服务方业务 组件(SBusiness.dll ),以及一个客户方业务组件(CBusiness.dll ),下面分别介绍这几个组件设 计中主要考虑的问题。 3,,,,加解密处理组件加解密处理组件加解密处理组件加解密处理组件((((EncDec.dll )))) ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 80 - 我们先考虑加解密处理组件(EncDec.dll ),这是提供系统加解密服务的公共组件,无论是 服务器还是客户端都需要这个组件支撑,它具备 RSA、RC2 和 M123 三套数据加解密方法组。 1))))RSA 加解密方法组加解密方法组加解密方法组加解密方法组 RSA 密钥将作为证书存在,为了简化同类型的操作,构建了两个专用的方法来完成加解密 处理,数据的输入和输出都为字节数组。 2))))RC2 加解密方法组加解密方法组加解密方法组加解密方法组 在这个加解密框架中中,我们把 RC2 算法作为公钥存在,它是加解密传输内容的最主要算 法。这种算法加解密速度快,加密后的文件大小不会膨胀。这个方法要求加密传入的数据是字 符串,其原因在于我们希望大部分数据能转换成 XML 格式(由于 XML Schema 标准的推行,即 使二进制数据也可以用 XML 表达),加密后的数据为字节数组。反之,解密的传入值为字节数组, 而解密后的传出值为字符串。加解密的密钥分别是 16 字节的 Key 和 8 字节的 IV,这两个数据 是由系统随即自动地产生的,将作为公钥经过加密后传输。 3))))M123 加解密方法组加解密方法组加解密方法组加解密方法组 这里所谓的 M123 加解密方法,实际上是一个自定义算法(这个算法还可以根据需要改变)。 我们把这个算法整个作为私钥存在,以使传输层加密具有私密性。这个算法与公钥的关联以及 区别,靠的是三个数字(m1 ,m2 ,m3 ),所以我们也由此把这个算法称作 M123 。这三个数字 决定了加密的结果(所以它们也是一种密钥),而且这三个数字是系统随机自动的产生,这就确 保了私钥的随机性。从算法的角度,这里使用了算术加逻辑的方法,也就是: B=((A XOR m1 )+m2) XOR m3 但是为了避免相同字符得到同一个变形码,使攻击者找到规律,我们把字符串的上一个字 符的内码经过某种计算,作为下一个字符加密的 m1 码存在,也就是: m1=B+m3 这样就实现了某种形式的链型加密,增加了破译的难度。这个加解密算法的作用,是作为 一种辅助,来对相互传输的公钥做二次加密,并不直接处理传输内容,速度上影响很小。而且 这种二次加密就使公钥和私钥之间具有了关联,符合不对称加密的定义。 4 ))))读取读取读取读取““““证书证书证书证书””””方法方法方法方法 不论是服务方还是客户方,都需要有一个读取证书的方法,其方法如下,其传入值是证书 所在路径,返回值是以XML表达的RSA密钥。 4,,,,服务方业务组件服务方业务组件服务方业务组件服务方业务组件((((SBusiness.dllSBusiness.dllSBusiness.dllSBusiness.dll )))) 本组件主要负责处理 Web Service 服务器端的一些公共非对称加解密服务业务,包括“证书” 的生成,公钥(甲)的生成,对客户端传过来的公钥(乙)的解密。 1 ))))生成生成生成生成双方的双方的双方的双方的““““证书证书证书证书”””” 在服务方需要有专门生成“证书”的能力,生成的证书通过专门设计的系统传递给约定方, 并且在各方安装,这个过程应该是自动的。这个“证书”事实上是一个随机生成的 RSA 加密算 法密钥,它以 XML 的形式表现。 2))))生成生成生成生成并且加密并且加密并且加密并且加密公钥公钥公钥公钥((((甲甲甲甲)))) 为了保证公钥有适当的动态性,我们设计在每当服务被第一个客户启动的时候,自动随机 的生成公钥(甲),经过 RSA 加密后保留在服务方,并且以静态数据存在,在任何客户登录成 功以后把此加密公钥传输给相应的客户。具体流程如下图所示。 公钥(甲)是由 key 、iv 、m1 、m2 和 m3 五个数据组成,为了简化步骤以及保证传输速率, 我们把它们先转换成字符串,用“&”作为标识符连接起来,然后作为一个整体加密和传输。使 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 81 - 用“&”作为标识符的原因,是因为 m1 ,m2 ,m3 的类型是数字,而 key 和 iv 分别是 16 位和 8 位的字节数组,发生冲突的机率很小。其说明性代码如下。 3 3 3 3))))解密公钥解密公钥解密公钥解密公钥((((乙乙乙乙)))) 本系统在设计的时候认为,为了确保安全性,公钥在传输的时候需要加密,而这个公钥加 密方法也成为关联公钥和私钥算法的基础。为了正确的设计解密公钥(乙)的方法,首先我们 需要对整个系统的不对称加密方案进行梳理。由于解密是加密的逆运算,所以只有说清楚加密 方法,才可以正确设计解密方法,本项目加解密放案是这样考虑的:我们定义公钥(甲)和公 钥(乙)在加密方案上是有区别的:  服务方的公钥向客户方传输的时候,由于不需要频繁传输,所以使用安全性比较好的 RSA加密方法,利用“证书”作为密钥对它进行加解密,具体方法已经在上面讨论过。  而在客户请求的时候,先用客户随机生成的RC2密钥对请求加密,这个RC2密钥作为客 户公钥(乙),我们将利用服务方公钥(甲),先进行M123加密,然后再采用RC2加密, 与请求内容一起打包传输。 这种对公钥(乙)的二次加密类似于连环锁,在不清楚算法的情况下,解密将会很耗费时 间,而且需要大型计算机进行穷举。由于每次请求公钥都是随机生成的,所以即使某次请求被 破解(这可能已经是很长时间以后的事情了),也不可能把所获得的密钥知识外推到其他的数 据传输中去,这就提高了传输的安全性。我们所定义的客户一次请求的加解密流程如下图所示。 客户端请求工作流程我们解释如下:  首先,当客户发生一次请求的时候(注意:这里所说的客户端并不是最终客户,对本系 统而言它实际上是请求方本地的服务器),客户端自动随机生成RC2公钥(乙),我们 已经说过,它们分别是16 字节的Key 和8字节的IV。  客户端用这个密钥对请求数据加密。  为了减少加密动作次数,我们把客户端生成的16 字节的Key 和8字节的IV 分别转成字符 串,然后中间用“&”作标识符,把这两个字符串连起来,我们称之为Key&IV 。  客户端用已经保留在当地的M123 (甲)的m1 、m2 、m3 作参数,对Key&IV 加密。  再使用RC2 (甲)对已经加密后的Key&IV 作二次加密。  把这个加密后的内容与加密后的请求一起打包发送给服务端。 服务端响应请求的工作流程我们解释如下:  首先利用服务已经存在的RC2 (甲)密钥对Key&IV 解密(先外后内)。  再利用服务已经存在的M123 (甲)的三个参数(m1 ,m2 ,m3 )进行二次解密。  然后利用“&”标识符把Key&IV 的Key 和IV 分开,并分别转换回字节数组的表示。  然后再用这个密钥(注意这属于公钥(乙))对已经加密的请求解密。  已经解密的请求将按照正常情况处理。 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 82 - 图 4-8 虚线框部分为服务器端解密方法的流程,该方法在SBusiness.dll中,具体说明性代 码如下。 5,,,,客户客户客户客户方业务组件方业务组件方业务组件方业务组件((((CCCCBusiness.dllBusiness.dllBusiness.dllBusiness.dll )))) 客户方除了需要与服务方一样的 EncDec.dll 支持以外,还需要满足客户方加解密流程的客 户方业务组件(CBusiness.dll ),我们可以设计这个客户方组件的两个方法,包括生成公钥(乙) 和解密公钥(甲)方法。 1))))生成公钥生成公钥生成公钥生成公钥((((乙乙乙乙))))方法方法方法方法 这个方法满足了上面所述加解密流程对客户端的要求。 2))))解密公钥解密公钥解密公钥解密公钥((((甲甲甲甲))))方法方法方法方法 我们已经讨论过,在本项目的加解密方案中,对公钥(甲)的解密需要使用 RSA 密钥。而 这个密钥已经以证书形式存在于客户方了。 七七七七、、、、传输层加解密业务流程分析传输层加解密业务流程分析传输层加解密业务流程分析传输层加解密业务流程分析 有了上面的这些组件,整个传输层不对称加解密的实现就变得相对容易,而且,我们还可 以根据需要改变这些业务流程,使加解密流程按照新的思想进行重新组合。下面介绍本项目加 解密流程的有关问题。首先在服务端启动服务的时候需要建立这一阶段服务的公钥(甲)。 1,,,,客户登录获取公钥客户登录获取公钥客户登录获取公钥客户登录获取公钥((((甲甲甲甲)))) 客户第一次申请需要登录,此时客户用 RSA 加密的密码进行登录,登录成功以后,服务方 就把已经加密的公钥(甲)传递给客户方,由客户程序暂时保留,此后客户对公钥(乙)的加 密将利用所保留的公钥(甲),直到客户退出,如下图所示。 2,,,,不对称加密不对称加密不对称加密不对称加密业务业务业务业务流程流程流程流程 利用上面的组件,我们就可以建立任何需要加密的一个请求/响应往返所需要的工作流程了, 以这个流程为基础,构建具体的系统就不是十分困难的事情。这种把业务细节封装成业务组件, 再用单独的层来构建业务流程的方法,从本质上也是属于基于服务的方法(业务组件被定义成 业务服务)。我们发现采用这种方法以后,具体的业务流程搭建将变得非常容易,而且业务流程 的变更也会变得相当敏捷。另外,当系统发生变更和升级的时候,只需要添加适当的业务组件 就可以了,使系统的可维护性得以提高。本项目安全的请求/响应整体业务流程如下:  当客户发出某个服务的请求的时候,客户自动生成一对随机密钥,包括 RC2 公钥(Key , IV),以及连接私钥(M123 自定义加密算法)的三个参数(m1 ,m2 ,m3 )。我们将用 这个动态 RC2 密钥用来加密请求内容,再由保留在客户方的公钥(甲)来加密公钥(乙), 并打包一起发送给服务方。  服务方收到后,通过本地的公钥(甲)来解密相应的公钥(乙),再用这个已经解开的 密钥来解密请求内容。  服务方用普通方式来处理请求。  返回的数据,也用同一个公钥(乙)中的 RC2 密钥加密返回。注意,此时的数据中并 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 83 - 不包括密钥本身。  客户方收到返回数据之后,用还保存在客户方的 RC2 密钥(乙)解密,完成这一次操 作以后,这一次往返所使用的公钥(乙)就可以删除掉了。 整个业务流程如下图所示。 这样做有几个好处:  只有第一次登录使用 RSA 加密,整体速度上不受影响,经测试能达到客户要求。  该方法的易使用性很好,用户不需要多余的工作。  攻击者即使截获了一个文件并成功解密,也无法利用已有的知识外推到其他传输中的 文件,提高了传输的安全性。  攻击者即使盗取了存储在服务器(或客户端)上的证书,也无法解开传输中的请求和 结果。因为实际使用的公钥是在服务器上随机的产生的,其产生频度为每次服务应用 程序被客户启动.  通过定期更换存储的证书,还可以进一步提升系统的安全性。  整个加密流程是自定义的,如果不了解具体项目传输层加密的思想,即使截获了数据, 也很难利用通常的思维进行解密,加大了解密的难度。 由于本项目定义的加密方法具有一定的反模式思维,所以直接开发风险是很大的。为此, 应该首先进行了垂直原型开发,以验证这个思想和架构的可行性。 安全性与系统其它的非功能需求,比如效率、易使用性等是矛盾的,所以需要平衡各方面 因素,寻求一个平衡的解决方案,既不能仅仅过分强调安全,使系统最终无法使用,更不能不考 虑安全问题,使系统失去使用价值。在设计方案发生争论的时候,我们可以快速研发小型的验 证性原型,用原型来支持某种主张,而不是争论不休没有结果,这些思想对整个项目的成功至 关重要。 2.5 产品产品产品产品架构模型的架构模型的架构模型的架构模型的分析与分析与分析与分析与设计设计设计设计 一一一一、、、、总体架构模型的建立总体架构模型的建立总体架构模型的建立总体架构模型的建立 为了使 PDM 系统发挥更大的作用,并且减少开发上的难度,本项目在设计的时候,共分成 三个子系统,每个子系统分配给一个独立的开发组完成,它们包括: ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 84 - 项目管理与过程管理子系统(Project Management and Process Management ,PM&PM)。 工程图档与文档管理子系统(Engineering Drawing and Document Management ,Ed&DM )。 配置管理与变更管理子系统(Configuration Management and Change Management , CM&CM)。 各子系统要求设计成具有独立系统架构的完整系统,各子系统之间不得交互,他们只能通 过共享的数据总线(Data Bus )进行交互,这样就减少了各子系统之间的偶合性,增加了子系统 的内聚度,减少了开发、集成、调试、维护以及后期升级的难度。系统的整体结构关系如下图 所示。 系统的数据总线通过 Web Service 技术,隔离了远程异构数据的物理位置、数据格式等信息, 把本地数据和远程数据结合起来,使用者与开发者并不需要知道这些远程异构数据源的具体情 况,这就大大减少了开发和应用上的难度。系统除了提供共享的数据总线以外,还提供了公用 的数据格式与交换、缓存和安全机制,提高了模块的可复用性 系统在设计中还注意到,系统采用垂直分层,水平分模块,力争结构非常清晰。垂直方向 基本按照表示层、业务层和持久化三个层次划分,使关注点分离功能分割清晰,而且通过接口 分解了模块之间的耦合性,便于系统维护。 具体地说:在表示层,按垂直方向分离了用户接口组件和用户接口过程组件;在业务层, 按照统一的接口对外,水平分离了业务流程、业务组件和业务实体;在持久化层,水平分离了 数据访问组件以及服务代理,实现了统一的数据总线机制,这样一来,就使这个体系结构非常 清晰。 二二二二、、、、子系统架构模型的建立子系统架构模型的建立子系统架构模型的建立子系统架构模型的建立 本系统要求子系统是具有独立架构的系统,各子系统之间通过数据总线进行交互,这种规 定确保了设计与开发的独立性,下面我们简要介绍各个子系统的高层架构。 1,,,,项目管理与过程管理子系统项目管理与过程管理子系统项目管理与过程管理子系统项目管理与过程管理子系统((((PM&PM)))) 本子系统是这个项目最具有特征的部分,由于合作方协同设计的要求,本子系统需要对本 设计项目与合作方进行统一的无缝的项目管理与监控,所以具备一般 PDM 系统所不具备的功 能。子系统的下层是分为模块,也就是独立的业务单元,项目设计规则要求,各模块是独立设 计的,模块之间不能直接交互,而只能通过接口用规则的方法交互,项目的这个要求,就确保 了模块的高内聚与低偶合,确保了后期的升级和维护成本比较低。该子系统的顶层架构如下图 所示。 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 85 - 各个模块的功能简单描述如下。 业务层:  Processes Processing :业务流程处理主模块,包括创建、修改、查询、审批、统计流程  Project Definition :项目组织定义业务模块。  Process Definition :协同项目开发过程定义业务模块。  Process unit Definition :过程单元定义业务模块。  Process Management :过程管理业务模块。  Tasks Assigned :人员任务指派业务模块。  Process Monitor :过程监控业务模块。  Permissions Assigned :操作权限指派业务模块。  Partners to Monitor :合作方监控业务模块。 表示层:  UI Management :管理交互模块。  UI Definition :定义交互模块。  UI Assigned :指派交互模块。  UI Monitor :监控交互模块。 2,,,,工程图档与文档管理子系统工程图档与文档管理子系统工程图档与文档管理子系统工程图档与文档管理子系统((((Ed&DM )))) 工程图档与文档管理子系统是这个项目最重要的部分,它也是 PDM 系统的核心功能,主要 用于检索、修改、变更工艺过程中所需要的各类设计文档与图形文档,其中可能还包括三维演 示视频文档,本子系统的顶层架构如下图所示。 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 86 - 各个模块的功能简单描述如下。 业务层:  Document Structures :工程图档结构建立业务模块。  Document Management :工程图档管理业务模块。  Basic Information :工程图档基本信息录入业务模块。  Check-in/Check-out :工程图档检入/检出业务模块。  Document Storage :工程图档入库业务模块。  Document Annotation :工程图档批注业务模块。 表示层:  UI File Information :工程图档信息显示交互模块。  UI Image Display :图形显示交互模块。  UI Video Display :工程视频显示交互模块。  UI Check-in/Check-out :工程图档检入/检出交互模块。  UI Basic Information :工程图档基本信息录入交互模块。  UI Document Annotation :工程图档批注交互模块。 3,,,,配置管理与变更管理子系统配置管理与变更管理子系统配置管理与变更管理子系统配置管理与变更管理子系统((((CM&CM)))) 本子系统是这个项目开发中最困难也是最具挑战的部分,它主要用于处理整个工程文档的 演化与版本控制,其中包括可视化的版本跟踪,企业编码的生成与应用,批次文档的查询与组 合,以及产品零部件的配置等重要信息处理。可以说,PDM 文件处理,只有和配置管理系统结 合起来,才可能发挥更大的作用。而变更管理是新产品设计与发布的重要一环,PDM 文件系统 必须对变更管理提供有效的支持。本子系统的顶层架构如下图所示。 各个模块的功能简单描述如下。 业务层:  Structure Tree Generated :结构树生成业务模块。  Version Evolution :版本演化生成业务模块。  Batch Information :产品批次文档信息查询业务模块。  Batch Information Denerate :产品批次信息生成业务模块。  Components Configuration Query :产品零部件配置查询业务模块。  Version Control :版本数据控制业务模块。  Enterprise Coding Denerate : 企业编码生成业务模块。  Enterprise Coding Definition :企业编码定义业务模块。 表示层: ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 87 -  UI Structure Tree :产品结构树显示与交互模块。  UI Version Evolution : 产品版本演化显示与交互模块。  UI Product Batch :产品批次文档信息显示与交互模块。  UI Components Configuration : 产品零部件配置显示与交互模块。 上面我们通过一个实际项目的案例,仔细探讨了在设计过程中,模型驱动的架构设计所需 要考虑的若干问题。探讨了在这样一个特殊项目背景下我们对一些关键问题的详细思考过程, 包括: 1)项目总体概念架构的选型。 2)产品系统级的需求分析。 3)为保证文档的一致性所构建的并发处理框架需求分析。 4)在远程交互环境下的数据模型建立。 5)系统安全性策略分析。 6)传输层安全问题的解决以及技术实现的原型分析。 7)整个系统的架构模型设计。 这些问题的解决对项目的成功至关重要。在上述问题的讨论过程中,我们并不是仅仅给出 了结论,而是从方法论的层面,站在更高的视角仔细审视解决问题的思考过程,而这种思考方 式是可复制的,因而也是可以进一步发展的。 在软件工程领域是需要创新思想的,但我们并不认为盲目的采用某种新技术就是创新了。 一个软件项目只要条件许可,应该尽可能采用成熟技术以保证系统可靠性并降低开发风险。软 件工程领域的创新应该更多的在业务方法和工程方法中寻求突破,当然这种创新并不是对经典 方法论的全面推翻,但需要对经典方法论不足之处实施改良,软件工程学正是在这种不断改进 中向前发展的。 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 88 - 第三章 软件架构的重构与优化 3.1 研发型项目的研发型项目的研发型项目的研发型项目的敏捷过程与重构敏捷过程与重构敏捷过程与重构敏捷过程与重构 一一一一、、、、敏捷过程的提出的原因敏捷过程的提出的原因敏捷过程的提出的原因敏捷过程的提出的原因 1,,,,规范式过程的问题分析规范式过程的问题分析规范式过程的问题分析规范式过程的问题分析 规范化的软件项目过程经过 20 年的应用,人们发现存在很多问题,特别是在研发型项目中, 很多问题是后期产生而不是早期能够发现,于是人们做了很多调查和研究,一些发人深省的研 究结果如下:  大约 2/3 的项目会显著超出费用预算(Lederer and Prasad 1992 )。  产品中 64% 的功能很少或者从不会被使用(Johnson 2002 )。  一般项目花费的时间会超出进度表 100% (Stndish 2002 )。 这是为什么?为了解决这些问题,这就迫使我们仔细研究项目失败的原因,根据分析,人 们归纳起来可以有 5 个原因。 1))))初期的估计偏差可能很大初期的估计偏差可能很大初期的估计偏差可能很大初期的估计偏差可能很大 下图显示了 Boehm 所考虑的不确定性在顺序开发过程不同点的范围,这个图称之为不确定 性锥形。 图上表明,在项目定义阶段,对进度估计的偏差可能达到 60% ~160% ,也就是说一 个预 期 20 周完成的项目,实际花费可能在 12 ~32 周之间。而在写下需求之后,估计的偏差可 能还在±15% ,这时的 20 周预期可能实际上可能会花 17 ~23 周。这么大的预估偏差根本就无 法实施有效的项目管理。 2))))活动不会提前完成活动不会提前完成活动不会提前完成活动不会提前完成 如果一项工作在甘特图上分配了 5 天,即使能够提前完成,处理这个活动的员工一定会用 满 5 天。在不少企业文化中,一项活动提前完成,往往被指责为当初他做的估计不准确,或者 会另派其它的任务给他,为什么要冒这个风险来提前完成呢?人的本性就是如此:用多余的时 间去做一些对自己有价值,但对别人不一定有用的事情。 3))))延误沿着进度表向下传递延误沿着进度表向下传递延误沿着进度表向下传递延误沿着进度表向下传递 由于传统的计划是基于活动的,因此它们主要关注活动之间的依赖性。考察下面的甘特图, 它显示了 4 项活动及它们之间的依赖关系。 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 89 - 关键之处在于,即使一个如此简单的案例中,在启动测试之前也有 3 件事情必须发生,但 是下面任何一件事情,都可能导致测试推迟:  用户界面编码结束时间延误。  对中间层编码花费时间超出计划。  中间层编码花费时间符合要求,但是向数据库添加数据表结束过晚,导致延误了测试 时间。  未安排好测试人员。 也就是说提前启动测试需要完成很多事情,其中一件事情延误,都可能导致总体上的延误。 事实上我们已经确认了活动很少会提前完成,所以发生的绝大多数事情是延误,而这种延误会 沿着进度表传递下去,最终导致后续项目很少会提前启动。 4))))不按照优先级开发功能不按照优先级开发功能不按照优先级开发功能不按照优先级开发功能 传统项目管理方法还有一个缺点,那就是制定的计划没有按照对用户或者客户所具有的价 值大小来排列工作的优先级。很多传统的计划实际上假定工作都可以完成,工作的顺序主要是 由依赖性来决定。但是随着项目结束时间的逼近,开发小组会匆忙放弃一些功能以跟上进度, 由于不是按照功能优先级顺序开发的,某些被放弃的功能反而比交付的功能更重要。 5))))忽视了不确定性忽视了不确定性忽视了不确定性忽视了不确定性 传统规划方法的第 5 个缺点,是不承认不确定性的存在。人们假定最初的需求分析就可以 产生对产品来说完整的、完善的定义。我们假定用户在计划覆盖的整个时间内都不会改变想法, 他们的观点也不会更细化,也不会提出新的需求。 与之类似,我们还忽视了如何构建产品这样的不确定性,某种技术在实现中才发现并不一 定合适,但我们已经给它分配了确定的时间(两个星期),事实上我们不可能指望一开始就确定 项目进程中所需要的所有活动,但我们又不愿意承认这一点。 在分析了传统项目管理方法所存在的问题以后,我们对那么多项目令人失望就不会感到奇 怪了。在今天的项目中,人们往往对标准的执行达到了迷信的地步,以为只要严格执行了标准 就能够生产出高质量的软件,但是严酷的现实往往又告诉我们相反的结论,因此,在这些分析 的基础上,我们就必须考虑解决这些问题的办法。 二二二二、、、、敏捷过程的价值观与方法论敏捷过程的价值观与方法论敏捷过程的价值观与方法论敏捷过程的价值观与方法论 1,,,,敏捷模型的价值观敏捷模型的价值观敏捷模型的价值观敏捷模型的价值观 1))))变化的业务现实是敏捷过程提出来的原因变化的业务现实是敏捷过程提出来的原因变化的业务现实是敏捷过程提出来的原因变化的业务现实是敏捷过程提出来的原因 为什么我们要把变化作为重要的因素来考虑呢?这是因为在当今的企业环境下,变化就意 味着胜出。如果一个企业失去了探索精神,而热衷于停留在早期的工作上,它的发展也就停止 了,但是发展就意味着变化。 我们总是希望在深入收集需求的基础上,能够制定一个稳定的、考虑周全的计划。但是站 在用户的角度来考虑问题,在市场发展如此易变的环境下,执行长期计划几乎是不可能的,需 求不变更也几乎是不可能的,因此寻求一种在滚动基础上执行计划的方法论成为解决问题的关 键。为了获取这样的方法论,人们对大量的成功软件项目实践进行了分析和研究,通过归纳发 现软件过程基本上可以分为来种类型,也就是静态的重量级过程和动态的轻量级过程。 2))))敏捷模型的价值观敏捷模型的价值观敏捷模型的价值观敏捷模型的价值观 在 2001 年由 17 个敏捷专家签名发布的“敏捷软件宣言”(Manifesto for Agile Software ),是 软件工程的一个重要里程碑,它是这样表达的:我们展示开发的更好途径,软件通过它实现并 且帮助别人使用它,通过这项工作我们实现下列价值:  个人与交互 胜过 开发过程与工具;  可用的软件 胜过 复杂的文档; ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 90 -  寻求客户的合作 胜过 对合同的谈判;  对变化的响应 胜过 始终遵循固定的计划。 这些是在项目体现的直接价值,我们认为还有更多的价值。 这就是敏捷方法的价值观。敏捷过程代表着软件工程领域的一种变革力量,它把人与变化 作为一个重要的要素进行考虑,把重构作为实现这种方法的基础。它通过增量交付保证了 IT 与 用户业务发展的同步,减少了用户的风险,从而增加了用户对 IT 产品的信任。敏捷性是一个组 织最有价值的东西,因为它可以满足不断变化的市场需求,具备在机遇失去之前或者在竞争对 手之前抓住机会的灵活性。 2,,,,敏捷模型的方法论敏捷模型的方法论敏捷模型的方法论敏捷模型的方法论 在敏捷宣言中,提出了敏捷软件开发最普遍的方法论: 我们遵循以下准则:  我们重视通过尽早、连续的提供有价值的软件来满足顾客。  欢迎更改需求,即使是在开发的后期。敏捷过程为了顾客有竞争力的利益来管理这些 变化。  经常性的发布可以工作的软件,从几个星期到几个月,我们偏爱短的时间周期。  在项目中业务人员和开发人员必须日常共同工作。  通过激发个体的努力完成计划。  给他们需要的环境,提供他们需要的支持,并且相信他们可以做好他们的工作。  最有效和最实际在开发团队内部传递知识的方法是面对面的交谈。  可以工作的软件是进度的主要度量指标。  敏捷过程促进持续的开发,发起人,开发者,使用者能维持一个不确定的恒定的步调。  持续地注意技术优势和良好设计来提高灵活性。  简单,不使工作最大化的艺术,才是开发的本质。  最好的架构、需求、和设计出现在有组织的团队中。  每隔一定时间,团队反省如何更加有效,然后调整他们的行为。 敏捷模型不同的方法论比较多,包括极限编程(XP)、Scrum 、功能驱动开发以及统一过程 等多种法,这些方法本质实际上是一样的。 归纳起来,任何一种敏捷过程的方法论都有如下一些特征。 1))))初期把目光关注在抽象层面上初期把目光关注在抽象层面上初期把目光关注在抽象层面上初期把目光关注在抽象层面上 一开始并不要事无巨细的收集详细的需求,而是把目光关注在抽象的层面上,以后在每个 迭代阶段增加细节。这种增量式的开发软件,然后在开发的每一阶段改善需求的方法,在现代 软件开发实践中取得了很好的效果。 2))))使用使用使用使用用户故事用户故事用户故事用户故事反映初始需求反映初始需求反映初始需求反映初始需求 在研究初始需求的时候,到底用什么方法描述比较好呢?在敏捷模型中推荐使用用户故事 (user story )。“用户故事”是一种轻量级的表达方式:。一旦选中了若干“故事”进入迭代周期, 就需要把这些用户故事用正规的方式把需求表达出来,也就是说每个迭代周期都有需求分析过 程,这个时候是视野比较小,也更容易把需求描述清楚。 用户故事是从客户的角度出发对功能的一个简短描述。一般的表达方式是:“作为(用户类 型),我们希望可以(能力)以便(业务价值)”,例如:“作为购书者,我们希望可以根据 ISBN 找到一本书,以便更快找到正确的书。” 并不需要一开始就把用户故事全部收集和记录下来,或者编写复杂的需求说明。不管怎么 说,收集用户故事应该相对比较容易,每个故事一个卡片,产品所有者和开发人员都比较容易 针对这样的简短描述进行交流。 3))))用户故事用户故事用户故事用户故事和主题和主题和主题和主题 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 91 - 有时把一组相关的用户故事被结合在一起,比如把这些故事卡片用回形针别在一起,当作 一个实体来看,我们常常称之为主题(theme )。还需要注意到的是,用户故事的主题往往构成 了架构的单元。一旦确定一次迭代需要完成哪些故事,就需要编写正规的需求文档,由于此时 的视野比较小,处理这样的问题一般是没有太大困难的。 4))))确定主题的优先级确定主题的优先级确定主题的优先级确定主题的优先级 即使我们有时间,也很少会有足够的时间来做所有的事情,所以需要确定优先级。尽管确 定优先级的责任由整个开发小组共同承担,但成果由产品所有者享用。遗憾的是,估计少量的 或者单个用户故事的价值是比较困难的,所以我们需要把若干用户故事或功能聚集到一些主题 当中。然后根据用户故事和主题之间的相互关系,来确定它们的优先级。 5))))敏捷小组的工作特点是迭代敏捷小组的工作特点是迭代敏捷小组的工作特点是迭代敏捷小组的工作特点是迭代 以 Scrum 为例,敏捷开发小组主要的工作方式如下图所示。 6))))把变化作为成功的驱动因素把变化作为成功的驱动因素把变化作为成功的驱动因素把变化作为成功的驱动因素 任何项目开始的时候所建立的计划,仅仅是一个当前的猜测。有很多事情可以让这样的计 划失效:项目成员的增减,某种技术比预期的更好或更差,用户改变了想法,竞争者迫使我们 做出不同的反应,等等。对此,敏捷小组不是害怕这种变化,而是把这种变化看成使最终软件 更好地反映实际需要的一个机会。 7))))通过反馈和调整使项目走向正确的方向通过反馈和调整使项目走向正确的方向通过反馈和调整使项目走向正确的方向通过反馈和调整使项目走向正确的方向 每次新迭代开始,敏捷小组都会结合上一次迭代中获得新知识做出相应调整。如果认为一 些因素可能会影响计划的准确性,也可能更改计划。比如发现某项工作比预计的更耗费时间, 可能就会调整进展速度。也许,用户看到交付的产品后改变了想法,这就产生反馈,比如他发 现他更希望有另一项功能,或者某个功能并不像先前看得那么重。通过先期发布增加更多的用 户希望的功能,或者减少某些低价值功能,就可以增加产品的价值。 8))))在变和不变中寻求平衡在变和不变中寻求平衡在变和不变中寻求平衡在变和不变中寻求平衡 迭代开发是在变与不变中寻求平衡,在迭代开始的时候寻求变,而在迭代开发期间不能改 变,以期集中精力完成已经确定的工作。由于一次迭代的时间并不长,所以就使稳定性和易变 性得到很好的平衡。在两次迭代期间改变优先级甚至功能本身,对于项目投资最大化是有益处 的。从这个观点来看,迭代周期的长度选择就比较重要了,因为两次迭代之间是提供变更的机 会,周期太长,变更机会就可能失去;周期太短,会发生频繁变更,而且分析、设计、编码、 测试这些工作都不容易做到位。综合考虑,对于一个复杂项目来说,迭代周期选择 4 周还是有 道理的。 3,,,,敏捷过程敏捷过程敏捷过程敏捷过程成功的核心因素是团队成功的核心因素是团队成功的核心因素是团队成功的核心因素是团队 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 92 - 很多人以为敏捷过程的核心因素是螺旋迭代,其实螺旋迭代是敏捷模型的表现形式,它的 更核心因素是团队。充分发挥人的主观能动性,充分尊重人的创造力,并且以团队集体项目的 形式表达出来,这是敏捷模型得以成功的最重要要素。为什么很多人说他已经是敏捷模型了, 我说不是呢?关键在于对团队的理解。 1))))敏捷过程敏捷过程敏捷过程敏捷过程需要文化支撑需要文化支撑需要文化支撑需要文化支撑 这是一个文化层面的事情,Scrum 是模拟橄榄球运动,团队自组织,为了团队的共同承诺 在动态中互相协调。团队赢我就赢的概念需要变成一种自然的理念。极限编程(XP)中的结对 编程,需要一种讨论的文化,必然造成开发过程叽叽喳喳,开发团队房间里充满了嗡嗡的讲话 声,这对习惯于听从领导指令的文化习惯并不融合。 2))))敏捷过程是一项集体运动敏捷过程是一项集体运动敏捷过程是一项集体运动敏捷过程是一项集体运动 应该注意,敏捷模型是一种集体运动,它必须以集体运动的形式表现出来。“讨论”是敏捷 模型的精髓所在。但是,文化不是可以随意摆布的,我们应该仔细考虑在企业现有文化背景下, 如何使我们的工作氛围变得更好?人们应该如何交流?如何分享信息?如何相互理解和解决问 题?如何使团队成员从工作中体会到无比的快乐?应该寻找怎样一种方法,对于各种文化背景 的员工群体来说,使一切都自然、和谐、不别扭?而且符合企业文化特点。其难度要超过理解 敏捷概念本身。 3))))敏捷过程需要在工作中寻找到乐趣敏捷过程需要在工作中寻找到乐趣敏捷过程需要在工作中寻找到乐趣敏捷过程需要在工作中寻找到乐趣 我们可以观察一下,很多单位的员工,上班时仅仅在隔间内盯着计算机屏幕,被动的完成 领导交待的任务。没有交谈,没有一起活动,没有集体从事所喜爱的工作的氛围。大家致力于 面对面交流最小化,强调书面交流,造成人与人的关系越来越公文化。大家觉得这种工作氛围 很正常也很习惯。但是这样一种工作氛围,即使采用了迭代过程,也不能说是运用了敏捷模型。 敏捷过程成功的表现,是我们的团队积极性和凝聚力被调动了起来,达到大家互相帮助, 向着同一个目标进取,并且学会在工作中分享乐趣,完成他非常乐于完成的事情。员工不再唯 唯诺诺满足于听从指令,而是讨论和思考,张开想象的翅膀,创造性地完成工作。我可以说, 即使形式上不是美国式的张扬,你也理解并实践敏捷模型了,你会发现,这样的氛围下成长起 来的员工,对公司的价值将更大,员工的成长也更快。 三三三三、、、、敏捷过程对架构的影响敏捷过程对架构的影响敏捷过程对架构的影响敏捷过程对架构的影响 下面我们列出一些重要的敏捷概念:  拥抱变更拥抱变更拥抱变更拥抱变更::::视变更为朋友而非敌人,变更可以激发更多的创造力,并可以为客户创造 更多的价值。  短迭代周期短迭代周期短迭代周期短迭代周期/频繁交付频繁交付频繁交付频繁交付::::以短的时间减个安排多次发布;仅仅是优先级最高的功能,快 速为客户提供价值,加速需求的浮现。  简单设计简单设计简单设计简单设计::::为当前的需要而设计,不要考虑将来。使设计刚好能覆盖当前的需求,变 更是不可避免的,为将来的功能作设计徒劳无益。  重构重构重构重构::::在不改变行为的前提下,对软件进行重新组织,除去其中重复的部分,提高其 表达力,简化它,或者增加一些灵活性。即时的重新设计。  回顾回顾回顾回顾::::迭代结束之后,对于完成的工作、所使用的方法和估算的效果进行复查。该复 查为以后的迭代提供知识和估算方面的帮助。  测试驱动开发测试驱动开发测试驱动开发测试驱动开发::::模块或者方法的测试是由开发者和客户在编码前以及编码过程中间增 量编写的。支持和鼓励使用很短的迭代周期。  团队承诺团队承诺团队承诺团队承诺::::团队对短期目标的承诺,是敏捷方法成功的关键。 由于敏捷过程认为变化是不可避免的驱动因素,整个设计是在迭代变更中完成的,整个架 构应该适应这种变更。因此在敏捷过程中,我们将更提倡面向对象的方法。我们的设计理念将 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 93 - 更加强调拥抱变化而设计,在架构设计的时候,我们将更下希望架构具有弹性。 四四四四、、、、软件软件软件软件重构重构重构重构与架构优化与架构优化与架构优化与架构优化 1,,,,重构的定义重构的定义重构的定义重构的定义 重构是以各种方式对设计进行重新安排使之更灵活并且/或者可重用的过程。效率和可维 护性可能是进行重构最重要的理由。重构定义为名词形式和动词形式两部分: 重构(Refactoring ,名词):是对软件的内部结构所作的一种改变,这种改变在可观察行为 不变的条件下使软件更容易理解,而且修改更廉价。 重构(Refactor ,动词):应用一系列不改变软件行为的重构操作对软件进行重新组织。 这些定义中最重要的方面是不改变软件系统的可观察行为,并且改变软件结构是朝着更好 的设计和更能理解,而且可重用的方向进行。 2,,,,重构的原则重构的原则重构的原则重构的原则 1))))一个时刻只戴一顶帽子一个时刻只戴一顶帽子一个时刻只戴一顶帽子一个时刻只戴一顶帽子 如果你使用重构开发软件,你把开发时间分给两种不同的活动:增加功能和重构。 第一顶帽子是功能,增加功能时,你不应该改变任何已经存在的代码,你只是在增加新功 能。这个时候,你增加新的测试,然后让这些新测试能够通过。当你换一顶帽子重构时,你要 记住你不应该增加任何新功能,你只是在重构代码,目标是提高代码的结构质量。你不会增加 新的测试。只有当重构改变了一个原先代码的接口时才改变某些测试。 在一个软件的开发过程中,你可能频繁地交换这两顶帽子。 关于两件工作交换的故事不断地发生在日常开发中,但是不管你做哪件工作,一定要记住 一个时刻只戴一顶帽子。 2))))小步前进小步前进小步前进小步前进 保持可观察行为不变称为重构的安全性。重构的另一个原则是小步前进,即每一步总是做 很少的工作,每做少量修改,就进行测试,保证重构的程序是安全的。如果你一次做了太多的 修改,那么就有可能介入很多的错误使之难以调试。 这些细小的步骤包括:确定需要重构的位置(发现坏味),编写并运行单元测试,找到合适 的重构并进行实施,运行单元测试,修改单元测试,运行所有的单元测试和功能测试等。如果 按照小步前进的方式去做重构,那么出错的机会可能就很小。 小步前进使得对每一步重构进行证明成为可能,最终通过组合这些证明,可以从更高层次 上来证明这些重构的安全性和正确性。现在的问题是我们重构系统的目标是什么?或者说我们 认为一个好的系统架构,它的特点应该是什么样的?不了解这一点,软件重构就成了无木之本。 3,,,,面向对象设计的基本原则面向对象设计的基本原则面向对象设计的基本原则面向对象设计的基本原则 在讨论结构化设计与面向对象设计的根本区别的时候,我们应该注意到面向对象理念是认 为变化是软件产品设计中不可避免会遇到的问题。如果我们认为软件开发是一项创造,那么变 化就不可避免,我们就必须面对变化的环境提出相应的设计原则。因为只有变化才可能设计出 更加精良的产品,这就解决了我们提出来的软件虫狗的目标问题。 在面向对象的理念中,无论是封装、继承还是多态特征,其根本的目得就是在未来发生变 化的时候,不至于对产品结构发生崩溃性的影响。但是,并不等于我们使用了面向对象的语言 就自然具备了面向对象设计的优点,它需要有更多的设计原则来保证我们在变化驱动的过程环 境下的结构合理性。 根据这样一个基本原则,延伸出了诸如单一职责原则、开放—封闭原则、依赖倒置原则、 接口隔离原则、包的内聚性原则以及包的依赖性原则等一系列设计原则。这些原则极大地丰富 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 94 - 和发展了软件设计理念,扩展了软件设计方法论,对于任何系统架构设计都有很好的借鉴作用, 下面我们分别进行讨论。 3.2 通过优先级分析澄清通过优先级分析澄清通过优先级分析澄清通过优先级分析澄清关键特征关键特征关键特征关键特征的价值的价值的价值的价值 架构设计必须澄清哪些是这个项目的关键特征,而这些价值的取得需要通过优先级分析。 作为一个优秀的架构设计,仅仅发现和列出了所有的功能这只是第一步,我们需要对所有的功 能优先级评价,从而发现最重要的功能,这也是分析和设计的精化过程,对软件架构设计来说 是很重要的一步。 1,,,,澄清关键特征的价值澄清关键特征的价值澄清关键特征的价值澄清关键特征的价值 简化需要澄清关键特征的价值,我们需要仔细考虑,所有这些特征哪些是最重要的?哪些 是最关键的?哪些是可以先放一放的?哪些是必须优先解决的?抓住了重点,就可能抓住了纲, 使事情解决起来更加的快速有效。 在确定重点功能的时候,粒度也是一个问题,面对大批的事无巨细的功能,耗费巨大的精 力对每个细小的功能进行优先级排序是得不偿失的,我们建议优先级讨论的粒度应该粗一些, 比如若干功能组合成的能力(或者说是主题),这样的归纳本身也是一个对需求进行梳理的过程 能力的价值其实很难确定,当产品负责人提出“要根据业务价值确定优先级”的伟大建议 的时候,业务价值到底是什么?因此需要有更确切的指导原则,我们必须考虑 4 个因素:  获得这些能力所带来的经济价值。  开发新能力所需要的成本。  开发新能力需要学习知识的量及重要性。  开发这些能力所减少的风险。 由于多数项目都考虑节约开支与赚钱,所以前两个因素往往比较受到重视,但为了最优的 确定优先级,对于学习与风险的考虑也是重要的。 1))))价值价值价值价值 确定优先级的第一个因素是能力的经济价值,获得了能力的能力,可以让公司获得或者节 省多少钱?这本身就具有“要根据业务价值确定优先级”的含义。 确定能力价值的理想方法,使估计它在一段时间内(几个月或者几年)所带来的经济影响。 确定能力的经济回报是很困难的事情,它通常要求对新产品的销售数量、每次销售的平均价格 (包括后续销售和维护协议)、销售上升的时机等都进行估计等。 2))))成本成本成本成本 很自然的,开发能力的成本是优先级的重要考虑因素。很多能力看起来不错,但了解倒它 的成本之后可能会改变主意。由一个常常被忽视的问题,就是成本会随时间变化。假定开发某 个能力现在需要 4 周的时间,但 6 个月以后我们会由于所获得的知识的改变,还需要花额外的 3 周对已经开发的能力进行改变,那就需要等一等。或者 6 个月之后预计我们会发现一种更简单 的方法来开发这个能力,那为什么不等一等呢? 3))))新知识新知识新知识新知识 在很多项目中,整体工作中的大部分是花在对新知识的追寻上,重要的是承认这种努力, 并把它看作是项目的一个重要组成部分。获取新知识很重要,因为项目开始的时候,我们并不 知道项目结束前我们所需要知道的所有的事情。在开发过程中所形成的知识包括两类:  关于产品的知识关于产品的知识关于产品的知识关于产品的知识:这是关于将要开发的能力的知识,一个小组关于产品的知识越多, 就能更好的作出产品特性和能力的决策。  关于项目的知识关于项目的知识关于项目的知识关于项目的知识:这是关于如何建立产品的知识,例如将要使用的技术、技能、小组 共同工作所需的相关知识。 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 95 - 4))))风险风险风险风险 与新知识的概念密切相关的是风险。几乎所有的项目都蕴藏着大量风险。风险指的是目前 尚未发生但是可能发生,而且会妨碍或者限制项目成功的事情,在项目中不同的风险包括:  进度风险  成本风险  能力风险 此外,风险还可以分为技术风险和商业风险。能力上的高风险和高价值存在着典型的竞争, 要在它们之间做出选择先要考虑每种方法的缺点。风险驱动的开发可能花了很多努力,到最后 才发现这个能力其实是不必要的。价值驱动的开发首先开发了很多高价值能力,到最后才在一 个不经意的地方发生危及整个项目的风险,造成项目崩溃。这两种情况其实都有可能发生。 解决的办法是不要让风险也不要让价值在确定优先级的时候占绝对主要地位。我们考虑一 下下面的关于风险价值关系 4 象限图。开发的优先级是从高风险高价值开始,沿着下图所示的 曲线安排比较合理。 图中表达的方法是要“避免”高风险低价值的能力,但这个避免不是绝对的,今天被认为 是要避免的,6 个月后随着开发的进展,或者风险降低,或者价值提高,这个能力可能会处于首 先要处理的位置。 要综合 4 个优先级因素,基本的工作方法是这样的: 首先考虑能力的价值与现在就开发它所需的成本之间的关系,这会给您一个初始的优先级 顺序,具有高价值/成本比的主体应该首先完成。 其次,考虑其它优先级因素把主体向前或者向后移动。假定一个能力根据价值/成本比具有 中等优先级,但发现这个能力有很大的技术风险,这会导致这个能力在进度表上往前移动。 初始排序并不是很正式的,甚至只是产品负责人在一张纸上的涂鸦,然后产品负责人向开 发小组提出自己的想法,小组作出恰当的评估,最后由产品负责人确定最后的顺序 2,,,,确定合意性优先级确定合意性优先级确定合意性优先级确定合意性优先级 产品的价值很大程度上来自于客户满意度,因此在考虑合意性优先级的时候,我们需要研 究产品能力与用户满意度的关系。 1))))客户满意度的客户满意度的客户满意度的客户满意度的 Kano 模型模型模型模型 最先提出为新产品发布提供优先级指导的,是日本管理学家狩野纪昭(Noriaki Kano ),他 的方法是把能力分成 3 类:  作为阈值的能力,或者说必需的能力。  线性能力。  兴奋点和惊喜点。 这几种能力与客户满意度的关系见下图,这个图称之为 Kano 模型。 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 96 - 阈值能力是产品要成功必须具备的那些能力,也常常也称之为必需的能力。改善阈值能力 和增加阈值能力的数量对客户满意度并没有多大的影响。 由于产品要有那些必需的能力才能在市场上生存,应该强调优先开发所有那些阈值能力。 但并不是一定要在第一次迭代中就开发所有产品必须能力,但是由于用户把这些能力看成强制 性的,他们必须要在发布产品之前变成可用。从图上可以看出来,有的时候只需要满足必须能 力的部分实现就可以了,因为对必须能力一定程度的支持以后,客户满意度的上升幅度就趋于 平缓。 线性能力是一个处于“越多越好”状态的能力。这里客户满意度会随着这部分内容的上升 而直线上升,而产品的价格也与线性特性相关。 最后,兴奋点和惊喜点是那些提供了很高的满意度,并常常可以为产品增加额外价格的那 些能力。但是缺少兴奋点和惊喜点并不会让客户满意度降到中性以下。兴奋点的特点是,用户 会喜欢它,但如果没有它用户也不会拒绝这个产品。实际上兴奋点和惊喜点也被称之为未被了 解的需求,因为在大家没有很好的研究它的时候,并不知道自己需要它。 一般来说的优先级是:首先是阈值能力,其次是现行能力,最后的兴奋点能力。 2))))用用用用 Kano 模型评估模型评估模型评估模型评估能力能力能力能力 在敏捷开发项目中使用 Kano 模型最简单的方法,是考虑每个能力,对它所属的类型作出有 根据的猜测。不过更好的办法是与客户或者用户进行讨论,确定每个能力的类型。一般来说, 只需要向少至 20 ~30 个人进行一次书面问卷,就可以准确的知道需求的优先级。Kano 建议通 过两个问题来确定一个能力的分类。 第一个问题是能力存在形式:如果一个产品中有这个能力用户会怎样? 第二个问题是能力缺失形式:如果一个产品中没有这个能力用户会怎样? 每个问题都可以通过 5 点的度量方式进行回答: (1)我希望这样 (2)我预期就是这样 (3)我没有意见 (4)我可以忍受这样 (5)我不希望这样 例如,我们正考虑要建立一个运动员网站 SwimStats ,假定我们正在考虑 3 个新能力:  查看一张图,显示一个运动员在过去的赛季中某个项目的成绩能力。  让运动员发布自传简历的能力。  让注册的网站成员上传照片的能力。 要确定这些能力属于哪个类别,就需要对用户进行调查,可以问他们以下问题: 合意性调查表合意性调查表合意性调查表合意性调查表 题目题目题目题目 1 2 3 4 5 1 如果可以绘制一个运动员在过去赛季中某个项目上的成绩,您 √ ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 97 - 觉得怎么样? 2 如果不可以绘制一个运动员在过去赛季中某个项目上的成绩, 您觉得怎么样? √ 3 如果有让运动员发布自传简历的能力,您觉得怎么样? √ 4 如果没有让运动员发布自传简历的能力,您觉得怎么样? √ 5 如果有让注册的网站成员上传照片的能力,您觉得怎么样? √ 6 如果没有让注册的网站成员上传照片的能力,您觉得怎么样? √ 说 明 1,我希望这样 2 ,我预期就是这样 3 ,我没有意见 4 ,我可以忍受这样 5,我不希望这样 对这一叠调查表,需要一种方法,对用户的观点做出评估。 2))))将答案分类将答案分类将答案分类将答案分类 我们可以使用一个分析矩阵对每个人的回答做出判断,如下表所示。 答案分析答案分析答案分析答案分析 能力能力能力能力缺失缺失缺失缺失 希望希望希望希望 预期预期预期预期 无意见无意见无意见无意见 忍受忍受忍受忍受 不希望不希望不希望不希望 希望希望希望希望 Q E E E L 预期预期预期预期 R I I I M 无意见无意见无意见无意见 R I I I M 忍受忍受忍受忍受 R I I I M 能力能力能力能力 存在存在存在存在 不希望不希望不希望不希望 R R R R Q M 必须的必须的必须的必须的 L 线性的线性的线性的线性的 E 兴奋点兴奋点兴奋点兴奋点 R 反对的反对的反对的反对的 Q 存在疑问的存在疑问的存在疑问的存在疑问的 I 无所谓的无所谓的无所谓的无所谓的 在这个分析表上,如果用户对这个能力的存在认为他预期、无意见、可以忍受,但是不希 望没有,这一般可以认为是阈值能力。如果用户希望有这个能力,而且不希望没有这个能力, 那么这是一个线性能力,客户满意度会随着这样的能力增多而增加,这个能力也是强制性的, 例如上面关于绘图的回答。如果客户希望有这个能力,但对没有这个能力它的反映是预期、无 意见、可以忍受,那这一般是一个兴奋点能力。 最后把每个人的分析统计在一张表上,就可以看出每个能力的性质了,如下表所示。 用户调查结果分析用户调查结果分析用户调查结果分析用户调查结果分析 能力能力能力能力 E L M I R Q 类别类别类别类别 对项目成绩作图 18.4 43.8 22.8 12.8 1.7 0.5 线性 上传照片 8.3 30.9 54.3 4.2 1.4 0.9 必须 发布自传简历 39.1 14.8 36.6 8.2 0.2 1.1 兴奋点,必须 可见,上传照片是必须的,对成绩作图是线性能力。对于发布自传简历,一部分人认为是 必须,还有一部分人感觉是一个兴奋点,这就需要对结论进一步分析。某些情况下也可以利用 专家来判断,开发小组共同对下一次发布所考虑的每个能力进行评估,通过价值和成本的分析 来订出不同能力的权重。 3.3 单一职责原则单一职责原则单一职责原则单一职责原则(SRP) 这条原则也被称之为内聚性原则。内聚性的原始定义为一个模块的组成元素之间的功能相 关性。但是在我们的问题中,我们稍微改变一下它的含意,由于我们关注的是需求变更造成的 影响,所以,我们把内聚性和引起一个模块或者类改变的作用力联系起来。SRP 原则的描述为: 就一个类而言,应该仅有一个引起它变化的原因。 一一一一、、、、职责是变化的一个轴线职责是变化的一个轴线职责是变化的一个轴线职责是变化的一个轴线 1))))普通的设计方法是以功能普通的设计方法是以功能普通的设计方法是以功能普通的设计方法是以功能相关相关相关相关为依据进行封装为依据进行封装为依据进行封装为依据进行封装 普通的设计方法是以功能内聚为原则设计的,我们来考虑下图中的设计。Retangle 类具有 两个方法,一个方法把矩形绘制在屏幕上,另一个方法计算矩形的面积。从功能内聚的观点来 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 98 - 看,这并没有什么错。 当两个不同的应用程序(ComputationalGeometryApplication 和 GraphicalApplication )使用 Rectangle 类,一个是有关计算几何学方面的,Rectangle 类会在几何形状计算方面为它提供帮助, 它从来不会在幕上绘制矩形。另外一个应用程序实质上是有关图形绘制方面的,它可能也会进 行一些计算几何学方面的工作,但是它肯定会在屏幕上绘制矩形。 2))))单一职责的原则主要考虑变化的原因单一职责的原则主要考虑变化的原因单一职责的原则主要考虑变化的原因单一职责的原则主要考虑变化的原因 这个设计违反了单一职责原则(SRP),Rectangle 类具有两个职责,第一个职员提供了 一个 矩形几何形状的数学模型;第二个职责是把矩形在—个图形用户界面上绘制出来。而这两个职 责变化的轴线是不一样的。 对于 SRP 原则的违反导致了一些严重的问题。首先,我们必须在计算几何应用程序中包含 进 GUI 代码。如果这是一个 C++ 应用程序,就必须要把 GUI 代码链接进来,这会浪费链接时间、 编译时间以及内存占用。如果是—个 Java 应用程序,GUI 的 CIass 文件必须要被部署到目标平 台, 其次,如果 GraphicalApplication 的改变由于这些原因导致 Rectangle 的改变,那么这个改变 会迫使我们重新构建、测试以及部署 ComputationalGeometryApplication 。如果忘记了这样做, ComputationalGeometryApplication 能会以不可预测的方式失败。 3))))比较好的设计是分离不同的变化职责比较好的设计是分离不同的变化职责比较好的设计是分离不同的变化职责比较好的设计是分离不同的变化职责 —个较好的设计是把这两个职责分离到两个完全不同的类中,如下图所示。我们把 Rectangle 类中进行计算的部分移到 GeometryRectangle 类 中。现在矩形绘制方式的改变不会对 ComputationalGeometryApplication 造成影响。 这种分离的原因是由于每一个职责都是变化的一个轴线。当需求变化时,该变化会反映为 类的职责的变化。如果一个类承担了多于一个的职责,那么引起它变化的原因就会有多个。如 果一个类承担的职责过多,就等于把这些职责耦合在了一起。一个职责的变化可能会削弱或者 抑制这个类完成其他职责的能力。这种耦合会导致脆弱的设计,当变化发生时,设计会遭受到 意想不到的破坏。 二二二二、、、、分离耦合的职责分离耦合的职责分离耦合的职责分离耦合的职责 1))))在在在在 SRP 中的职责定义为中的职责定义为中的职责定义为中的职责定义为““““变化的原因变化的原因变化的原因变化的原因”””” 在 SRP 中,我们把职责定义为“变化的原因”。如果你能够想到多于一个的动机去改变一个 类,那么这个类就具有多于—个的职责。有时,我们很难注意到这一点。我们习惯于以组的形 式去考虑职责。例如,考虑下面的 Modem 接口。大多数人会认为这个接口看起来非常合理。该 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 99 - 接口所声明的 4 个函数确实是调制解调器所具有的功能。 interface Modem{ public void dial(String pno); public void hangup(); public void send(char c); public void recv(); } 然而,该接口中却显示出两个职责。第一个职责是连接管理(dial 和 hangup 函数);第二个 职责是数据通信(send 和 recv 函数)。 2))))关键是考虑变化是不是造成共同的影响关键是考虑变化是不是造成共同的影响关键是考虑变化是不是造成共同的影响关键是考虑变化是不是造成共同的影响 这两个职责应该被分开吗?这依赖于应用程序变化的方式。如果应用程序的变化会影响连 接函数的签名,那么这个没计就具有僵化性的臭味,出为调用 send 和 recv 函数的类必须要重新 编译,部署的次数常常会超过我们希望的次数。在这种情况下,这的个职责应该被分离,如下 图所示。这样做避免了客户应用程序和这两职责耦合在一起。 另一方面,如果应用程序的变化方式总是导致这两个职贡同时变化,那么就不必分离它们, 实际上,分离它们就会只有不必要的复杂性的臭味。在此还有一个推论。变化的轴线仅当变化 实际发生时才具有真正的意义。如果没有征兆,那么去应用 SRP,或者任何其他原则都是不明 智的。 3))))职责分离不是绝对的职责分离不是绝对的职责分离不是绝对的职责分离不是绝对的 请注意,在上图中本来应该是有两个实现类,但我们把两个职责都混合进了一个 ModemImplementation 类中了。这不是原本所希望的,但是或许是必要的。常常会有一些和硬件 或者操作系统的细节有关的原因,迫使我们把不愿意耦合在一起的东西耦合在一起了。然而, 对于应用的其余部分来说, 通 过分离它们的接口我们已经解耦了概念。 我 们 可 以 把 ModemImplementation 类看作是一个瑕疵。然而,请注意所有的依赖关系都和它无关。谁也不需 要依赖于它。除了 main 外,谁也不需要知道它的存在。 三三三三、、、、业务规则和持久化业务规则和持久化业务规则和持久化业务规则和持久化 下图展示了—种常见的违反SRP 的情形。Employee 类包含了业务规则和对于持久化的控制。 这两个职责在大多数情况下决不应该混合在一起。业务规则往往会频繁的变化,而持久化的方 式都不会如此频繁的变化,并且变化的原因也是完全不同的,把业务规则和持久化子系统绑定 在一起的做法是自讨苦吃。 SRP 是所有原则中层简单的之一,也是最难正确运用的原则之一。我们会自然地把职责结 合在一起,在内聚性的考虑中,往往只是考虑功能相关,而没有考虑需求变化的影响,这就使 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 100 - 设计出现瑕疵。软件设计真正要做的许多内容,就是发现职责并把那些职责相互分离。事实上, 我们将要论述的其余原则都会以这样或那样的方式回到这个问题上。 3.4 开放开放开放开放————封闭原则封闭原则封闭原则封闭原则(OCP) 任何系统在其生命周期中都会发生变化。如果我们期望开发出的系统不会在第 1 版后就被 抛弃,就必须牢牢地记住这一点。那么怎样的设计才能面对需求的改变却可以保持相对稳定, 从而使得系统可以在第一个版本以后不断推出新的版本呢?著名的开放一封闭原则(The Open-Closed Principle ,简称 OCP),为我们提供了指引。 一一一一、、、、OCP 原则的基本概念原则的基本概念原则的基本概念原则的基本概念 OCP 原则的目的,是要求我们设计的软件实体(类、模块、函数等等)应该是可以扩展的, 但是不可修改的。如果程序中的一处改动就会产生连锁反应,导致一系列相关模块的改动,那 么设计就具有僵化性的臭味。OCP 建议我们应该对系统进行重构,以保证将来对系统再进行那 样的改动时,不会导致更多的修改。我们只需要添加新的代码,而不必改动已经正常运行的代 码。也许,这看起来像是众所周知的可望而不可及的美好理想,然而,事实上却有一些相对简 单并且有效的策赂可以帮助我们接近这个理想。 遵循开放一封闭原则设计出的模块具有两个主要的特征,它们是:  对于扩展是开放的对于扩展是开放的对于扩展是开放的对于扩展是开放的:这意味着模块的行为是可以扩展的,当应用的需求改变时,我们 可以对模块进行扩展,使其具有满足那些改变的新行为。换句话说,我们可以改变。 模块的功能。  对于更改是封闭的对于更改是封闭的对于更改是封闭的对于更改是封闭的:对模块行为进行扩展时,不必改动模块的源代码,无论是动态链 接库、DLL 或者是 Java 的 jar 文件,都无需改动。 这两个特征好象是互相矛盾的。我们通常遇到的扩展模块行为的方式就是修改模块的源代 码,不允许修改的模块常常都被认为是具有固定的行为。怎样才能在不改动源代码的情况下去 更改它的行为呢?怎样才能在无需对模块进行改动的情况下就能改动它的功能呢? 二二二二、、、、实现实现实现实现 OCP 的关键是抽象的关键是抽象的关键是抽象的关键是抽象 在 C++ 、Java 或者其它任何的 OOP 中,可以创建出固定却能够描述一组任意个可能行为的 抽象体。这个抽象体就是抽象基类(或者是接口)。而一组任意个可能的行为则表现为可能的派 生类。模块可以操作一个抽象体。由于模块依赖于一个同定的抽象体,所以它对于更改可以是 关闭的。同时,通过从这个抽象体派生,也可以扩展这个模块的行为。 1))))依赖于具体的类依赖于具体的类依赖于具体的类依赖于具体的类,,,,被依赖者的变化将影响依赖者被依赖者的变化将影响依赖者被依赖者的变化将影响依赖者被依赖者的变化将影响依赖者 下图(A)展示了一个简单的不道循 OCP 的设计。Client 类和 Server 类都是具体类。Client 类使用了 Server 类。如果我们希望 Client 对象使用另外一个不同的服务器对象,那么,就必须 要把 Client 类中使用的 Server 类的地方更改为新的服务器类。 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 101 - 2))))依赖于抽象依赖于抽象依赖于抽象依赖于抽象,,,,将隔离被依赖者的变化将隔离被依赖者的变化将隔离被依赖者的变化将隔离被依赖者的变化 图(B)展示了一个针对上述问题的遵循 OCP 的设计,在这个设计中,ClientInterface 类是 一个拥有抽象成员函数的抽象类,然而,Client 类的对象却使用 Server 类的派生类对象。如果 我们希望 Client 对象使用一个不同的服务器类,那么只需要从 ClientInterface 类派生一个新的类, 不需要对 Client 类作任何改动。 Client 类要实现—些功能,它可以使用 ClientInterface 抽象接口描绘那些功能,ClientInterface 的子类型可以以任何它们所选择的方式去实现这个接口。这样,就可以通过创建 ClientInterface 的新的子类型的方式去扩展、更改 Client 中指定的行为。 3))))抽象类也可以隔离这种变化抽象类也可以隔离这种变化抽象类也可以隔离这种变化抽象类也可以隔离这种变化 下图展示了另一个可选的结构。 Policy 类具有一组实现了某种策略的公有函数。前面 Client 类的函数类似,这些策略函数 使用一些抽象接口描绘了一些要完成的功能。不同的是,在这个结构中,这些抽象接口是 Policy 类本身的一部分。它们在 C++ 中表现为纯虚函数,在 Java 中表现为抽象方法。这些函数在 Policy 的子类型中实现。这样,可以通过从 Policy 类派生出新类的方式,对 Policy 中指定的行为进行 扩展或者更改,显然这就是模板方法模式(Template Method )。 这两个模式是满足 OCP 的最常用的方法。应用它们,可以把一个功能的通用部分和实现细 节部分清晰的分离开来。 三三三三、、、、预测变化和预测变化和预测变化和预测变化和““““贴切的贴切的贴切的贴切的””””结构结构结构结构 通过上面的讨论,我们可以归纳出:如果我们预测到了变化,那么就可以设计一个抽象来 隔离它。行为型模大多数涉及两种对象,即封装可变化特征的新对象,和使用这些新对象的已 经有的对象。二者之间通过对象组合在一起工作。这就避免了变化的功能功能成为这些已有对 象的难以分割的一部分。因此,大多数行为型模式都具有如下结构。 1,,,,合理猜测变化种类合理猜测变化种类合理猜测变化种类合理猜测变化种类 1))))应该对哪种变化封闭做出选择应该对哪种变化封闭做出选择应该对哪种变化封闭做出选择应该对哪种变化封闭做出选择 这种分离也导致了一个麻烦的结果,一般而言,无论模块是多么的“封闭”,都会存在一些 无法对之封闭的变化。很难有对于所有的情况都贴切的模型。既然不可能完全封闭,那么就必 须有策略地对待这个问题。也就是说,设计人员必须对于他设计的模块应该对哪种变化封闭做 出选择。他必须先猜测出最有可能发生的变化种类,然后构造抽象来隔离那些变化。 2))))需要对用户领域有了解需要对用户领域有了解需要对用户领域有了解需要对用户领域有了解 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 102 - 这需要设计人员具备一些从经验中获得的预测能力。有经验的设计人员希望自己对用户和 应用领域很了解,能够以此来判断各种变化的可能性。然后,他们往往针对最有可能发生的变 化的地方遵循 OCP 原则进行设计。 这一点不容易做到。因为它意味着要根据经验猜测那些应用程序在生长历程中有可能遭受 的变化。如果开发人员猜测正确,他们就获得成功。如果他们猜测错误,他们会遭受失败。并 且在大多数情况下,他们都会猜测错误。 3))))要考虑封闭的代价要考虑封闭的代价要考虑封闭的代价要考虑封闭的代价 同时,遵循 OCP 的代价也是昂贵的。创建正确的抽象是要花费开发时间和精力的。同时, 那些抽象也增加了软件设计的复杂性。开发人员有能力处理的抽象的数量也是有限的。显然, 我们希望把 OCP 的应用限定在可能会发生的变化上。 我们如何知道哪个变化有可能发生呢?我们进行适当的调查,提出正确的问题,并且使用我 们的经验和一般常识。最终,我们会一直等到变化发生时才采取行动。 2,,,,放置吊钩放置吊钩放置吊钩放置吊钩也要考虑会引入不必要的复杂性也要考虑会引入不必要的复杂性也要考虑会引入不必要的复杂性也要考虑会引入不必要的复杂性 1))))放置吊钩是隔离变化的一种解决方案放置吊钩是隔离变化的一种解决方案放置吊钩是隔离变化的一种解决方案放置吊钩是隔离变化的一种解决方案 我们怎样去隔离变化呢?一个解决方案是,我们会在我们认为可能发生变化的地方放置吊 钩(hook) 。我们觉得这样做会使软件灵活一些。然而,现实情况是我们放置的吊钩常常是错误的。 更糟的是,即使不使用这些吊钩。也必须要去支持和维护它们,从而就具有了不必要的复杂性 的臭味。这并不是一件好事。我们不希望设计背上许多不必要的抽象。通常,我们更愿意一直 等到确实需要那些抽象时再把它放置进取。 2))))尽可能早的发现变化的原因尽可能早的发现变化的原因尽可能早的发现变化的原因尽可能早的发现变化的原因 如果我们决定接受变化的现实,那么变化到来的越早、越快就对我们越有利。我们希望在 开发工作展开不久就知道可能发生的变化。查明可能发生的变化所等待的时间越长,要创建正 确的抽象就越困难。因此,我们需要去刺激变化,常用的做法是:  我们使用很短的迭代周期进行开发,一个周期为几天而不是几周。  我们在加入基础结构前就开发特性,并且经常性地把那些特性展示给涉众。  我们首先开发最重要的特性。  尽早地、经常性地发布软件。尽可能快地、频繁地把软件展示给客户和使用人员。 3.5 依赖倒置原则依赖倒置原则依赖倒置原则依赖倒置原则((((DIP)))) 一一一一、、、、对传统层次结构的倒置对传统层次结构的倒置对传统层次结构的倒置对传统层次结构的倒置 依赖倒置原则(DIP)的原则如下:  高层模块不应该依赖于低层模决。二者都应该依赖于抽象  抽象不应该依赖于细节。细节应该依赖于抽象。 1))))传统的结构化设计是高层依赖底层传统的结构化设计是高层依赖底层传统的结构化设计是高层依赖底层传统的结构化设计是高层依赖底层 应用“倒置”这个词可能会给人以误会。这是由于许多传统的软件开发方法,比如结构化 分析和设计,总是倾向于创建一些高层模块依赖于低层模块、策赂依赖于细节的软件结构。实 际上这些方法的目的之一就是要定义子程序层次结构,该层次结构描述了高层模块怎样调用低 层模块。在人们的概念中,程序的初始设计就是这种层次结构。一个设计良好的面向对象的程 序,其依赖程序结构相对于传统的过程式方法设计的通常结构而言就是被“倒置”了。 2))))高层对底层的依赖使底层模块必须稳定高层对底层的依赖使底层模块必须稳定高层对底层的依赖使底层模块必须稳定高层对底层的依赖使底层模块必须稳定 请考虑一下当高层模块依赖于低层模块时意味着什么。高层模块包含了一个应用程序中的 重要的策略选挥和业务模型。正是这些高层模块才使得其所在的应用程序区别于其他。然而, ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 103 - 如果这些高层模块依赖于低层模块,那么对低层模块的改动就会直接影响到高层模块,从而迫 使它们依次做出改动。 这种情形是非常荒谬的,本应该是高层的策略设置模块去影内低层的细节实现模块的。包 含高层业务规则的模块应该优先并独立于包含实现细节的模块。无论如何高层模块都不应该依 赖于低层模块。 3))))我们更希望能够重用的是高层的策赂模块我们更希望能够重用的是高层的策赂模块我们更希望能够重用的是高层的策赂模块我们更希望能够重用的是高层的策赂模块 此外,我们更希望为能够重用的是高层的策赂设置模块。我们已经非常擅长于通过子程序 库的形式来重用低层模块。如果高层模块依赖于低层模块,那么在不同的上下文中重用高层模 块就会变得非常困难。然而,如果高层模块独立于低层模块,那么高层模块就可以非常容易地 被重用。这个原则也是框架(Framework) 设计的核心原则。 二二二二、、、、依赖倒置原则的设计方法依赖倒置原则的设计方法依赖倒置原则的设计方法依赖倒置原则的设计方法 1,,,,更加合理的模型更加合理的模型更加合理的模型更加合理的模型 1))))传统的模型存在缺陷传统的模型存在缺陷传统的模型存在缺陷传统的模型存在缺陷 如下图所示,在经典的层次结构中,高层的 Policy Layer 使用了低层的 Mechanism Layer 、 而 Mechanism Layer 又使用了更细节的层 Utility Layer 。这看起来似乎是正确的,然而它存在一 个隐含的错误特征,那就是:Policy Layer 对于其下一直到 Utility Layer 的改动都是敏感的。这 种依赖关系是传递的。Policy Layer 依赖于某些依赖于 Utility Layer 的层次;因此 PoIicy Layer 传递性地依赖于 Utility Layer 。这是非常糟糕的。 2))))更合理的模型是上层设置抽象更合理的模型是上层设置抽象更合理的模型是上层设置抽象更合理的模型是上层设置抽象 下图展示了一个更为合适的模型。每个较高层次都为它所需要的服务声明一个抽象接口, 较低的层次实现了这些抽象接口,每个高层类都通过该抽象接口使用下一层,这样高层就不依 赖于低层。低层反而依赖于在高层中声明的抽象服务接口。这不仅解除了PoIicy Layer 对于 Utility Layer 的传递依赖关系,甚至也解除了 PoIicy Layer 对于 Mechanism Layer 的依赖关系。 2,,,,倒置的接口所有权倒置的接口所有权倒置的接口所有权倒置的接口所有权 请注意这里的倒置不仅仅是依赖关系的例置,它也是接口所有权的倒置。我们通常会认为 工具库应该拥有它们自己的接口。但是当应用了 DIP 时,我们发现往往是客户拥有抽象接口, 而它们的服务者则从这些抽象接口派生。 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 104 - 通过这种倒置的接口所有权,对于 MechanismLayer 或者 Utility Layer 的任何改动都不会再 影响到 PoIicy Layer 。而且,PoIicy Layer 可以在定义了符合 PoIicyServiceInterface 的任何上下文 中重用。这样,通过倒置这些依赖关系,我们创建了一个更灵活、更持久、更易改变的结构。 3,,,,依赖于抽象依赖于抽象依赖于抽象依赖于抽象 1))))依赖倒置可以描述为依赖于抽象依赖倒置可以描述为依赖于抽象依赖倒置可以描述为依赖于抽象依赖倒置可以描述为依赖于抽象 一个稍微简单但仍然非常有效的对于 D1P 的解释,是这样一个简单的启发式规则:“依赖于 抽象。”这是一个简单的陈述,该启发式规则建议不应该依赖于具体类——也就是说,程序中所 有的依赖关系都应该终止于抽象类或者接口。 根据这个启发式规则,可知:  任何变量都不应该持有一个指向具体类的指针或者引用;  任何类都不应该从具体类派生;  任何方法都不应该覆盖它的任何基类中的已经实现了的方法 2))))并不是什么时候都需要依赖于抽象并不是什么时候都需要依赖于抽象并不是什么时候都需要依赖于抽象并不是什么时候都需要依赖于抽象 当然,每个程序中都会有违反该启发规则的情况。有时必须要创建具体类的实例,而创建 这些实例的模块将会依赖于它们。此外,该启发则对于那些虽是具体但却稳定的类来说似乎不 太合理。如果一个具体类不太会改变,并且也不会创建其他类似的派生类,那么依赖于它并不 会造成损害。比如,在大多数的系统中,描述字符串的类都是具体的。例如,在 Java 中,表示 字符串的是具体类 String 。该类是稳定的,也就是说,它不太会改变。因此,直接依赖于它不会 造成损害。 3))))也要看到大多数的类是不稳定的也要看到大多数的类是不稳定的也要看到大多数的类是不稳定的也要看到大多数的类是不稳定的 然而,我们在应用程序中所编写的大多数具体类都是不稳定的。我们不想直接依赖于这些 不稳定的具体类。通过把它们隐藏在抽象接口的后面,可以隔离它们的不稳定性。这并不是一 个完美的解决方案。常常,如果一个不稳定类的接口必须要变化时,这个变化一定会影响到表 示该类的抽象接口。这种变化破坏了由抽象接口维系的隔离性。 4))))由客户类来由客户类来由客户类来由客户类来声明它所需要的服务接口声明它所需要的服务接口声明它所需要的服务接口声明它所需要的服务接口 由此可知,这个启发规则对问题的考虑有点简单了。另一方面,如果看得更远一点,认为 是由客户类来声明它们需要的服务接口,那么仅当客户需要时才会对接口进行改变。这样,改 变实现抽象接口的类就不会影响到客户。 4,,,,依赖倒置的示例依赖倒置的示例依赖倒置的示例依赖倒置的示例 我们来看一个例子,假定设计一个的空对空导弹控制系统软件,该软件从一个 IO 通道中读 取红外测角仪目标信息,通过和基准数据(BenchmarkData )比较,再计算综合飞行矢量 (FlightVectorCalculation ),通过计算前置角(FrontAngle )和跟踪方式(TrackingMode ),向另 一个 IO 通道发送舵面控制(RudderControl )命令来控制舵面。算法结构如下图所示。 为此我们构造初步的软件结构如下: ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 105 - 这种软件结构有什么臭味呢?由于这个计算模块希望使用在不同型号的导弹上,飞行矢量 计算方法也可能会修改, 不同型号的导弹红外测角仪与舵面控制可能不同,IO 通道也可能不 一样,但图中下层被依赖将更不容易变化,所以需要利用依赖倒置原则来隔离这些变化。由于 飞行矢量计算变化的轴线与处理角度基准不一样,根据单一职责原理,应该分开成为独立的类。 改进的图如下所示: 5,,,,依赖倒置是面向对象设计的标志所在依赖倒置是面向对象设计的标志所在依赖倒置是面向对象设计的标志所在依赖倒置是面向对象设计的标志所在 使用传统的结构化设计所创建出来的依赖关系结构,策略是依赖于细节的。这是糟糕的, 因为这样会使策略受到细节改变的影响。面向对象的程序设计倒置了依赖关系结构,使得细节 和策略都依赖于抽象、并且常常是客户拥有服务接口。 事实上,这种依赖关系的倒置正是好的面向对象设计的标志所在。使用何种语言来编写程 序是无关紧要的。如果程序的依赖关系是倒置的,它就是面向对象的设计。如果程序的依赖关 系不是倒置的,它就是过程化的设计。 依赖倒置原则是实现许多面向对象技术所宣称的好处的基本底层机制。它的正确应用对于 创建可重用的框架来说是必须的。同时它对于构建在变化面前富有弹性的代码也是非常重要的。 由于抽象和细节被彼此隔离,所以代码也非常容易维护。 三三三三、、、、架构架构架构架构、、、、框架与业务层面的复用框架与业务层面的复用框架与业务层面的复用框架与业务层面的复用 1))))框架框架框架框架是是是是复用技术的延伸复用技术的延伸复用技术的延伸复用技术的延伸 对于依赖倒置原则的进一步延伸,就是框架技术。依赖倒置原则引发了一个实现上的困惑, 那就是如果细节是可变的,那么为什么不能把细节放到上层呢?如果把细节放到上层,进行彻 底的倒置,就实现了框架(Framework )结构。让业务单元依赖于业务流程,这本身就是依赖倒 置原则所追求的,通过框架技术,将使依赖倒置原则的实现更加流畅而合理。 框架是可以通过某种回调机制进行扩展的软件系统或者子系统。框架的概念主要来自于对 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 106 - “重用概率”的分析。一个软件单元被重用,单元粒度越大,重用概率越低,但是重用价值越 大。反之,单元粒度越小,重用概率越高,但是重用价值越小。这个矛盾,仅仅通过分析是解 决不了的。框架的智慧在于,在单元粒度比较大的情况下,追求高的重用概率。 2))))框架与架构的区别框架与架构的区别框架与架构的区别框架与架构的区别 人们对于架构(Architecture )和框架(Framework )实际上还存在很多混淆,认为框架就是 架构。其实一句话就可以区别出来,框架是一个软件,但架构不是软件。 框架是一种特殊的软件,它不能提供完整无缺的解决方案,但为解决方案提供和很好的基 础,它是一种系统或者子系统的半成品,框架中的服务可以提供最终应用系统的直接调用,而 框架中的扩展点题共有开发人员定制的“可变化点”。 这样一来,一个比较大的框架单元,就可能有比较大的重用概率。 软件架构不是软件,而是关于软件如何设计的重要决策,软件架构解决的问题,是关于软 件有几个部分,各部分静态关系与动态关系是如何交互的,经过完整的开发过程以后,这些决 策将体现在最终系统中。在引入软件框架以后,软件架构决策往往会体现在框架设计之中。 软件架构是比具体代码更高一个抽象层次的概念,架构必须被代码体现和遵循,但任何一 段具体代码都代表不了架构。 3 ))))框架和架构的本质都是分而治之框架和架构的本质都是分而治之框架和架构的本质都是分而治之框架和架构的本质都是分而治之 不论是架构技术还是框架技术,都是为了解决软件日益复杂所带来的困难,而采取的“分 而治之”的结果。架构的思维是先大局后局部,这是一种问题在抽象层面地解决方案,首先考 虑大局而忽略细节。框架的思维是先通用后专用,这是一种半成品,还需要通过后期的定制才 能成为具体的软件。框架与架构设计的关系可以由下图表示。 框架和架构的关系可以总结为两个方面:  为了尽早验证架构设计,或者出于支持产品线开发的目的,可以把通用机制甚至整个 架构以框架方式实现。  企业可能存在大量可重用框架,这些框架可能已经实现了架构所需的重要机制,或者 对某个子系统提供了可扩展的半成品,最终软件架构可以借助这些框架来构造。。 4))))框架设计需要仔细思考业务过程框架设计需要仔细思考业务过程框架设计需要仔细思考业务过程框架设计需要仔细思考业务过程 框架设计最重要的部分,其实并不在于采用何种技术方案来实现,而是对已经存在的业务 过程进行深入思考,寻找它们的共性,探究其中的规律,建立恰当的模式,然后选择恰当的技 术实现方案。 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 107 - 3.6 接口隔离原则接口隔离原则接口隔离原则接口隔离原则(ISP) 这个原则用来处理“胖(fat )”接口所具有的缺点。类的“胖”(不内聚)接口可以分解成 多组方法。每一组方法都服务于一组不同的客户程序。这样,一些客户程序可以使用一组成员 函数,而其他客户程序可以使用其它组的成员函数。实际中当然也存在有一些对象,它们确实 不需要内聚的接口,但是 ISP 建议客户程序不应该看到它们作为单一的类存在。相反,客户程 序看到的应该是多个具有内聚接口的抽象基类。 一一一一、、、、接口有可能被污染接口有可能被污染接口有可能被污染接口有可能被污染 考虑—个安全监视系统。在这个系统中,有一个 Door 接口,可以被加锁和解锁,并且 Door 接口的实现应该知道自己是开着还是关着。 interface Door { public void Lock(); public void Unlock(); public boolean IsDoorOpen(); public void TimeOut(); } 其中,TimeOut() 方法是发出警报声,下面是一个最简单的实现。 class TimerDoor implements Door{ public void Lock(){} public void Unlock(){} public boolean IsDoorOpen(){ return true; } public void TimeOut(){ System.out.println(" 实现警报"); } } class Timer{ public void Register(int timeout,Door client){ if (timeout>4){ client.TimeOut(); } } } class Test{ public static void main (String[] args){ Timer c=new Timer(); c.Register(5,new TimerDoor()); } } 虽然这个解决方案很常见,但是它也不是没有问题。最主要的问题是,并不是所有种类的 安全监控都需要发出警报声。如果创建了无需警报功能的 Door 的派生类,那么在这些派生类中 就必须要提供 TimeOut 方法的退化(degenerate) 实现——这就有可能违反 LSP。 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 108 - 这是一个接口污染的例子,这种情况在像 C++ 、Java 这样的静态类型语言中是很常见的。 Door 的接口被一个它不需要的方法污染了。在 Door 的接口中加入这个方法只是为了能给它的 一种客户需求带来好处,但带来了维护和重用方面的问题。 二二二二、、、、分离客户就是分离接口分离客户就是分离接口分离客户就是分离接口分离客户就是分离接口 1))))被不同客户使用的接口需要保持分离被不同客户使用的接口需要保持分离被不同客户使用的接口需要保持分离被不同客户使用的接口需要保持分离 Door 接口是被两种不同的客户程序使用的,一个是监测门的状态,另一个是处理监测结果。 既然客户程序是分离的,所以接口也应该保持分离。这就是客户对接口施加的反作用力 2))))迫使接口改变的往往正是使用者迫使接口改变的往往正是使用者迫使接口改变的往往正是使用者迫使接口改变的往往正是使用者 在我们考虑软件中引起变化的作用力时,通常考虑的都是接口的变化会怎样影响它们的使 用者。然而,存在着从另外一个方向施加的作用力。有时,迫使接口改变的,正是它们的使用 者。如果强迫用户程序依赖于那些它们不使用的方法,那么这些客户程序就面临着由于这些未 使用方法的改变所带来的变更。这无意中导致了所有客户程序之间的耦合。换一种说法.如果 一个客户程序依赖于一个含有它不使用的方法的类,但是其它客户却需要使用该方法,那么当 其他客户要求这个类改变时,就会影响到这个客户程序。我们希望尽可能地避免这种耦合,因 此我们希望分离接口。 3))))接口隔离原则的案例接口隔离原则的案例接口隔离原则的案例接口隔离原则的案例 如图所示是一个作战综合指挥平台系统架构,系统要求对数据进行实时处理,在业务层通 过信息处理类提供了四个方法,分别是:计算地图(Computational Map )、三维图形处理 (ThreeDimensional Graphics )、计算威胁(Computational Threat )与计算态势(Computational Trend )。 这四种处理都有可能变化 。 表 示 层 针 对 地 图 显 示 ( MapDisplay )、 情 报 处 理 (IntelligenceProcessing )和作战指挥(OperationalCommand )三种需求分别显示。 请问这个架构有什么臭味,如何改进呢?我们发现这个架构有如下一些缺点:  直接调用数据库无法处理实时数据;  Interface 是一个胖接口,无法适应变化;  信息处理类变化的轴线不同,互相牵制,无法适应变化;  没有实现依赖倒置,无法应对业务层的业务变化。 改动方案如下: ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 109 - 三三三三、、、、使用多重继承分离接口使用多重继承分离接口使用多重继承分离接口使用多重继承分离接口 下面程序展示了如何使用多重继承达到符合 ISP 的目标。 interface Door { public void Lock(); public void Unlock(); public boolean IsDoorOpen(); } interface TimerClient{ public void TimeOut(); } class TimerDoor implements Door,TimerClient{ public void Lock(){} public void Unlock(){} public boolean IsDoorOpen(){ return true; } public void TimeOut(){ System.out.println(" 实现警报"); } } class Timer{ public void Register(int timeout,TimerClient client){ if (timeout>4){ client.TimeOut(); } } } class Test{ public static void main (String[] args){ ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 110 - Timer c=new Timer(); c.Register(5,new TimerDoor()); } } 在这个模型中,TimerdDoor 同时继承 Door 和 TimerDoor 。尽管这两个基类的客户程序都可 以使用 TimedDoor ,但是实际上却都不再依赖于 TimerdDoor 类。这样,它们就通过分离的接口 使用同—个对象。 3.7 包的设计与重构原则包的设计与重构原则包的设计与重构原则包的设计与重构原则 随着应用程序规模和复杂度的增加,需要在更高层次对它们进行组织。类对于小型应用程 序来说是非常方便的组织单元,但是对于大型应用程序来说,如果仅仅使用类作为惟一的组织 单元,就会显得粒度过细。因此,就需要比类“大”的“东西”来辅助大型应用程序的组织。 本节阐述 6 个原则。前 3 个原则关注包的内聚性,这些原则能够指导我们对类组包。后 3 个原则关注包的耦合性,这些原则帮助我们确定包之间的相互关系。最后两个原则还描述了一 组依赖性管理度量方面的内容,开发者可以据此对设计中的依赖结构进行度量和刻画。 一一一一、、、、如何进行包的设计如何进行包的设计如何进行包的设计如何进行包的设计 在 UML 的概念中,包可以用作包容、组织类的容器。通过把类组织成包,我们可以在更高 层次的抽象上来理解设计。我们也可以通过包来管理软件的开发和发布。目的就是根据一些原 则对应用程序中的类进行划分,然后把那些划分后的类分配到包中。 类经常会和其他类之间存在依赖关系,这些依赖关系还经常会跨越包的边界。因此,包之 间也会产生依赖关系。包之间的依赖关系展现了应用程序的离层组织结构,我们应该对这些关 系进行管理,一般来说,我们感兴趣的是如下五个问题:  在向包中分配类时应该依据什么原则?  应该使用什么设计原则来管理包之间的关系?  包的设计应该允于类呢(自项向下)? 还是类的设计应该先于包(白底向上)?  如何实际表现出“包”?  包创建好后,我们应当将它们用于何种目的? 二二二二、、、、包的内聚性原则包的内聚性原则包的内聚性原则包的内聚性原则 这里要讲述的 3 个关于包的内聚性原则,可以帮助开发者决定如何把类划分到包中。这些 原则依赖于这样的事实:至少已经存在一些类,并且它们之间的相互关系也已经确定。因此, 这些原则是根据。“自底向上”的观点对类进行划分的。 1,,,,重用发布等价原则重用发布等价原则重用发布等价原则重用发布等价原则((((REP)))) 这个原则描述为:重用的粒度就是发布的粒度。 REP 带给我们了关于如何把设计划分到包中的第一个提示。由于重用性必须是基于包的, 所以可重用的包必须包含可重用的类。因此,至少,某些包应该由一组可重用的类组成。为什 么要这样考虑问题呢? 1))))重用与发布粒度相同的包便于维护重用与发布粒度相同的包便于维护重用与发布粒度相同的包便于维护重用与发布粒度相同的包便于维护 当我们重用一个类库时,对这个类库的作者有什么期望呢?你当然想得到好的文档,可以 工作的代码,规格清晰的接口等等。但是,你还会有其他的期望: ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 111 -  你希望代码的作者能保证为你维护这些代码,只有这样才值得你在重用这些代码上花 费时间。毕竞,如果需要你亲自来维护这些代码,那将会花费你大量的时间,这些时 间也许可以自己用来设计一个小的但足好些的包。  你希望代码的作者计划对代码的接口和功能进行任何改变时,提前通知你一下。但是, 仅仅通知一下是不够的。代码的作者必须尊重你拒绝使用任何新版本的权力。否则, 当你处在开发进度中的一个关键时刻时,他可能发都了一个新的版本,或者他对代码 进行了改变,之后就干脆再也无法与你的系统兼容了。  无论在哪种情况下,如果你决定不接纳新版本,作者必须保证对于仍然使用的旧版本 继续提供一段时间的支持。这段时间也许只有 3 个月,或者长达 1 年,你们两个人之 间必须就这些事情进行磋商。但是,他不能够和你断绝关系并且拒绝对你提供支持。 如果他不同意对你使用的稍旧一点的版本提供支持,那么你就应该认真的考虑一下是 否情愿忍受对方反复无常的变化,而继续使用他的代码。 2))))重用与发布粒度相同的包便于版本跟踪重用与发布粒度相同的包便于版本跟踪重用与发布粒度相同的包便于版本跟踪重用与发布粒度相同的包便于版本跟踪 这个问题主要是行政问题。如果有其他的人将要重用代码,就必须要进行行政和支持方面 的工作。但是这些行政上的问题对于软件的包结构具有深刻的影响。为了给重用者提供所需的 保证,代码的作者必须把他们的软件组织到——个可重用的包中,并且通过版本号对那些包进 行跟踪。 行政上的约束力将会影响到对于软件的划分,这看上去会令人个安,但是软件不是一个可 以依据纯数学规则组织起来的纯数学实体。软件是一个人的智力活动的产品。软件由人创建并 被人使用。并且如果我们将要对软件进行重用,那么它肯定以一种人认为方便重用的方式进行 划分。 3))))可重用的包需要提供变更通知可重用的包需要提供变更通知可重用的包需要提供变更通知可重用的包需要提供变更通知、、、、安全性以及支持安全性以及支持安全性以及支持安全性以及支持 REP 指出,一个包的重用粒废可以和发布粒度一样大。我们所重用的任何东西都必须同时 被发布和跟踪。简单的编写一个类,然后声称它是可重用的做法是不现实的。只有在建立一个 跟踪系统,为潜在的使用者提供所需要的变更通知、安全性以及支持后,重用才有可能。 那么,关于包的内部结构方面,我们学到了什么呢?我们必须从潜在的重用者的角度去考 虑包的内容。如果这个包中的软件是用来重用的,那么它就不能再包含不是为了重用目的而设 计的软件。一个包中的软件要么都是可重用的,要么都不是可重用的。 2,,,,共同重用原则共同重用原则共同重用原则共同重用原则((((CRP)))) 这个原则描述为:一个包中的所有类应该是共同重用的。 如果重用了包中的一个类,那么就要重用包的所有类。这个原则可以帮助我们决定哪些类 应该放进同—个包中。它规定了趋向于共同重用的类应该属于同一个包。 CRP 告诉我们更多的是,什么类不应该放在一起。CRP 规定相互之问没有紧密联系的类不 应该在同一个包中。 1))))一个包中的所有类对于同一类用户来说都是可重用的一个包中的所有类对于同一类用户来说都是可重用的一个包中的所有类对于同一类用户来说都是可重用的一个包中的所有类对于同一类用户来说都是可重用的 可重用性不是唯一的标准,我们也要考虑重用这些软件的人。当然,—个容器类库是可重 用的,—个金融方面的框架也是可重用的。但是,我们不希望把它们放进同一个包中。很多希 望重用容器类库的人可能对于金融框架根本不感兴趣。因此,我们希望一个包中的所有类对于 同一类用户来说都是可重用的。我们不希望—个用户发现包中所包含的类中,—些是他所需要 的,而另一些对他却完全不适合。 2))))如果包中的类之间如果包中的类之间如果包中的类之间如果包中的类之间互相依赖彼此互相依赖彼此互相依赖彼此互相依赖彼此紧密耦合紧密耦合紧密耦合紧密耦合,,,,就必须共同重用就必须共同重用就必须共同重用就必须共同重用 类很少会孤立的重用。一般来说,可重用的类需要与作为该可重用抽象一部分的其他类协 作。CRP 规定了这些类应该属于同一个包,在这样的一个包中,我们会看到类之间有很多的互 相依赖,这些类被此之间紧密耦合在一起,因此必须共同重用。 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 112 - 3))))共同重用的包便于版本控制共同重用的包便于版本控制共同重用的包便于版本控制共同重用的包便于版本控制 此外,包也经常以共享库、DLL、JAR 等物理表示的形式出现。如果被使用的包以 JAR 的 形式发布,那么使用这个包的代码就依赖于整个 JAR。对 JAR 的任何修改——即使所修改的是 与用户代码无关的类,仍然会造成这个 JAR 的一个新版本的发布。这个新 JAR 仍然要重新发行, 并且使用这个 JAR 的代码也要进行重新验证。 因此,当我们依赖于一个包时,我们将依赖于那个包中的每一个类。换句话说,如果我们 确信一个包中的所有类是不可分开的,仅仅依赖于共中—部分的情况是不可能的。否则,我们 就要进行不必要的重新验证和重新发行,并且会白费相当数量的努力。 3,,,,共同封闭原则共同封闭原则共同封闭原则共同封闭原则((((CCP)))) 这个原则描述为:包中的所有类对于同一类性质的变化应该是共同封闭的。 这实际上考虑了变化的轴线。一个变化若对一个包产生影响,则将对该包中的所有类产生 影响,而对于其他的包不造成任何影响。这也可以认为是单一职责原则(SRP)对于包的重新规 定。正如 SRP 规定的,一个类不应该包含多个引起变化的原因那样,这条原则规定了一个包不 应该包含多个引起变化的原因。 1))))可维护性是包设计的重要依据可维护性是包设计的重要依据可维护性是包设计的重要依据可维护性是包设计的重要依据 在大多数的应用中,可维护性的重要性是超过可重用性的。如果一个应用中的代码必须更 改,那么我们宁愿更改都集中在一个包中,而不是分布在多个包中。如果更改集中在—个单一 的包中,那么我们仅仅需要发布那一个更改了的包。不依赖于那个更改了的包的其他包则不需 要重新验证或者重新发布。 2))))信息隐蔽是共同封闭原则的一个应用信息隐蔽是共同封闭原则的一个应用信息隐蔽是共同封闭原则的一个应用信息隐蔽是共同封闭原则的一个应用 在设计中我们经常遇到信息隐蔽模块,就可以使用这个原则。信息隐藏的目的时把变更隔 离在一个模块内,防止变更扩散到其它的模块内,这是防止变更扩散最早的技术,由于它使用 预期变更作为分解的基础,到今天仍然是最重要的技术。 3))))把可能由于同样的原因而更改的所有类共同聚集在一个包内把可能由于同样的原因而更改的所有类共同聚集在一个包内把可能由于同样的原因而更改的所有类共同聚集在一个包内把可能由于同样的原因而更改的所有类共同聚集在一个包内 CCP 鼓励我们把可能由于同样的原因而更改的所有类共同聚集在同一个地方。如果两个类 之间有非常紧密的绑定关系,不管是物理上的还是概念上的,那么它们总是会一同进行变化, 因而它们应该属于同一个包中。这样做会减少软件的发布、重新验证、重新发行的工作量。 4))))这个原则和开放封闭原则这个原则和开放封闭原则这个原则和开放封闭原则这个原则和开放封闭原则(OCP) 密切相关密切相关密切相关密切相关 这个原则和开放封闭原则(OCP) 密切相关。本原则中“封闭”这个词和 OCP 中的具有同样 的含意。OCP 规定了类对于修改应该是封闭的.对于扩展应该是开放的。但是正如我们所学到 的,100 %的封闭是不可能做到的。应当进行有策略的封闭。我们所设计的系统应该对于我们经 历过的最常见的变化做到封闭。 CCP 通过把对于一些确定的变化类型开放的类共同组织到同一个包中,从而增强了上述内 容。因而,当需求中的一个变化到来时,那个变化就会很有可能被限制在最小数量的包中。 5))))对内聚性的重新认识对内聚性的重新认识对内聚性的重新认识对内聚性的重新认识 过去,我们对内聚性的认识要远比上面 3 个原则所蕴含的简单。我们习惯于认为内聚性不 过是指一个模块执行一项并且仅仅一项功能。然而,这 3 个关于包内聚性的原则描述了有关内 聚性的更加丰富的变化。在选择要共同组织到包中的类时,必须要考虑可重用性与可开发性之 间的相反作用力。在这些作用力和应用的需要之间进行平衡不是一件简单的工作。此外,这个 平衡几乎总是动态的。也就是说,今天看起来合适的划分到了明年也许就不再合适了。因此, 当项目的重心从可开发性向可重用性转变时,包的组成很可能会变动并随时间而演化。 三三三三、、、、包的耦合性原则包的耦合性原则包的耦合性原则包的耦合性原则((((ADP)))) ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 113 - 接下来的 3 个原则用来处理包之间的关系。这里,我们会再次碰到可开发性和逻辑设计之 间的冲突力。来自技术和行政方面的作用力都会影响到包的组织结构,并且这种作用力还是易 变的。我们应该有过这样的经历,工作了—整天,终于完成了某项功能后回家,不料第二天早 晨,却发现那项功能不再工作了。原因有人比你走的更晚,并且更改了你所依赖的某些东西。 这称之为“晨后综合症”。如果开发环境中存在许多开发人员都在更改相同的源代码文件集合的 情况,那么就会发生晨后综合症。在相对小的项目中,这不是一个大问题。但是当项目和开发 团队的规模增长时,晨后综合症就会带来可怕的恶梦。在缺乏规范的团队中,几周都无法构建 出—个稳定的项目版本的情况是很常见的,下面我们来考虑解决这个问题的办法。 1,,,,消除依赖环消除依赖环消除依赖环消除依赖环 1))))把包的发布和私有修改分开把包的发布和私有修改分开把包的发布和私有修改分开把包的发布和私有修改分开 通过把开发环境划分成可发布的包,可以解决上述问题。这些包可以作为上作单元被一个 开发人员或者一个开发团队检出(check out) 。当开发人员使一个包可以工作时,就把它发布给其 他开发人员使用。他们赋予该包一个版本号并把它移到—个供其他开发人员使用的目录中。接 着,他们可以在自己的私有区域中继续修改他们的包。其他所有人都使用那个已经发布的版本。 2))))开发团队独立决定何时采用包的新版本开发团队独立决定何时采用包的新版本开发团队独立决定何时采用包的新版本开发团队独立决定何时采用包的新版本 当制作了一个包的新版本时,其他开发团队可以决定是否马上采用这个新的版本。如果决 定不采用,则他们完全习以继续使用老的版本。一旦觉得自己准备就绪,就可以开始使用新的 版本。因此,所有的开发团队都不会受其他开发团队支配。对一个包作的更改个必立即反应到 其他开发团队中。每个开发团队独立决定何时采用包的新版本。此外,集成是以小规模增量的 方式进行的。这样,就不会再发生所有的开发人员必须集合到一起把他们做的每一件工作集成 起来的情况。 3))))配置管理对软件开发的支持配置管理对软件开发的支持配置管理对软件开发的支持配置管理对软件开发的支持 这是—个非常简单、合理的过程,并被广泛使用。也是配置管理对软件开发的支持。不过, 要使其能够工作,就必须要对包的依赖关系结构进行管理。包的依赖关系结构不能存在有环。 如果依赖关系结构中存在环,那么就不能避免晨后综合症。 4))))这种决定过程需要考虑包的依赖关系这种决定过程需要考虑包的依赖关系这种决定过程需要考虑包的依赖关系这种决定过程需要考虑包的依赖关系 考虑下图所示的包图。图中展示了组成—个应用程序的非常典型的包结构。相对于这个例 子的意图来说,这个应用程序的功能并不更要。重要的是包的依赖关系结构。请注意,该结构 是一个有向图。其中,包是结点,依赖关系是有向边。 现在,请注意另外—件事情。无论从哪个包开始,都无法沿着依赖关系而绕回到这个包。 该结构中没有环。它是一个有向无环图(DAG)。 当负责 MyDialogs 的团队发布了这个包的一个新版本时,很容易逆着依赖关系指向寻找出 受到影响的包。可以看出,MyTasks 和 MyApplication 都会受到影响。当前工作于这两个包的开 发人员就要决定何时应该和 MyDialogs 的新版本集成。 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 114 - 还耍注意,当 MyDialogs 发布时,完全不会影响到系统中许多其他的包。它们不知道 MyDialogs ,并且也不关心何时对 MyDialogs 进行了更改。这很好。这意味着发布 MyDialogs 的 影响相对较小。 当工作于 MyDialogs 包的开发人员想要运行这个包的测试时,只需把他们的 MyDialogs 版 本沿着正向依赖关系寻找,本例中是和当前正使用的 Windows 包的版本一起编译、链接即可。 不会涉及到系统中任何其他的包。这很好。这意味着工作于 MyDialogs 的开发人员只需较少的 工作即可建立一个测试,而且他们要考虑的变数也不多。 在发布整个系统时,是自底向上进行的。首先编译、测试以及发布 Windows 包。接着是 MesssageWindow 和 MyDialogs 。在它们之后是 Task ,然后是 TaskWindow 和 Database 。接着是 MyTasks ,最后是 MyApplication 。这个过程非常清楚并且易于处理。我们知道如何去构建系统, 因为我们理解系统各个部分之间的依赖关系。 3,,,,包依赖关系图中环造成的影响包依赖关系图中环造成的影响包依赖关系图中环造成的影响包依赖关系图中环造成的影响 1))))新的需求有可能造成依赖环新的需求有可能造成依赖环新的需求有可能造成依赖环新的需求有可能造成依赖环 如果一个新需求迫使我们更改 MyDialogs 中的一个类去使用 MyApplication 中的—个类,这 就产生一个依赖关系环,如下图所示。 2))))依赖关系环会导致依赖关系环会导致依赖关系环会导致依赖关系环会导致不良的后果不良的后果不良的后果不良的后果 例如,工作于 MyTasks 包的开发人员知道,为了发布 MyTasks 包,他们必须得兼容 Task 、 MyDialogs 、Database 以及 Windows 。然而,由于依赖关系环的存在,他们现在必须也要兼容 MyApplication 、TaskWindow 以及 MessageWindow 。也就是说,现在 MyTasks 依赖于系统所有 其他的包,这就致使 MyTasks 非常难以发布。 MyDialogs 有着同样的问题。事实上,这个依赖关系环会迫使 MyApplication 、MyTasks 以 及 MyDialogs 总是同时发布。它们实际上已经变成了同一个大包。于是,在这些包上工作的所 有开发人员就会再次遭受晨后综合症。他们彼此之间的发布行动要完全一致,因为他们必须都 要使用彼此间完全相间的版本。 这还只是问题的一部分。考虑一下我们想要测试 MyDialogs 包时会发生什么。我们必须要 链接进系统中所有其他的包,包括 Database 包。这意味着仅仅为了测试 MyDialogs 就必须要做 一次完整的构建,这是不可忍受的。 3))))单元测试可以发现这种后果单元测试可以发现这种后果单元测试可以发现这种后果单元测试可以发现这种后果 如果想知道为何必须要链接进这么多不同的库,以及这么多其他人的代码,只需运行一个 某个类的简单的单元测试就可以了,如果不断的提示你引用某个包,或许就是因为依赖关系图 中存在环的缘故。这种环使得非常难以对模块进行隔离,单元测试和发布变得非常困难且易于 出错。而且,在 C++ 中,编译时间会随模块的数目成几何级数增长。 此外,如果依赖关系图中存在环,就很难确定包构建的顺序。事实上,也许就不存在恰当 的顺序。对于像 Java 一样要从编译过的文件中读取它们的声明来说,这会导致一些非常讨厌的 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 115 - 问题。 3,,,,解除依赖环解除依赖环解除依赖环解除依赖环 任何情况下,都可以解除包之间的依赖环并把依赖关系图恢复为一个 DAG。有两个主要的 方法: 1))))使用依赖倒置原则使用依赖倒置原则使用依赖倒置原则使用依赖倒置原则((((DIP): 针对上图的情况.可以创建—个具有 MyDialogs 需要的接口。然后,把接口放进 MyDialogs 中,并使 MyApplication 中的类从其继承。这就倒置了 MyDialogs 与 MyApplication 的依赖关系, 从而解除了依赖环。 请注意,我们再次从客户的角度而不是服务器的角度出发来命名接口。这是接口属于客户 规则的又一次应用。 2))))新创建一个包新创建一个包新创建一个包新创建一个包 新创建一个 MyDialogs 和 MyApplication 都依赖的包 NewPackage 。把 MyDialogs 和 MyApplication 都依赖的类移到这个新包中,如下图所示。 这个解决方案意味着,在需求改变面前,包的结构是不稳定的。事实上,随着应用程序的 增长,包的依赖关系结构会抖动抖动抖动抖动((((yner ))))和增长。因此,必须要始终对依赖关系结构中环的情 况进行监控。如果出现了环,就必须要使用某中方法把其解除。有时这意味着要创建新的包, 这就造成依赖关系结构增长。 4,,,,不能自顶向下设计包结构不能自顶向下设计包结构不能自顶向下设计包结构不能自顶向下设计包结构 1))))包结构不是设计系统时首先考虑的事情之一包结构不是设计系统时首先考虑的事情之一包结构不是设计系统时首先考虑的事情之一包结构不是设计系统时首先考虑的事情之一 讨论到现在,我们可以得出—个必然的结论:不能自顶向下设计包的结构。这意味着包结 构不是设计系统时首先考虑的事情之一。事实上,包结构应该是随着系统的增长、变化而逐步 演化的。也许你会认为这是违反直觉的。我们已经认为像包这样的大粒度分解向样也是高层的 功能分解。当我们看到一个像包依赖关系结构这样的大粗度分组时,就会觉得应该以某种方式 描绘了系统的功能。然而,这可能不是包依赖关系图的一个属性。 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 116 - 2))))包的依赖关系应用程序的功能之间几乎没有关系包的依赖关系应用程序的功能之间几乎没有关系包的依赖关系应用程序的功能之间几乎没有关系包的依赖关系应用程序的功能之间几乎没有关系 事实上,包的依赖关系图和描绘应用程序的功能之间几乎没有关系。相反,它们是应用程 序可构建性的映射图。在项目开始的时候,可能会有一个依据于功能的粗略的包结构图,但无 需构建依赖关系图。但是,随着实现和设计初期累积的类越来越多,为避免项目开发中出现晨 后综合症,就需要对依赖关系进行管理。此外,我们也想尽可能地保持更改的局部化,所以我 们开始关注 SRP 和 OCP,并把可能会一同变化的类放在一起。 随着应用程序的不断增长,我们开始关注创建可重用的元素。于是,就开始使用 CRP 来指 导包的组合。最后,当环出现时,就会使用 ADP,从而包的依赖关系图会出现抖动以及增长。 3))))在设计类之前去设计包的依赖关系结构很可能会失败在设计类之前去设计包的依赖关系结构很可能会失败在设计类之前去设计包的依赖关系结构很可能会失败在设计类之前去设计包的依赖关系结构很可能会失败 如果在设计任何类之前试图去设计包的依赖关系结构,那么很可能会遭受惨败。我们对于 共同封闭还没有多少了解,也还没有觉察到任何可重用的元素,从而几乎当然会创建产生依赖 环的包。所以,包的依赖关系结构是和系统的逻辑设计一起增长和演化的。 四四四四、、、、包的稳定依赖原则包的稳定依赖原则包的稳定依赖原则包的稳定依赖原则((((SDO)))) 要使设计可维护,设计就不能是完全固定的,某种程度的易变性是必要的。我们通过遵循 共同封闭原则(CCP) 来达到这个目标。使用这个原则,可以创建对某些变化类型敏感的包。这些 包被没计成可变的。我们期望它们变化。 对于任何包而言,如果期望它是可变的,就不应该让一个难以更改的包依赖于它!否则, 可变的包同样也会难以更改。如果我们设计了一个易于更改的包,其他人只要创建了一个对它 的依赖,就可以使它变得难以更改,这就是软件的反常特性。没有改变你的模块中任何一行代 码,可是它突然之间就变得难以更改了。通过遵循 SDO,我们可以确保那些打算易于更改的模 块不会被那些比它们难以更改的模块所依赖。 1,,,,稳定性稳定性稳定性稳定性 稳定性和更改所需要的工作量有关。使软件包难以更改的因素有许多:它的规模、复杂性、 清晰程度等等。我们会忽略所有这些因素而关注某个不同的东西。要使一个软件包难以改变, 一 个肯定可行的方法,是让许多其他的软件包依赖于它。因为要使所有依赖于它的包能够相容于 对它所做的所有更改,往往需要非常大的工作量。 1))))一个被大量依赖的包应该是稳定的一个被大量依赖的包应该是稳定的一个被大量依赖的包应该是稳定的一个被大量依赖的包应该是稳定的 下图(A)中展示了—个稳定的包 X。有 3 个包依赖于它,因此,就有 3 个合理的理由不去 更改它。我们称 X 对这 3 个包负有责任。另外,X 不依赖于任何包,因此所有的外部影响都不 会使其改变。我们称 X 是无依赖性的。 2))))不被依赖的包可以是不稳定的不被依赖的包可以是不稳定的不被依赖的包可以是不稳定的不被依赖的包可以是不稳定的 另一方面,图(B)展示了—个非常不稳定的包 Y。没有任何其他的包依赖于 Y:我们称 Y 是不承担责任的。此外,Y 依赖于 3 个包,所以它具有 3 个外部更改源。我们称 Y 是有依赖性 的。 2,,,,并非所有的包都应该是稳定的并非所有的包都应该是稳定的并非所有的包都应该是稳定的并非所有的包都应该是稳定的 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 117 - 如果一个系统中所有的包都是最大程度稳定的,那么该系统就是不能改变的。这不是所希 望的情形。事实上,我们希望所设计出来的包结构中,一些包是不稳定的而另外一些是稳定的。 下图(A)中展示了—个具有 3 个包的系统的理想配置。 1))))可改变的包位于顶部并依赖于底部稳定的包可改变的包位于顶部并依赖于底部稳定的包可改变的包位于顶部并依赖于底部稳定的包可改变的包位于顶部并依赖于底部稳定的包 可改变的包位于顶部并依赖于底部稳定的包。把不稳定的包放在图的项部是一个有用的约 定,因为任何向上的箭头都意味着违反了 SDP。 2))))易于更改的包不应该被严重依赖易于更改的包不应该被严重依赖易于更改的包不应该被严重依赖易于更改的包不应该被严重依赖 上图(B)展示了会违反 SDP 的做法。我们本打算让 Flexible 包易于更改,也就是我们希望 Flexible 是不稳定的。然而,一些工作于包 Stable 的开发人员,创建了—个对 Flexible 的依赖。 这违反了 SDP,因为 Stable 的稳定度很高。结果,Flexible 就不再易于更改了。对 Flexible 的更 改会迫使找们去处理这个更改对 Stable 及其所有依赖者的影响。 3))))可以用依赖倒置原则修正这种依赖性可以用依赖倒置原则修正这种依赖性可以用依赖倒置原则修正这种依赖性可以用依赖倒置原则修正这种依赖性 要修正这个问题,我们就必须要以某种方式解除 Stable 对 FIexible 的依赖。为什么会存在 这个依赖关系呢?从下图可以看出来,Flexible 中有一个类 C 被 Stable 中的类 U 使用。 我们可以使用依赖倒置原则(DIP)来修正这个问题。如下图所示,我们创建一个接口类 IU 并把它放进包 UInterface 中。我们确保 IU 中声明了 U 要使用的所有方法。接着,找们让 C 从这 个接口继承,这就解除了了 StsbIe 对 FIexibIe 的依赖并促使这两个包都依赖于 UInterface 。 UInterface 非常稳定,而 Flexible 仍保持它必需的不稳定性。现在所有依赖方向都是顺着稳定性 增加的方向。 五五五五、、、、包的稳包的稳包的稳包的稳定抽象原则定抽象原则定抽象原则定抽象原则((((SAP)))) 1,,,,在哪里放置高层设计在哪里放置高层设计在哪里放置高层设计在哪里放置高层设计? 系统中的某些软件不应该经常改变。该软件代表着系统的高层架构和设计决策。我们希望 这些架构决策是稳定的。因此,应该把封装系统高层设计的软件放进稳定的包中。不稳定的包 中应该只包含那些很可能会改变的软件。 然而,如果把高层设计放进稳定的包中,那么体现高层设计的源代码就会难以更改。这会 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 118 - 使设计变得不灵活。怎样才能让一个具有最高稳定性的包足够的灵活,可以经受得住变化呢?在 OCP 中可以找到答案。OCP 原则告诉我们,那些足够灵活可以无需修改即可扩展的类是存在的, 并且是所希望的。哪种类符合 OCP 原则呢?抽象类。 2,,,,包的抽象程度应该和其稳定程度一致包的抽象程度应该和其稳定程度一致包的抽象程度应该和其稳定程度一致包的抽象程度应该和其稳定程度一致 这个原则把包的稳定性和抽象性联系起来。它规定,一个稳定的包应该也是抽象的,这样 它的稳定性就不会使其无法扩展。另一方面,它规定,一个不稳定的包应该是具体的,因为它 的不稳定性使得其内部的具体代码易于更改。 因此,如果一个包是稳定的,那么它应该也要包含一些抽象类,这样就可以对它进行扩展。 可扩展的稳定包是灵活的,并且不会过分限制设计。 SAP 和 SDP 结合在一起,形成了针对包的 DIP 原则。这样说是淮确的,因为 SDP 规定依 赖应该朝着稳定的方向进行,而 SAP 则规定稳定性意味着抽象性。因此,依赖应该朝看抽象的 方向进行。 然而,DIP 是一个处理类的原则。类没有灰度的概念(the shadrsnof grey) 。一个类要么是抽 象的,要么不是。SDP 和 SAP 的结合是处理包的,并且允许一个包是部分抽象、部分稳定的。 3.8 封装类或者接口的变化封装类或者接口的变化封装类或者接口的变化封装类或者接口的变化 一一一一、、、、设计模式的基本思想设计模式的基本思想设计模式的基本思想设计模式的基本思想 1,,,,模式概念的提出模式概念的提出模式概念的提出模式概念的提出 “模式”这个词最初来自于 Christopher Alexander (克里斯多弗. 亚历山大),在城市规划 和建设的过程中,他发现许多相同的原则,在 Pattern Language (模式语言)这本书中,他把建 筑学中大量简单事务划分为若干模式(咖啡馆、街角杂货铺、天窗、与腰等高的柜台等)当拥 有丰富的模式就相当于拥有的大量的词汇,有助于使设计更完美。所谓“模式”强调的是某种 功能单元可能被使用上百次,但使用的方式却不尽相同。模式是一种灵活的思想,运用它却需 要智慧和想象力,因为没有两种完全一样的功能需求。 到上个世纪 90 年代,一群优秀的开发者偶尔发现了 Alexander 关于“设计模式”的研究成 果,他们发现,建筑学中的“设计模式”理论也同样适合软件设计。因为,软件设计中同样存 在不断重复出现,可以用某种相同方式解决的问题。也可以按照某种模式进行识别,并且可以 在这个模式的基础上创建特定的解决方案。 如果这个假想是成立的,那么软件行业就可以建立自己的设计模式,并以此在企业级开发 中设计出更加优秀的系统来。 2,,,,可复用面向对象软件可复用面向对象软件可复用面向对象软件可复用面向对象软件 对设计模式影响最深刻的书,当推 Gamma 、Helm 、Johnson 和 Vissides 的 Design Patterns:Elements of Reusable Object-Oriented Software ,1995 ,p185 (中文版《设计模式:可复 用面向对象软件基础》,机械工业出版社,2000 年 9 月,p121 )。这四个人被称为四人团(GoF )。 该书认为,我们不能认为任何以面向对象方法构造的软件,都便于实现软件复用。在软件 分析与设计中如果拥有大量的模式就可以使复用成为可能。 该书认为,对于每个模式都必须有如下基本要素: 项目项目项目项目 描述描述描述描述 名称 每个模式都有一个独一无二的名称,人们用名称来鉴别模式。 意图 模式的目的。 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 119 - 问题 模式试图解决的问题。 解决方案 对于自己出现的场景的问题,模式怎样提供一个解决方案。 参与者和协作者 模式包括的实体。 效果 使用模式的效果,使用模式同时研究其约束。 实现 怎样实现模式,注意:实现只是模式的具体表现形式,而不能象模式 本身那样去分析。 GoF 参考 在四人团的书中得到更多的信息的位置。 设计模式并不是反映了业务领域事物事物事物事物之间特有的共性结构,而是抽取了具体的领域特征, 根据问题问题问题问题的共性特点,寻找到的解决方案的共性结构,因此,它具备更广阔的复用可能。 3,,,,利用设计模式利用设计模式利用设计模式利用设计模式处理变化处理变化处理变化处理变化 我们已经讨论了面向对象的设计原则,这些原则中把变化作为最最重要的设计环境来考虑。 而设计模式为我们具体这一类问题提供了现实的可能。 如果我们在项目开发中只醉心于解决眼前的、紧迫的需求,而不关心将来的维护,试问这 样开发出来的项目真的能用吗?我经常听到人们在抱怨,一个项目已经通过了交付测试,担投 运以后用户又提出了新的需求,这时就面临这样一个问题,修改一段代码就会需要几百个相关 代码跟着改变,因此升级就变成几乎不可能的事情,于是,开发者抱怨说,用户为什么当初不 做好需求分析呢?而用户抱怨说,随着时代的变化当初怎么可能预料到现在的需求呢?最后的 结果,恐怕只能是一个,那就是这个系统被弃之不用! 我们稍加注意就会发现,软件编程人员往往存在这样一种潜在的信仰,那就是“为变化进 行设计”比“不考虑变化进行设计”开销要大。但是事实是不是这样呢?其实情况往往正好相 反,当我们回过头来考虑已经完成的系统,看看它怎样随着时间的流逝而变化的时候,我们就 会发现,真正的开销是发生在后期不断应付需求的变更。因此为了适应变化我们将研究设计模 式,重要的一点是,我们将预料到变化将会发生,而且也预料到将会在哪里发生。这种方式基 于这样上面几个已经讨论过的原则: 1)针对接口编程而不是针对实现编程(依赖于抽象)。 2)优先使用对象组合,而不是类的继承(低耦合原则)。 3)考虑您的设计哪些是可变的,注意,不是考虑什么会迫使您的设计改变,而是考虑要素 变化的时候,不会引起重新设计。 最主要的一点就是,封装变化的概念是许多设计模式的主题。我要建议的是,在不可避免 的要求修改代码以处理新的需求的时候,你至少需要考虑这些策略,如果遵循这些策略不会使 设计和实现的开销严重增大,那就是用它们。你可以期待这些策略给你带来长期的利益,而足 以补偿短期开销的适度增加。 我并不是建议你盲目的遵循这些原则,其实为了同一个目的备选设计是有很多的,其实更 重要的还是依赖自己的经验,这就是跟着感觉走,结果是说明一切的。 4,,,,设计模式的原则和策略设计模式的原则和策略设计模式的原则和策略设计模式的原则和策略 设计模式提出了一系列的设计原则,这些原则和我们已经讨论过的面向对象的设计原则是 相符合的,也是面向对象原则的进一步细化。。 1))))开放开放开放开放-封闭原则封闭原则封闭原则封闭原则 由于对软件的修改可能会引入问题,这种困境促使 Betrand Meyer 提出开放-封闭原则,这 条原则的意思是说:模块、方法和类应该对扩展是开放的,而对更改是封闭的。换句话说,我 们应该把我们的软件设计成这样的:我们可以在不修改代码的前提下,对我们的软件进行扩展。 2))))从场景进行设计的原则从场景进行设计的原则从场景进行设计的原则从场景进行设计的原则 在设计我们的软件片断细节之前,首先创建整体视图,几乎所有的设计模式都遵循这条途 径,因为设计模式都是接口和类协调工作的。 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 120 - 3))))封装封装封装封装变化的原则变化的原则变化的原则变化的原则 封装变化就是尽可能把预期可能变化的部分给隔离出来,这样就有利于在发生变化的时候 修改量小。例如,有一些变化包括类的变化或者接口的变化,当预测这种变化可能存在的时候, 可以使用外观模式或者适配器模式。 二二二二、、、、利用外观模式封装类的变化利用外观模式封装类的变化利用外观模式封装类的变化利用外观模式封装类的变化 1,,,,意图意图意图意图 外观模式定义了一个把子系统的一组接口集成在一起的高层接口,以提供一个一致的处理 方式,其它系统可以方便的调用子系统中的功能,而忽略子系统内部发生的变化。 2,,,,使用场合使用场合使用场合使用场合  为一个比较复杂的子系统,提供一个简单的接口。  把客户程序和子系统的实现部分分离,提高子系统的独立性和可移植性。  简化子系统的依赖关系 3,,,,结构结构结构结构 外观模式为用户提供了使用子系统组件的统一的接口,使用户减少了处理对象的数目,并 且使子系统使用简单。使用外观模式使子系统和客户之间实现松散耦合关系,由于用户针对接 口编程,因此子系统的变化不会影响到客户的变化,而且有助于分层架构的实现。 如图所示某信息系统的总体体系结构图,其中客户端使用了分层结构。 在这个结构中,应用层与领域层的连接关系非常混乱,领域层中类的任何变化都可能引起 应用层大量的未知变化,使系统的升级时成本很高,可维护性大幅降低。由于这种混乱是在类 的(或者模块)的层面上,为了解决这个问题,我们可以使用外观模式,如下图所示。 这种模式一个显而易见的好处,本来一个类的修改可能会影响一大片代码,而加了外观类 以后只需要修改很少量的代码就可以了,这就使系统的高级维护成为可能。 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 121 - 三三三三、、、、利用适配器模式封装接口变化利用适配器模式封装接口变化利用适配器模式封装接口变化利用适配器模式封装接口变化 在系统之间集成的时候,最常见的问题是接口不一致,很多能满足功能的软件模块,由于 接口不同,而导致无法使用。在这种情况下可以使用适配器模式。 1,,,,意图意图意图意图 适配器模式的含义在于,把一个类的接口转换为另一个接口,使原本不兼容而不能一起工 作的类能够一起工作。 2,,,,结构结构结构结构 适配器有类适配器和对象适配器两种类型,二者的意图相同,只是实现的方法和适用的情 况不同。类适配器采用继承的方法来实现,而对象适配器采用组合的方法来实现。 1))))类适配器类适配器类适配器类适配器 类适配器采用多重继承对一个接口与另一个接口进行匹配,这种方式有一个限制,由于大 部分面向对象语言不承认多重继承,所以当 Adapter 类需要继承多个类的时候就没有办法实现, 这时,可以使用对象适配器。 2))))对象适配器对象适配器对象适配器对象适配器 对象适配器采用对象组合,通过引用一个类与另一个类的接口,来实现对多个类的适配。 3,,,,使用场合使用场合使用场合使用场合 当需要使用一个已经存在的类,但接口与设计要求不符合的时候,使用适配器模式可以是 一个解决方案。例如,如图所示某信息系统的总体体系结构图,其中“三维图形处理组件”是 外包开发,该组件接口随着版本升级可能发生改变。由于接口变化将会引起客户端多处发生改 变,使系统的升级时成本很高,可维护性大幅降低,怎么解决呢? 我们来观察一下这个系统,发现有如下臭味:  “三维图形处理组件”的接口变化将会引起客户端多处发生改变,使系统的升级时成 本很高,可维护性大幅降低。  组件直接与信息处理服务器通信,破坏了 Layer 架构风格的优势。 因此,我们可以使用适配器模式(Adapter )来屏蔽接口的变化,用外观(facade )模式解 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 122 - 决这些问题。其中使用 façade 的原因是“信息处理服务器”视作子系统。解决方案的结构图如 下,把接口放在上层是希望实现依赖倒置。 3.9 封装业务单元的变化封装业务单元的变化封装业务单元的变化封装业务单元的变化 设计弹性的架构,关键是要把模块中不变部分与预测可变部分分开,以防止升级过程中对 基本代码的干扰。如果我们遇到的是业务流程不变,但是业务单元可能改变,这种分离可以有 多种方式,一般来说可以从纵向、横向以及外围三个方面考虑。 一一一一、、、、利用模板方法封装业务单元变化利用模板方法封装业务单元变化利用模板方法封装业务单元变化利用模板方法封装业务单元变化 1、、、、意图意图意图意图 软件复用的关键是寻找相似性,在很多情况下,相似性表现为业务流程相似,但是业务单 元具有特殊性。如果是这种情况,可以定义一个操作中的业务流程骨架,而将一些业务单元的 实现延伸到子类中去,使得子类可以不改变一个业务流程的的结构,即可重新定义该业务流程 的某些特定业务单元。 2、、、、结构结构结构结构 模板方法模式(Template Method )是准备一个抽象类,将部分逻辑以具体方法以及具体构 造子类的形式实现,然后声明一些抽象方法来迫使子类实现剩余的逻辑。不同的子类可以以不 同的方式实现这些抽象方法,从而对剩余的逻辑有不同的实现。 代码: public abstract class Payment{ private double amount; public double getAmount(){ return amount; } ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 123 - public void setAmount(double value){ amount = value; } public String goSale(){ String x = " 不变的流程一 "; x += Action(); // 可变的流程 x += amount + ", 正在查询库存状态"; // 属性和不变的流程二 return x; } public abstract String Action(); } class CashPayment extends Payment{ public String Action(){ return " 现金支付"; } } 测试: public class Test{ public static void main (String[] args){ Payment o; o = new CashPayment(); o.setAmount(555); System.out.println(o.goSale()); } } 假定系统已经投运,用户提出新的需求,要求加上信用卡支付和支票支付,可以这样写: public class CreditPayment extends Payment{ public String Action(){ return " 信用卡支付,联系支付机构"; } } class CheckPayment extends Payment{ ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 124 - public String Action(){ return " 支票支付,联系财务部门"; } } 调用: public class Test{ public static void main (String[] args){ Payment o; o = new CashPayment(); o.setAmount(555); System.out.println(o.goSale()); o = new CreditPayment(); o.setAmount(555); System.out.println(o.goSale()); o = new CheckPayment(); o.setAmount(555); System.out.println(o.goSale()); } } 二二二二、、、、利用工厂模式封装对象变化利用工厂模式封装对象变化利用工厂模式封装对象变化利用工厂模式封装对象变化 1、、、、意图意图意图意图 简单工厂的作用是实例化对象,而不需要客户了解这个对象属于哪个具体的子类。我们可 以这样来理解,简单工厂是参数化的工厂方法,由于它可以处理粒度比较大的问题,所以还是 单独列出来比较有利。 2、、、、使用场合和效果使用场合和效果使用场合和效果使用场合和效果 简单工厂实例化的类具有相同的接口,类的个数有限而且基本上不需要扩展的时候,可以 使用简单工厂。使用简单工厂缺点是实例化的类型在编译的时候已经确定,如果增加新的类, 需要修改工厂。 3、、、、结构结构结构结构 通常简单工厂需要采用静态方法来实现。下面是一个简单工厂的基本框架,Factory 类为工 厂类,里面的静态方法 PaymentFactory 决定了实例化哪个子类。 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 125 - // Payment.java public abstract class Payment{ private double amount; public double getAmount(){ return amount; } public void setAmount(double value){ amount = value; } public String goSale(){ String x = " 不变的流程一 "; x += Action(); // 可变的流程 x += amount + ", 正在查询库存状态"; // 属性和不变的流程二 return x; } public abstract String Action(); } class CashPayment extends Payment{ public String Action(){ return " 现金支付"; } } // CreditPayment.java public class CreditPayment extends Payment{ public String Action(){ return " 信用卡支付,联系支付机构"; } } class CheckPayment extends Payment{ public String Action(){ return " 支票支付,联系财务部门"; } } // 这是一个工厂类 Factory.java public class Factory{ public static Payment PaymentFactory(String PaymentName){ Payment mdb=null; if (PaymentName.equals(" 现金")) mdb=new CashPayment(); else if (PaymentName.equals(" 信用卡")) mdb=new CreditPayment(); else if (PaymentName.equals(" 支票")) mdb=new CheckPayment(); return mdb; } ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 126 - } 调用: public class Test{ public static void main (String[] args){ Payment o; o = Factory.PaymentFactory(" 现金"); o.setAmount(555); System.out.println(o.goSale()); o = Factory.PaymentFactory(" 信用卡"); o.setAmount(555); System.out.println(o.goSale()); o = Factory.PaymentFactory(" 支票"); o.setAmount(555); System.out.println(o.goSale()); } } 三三三三、、、、利用桥接模式封装业务单元变化利用桥接模式封装业务单元变化利用桥接模式封装业务单元变化利用桥接模式封装业务单元变化 模板方法是利用继承来完成切割,当对耦合性要求比较高,无法使用继承的时候,可以横 向切割,也就是使用桥接模式。我们还是通过上面的关于支付的简单例子可以说明它的原理。 显然,它具备和模版方法相类似的能力,但是不采用继承。 public class Payment{ private double amount; public double getAmount(){ return amount; } public void setAmount(double value){ amount = value; } private Implementor imp; public void setImp(Implementor s){ imp=s; } ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 127 - public String goSale(){ String x = " 不变的流程一 "; x += imp.Action(); // 可变的流程 x += amount + ", 正在查询库存状态"; // 属性和不变的流程二 return x; } } interface Implementor{ public String Action(); } class CashPayment implements Implementor{ public String Action(){ return " 现金支付"; } } 调用: public class Test{ public static void main (String[] args){ Payment o=new Payment(); o.setImp(new CashPayment()); o.setAmount(555); System.out.println(o.goSale()); } } 假定系统已经投运,用户提出新的需求,要求加上信用卡支付和支票支付,您将怎样处理 呢? public class CreditPayment implements Implementor{ public String Action(){ return " 信用卡支付,联系支付机构"; } } class CheckPayment implements Implementor{ public String Action(){ return " 支票支付,联系财务部门"; } ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 128 - } 调用: public class Test{ public static void main (String[] args){ Payment o=new Payment(); o.setImp(new CashPayment()); o.setAmount(555); System.out.println(o.goSale()); o.setImp(new CreditPayment()); o.setAmount(555); System.out.println(o.goSale()); o.setImp(new CheckPayment()); o.setAmount(555); System.out.println(o.goSale()); } } 这样就减少了系统的耦合性。而在系统升级的时候,并不需要改变原来的代码。 四四四四、、、、利用装饰器模式封装核心业务单元利用装饰器模式封装核心业务单元利用装饰器模式封装核心业务单元利用装饰器模式封装核心业务单元 有的时候,希望实现一个基本的核心代码快,由外围代码实现专用性能的包装,最简单的 方法,是使用超类,但是超类使用了继承而提升了耦合性。在这样的情况下,也可以使用装饰 器模式,这是用组合取代继承的一个很好的方式。 1、、、、意图意图意图意图 上面所要解决的意图可以归结为“在不改变对象的前提下,动态增加它的功能”,也就是说, 我们不希望改变原有的类,或者采用创建子类的方式来增加功能,此时可以采用装饰模式。 2、、、、结构结构结构结构 装饰器结构的一个重要的特点是,它继承于一个抽象类,但它又使用这个抽象类的聚合(即 即装饰类对象可以包含抽象类对象),恰当的设计,可以达到我们提出来的目的。 假定我们已经构造了一个基于支付的简单工厂模式的系统。现在需要每个类在调用方法 goSale() 的时候,除了完成原来的功能以外,先弹出一个对话框,显示工厂的名称,而且不需要 改变来的系统,为此,在工厂类的模块种添加一个装饰类 Decorator ,同时略微的改写一下工厂 类的代码。 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 129 - // 装饰类 public class Decorator extends Payment{ private String strName; public Decorator(String strName){ this.strName = strName; } private Payment pm; public void setPm(Payment value){ pm = value; } public String Action(){ // 在执行原来的代码之前,显示提示框 System.out.println(strName); return pm.Action(); } } 而工厂类: // 这是一个工厂类 public class Factory{ public static Payment PaymentFactory(String PaymentName){ Payment mdb=null; if (PaymentName.equals(" 现金")) mdb=new CashPayment(); else if (PaymentName.equals(" 信用卡")) mdb=new CreditPayment(); else if (PaymentName.equals(" 支票")) mdb=new CheckPayment(); //return mdb; Decorator m=new Decorator(PaymentName); m.setPm(mdb); return m; } } 可以说,这是在用户不知晓的情况下,也不更改原来的类的情况下,改变了性能。 3.10 利用观察者模式处理业务单元的变化利用观察者模式处理业务单元的变化利用观察者模式处理业务单元的变化利用观察者模式处理业务单元的变化 当需要上层对底层的操作的时候,可以使用观察者模式实现向上协作。也就是上层响应底 层的事件,但这个事件的执行代码由上层提供。 1、、、、意图意图意图意图:::: 定义对象一对多的依赖关系,当一个对象发生变化的时候,所有依赖它的对象都得到通知 并且被自动更新。 2、、、、结构结构结构结构 传统的观察者模式结构如下。 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 130 - 3,,,,举例举例举例举例:::: // PaymentEvent.java 传入数据的类 import java.util.*; public class PaymentEvent extends EventObject { private String Text; // 定义 Text 内部变量 // 构造函数 public PaymentEvent(Object source,String Text) { super(source); this.Text=Text; // 接收从外部传入的变量 } public String getText(){ return Text; // 让外部方法获取用户输入字符串 } } // 监听器接口 //PaymentListener.java import java.util.*; public interface PaymentListener extends EventListener { public String Action(PaymentEvent e); } // Payment.java 平台类 import java.util.*; public class Payment{ private double amount; public double getAmount(){ return amount; } public void set(double value){ amount = value; } // 事件编程 private ArrayList elv; // 事件侦听列表对象 // 增加事件事件侦听器 public void addPaymentListener(PaymentListener m) { // 如果表是空的,先建立它的对象 if (elv==null){ elv=new ArrayList(); ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 131 - } // 如果这个侦听不存在,则添加它 if (!elv.contains(m)){ elv.add(m); } } // 删除事件侦听器 public void removePaymentListener(PaymentListener m) { if (elv!= null && elv.contains(m)) { elv.remove(m); } } // 点火 ReadText 方法 protected String fireAction(PaymentEvent e) { String m=e.getText(); if (elv != null) { // 激活每一个侦听器的 WriteTextEvett 事件 for (int i = 0; i < elv.size(); i++) { PaymentListener s=(PaymentListener)elv.get(i); m+=s.Action(e); } } return m; } public String goSale(){ String x = " 不变的流程一 "; PaymentEvent m=new PaymentEvent(this,x); x = fireAction(m); // 可变的流 x += amount + ", 正在查询库存状态"; // 属性和不变的流程二 return x; } } 调用:Test.java import java.util.*; public class Test { // 入口 public static void main(String[] args) { Payment o1 = new Payment(); Payment o2 = new Payment(); Payment o3 = new Payment(); o1.addPaymentListener(new PaymentListener(){ public String Action(PaymentEvent e){ return e.getText()+" 现金支付 "; ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 132 - } }); o2.addPaymentListener(new PaymentListener(){ public String Action(PaymentEvent e){ return e.getText()+" 信用卡支付 "; } }); o3.addPaymentListener(new PaymentListener(){ public String Action(PaymentEvent e){ return e.getText()+" 支票支付 "; } }); o1.set(777); o2.set(777); o3.set(777); System.out.println(o1.goSale()); System.out.println(o2.goSale()); System.out.println(o3.goSale()); } } 3.11 代理模式在架构代理模式在架构代理模式在架构代理模式在架构设计中的应用设计中的应用设计中的应用设计中的应用 一一一一、、、、代理模式代理模式代理模式代理模式应用应用应用应用简述简述简述简述 代理模式的意图,是为其它对象提供一个代理,以控制对这个对象的访问。 首先作为代理对象必须与被代理对象有相同的接口,换句话说,用户不能因为使不使用代 理而做改变。其次,需要通过代理控制对对象的访问,这时,对于不需要代理的客户,被代理 对象应该是不透明的,否则谈不上代理。下图是代理模式的结构。 二二二二、、、、在团队并行开发中使用代理模式在团队并行开发中使用代理模式在团队并行开发中使用代理模式在团队并行开发中使用代理模式 在软件开发过程中,需要不断的测试。然而,由于软件模块之间需要相互调用,对某一模 块的测试,又需要其它模块的配合。而且在模块开发过程中也不可能完全同步,从而给测试带 来了问题。 假定在我们设计的订单处理子系统中, Ordre (订单)类在计算订购项目金额总合的时候, ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 133 - 需要由客户服务子系统根据客户级别和销售策略来计算实际收取的费用,而客户服务系统由 OrderItme (订单项)类提供这个服务,显然这是由另一个开发组完成。 其中:Ordre 包括若干 OrderItme ,订单的总价是每个订单项之和。 在两个开发组共同完成这个项目的情况下,如果 OrderItme 没有完成,Ordre 也就没有办法 测试。一个简单的办法,是 Ordre 开发的时候屏蔽 OrderItme 调用,但这样代码完成的时候需要 做大量的垃圾清理工作,显然这是不合适的,我们的问题是,如何把测试代码和实际代码分开, 这样更便于测试,而且可以很好的集成。 如果我们把 OrderItem 抽象为一个接口或一个抽象类,实现部分有两个平行的子类,一个是 真正的 OrderItem ,另一个是供测试用的 TestOrderItem ,在这个类中编写测试代码,我们称之为 Mock 。 这时,Order 可以使用 TestOrderItem ,测试。当 OrderItem 完成以后,有需要使用 OrderItem 进行集成测试,如果 OrderItem 还要修改,又需要转回 TestOrderItem 。 我们希望只用一个参数就可以完成这种切换,比如在配置文件中,测试设为 true ,而正常 使用为 false 。 这些需求牵涉到代理模式的应用,现在可以把代理结构画清楚。 这就很好的解决了问题,实例: 在配置文件 Bean.xml 中加一个元素: 编写抽象的定单类: package demo; public abstract class AbstractOrderItem{ private String goodName; private long count; private double price; public void setGoodName(String m_GoodName){ goodName=m_GoodName; } public String getGoodName(){ return goodName; } ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 134 - public void setCount(long m_Count){ count=m_Count; } public long getCount(){ return count; } public void setPrice(double m_Price){ price=m_Price; } public double getPrice(){ return price; } // 价格求和,这个计算方式是另外的人编写的 public abstract double GetTotalPrice() throws Exception; } 编写订单代码: package demo; // 处理订单代码 public class Order{ public String Name; //public DateTime OrderDate; private java.util.ArrayList oitems; public Order(){ oitems=new java.util.ArrayList(); } public void AddItem(AbstractOrderItem it){ oitems.add(it); } public void RemoveItem(AbstractOrderItem it){ oitems.remove(it); } public double OrderPrice() throws Exception{ AbstractOrderItem it; double op=0; for (int i=0;i ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 252 - 上面定义的是一个消息类型,在具体的消息中需要与之建立关联。对于导入的数据类型与 结构,一般用命名空间(namespaces )来限定其元素名与属性名. 下面,为模式数据类型 CudtomerInfo 与 WSDL 消息类型 CustomerMessage 建立了关联。 要使用 CustomerInfo 数据类型,需要定义命名空间,比如: xmlns:openA="http://www.bank.com/xsd/AccountManagement" 第二步第二步第二步第二步 为消息定义接口类型为消息定义接口类型为消息定义接口类型为消息定义接口类型:::: 然后,需要为消息定义 portType (丛 WSDL 1.2 开始,portType 改名为 Interface ),它包括操 作名称以及输入/输出消息,例如: 绑定(bindings )属于 WSDL 的物理部分,这里省略了它们,因为采用何种通信协议,并不影响 到 WSDL 的逻辑部分或者 WS-BPEL 的定义。 第三步第三步第三步第三步 定义合作链接定义合作链接定义合作链接定义合作链接:::: 在 WSDL porTypes 的后面,需要添加称之为合作链接(partner links )的结构,它用于连接 portType 与 WS-BPEL 流程定义,例如: ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 253 - 这些合作伙伴链接把 WSDL 操作()与 WS-BPEL 过程中的步骤()相关联,并且用于衔接 “服务以及接口的描述”和“使用这些服务的过程流的描述”。 第四步第四步第四步第四步 定义定义定义定义 WS-BPEL 过程过程过程过程:::: 在扩展的 WSDL 中,WS-BPEL 部分是通过一个过程名称(proccess name )来标识的,例如: 一个抽象流程是是不可直接执行的,如果要用 WS-BPEL 来编排而不是编制,就需要设定 abstractProcess="yes"。这部分定义所需要的命名空间就在这部分定义,给出过程名称以后,还 要引用该过程合作者链接(partner links ),以指出该过程所要使用的 WSDL 相应的合作者链接, 例如: 这里列出了过程流中的六个步骤所需的六个合作链接,包括: CollectAccountInfomation :收集账户信息; ValidateAccountInfomation :有效帐户信息; OpenAccount :新建帐户; SendConfirmation :发送确认信息; RepairAccountInfomation :修改帐户信息; DeclineAccountInfomation :降级帐户信息 在合作链接列表之后是变量名称的声明,也就是过程所需的 XML Schema 、XML Simple 以及 WSDL 消息定义,例如: ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 254 - 如果过程需要错误处理的话,可以进行如下定义: 这个错误处理程序用于捕捉在验证客户数据的过程中产生的错误,比如错误的信用数据, 或者过去与银行发生的问题。 第五步第五步第五步第五步 定义定义定义定义过程流序列过程流序列过程流序列过程流序列:::: 最后,定义过程流序列,把操作放到执行关系中去,例如: ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 255 - 这个例子展示了过程流如何先通过收集客户信息功能(CollectAccountInfomation )接受输入 的客户数据,然后调用验证帐户信息功能(ValidateAccountInfomation )检查数据。根据验证结 果的不同,过程流可以进入批准阶段,也可以进入尝试清除错误阶段。WS-BPEL 为这种分支提 供了多种不同的条件动词,如 switch 、pick 、while 等。 WS-BPEL 关联集(correlation sets )标识在过程流中的多个 Web 服务间共享的数据,补偿 处理程序将执行有可能撤销先前结果的补偿程序(比如关闭前面未正确打开的账户等)。 在设计中需要注意的是,除了把 WS-BPEL 语法合并到 WSDL 所带来的麻烦以外,还必须把 WS-BPEL 构词与其它技术(比如安全性、可靠性、事务性等)的过程流构词区分开来,以免在 一起使用时发生混淆,这样才能确保整个过程设计的正确工作,当然,这也有赖于 SOA 构词描 述的进一步标准化。 3,,,,以编制为中心的服务合成案例以编制为中心的服务合成案例以编制为中心的服务合成案例以编制为中心的服务合成案例 所谓以编制为中心(orchestration-centric )的服务合成,是因为它使用自上而下的方式定义 整个过程,其中位于顶层的是一个编制,编制中的各个任务(task ),要么是一个 Web 服务,要 么是一个被顶层编制调用的子编制(sub-orchestration )。在子编制中的各个任务,要么是一个 Web 服务,要么是一个被子编制调用的编制,以此类推。 下面的例子显示了一个用于“新建账户”(OpenAccount )过程的 WS-BPEL 伪码,这个伪 码使用了 WS-BPEL 关键字,但没有采用 XML 格式,而只是为了显示 Web 服务编制的逻辑。 receive 'OpenAccountRequest' invoke CollectAccountInfo invoke ValidateAccountInfo assign AccountInfoInvalid=ValiDateAccountInfoResponse while AccountInfoInvalid=true invoke RepairAccountInfo pick onRepairAccountInfoCB invoke ValidateAccountInfo assign AccountInfoInvalid=AccountInfoResponse otherwise //timeout-assume AccountInfo can't be repaired invoke DeclineAccountApplication terminate ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 256 - end pick end while invoke OpenAccount invoke SendConfirmation 下图显示了一个 OpenAccount 过程是如何编制一系列 Web 服务请求执行的。 这里,OpenAccount 过程是作为一个 WS-BPEL 编制实现的,这个 WS-BPEL 编制:  在收到 OpenAccountRequest 时启动。  调用 OpenAccount 、CollectAccountInfomation 等 Web 服务来完成编制中的各个步骤。  为 OpenAccount 过程定义业务逻辑,包括控制逻辑(例如控制处理无效账户信息的循 环)和数据流。 虽然图中没有显示出循环机条件处理等构词,但实际上它们是存在的(它们是由编制控制 点,而不是在各个服务内部处理的)。 4,,,,Web 服务编排描述语言服务编排描述语言服务编排描述语言服务编排描述语言 W3C Web 服务编排工作组(Web Service Choregraphy Working Group )正在制定 Web 服务编 排描述语言(WS-CDL)。WS-CDL 是作为 WS-BPEL 等补充 Web 服务技术的补充而提出的,它 定义了实现业务编排或者 B2B 场景所需的可执行过程。 常见的 B2B 场景,如 RosettaNet 的合作伙伴信息流程(Partner Information Process ,PIP) 涉及到一个贸易方向另一个或者多个贸易方提交 XML 文档(例如订单)供其执行。WS-BPEL 可以定义执行流、执行流中的消息及其它活动(比如错误处理程序)。WS-BPEL 的抽象流程是 用于 B2B 交互的,而 WS-CDL 提供了更多的能力,比如不同的业务流程引擎之间彼此如何对话, 比方说,一方是 WS-BPEL 引擎,另一方是 RosettaNet 引擎,反之亦然。 WS-CDL 是从“全局的”观点为消息交换定义了公共的排序条件与约束,各个参与者可以 利用这个“全局的”定义来构建并测试解决方案。WS-CDL 不是一种可执行的语言,而是一种 定义交互模式的说明性语言,参与各方都可以把这个交互模式作为协定。 WS-CDL 文档是一组可以被各方引用的、具名的定义集和,它的根元素是 package 元素, 其中包括一个或者多个协作类型定义,package 构词的语法如下: ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 257 - importDefinitions* infomationType* token* tokenLocator* role* relationship* participant* channelType* choreography-Notation* Package 模型定义了协作的参与者、以及各个参与者的角色和相互关系,一旦达成协定, package 就跨越个协作机构的信任边界进行交换,以共享明确的定义。 可以在 package 构词中汇集一些编排定义,其中的 infomationType 、token 、tokenLocator 、role 、 relationship 、participant 、channelType 等元素被重用于当前 package 中定义的所有编排。 4,,,,以编排为中心的服务合成案例以编排为中心的服务合成案例以编排为中心的服务合成案例以编排为中心的服务合成案例 以编排为中心(choreography-centric )指的是通过一系列编排,把所有顶层业务流程中的任 务连接起来,而没有某个处于控制地位的流程执行引擎。在这里,交互是对等的,而不是像以 编制为中心的方法那样用命令来控制。 下图展示了以编排为中心的 OpenAccount 流程 例如,下面这些任务对之间的交互是作为编排定义的: CollectAccountInfomation 与 ValidateAccountInfomation ValidateAccountInfomation 与 RepairAccountInfomation RepairAccountInfomation 与 ValidateAccountInfomation OpenAccount 与 SendConfirmation RepairAccountInfomation 与 DeclineAccountInfomation 从某种意义上说,业务流程的编排描述体现了 Web 服务的大粒度要求,对于某些大粒度、 分布式的业务重用还是很有意义的。 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 258 - 7.6 SOA 的业务效益与的业务效益与的业务效益与的业务效益与误区误区误区误区 一一一一、、、、SOA 的业务效益的业务效益的业务效益的业务效益 SOA 所描述特征的服务,将具有如下业务效益。 1,,,,增强业务的机动性增强业务的机动性增强业务的机动性增强业务的机动性 增强业务的机动性,是到目前为止 SOA 最重要的业务效益。目前对许多机构而言,对新业 务需求与快速响应的业务机动性,是比开发效率还要重要的。业务机动性两个关键要素是速率 (velocity )和灵活性(flexibility )。 速率(velocity ):指的是沿着既定的路线快速前进,更快的产品或者服务的上市速度。SOA 显著降低了利用现有服务和 IT 资产组装新业务应用所需的时间,因而提高了速率。 灵活性(flexibility ):根据需要适应 IT 系统的能力。由于不断变化是业务和软件所必须面 对的现实,而且也是开销的主要源头,因此,在 IT 可以迅速修改现有系统的情况下,业务可以 快速适应新的机遇与竞争威胁。 2,,,,更好的配合业务更好的配合业务更好的配合业务更好的配合业务 当所有的业务都为共同的目标和结果提供支持的话,我们就称之为配合(alignment )。我们 可以而且应该把 IT 系统通过 SOA 提供的服务定义为直接支持组织向顾客、客户、公民与合作 伙伴等提供的服务。 用面向服务的架构做到业务与 IT 的相互配合,可以改善业务的设计与开发,这是通过业务 用户与 IT 技术的要求沟通更加流畅做到的,这也有助于把交流提升到业务层面。 3,,,,改善客户满意度改善客户满意度改善客户满意度改善客户满意度 许多机构都致力于建立一种在不同的服务渠道(面对面、Web 自助服务、移动用户、呼叫 中心、ATM 等)一致的用户体验,如果客户从不同的渠道获得自相矛盾的信息,客户满意度就 会下降。 以客户为中心的 SOA 致力于确保一致的用户体验,通过创建与任何具体技术和最终设备无 关的服务来实现,将更加容易重用于各种服务渠道。 4,,,,降低对厂商的降低对厂商的降低对厂商的降低对厂商的依赖和降低转换成本依赖和降低转换成本依赖和降低转换成本依赖和降低转换成本 传统的 IT 系统中,对厂商技术的依赖发生于各个层面上:  应用平台(如 J2EE 、.NET 框架、Oracle 、 CICS );  套装应用软件(如 SAP、PeopleSoft 等);  中间件技术(如 WebSphere MQ );  特定产品功能(如存储过程、群集缓存)。 我们应该注意到,如果中断与套装应用软件、开发平台、中间件系统的长期关系,是需要 付出很大代价的。 SOA 为机构提供了发展空间以适应未来的发展,并显著降低了对厂商技术的依赖。因为以 SOA 为中心的机构是基于服务契约来构建下层 IT 架构的,该服务契约与业务服务层是一致的, 并且技术中立、与应用无关和不了解中间件的。这种层次结构更容易替换应用程序、技术和中 间件。 5,,,,降低集成成本降低集成成本降低集成成本降低集成成本 SOA 能显著降低集成成本,其原因已经在前面讨论过。 在采用不同的套装应用程序和应用程序的异构环境中,这种成本的降低尤其显著,因为 SOA 提供了一种统一的、一致的技术基础设施,不必为定制集成编写代码,也不用部署和配置许多 特定用途的应用程序适配器。 6,,,,提高现有的提高现有的提高现有的提高现有的 IT 资产投资回报率资产投资回报率资产投资回报率资产投资回报率 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 259 - 面向服务的架构能显著提高现有 IT 资产的投资回报率,因为该架构的 IT 资产被重用为服 务,确定现有系统的关键业务能力,然后把它们作为构建新服务的基础,这样,SOA 有助于最 大化现有 IT 投入的价值,并降低风险。 但是要注意到不是所有的 IT 资产都能够被重用,所以需要一个评估和筛选的过程,这个过 程必须特别注意抽象接口的定义,这样的接口应该能够既体现业务功能的本质,又封装了技术 细节。 二二二二、、、、达成达成达成达成 SOA 的方法及需要解决的问题的方法及需要解决的问题的方法及需要解决的问题的方法及需要解决的问题 1,,,,SOA 业务架构的达成业务架构的达成业务架构的达成业务架构的达成 构建一个合理的 SOA 应采用何种开发方法?从前面的部分可以看出,有业务流程、应用 程序和服务。显然,对服务建模是此类方法必须支持的主要任务。另一个重要的方面是确保业 务流程和服务之间的链接。 我们必须搞清楚现有的模型(例如面向对象的分析和设计、企业架构框架和业务流程建模 技术)对 SOA 设计的作用。我们需要将其它方法元素用于 SOA ,例如用于服务标识和聚合的 方法和技术、业务跟踪能力、现有资产的集成和重用。我们还需要进行服务的建模,它是在域 分解、现有系统分析和目标服务建模之类的技术支持下实现的。 事实上 SOA 并不仅仅是一个 IT 概念,而是偏重于组织、管理以及商业模式。部署 SOA 不 仅牵涉到 IT 系统的构建模式,同时也涉及到业务流程架构和业务的管理运作模式,因为 SOA 必须对业务的改变作出迅速反应。达成 SOA 业务需要经过以下几个阶段: 1))))行业业务模型和标准的跟踪行业业务模型和标准的跟踪行业业务模型和标准的跟踪行业业务模型和标准的跟踪、、、、学习学习学习学习:要学习行业业务模型和标准,从做咨询顾问开始我 们的 IT 项目。 2))))融会贯通业务服务化过程融会贯通业务服务化过程融会贯通业务服务化过程融会贯通业务服务化过程:与行业业务专家一起,从划分不同的业务功能域开始,界定 项目范围中都包含那些功能域,每个功能域都有哪些过程组成,注意梳理和分解,整理出可重 用的业务服务,要注意只有重用才提炼出业务服务、进行业务化处理。 3))))完成完成完成完成 SOA 项目是个渐进的过程项目是个渐进的过程项目是个渐进的过程项目是个渐进的过程:在进行整体规划的时候,千万不要与技术层面的 Web 服务、对象、组件混淆起来,和业务人员交流只考虑业务如何组织、流程整合哪些部门和合作 伙伴,业务在哪些方面会重用等问题,此时一定要屏蔽实现细节,专注于粗粒度、松耦合的业 务。SOA 项目是个渐进的过程,并不需要一蹴而就,这就需要对业务的演进有比较深刻的理解。 4))))自上而下形成业务服务的制品自上而下形成业务服务的制品自上而下形成业务服务的制品自上而下形成业务服务的制品:业务服务化的过程是自上而下的,从功能域、业务流程 到业务服务。一般来说,业务服务是稳定的、不易变化的、可重用的业务逻辑部分,是行业业 务模式的共性所在。而业务流程是善变的、随着业务发展而不断变化的,它是企业真正的核心 竞争力的所在。企业业务服务化的过程,就是把变化的部分与稳定的部分区别开来,过程控制 变化的部分,业务服务概括稳定的业务模型部分。 2,,,,SOA 需要解决的问题需要解决的问题需要解决的问题需要解决的问题 作为一个具有发展前景的应用系统架构,SOA 尚处在不断发展中,肯定存在许多有待改进 的地方。随着标准和实施技术的不断完善,这些问题将迎刃而解,SOA 应用将更加广泛。一般 认为,SOA 还是有一定的缺憾的: 1))))可靠性可靠性可靠性可靠性(Reliability )))) SOA 还没有完全为事务的最高可靠性包括不可否认性(nonrepudiation) 、消息一定会被传送 且仅传送一次(once-and-only-once delivery )以及事务撤回(rollback )等做好准备,不过等标准 和实施技术成熟到可以满足这一需求的程度并不遥远。 2))))安全性安全性安全性安全性((((Security )))) 在过去,访问控制只需要登录和验证;而在 SOA 环境中,由于一个应用软件的组件很容易 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 260 - 去与属于不同域的其他组件进行对话,所以确保迥然不同又相互连接的系统之间的安全性就复 杂得多了。 3))))编排编排编排编排 (Orchestration) 统一协调分布式软件组件以便构建有意义的业务流程是最复杂的,但它同时也最适合面向 服务类型的集成,原因很显然,建立在 SOA 上面的应用软件被设计成可以按需要拆散、重新组 装的服务。作为目前业务流程管理(BPM)解决方案的核心,编排功能使 IT 管理人员能够通过 已经部署的套装或自己开发的应用软件的功能,把新的元应用软件(meta-application )连接起来。 事实上,最大的难题不是建立模块化的应用软件,而是改变这些系统表示所处理数据的方法。 4))))遗留系统处理遗留系统处理遗留系统处理遗留系统处理((((Legacy support )))) SOA 中提供集成遗留系统的适配器, 遗留应用适配器屏蔽了许多专用性 API 的复杂性和 晦涩性。一个设计良好的适配器的作用好比是一个设计良好的 SOA 服务:它提供了一个抽象层, 把应用基础设施的其余部分与各种棘手问题隔离开来。一些厂商就专门把遗留应用软件“语义 集成”到基于 XML 的集成构架中。 但是集成遗留系统的工作始终是一种挑战。 5))))语义语义语义语义((((Semantics )))) 定义事务和数据的业务含义,一直是 IT 管理人员面临的最棘手的问题。语义关系是设计良 好 SOA 架构的核心要素。 就目前而言,没有哪一项技术或软件产品能够真正解决语义问题。 为针对特定行业和功能的流程定义并实施功能和数据模型是一项繁重的任务,它最终必须由业 务和 IT 管理人员共同承担。不过,预制组件和经过实践证明的咨询技能可以简化许多难题。 采用 XML 技术也许是一个不错的主意。许多公司越来越认识到制定本行业 XML 标准的重 要性。譬如,会计行业已提议用可扩展业务报告语言(XBRL)来描述及审查总账类型的记录。 重要的是学会如何以服务来表示基本的业务流程。改变开发方式需要文化变迁,相比之下, 解决技术难题只是一种智力操练。 6))))性能性能性能性能((((performance )))): 这是 SOA 的第六个缺憾吗?批评 SOA 的人士经常会提到性能是阻碍其采用的一个障碍, 但技术的标准化总需要在速度方面有一些牺牲。这种怀疑观点通常针对两个方面:SOA 的分布 性质和 Web 服务协议的开销。 不可否认,任何分布式系统的执行速度都不如独立式系统,这完全是因为网络的制约作用 造成的。当然,有些应用软件无法容忍网络引起的延迟,例如那些对实时性要求很高的应用软 件。所以在应用 SOA 架构之前,搞清楚它的适用范围就显得很重要了。 除了上述几点之外,我们认为还有几点也颇值得关注: 7))))松耦合和敏捷性要求之间的权衡难题松耦合和敏捷性要求之间的权衡难题松耦合和敏捷性要求之间的权衡难题松耦合和敏捷性要求之间的权衡难题: 服务松耦合设计其实是一把双刃剑,在带来应变敏捷性的同时,也给业务建模和服务划分 带来难题。这就是为什么在 SOA 讨论中,业务建模的争论总是最多的原因。 8))))跨系统集成难题跨系统集成难题跨系统集成难题跨系统集成难题: 面向服务的架构设计将跨越计算机系统,并且还可能跨越企业边界。我们不得不考虑在使 用 Internet 时安全性功能和需求,以及如何链接伙伴的安全域。Internet 协议并不是为可靠性(有 保证的提交和提交的顺序)而设计的,但是我们需要确保消息被提交并被处理一次。当这不可 能时,请求者必须知道请求并没有被处理。 . 9))))SOA 与网格计算与网格计算与网格计算与网格计算((((Grid Computing ))))的关系的关系的关系的关系: 网格计算(Grid Computing )是利用互联网技术,把分散在不同地理位置的计算机组成一台 虚拟超级计算机。每一台参与的计算机就是其中的一个“节点”,所有的计算机就组成了一张节 点网——网格。从实质上来说“网格计算”是一种分布式应用,网格中的每一台计算机只是完 成工作的一个小部分,虽然单台计算机的运算能力有限,但成千上万台计算机组合起来的计算 能力就可以和超级计算机相比了。 网格计算基于因特网,提供了资源整合和共享的平台。十分适合作为 SOA 架构的实施平台。 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 261 - 我们来具体地看一下:  SOA 的构建策略的构建策略的构建策略的构建策略:创建一个面向服务的计算 SOC(service-based computing )环境;可 以用类似于 web services 的技术来设计服务:使用 SOAP 通信机制;采用 XML 数据格 式;强调服务的重用和互操作;最大化的应用现有资源;希望有一个类似于网格计算 环境的基础平台。  网格作为平台的基本特点网格作为平台的基本特点网格作为平台的基本特点网格作为平台的基本特点:网格被视为一个由各种计算资源组成的统一环境,其管理 软件将网格整合成一个完整而协调的透明计算整体;网格是一个虚拟的应用服务器; 是一个应用实现和数据处理的理想平台;服务在网格中部署和调用执行;商业逻辑和 服务调用被当成网格程序一样在平台上运行;网格为 SOC 计算的有效性、快速性、灵 活性、伸缩性和计算环境的管理提供便利。 3,,,,SOA 带给企业什么带给企业什么带给企业什么带给企业什么???? 作为需要构建 SOA 应用的企业来说,究竟有些什么好处呢?我们来看一下:  集成现有系统集成现有系统集成现有系统集成现有系统,,,,不必另起炉灶不必另起炉灶不必另起炉灶不必另起炉灶:面向服务的架构可以基于现有的系统投资来发展,而 不需要彻底重新创建系统。通过使用适当的 SOA 框架并使其用于整个企业,可以将 业务服务构造成现有组件的集合。使用这种新的服务只需要知道它的接口和名称。服 务的内部细节以及在组成服务的组件之间传送的数据的复杂性都对外界隐藏了。这种 组件的匿名性使组织能够利用现有的投资,从而可以通过合并构建在不同的机器上、 运行在不同的操作系统中、用不同的编程语言开发的组件来创建服务。遗留系统可以 通过 Web 服务接口来封装和访问。  服务设计松耦合服务设计松耦合服务设计松耦合服务设计松耦合,,,,带来多方面优点带来多方面优点带来多方面优点带来多方面优点:服务是位置透明的,服务不必与特定的系统和特 定的网络相连接。服务是协议独立的,服务间的通信框架使得服务重用成为可能。对 于业务需求变化,SOA 能够方便组合松耦合的服务,以提供更为优质和快速的响应, 允许服务使用者自动发现和连接可用的服务。松耦合系统架构使得服务更容易被应用 所集成,或组成其他服务,同时提供了良好的应用开发、运行时服务部属和服务管理 能力。提供对服务使用者的验证(authenticatio )、授权(authorization ),来加强安全性 保障,这一点也优于其他紧耦合架构。  统一了业务架构统一了业务架构统一了业务架构统一了业务架构,,,,可扩展性增强可扩展性增强可扩展性增强可扩展性增强:在所有不同的企业应用程序之间,基础架构的开发 和部署将变得更加一致。现有的组件、新开发的组件和从厂商购买的组件可以合并在 一个定义良好的 SOA 框架内。这样的组件集合将被作为服务部署在现有的基础构架 中,从而使得可以更多地将基础架构作为一种商品化元素来加以考虑,增强了可扩展 性。又由于面向服务的敏捷设计,在应对业务变更时,有了更强的“容变性”。  加快了开发速度加快了开发速度加快了开发速度加快了开发速度,,,,减少了开发成本减少了开发成本减少了开发成本减少了开发成本:组织的 Web 服务库将成为采用 SOA 框架的组 织的核心资产。使用这些 Web 服务库来构建和部署服务将显著地加快产品的上市速 度,因为对现有服务和组件的新的创造性重用缩短了设计、开发、测试和部署产品的 时间。 SOA 减少了开发成本,提高了开发人员的工作效率。 市场和制度的不断变化,要求组织具有相当的灵活性,软件架构师提供一种通用的、基于服务 的解决方案,将有助于实现组织的灵活性,也更容易实现生产力的提高。尤其在为业务流程管 理(BPM)奠定了 SOA 架构基础以后,企业就可以把思想集中于更高层次的问题,比如设计更 好的业务流程,而不是考虑实现业务流程的技术细节。 4,,,,SOA 的七的七的七的七大误区大误区大误区大误区 许多人或多或少存在对 SOA 的误解,这些误解可能出自厂商的市场宣传误导,也可能是由 于不同 IT 机构的解释不同。作为系统架构师可能会面对这些误区,需要对用户、开发人员甚至 管理层作出解释,下面是一些常见的对 SOA 的误解。 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 262 - 1))))SOA 是一个新概念是一个新概念是一个新概念是一个新概念 错误。自从企业组织中有不止一台计算机运行,我们就开始尝试围绕共享功能或服务创造 各种解决方案和科技工具。事实上,最早的 RPC 协议试图提供这种类型的架构,然后是 IPC 协 议,以至分布式组件对象技术(比如 DCOM 和 CORBA)。虽然 Web 服务提供了新的标准方式, 但它还是像传统分布式对象技术那样运行。换句话说,SOA 只是一种演变而不是革命。 2))))必须用必须用必须用必须用 Web 服务协议创建服务协议创建服务协议创建服务协议创建 SOA 不是。虽然 Web 服务协议到目前为止还是首选的创建和部署 SOA 架构的标准,但是你也 可以使用其他标准,比如 CORBA、DCOM 和 J2EE 。我们甚至可以采用某些私有技术来创建 SOA。记住,SOA 只是关于共享和管理服务一种架构形式,我们所采用的技术只需要满足它的 需要就可以了。 3))))我们如果购买了企业服务总线我们如果购买了企业服务总线我们如果购买了企业服务总线我们如果购买了企业服务总线((((ESB),),),),那么就拥有了那么就拥有了那么就拥有了那么就拥有了 SOA 错误。ESB 是非常强大的技术,它允许我们通过 Web 服务界面在应用程序内和应用程序之 间传递信息。但是,ESB 并非完全基于行为的整合,或者共享真实的应用,它更多是信息导向。 4))))SOA 总是会取得好结果的总是会取得好结果的总是会取得好结果的总是会取得好结果的 在很多案例中,我们会发现 SOA 在商业上的两种反应,即节省组织成本,包括重复利用已 存在的软件作为服务,以及增强改变 IT 方案适应商业需求变革或灵活性的能力。但也可能会带 来相反的结果。在我们计划和部署 SOA 之前必须做一个评估,在我们充分了解 SOA 的价值和 项目成本之后再搭建商业模型。大多数案例中成本会发生调整,这意味着企业可以从中获利, 但是有一些案例也并非如此。 5))))当部署当部署当部署当部署 SOA 时时时时,,,,我们只能选择一个供应商我们只能选择一个供应商我们只能选择一个供应商我们只能选择一个供应商 当面对很多供应商时会出现兼容性问题。但是,事实是没有一个供应商可以为创建和部署 大多数 SOA 提供的点到点解决方案,你必须选择在这一类里最好的。你可以通过在项目早期进 行一些测试来解决兼容性问题。 6))))当创建当创建当创建当创建 SOA 时时时时,,,,只要我们选择好技术和供应商就可以了只要我们选择好技术和供应商就可以了只要我们选择好技术和供应商就可以了只要我们选择好技术和供应商就可以了 千万不要。只有我们理解了我们真正的需求所在,什么问题是我们最期望首先解决的,据 此做好一个商业模型,然后设计我们的系统。 当然,这意味着我们必须要做一系列工作,包括弄懂代码、安全性、完善性、辨识已经存 在的服务、我们需要新创建的服务,等等方面。然后,我们需要配置这些服务到相应的方案中 去,以及保证让这些方案随着商业的改变而变化。最后,我们再来讨论技术问题,别忘了做测 试以验证系统的有效性。 7))))当你拥有当你拥有当你拥有当你拥有 SOA 后后后后,,,,我们就我们就我们就我们就不再需要应用整合技术不再需要应用整合技术不再需要应用整合技术不再需要应用整合技术了了了了 不。虽然 SOA 使系统整合更容易,但是我们还会发现仍然需要核心的整合技术,例如转换、 挖掘、流程整合、适配器,等等。实际上,这些整合手段可以成为 SOA 的一部分,但我们的 SOA 不会自动把他们包含进来,它们必须成为架构和规划中的。 7.7 时代呼唤优秀的时代呼唤优秀的时代呼唤优秀的时代呼唤优秀的软件架构师软件架构师软件架构师软件架构师 在软件组织中,架构师的作用是举足轻重的,当企业把一个方向的生命线托付给你的时候, 责任也是重大的,因此架构师必须十分谨慎和细致,最后我给你提如下一些建议: 1,,,,架构师的知识结构架构师的知识结构架构师的知识结构架构师的知识结构 1 )首先必须是一个好的程序员,技术上要强 2 )知识结构:对象的观点,UML,RUP,设计模式 关键不是懂得了原理,而是灵活融合的应用 3 )系统的观念:分析能力,把握抽象的能力 4 )沟通能力:与客户沟通能力,与项目其它成员的沟通能力 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 263 - 5 )知识面要广,把握行业流行趋势,但不要赶时髦 6)灵活机动,不能教条 2,,,,聚焦于人聚焦于人聚焦于人聚焦于人,,,,而不是工艺技术而不是工艺技术而不是工艺技术而不是工艺技术 事实上,软件开发是一个交流游戏,你必须保证人们能彼此有效的沟通(开发人员、项目 涉众)。架构师要以最高效的可能方式与客户和开发人员一起工作和讨论,白板上书写讲解、视 频会议、电子邮件都是有效的交流手段。 3,,,,保持简单保持简单保持简单保持简单 建议“最简单的解决方案就是最好的”,你不应该过度制作软件。在架构设计上,你不应该 描述用户并不真正需要的附加特性一个辅助的原则就是:“模型来自于目的”。 这个原则引发了两个核心的实践。 第一个就是描述模型的文档力求简单明了,切中要害。 第二个就是架构设计避免不必要的复杂性,以减少不必要的开发、测试和维护工作。 你的架构和文档只要足够好,并不需要完美无缺,事实上也做不到,因为建模的原则就是 “拥抱变化”。你的文档应该重点突出,这样可以增加受众理解它的机会,同样这个文档会不断 更新,因此如何管理好文档显得十分重要。 4,,,,迭代和递增的工作迭代和递增的工作迭代和递增的工作迭代和递增的工作 这种迭代和递增的工作,对项目管理和软件产品开发,事实上提出了更高的要求,你必须 时时检验你的项目进展,不要使它偏离了方向。 5,,,,亲自动手亲自动手亲自动手亲自动手 考察一下你遇见过的“架构师”,最棒的那一个一定是需要的时候立刻卷起袖子参加到核心 软件开发中的那个人。架构师首先必须是编程专家,这是没有错的。积极参与开发,和开发人 员一起工作,帮助他们理解架构,并在实践中试用它,会带来很多好处。  你会很快发现你的想法是否可行。  你增加了项目组理解架构的机会。  你从项目组使用的工具和技术,以及业务领域获得了经验,提高了你自己对正在进行 的架构事务的理解。  你获得了具体的反馈,用它来提高架构水平。  你获得客户和主要开发人员的尊重,这很重要。  你可以指导项目组的开发人员建模和小粒度架构。 6,,,,在开口谈论之前先实践在开口谈论之前先实践在开口谈论之前先实践在开口谈论之前先实践 不要作无谓的空谈和争论,你可以写一个满足你的技术主张的小版本,来保证你的方案切 实可行,这个小版本只研究最最关键的技术。这些主张只写够用的代码就行了,来验证你的方 案切实可行。这会减少你的技术风险,因为你让技术决策基于已知的事实,而不是美好的猜想。 7,,,,让架构吸引你的客户让架构吸引你的客户让架构吸引你的客户让架构吸引你的客户 架构师需要很好的与客户沟通,让客户理解你的工作的价值,他如果明白你的架构工作会 帮助他们的任务,那他们就会很乐意的和你一起工作。架构师的这种与客户沟通的技巧极其重 要,因为如果客户认为你在浪费他的时间,那他就会想方设法回避你。你的架构描述能不能吸 引客户,也成了建模是不是能顺利进行的关键。 8、、、、架构师面对时代的考验架构师面对时代的考验架构师面对时代的考验架构师面对时代的考验 年轻人需要成长为合格的架构师,需要扎扎上实实的从基础做起,不断提升自己的能力, 并不是听过几个课程,就能够成为一个合格的架构师的。架构师必须善于学习,一个人最大的 投资莫过于对自己的投资,每周花三个小时时间用于学习是完全必要的。 架构师的知识在必要的时候要发生飞跃,但是,这种知识的飞跃必须是可靠的,是经过深 思熟虑和实验的,同时要反复思索,把自己的思维实践和这种知识的飞跃有机的结合起来。 架构师要更看重企业所要解决的问题。 ◆中科院计算所培训中心 高级系统架构师培训 网址 http://www.tcict.cn - 264 - 架构师要学会在保证性能的前提下,寻找更简单的解决方案。 做一个好的架构师并不是一个容易的事情,这需要我们付出极其艰苦的努力。 我这个课程的主题就是“拥抱变化”,需求是在变化的,架构是在变化的,设计模式也是在 变化的,项目管理当然也是变化的。知识经济的时代在呼唤优秀的软件架构师,在这个大变动 时期,给我们每个人提供了巨大的机会,也提出了巨大的挑战。 时代呼唤着优秀的系统架构师,好的架构师的优势在于他的智慧,而智慧的获得,需要实 实在在的努力。
还剩263页未读

继续阅读

下载pdf到电脑,查找使用更方便

pdf的实际排版效果,会与网站的显示效果略有不同!!

需要 10 金币 [ 分享pdf获得金币 ] 2 人已下载

下载pdf

pdf贡献者

ngd7

贡献于2014-04-25

下载需要 10 金币 [金币充值 ]
亲,您也可以通过 分享原创pdf 来获得金币奖励!
下载pdf