OK,让我们开始吧.解决软件架构到底要设计到什么程度?
* 首先,对软件架构的设计程度问题展开探讨,得出基本结论。从对“分而治之”的讨论入手,说明软件架构是团队开发的基础,从而,软件架构必须设计到“能为开发人员提供足够的指导和限制”的程度;
* 之后,从问题入手,认识高来高去式架构设计的“症状”。主要分析实际工作中常见的架构设计不足的几种表现,找到要解决的问题;
* 然后,说明如何解决架构设计高来高去、指导不足的问题;
* 最后,结合案例,说明如何一步步地将架构设计落实到实处。
-------------------------------------------------------------------------------------
8.1 软件架构要设计到什么程度
软件架构必须设计到“能为开发人员提供足够的指导和限制”的程度。
8.1.1 分而治之的两种方式
为什么要分而治之?简单说,就是问题太复杂了,超出了人们能够“一蹴而就”的范围。
面对一个复杂的问题,我们如何进行分而治之呢?策略有二:
一、先不把问题研究得那么深,那么细,浅尝辄止,见好就收。这种分而治之的方式称为“按问题深度分而治之”。
二、先不研究整个问题,而是研究问题的一部分,分割问题,各个击破。这种分而治之的方式称为“按问题广度分而治之”。
例如:
接口和实现分离,就是“按问题深度分而治之”的一个例子。在架构设计之时,我们往往无需深入到一个子系统的实现细节中去,而是分而治之,先确定该子系统的接口。接口的设计在整个架构设计中占有重要地位,它定义了一个子系统为其他子系统所提供服务的契约。软件架构通过明确每个子系统所要实现的接口及所要调用的接口,为我们展现了一个软件系统如何分割为多个相互协作的子系统。
“按问题广度分而治之”的例子也很常见,比如展现层、业务层和数据层的开发往往需要不同的技术,可以分派给不同的小组承担等,不一而足。
8.1.2 架构设计与详细设计
随着软件设计工作越来越复杂,将架构设计和详细设计分离已成为普遍的做法。Garlan就曾指出:“随着软件的规模和复杂度增加,算法和数据结构以外的设计问题就会出现:设计和制定系统整体结构将成为新的一类问题......这是软件架构层次的设计。”
将设计分为架构设计和详细设计,是对“按问题深度分而治之”思想的运用。
* 所谓架构设计,就是关于如何构建软件的一些最重要的设计决策,这些决策往往是围绕将系统分为哪些部分,各部分之间如何交互展开的;
* 而详细设计针对每个部分的内部进行设计。
可以这么说,软件架构设计应当解决的是全局性的、涉及不同“局部”之间交互的设计问题,而不同“局部”的设计由后续的详细设计负责。于是,在软件架构所提供的“合作契约”的指导之下,众多局部问题被很好地“按问题广度分而治之”了----对局部的设计完全可以并行进行。
总之,这种先确定软件架构,而后基于软件架构进行并行开发的做法,综合利用了两种分而治之的方法,利于控制复杂性,提高开发效率。这是一种值得推崇的开发方式,常被称为“以架构为中心的开发方法”。
8.1.3 软件架构是团队开发的基础
正如大家所看到的,因为软件变得越来越复杂了,所以单兵作战不再是普遍的软件开发方式,取而代之的是团队开发:而团队开发又反过来使软件开发更加复杂,因为现在不仅仅有技术复杂性的问题,还有管理复杂性的问题。
面对“技术复杂性”和“管理复杂性”这样的双重困难,以架构为中心的开发方法是有效的途径:
* 一方面,软件架构从大局着手,就技术方面的重大问题作出决策,构造一个具有一定抽象层次的解决方案,而不是将所有细节统统展开,从而有效地控制了“技术复杂性”。可以看出,软件架构这一步没有“把问题研究那么深、那么细”,属于“按问题深度分而治之”。对此,Ivar Jacobson给我们提供了非常形象的说法,“软件系统的架构涵盖了整个系统,尽管架构的有些部分可能只有'一寸深'”;
* 另一方面,有了软件架构设计方案之后呢?因为“架构中包含了关于各元素应如何彼此相关的信息”,从而可以把不同模块分配给不同小组分头开发,而软件架构设计方案在这些小组中间扮演“桥梁”和“合作契约”的作用。每个小组的工作覆盖了“整个问题的一部分”,各小组之间可以互相独立地进行并行工作,这种“分割问题,各个击破”的策略,属于“按问题广度分而治之”。
这两方面是相辅相成的关系。具体而言,正因为软件架构是大规模开发的基础,所以架构中应包含软件系统的各元素如何彼此相关的设计决策;也正是因为软件架构中包含了软件系统如何组织等关键决策,才使得它能够成为大规模开发的基础。
这样一来,模块的技术细节被局部化到了小组内部,内部的细节不会成为小组间协作沟通的主要内容,理顺了沟通的层次。另外,对“人尽其才”也有好处,不同小组的成员需要精通的技术各不相同。例如,用户界面层的开发小组需要了解将使用的用户界面工具包;数据管理层的并发小组需要熟悉相关的数据库、持久工具或者使用的文件系统;系统交互层的开发小组需要了解通讯和用到的中间件产品等。
由此可见,软件架构为开展系统化的团队开发奠定了基础,为解决“管理复杂性”提供了有力的支持。对此Barry Boehm曾经明确指出,“如果一个项目的系统架构(包括理论基础)尚未确定,就不应该进行此系统的全面开发。”
8.1.4 架构要进行到什么程度
既然软件架构是团队开发的基础,那么它就应该比较明确地规定后期分头开发所必须的公共性的设计约定,从而为分头开发提供足够的指导和限制。
另一方面,具体的架构设计程度还会因软件项目的不同而不同,例如航空航天领域中的软件系统对系统可靠性要求非常高,这种情况下对架构设计详细程度的要求也会比较高;同时,架构设计的程度也会受团队具体情况的影响,有类似项目经验的团队可以适当放宽标准,而分布团队或者涉及外包的情况则应更强调架构的明确性。
架构设计对软件的不同部分的设计程度并不是整齐划一的。例如,通信机制、持久化机制和消息机制等对应的公共模块,在架构设计时会设计得比较深入,因为它们较多地涉及软件的不同部分之间的交互;而具体的业务功能模块在架构设计中往往设计程度不深。
总之,关于软件架构到底要设计到什么程度,可以归纳为两句话:
* 由于项目的不同、开发团队情况的不同,软件架构的设计程度会有不同;
* 软件架构应当为开发人员提供足够的指导和限制。
8.2 高来高去式架构设计的症状
所谓“高来高去式架构设计”,是指不能为开发人员提供足够的指导和限制的那种架构设计方案。高来高去式架构设计现象极为普遍,它可能带来的危害包括:
* 缺少来自架构的足够的指导和限制,开发人员在进入分头开发阶段之后会碰到很多问题,并且容易造成管理混乱,沟通和协作效率低;
* 对软件质量非常关键的全局性设计决定被拖延到分头开发期间草率决定,严重降低了软件产品质量;
* 没有完成化解重大技术风险的职责,可能造成整个项目失败;
* 团队成员对架构师意见很大,团队士气受到打击。
“发现问题是解决问题的一半”,下面为高来高去问题归类。
症状一:缺失重要架构视图。为了给团队的不同角色提供切实的指导,软件架构师应从不同视图进行架构的设计和归档。如果忽视了在某重要架构视图方面的设计,就会遗漏重要设计决策,具体的开发工作将会陷入缺乏应有指导和限制的困境。
症状二:浅尝辄止、不够深入。架构设计方案过于笼统,基本还停留在概念性架构的层面,没有提供明确的技术草图。于是,全局性的设计决策最后由具体开发人员从局部视角考虑并确定下来,造成技术和管理上的种种问题。
症状三:名不副实的分层架构。通过分层将架构系统模块之后,就迫不及待地喊出“分层架构”的口号,对各层之间交互接口和交互机制的设计严重不足。
8.2.1 缺失重要架构视图
如你所知,由于角色和分工不同,整个软件团队以及客户等涉及各自需要掌握的技术或技能存在很大差异。这就使得他们为了完成各自的工作,需要了解整套软件架构决策的不同子集。基于多重视图开展软件架构设计的方法,就能够解决上述问题。
实际经验表明,越是复杂的系统,越是需要从多个方面进行架构设计,这亲才能把问题研究和表达清楚。Grady Booch 在其著作《UML用户指南》中指出:“如果选择视图的工作没有做好,或者以牺牲其他视图为代价只注重一个视图,就会冒掩盖问题以及延误解决问题(这里的问题是指那些最终会导致失败的问题)的风险。”
为不同的软件系统进行架构设计时,对不同的架构视图的重视程度并不相同。例如,用于反映软件系统运行时的动态结构,以及组成软件系统的目标程序如何部署到硬件上的物理架构视图,对于分布式系统的架构设计来说是必不可少的。再例如,现在大量采用现成框架(比如众多开源框架)进行开发的软件系统越来越多了,这时开发架构视图就显得极为必要----开发架构关注程序包,不仅包括要编写的源程序,还包括可以直接使用的第三方SDK和现成框架和类库,以及开发的系统将运行于其上的系统软件或中间件。
“缺失重要架构视图”的一种表现是,认为软件架构设计完全是用例驱动的,片面强调用例描述的功能需求。此时,架构设计对非功能需求关注不够,既没有深入设计软件的运行架构(对性能、可伸缩性、持续可用性等运行期质量属性很重要),也没有深入设计软件的开发架构(对可扩展性、可重用性、可测试性和可移植性等开发期质量属性很重要)。软件开发人员会感觉到架构设计方案离他们很“遥远”,既没有说明程序包的组织结构,也没有明确架构设计中的关键抽象和所采用框架的关系,等等。
8.2.2 浅尝辄止、不够深入
此时,架构设计方案往往过于笼统,基本还停留在概念性架构的层面,没有提供明确的技术蓝图。
概念性架构虽说不用,但“不用”不代表“够用”。概念性架构对开发人员的指导和限制是不够的。为了化解高技术风险,证明技术上的可行性,必须充分考虑技术,例如关键机制、核心技术和第三方框架都应明确。
另外,投票或售前演示级别的架构方案对市场活动或许早够了,但对实际的开发却显得过于笼统。比如,对如何达到高安全性目标,仅提出了采用传输加密、存储加密和数字签名等技术,但并未明确这些技术如何影响软件系统的其他部分,它们是否通过统一的服务接口封装,别的模块是直接调用它们还是利用AOP机制松耦合地触发等问题。同样,为了达到高可扩展性的要求,轻描淡写地“采用模块化设计”对实际开发也过于笼统。
无论上述的哪一种情况,它们造成的危害都是相同的;架构设计阶段遗漏了全局性的设计决策,到了大规模开发实际阶段,这些设计决策往往被具体开发人员从局部视角考虑并确定下来,如此一来,就会在模块协作方面出现问题,而且公共的服务模块也未能被识别出来。
8.2.3 名不副实的分层架构
“名不副实的分层架构”可以认为是“浅尝辄止、不够深入”式架构设计的一种具体表现,但由于分层架构的应用太广泛了,几乎无处不在,因此我们把它单独列出并着重讨论。
“名不副实的分层架构”是指那些号称采用分层架构,却仅用分层来进行职责划分,而没有规划层次之间的交互接口和交互机制的情况,而经典的分层架构属于“调用 - 返回”式的架构模式,和“主程序 - 子程序”架构模式同属一种类型。可以说,缺失交互接口和交互机制的分层架构中,其中“层”已退化成笼统意义上的“职责模块”了。
很多道理是相通的。一个公司,它的组织结构图就挂在墙上----再清晰不过了,但公司的运营却很混乱,这是为什么呢?来了任务、出了事情不清楚找哪个经理,此谓接口不清;日常的汇报体系如何,突发事件如何处理也未明确,此谓机制不明。事实,这何尝不是一种架构不够明确的表现呢?
对软件系统也是同样,而对缺失交互接口和交互机制的分层架构,许多开发人员依然得不到足够明确的指导。
“名不副实的分层架构”常见于各大报纸、各种市场材料。由于它们常冠以“总体架构”等名称出现,而不是实际上的“软件架构之冰山一角”,所以,有些没有经验的架构师会误认为他们要设计的也是这种“高来高去式的软件架构”。
让我们来重温一下学生时代的“反证法”:
(1)假设,市场材料里的软件架构不是高来高去的,而是程度足够深入的;
(2)那么,竞争对手可以轻松地从市场材料里获知你的核心技术;
(3)但是,是没有人会把核心技术写到市场材料里公开宣扬的;
(4)因此,假设不成立,这意味着市场材料里的软件架构是高来高去的。
8.3 如何克服高来高去症
批评应有理有度。
可以这么说,高来高去式的架构本身并没有错,它们往往属于概念性架构的范畴;一来它是对于市场宣传来讲已经足够了,二来它往往是循序渐进进行软件架构设计的良好起点。但是,如果停留在高来高去的架构设计上止步不前。并以之作为最终的架构设计方案,就会为后期开发埋下重大风险。
将高来高去架构设计的症结、问题与对策归纳如下:
-----------------------------------------------------
症结:缺失重要架构视图
问题:遗漏了对团队某些角色的指导
对策:针对遗漏的架构视图进行设计
-----------------------------------------------------
症结:浅尝辄止、不够深入
问题:将重大技术风险遗留到后续开发中
对策:设计决策须细化到和技术相关的层面
-----------------------------------------------------
症结:名不副实的分层架构
问题:只用了分层架构的分层概念来进行职责划分,没有明确层次间的交互接口和交互机制。
对策:步步深入,明确各层之间的交互接口和交互机制。
8.4 网络管理系统案例:如何将架构设计落到实处
本节通过网络管理系统架构的“设计片断”,演示如何将架构落到实处的。
8.4.1 网管产品线的概念性架构
本案例的网络管理软件是作为软件产品线出现的,应充分考虑多个产品之间的重用,建立共享的产品线架构。
概念性架构清晰定义了架构的大局,并充分考虑了可移植性、可扩展性、性能和版权等商业因素,以及较长的生命周期等商业目标这些因素,制定了相应的高层设计决策。
但是,概念性架构毕竟是概念性架构,并不能为实际的开发工作提供足够的指导和限制。下面我们来进行实际架构层面的设计:篇幅有限,仅涉及识别功能块、规划功能块的接口、明确功能块之间的使用关系和使用机制等话题。
8.4.2 识别每一层中的功能模块
抽象的职责最终必须由具体的功能模块来承担。我们接下来必须识别每一层中的功能模块、以及各模块承担的职责。
8.4.3 明确各层之间的交互接口
在分层架构中,下层对于上层应尽量做到“黑盒”封装。这样一来,为每一层规划接口就显得非常重要。需要定义各层之间的交互接口。
8.4.4 明确各层之间的交互机制
更进一步,有了接口,就可以明确交互机制。设计中采用的其实是一种基于方法调用的事件机制。
8.4.5 案例小结
我们没有深入描述设计时所考虑的细节,而是着重描述了设计从不明确步步走向明确的过程。
我们还必须说明,如何将架构设计落到实处,其实根据架构设计视图的不同而不同。这是因为,不同的软件架构视图关注的对象不同(从模块--到程序包--到进程--到数据库表--到物理节点等),从而设计手段也就会有差异。
8.5 总结与强调
本篇讨论了一个对软件开发和管理都有深刻影响的问题,软件架构要设计到什么程度?如果说前面讨论的架构视图关注了软件架构的横向宽度,那么本章就是关注软件架构的纵向深度。
----------------------------------------------------------------------------------
个人理解部分:
看了本章后,有一种茅塞顿开的感觉。对以下一些问题有了更清晰的理解:
1. 在架构方面,有可能是售前人员在做概要性架构,也可能是软件需求人员在做,作为众开发程序员技术掌控者的软件架构师,他需要对概要性架构进行细化。站在一个较高的地方,对整个系统不仅在业务逻辑上有清晰的理解和表述,而且要站在开发、测试、部署等人员的角度上去进行综合设计,很多时候团队部分成员在技能和专业知识上不是很成熟,在项目中,可以通过培训或者知识点的补充让成员更快的融入项目中,并很好的领会架构,使架构能真正的成为指导,能用起来。让项目组成员真正的以架构为核心,不要走出这个圈圈。并且配合项目经理做好对投资人、上级领导的沟通工作。在第5章的5视图法这个工具在此处可以发挥较大的作用。架构师给出的5视图。对概要性架构是一种补充和完善。
2. 本文也对分层架构和各分层和模块,在交互接口和交互机制提出了强调。不仅懂原理,而且要在实践中用起来。我甚至觉得,在各角色人员的分工和合作方面。也可以更加紧密的和项目经理合作,将各工种的合作方式、接口、机制进行定义。以更有效的提高工作效率。减少沟通上的时间和资源损失。并且架构师是站在整体的角度来考虑问题,所以可以将共同的部分抽象出来,并建立一套调用机制。在细节上,可以和技术员们共同讨论,以完善和优化调用机制。
3. 在对一个系统的分析方法上,提出的按广度和按深度的不同考虑角度是很有益的。其实,我个人感觉,在实际操作中,其实是在不断的交互。不断的螺旋上升的过程。结合5视图法,只有这种,才能更加清晰,更加快速的将系统的蓝图展现在众人面前。设计也是需要效率的。
4.团队开发的方式和作用。文中不仅对大团队合作开发的方式提出了有益的指导。而且我觉得稍加改变,也可以运用到小团队、小项目的合作开发中。比如和快速抛弃原型法结合。一二个开发和美工就可以利用.net快速的开发。如果在小团队中,有高明的架构做为指导,再结合较成熟的企业框架的应用。这几杆枪也可以发挥出小炮的威力的。
5.在架构设计和详细设计间的关系及应用。结合需求分析的方法。可以指导开发人员制作详细设计。减少架构师的工作量和培训提升开发人员在设计方面的能力。
6.带领团队一起进步。一起把项目做细做好。怎么把团队成员的思想往一处带是很重要的。团队中,有可能有初程、中程、高程。大家的经历、特长也不尽相同。那么怎么培训就显示尤为重要了。对一些基础性的常识、或者专业的术语在团队内进行普及。不同的岗位在项目的不同阶段,能给出指导性的纲领计划、执行方法、相关知识获取、学习方法也可以使项目组成员更好的执行架构思想和团结在架构师周围。更有利于架构的推广。当然,能带出架构师的人。更是牛人。