文章: 更快,更好,更强——怎么才能做到呢?
设计软件架构时常常遇到的一大难题就是质量属性。为此不仅会使设计变得困难,规格难度也会变大。因此,软件系统中的许多问题都与规格和质量属性(如可变性或性能)设计直接相关。质量属性对客户及终端用户认可的影响较大。找到系统性的合适解决方法至关重要,这也是我们所要面临的一大挑战。
质量属性的困顿局面
质量属性比较难以处理,因为它们需要根据不同情况做不同处理,特别是它们不仅影响系统的某一部分也会影响整个系统。例如,工程师无法在系统的某一个特定地方限制安全或性能属性。很多情况下这样的尝试都无法实现,因为大家关注的问题是互相交织而且甚至常常是很宽泛的,比如,他们会要求软件工程师向现有组件植入设计和代码。换句话说,大多数质量属性是整体性的,需要总体上的战略应对策略。
Grady Booch曾说过,软件架构就是不惜一切代价去改变以满足要求,尤其是质量属性的要求。Martin Fowler也同样提到过:软件架构至关重要——不管那意味着什么。
理解是成功设计的关键
那么软件工程师应如何应对复杂局面呢?第一步就是要确保充分理解所有的需求以及排好优先次序表。对于类似“应具有高性能”或“需要提供更高的安全性”之类的需求规格其实意义并不大。这些说法对于高层来说似乎是合乎逻辑的。但是实际操作起来,到底是什么意思呢?
对于任何好的设计来说,首要的挑战及前提就是创建好的需求规格。但是,到底什么才算是好的需求呢?根据ISO的原则,好的需求应涵盖以下特征:
- 紧凑: 需求应只针对一件事情
- 完整: 应在一处将需求完整的阐述,无任何信息遗漏。
- 一致: 各需求不应互相矛盾并应完全符合文档
- 准确: 所有相关利益人的业务要求需得到满足。
- 现行: 项目进行过程中需求都不可过时。
- 外部可见: 需求所指定产品的某一特性是可以被用户外部可见或可经历的。有关内部架构、设计、实施、或测试决定的“要求”应得以合理限制,并应在需求文档的约束部分作明确说明。
- 可行: 需求在项目约束范围内应做到可实施。
- 明确: 需求的表达应简洁明了,不含专业术语、缩写(除非在要求文档中有明确定义)、或其它深奥用语。应该表达客观事实而非主观意愿。
- 强制性: 需求所代表的是利益相关者定义的特征,如有遗漏会导致不可弥补的缺失。
- 可检验: 需求的实施可通过以下四种可行的方法来决定:检验、分析、演示、或测试。
当软件工程师收到一份需求说明时,应保证其质量。一份不佳的需求说明会不可避免地导致一个不良的软件系统,哪怕是再好的设计师以及实施者投入其中也不会起作用。因此,测试和评估要求说明是重中之重。
注意隐藏的秘密
有一项需要架构师们十分注意的事项是,应当谨防那些隐蔽的或是隐含意义的需求。这样的需求可能不会记录在文档中。比方说,智能手机应该随时都有反应,或者键盘和显示器应放在同一边。这类需求可能看起来是显而易见的,但是并非所有隐含的需求都是如此。这已经超出本文要讨论的内容,大家可以参看 《KANO分析》一文,或许对解决此类问题有所帮助。
另一重要问题在于相关利益人应得到她客观必需的,而非她主观想要的。有个老掉牙的故事是关于某车主总是向经销商抱怨应该给他配个更好的保险杠。每次他在高速公路上行驶,总是有该死的兔子横穿出来。为了躲开而不撞到兔子,他的车子就会在湿滑的公路上避让滑行撞到树上。当然了,经销商是可以卖给他一辆配备更牢固保险杠的车,但是一辆配备ABS的车子对于顾客来说岂不是更好的选择?
最后同样重要的是,在考虑质量属性的时候观察上下文总是很关键。试想,有要求是你的系统能提供更高的安全性,不管用什么办法。哪怕你的应用是全宇宙最安全的系统,但如果要将不安全的遗留代码集成其中,就会在整个系统中留一个后门,那这个系统就不会安全。请记住,任何系统的质量高低总是取决于它最薄弱的部分。
世界不是平的
在处理质量属性时,需考虑的一项重要事项就是其所产生的多维度宇宙。例如,性能这样的属性就能够反映在多个方面——由IBM的一篇文章所提出的分类如下:
- 它可以解决吞吐量问题,例如大量的信息可以通过某一消息中间件以秒速进行传递。
- 它还可以说明反应时间,即提出请求到收到响应的时间。
- I/O速度是指系统所处理的批量数据。
- 察觉性能是指用户在与系统互动时的速度体验。
- 同时它还涵盖了启动时间,即从系统启动到各个操作部分完全可用所需的时间。
- 最后同样重要的是,它还可以定义可伸缩性——尽管有些人可能并不认为这也与性能有关。
因此,在处理性能问题时,软件工程师应当准确地描述其所指的性能是哪一方面。处理I/O(输入/输出)速度相较处理吞吐量问题所产生的结果会有差别。
基于场景的方法
要以更加明确的方式来存档、建模、以及表述质量属性,一种比较好的途径就是使用一种基于场景的方法,这和结构评估方法如ATAM类似。所有重要的属性都应使用不同场景来描述。在某一场景中,外部用户或外部系统在有待开发的系统内部或其中一部分触发某一事件。
例如,僵尸网络为了让网络服务器瘫痪会向服务器发送高频次的需求。这样的情况下系统即网络服务器可能也正处于某一特定状态,如联网或未联网。只要发生这样的情况,系统应该以某一特定的方式作反应,如只要DDoS(分布式拒绝服务)攻击被traffic模式分析探测出来,就进行网络阻隔。我们也应该通过反馈测量来为系统的反馈作定量。比如,DDoS攻击应该被探测到并在3分钟内得到解决。在这种方法中系统被视为一个黑/灰匣子。
场景会提供很多益处,如:
- 在处理用于系统某一部分的一个质量属性的某一具体方面的时候,场景会比较具体、明确、且简明。
- 场景有助于定性定量地去分析质量属性。
- 或许场景最重要的优势在于容易被利益相关者所理解。业务利益相关者和工程师双方都能理解、定义、并一起讨论场景。
- 最后同样重要的是,场景可以帮助测试经理明确测试内容以确保质量属性在产品或解决方案中真正得以实施。
效用树是我们的良师益友
下一步就是创建效用树来明确质量属性,它以树形的样式呈现,枝叶包含各种场景。该效用树既可以由业务和开发部门的联合定义也可以由架构师们作为讨论的基础进行准备。在研讨会议中,业务和开发部门的相关利益人会为每个场景指定相应的标准。例如,业务相关利益人可能会根据场景的重要性划分为高、低、中各个等级,而工程师可能会根据其实施的难度进行等级划分。两个方面的考量叠加后有助于对场景进行优先次序排列。显然,重要的场景实施起来也比较复杂,这样的场景相比那些与业务相关程度低的就应该得到更高的优先级别。
效用树下直接位于根部的节点是那些质量属性等级特别高的,如可用性和可变性。效用树中间的节点代表之前显示性能的方面,而枝叶部分表示场景。
战略战术设计
对于每一个场景,从最重要的即那些有战略意义的开始,应采用所谓的设计战术。
让我们以某一设计战术图表为例。为了解决某一应用中的安全问题,软件工程师可以使用不同的战略,如某一合适的资源管理战略。对于每一个战略,我们都可以应用设计战术。在资源管理中,我们可以利用诸如迟缓计算或catching等之类的战术。设计战术图表展示了许多战略以及战术,用以解决某一特定的质量属性问题。
当我们选定设计战术用以实施到某一场景时,通常我们会发现更多细节问题。有些设计战术代表了设计模式本身,而另一些多种设计模式也可能存在以支持每一设计战术的实施。因此,选择正确的模式或风格是软件架构师和开发者在这一阶段的主要职责。
可追溯性的本质
经验告诉我们“自动神奇地”方式为需求提供了可追溯性。请记住我们开始时是要通过场景精确地描述质量属性,进而进行优先排序。然后,我们将场景一个个朝下排列进行具体化,在最终所引入的设计模式中使用相应的设计战术。现在,我们在架构驱动因素和架构决策之间就有了一个双向的关系。只要任一场景被修改或重新排列次序,我们就可以追踪所有受影响的架构组件。相反,当我们修改某一架构组件时,我们也要检查哪些要求会因这一改变而受到影响。
在ATAM架构评估方法中,两项重要的原则相互印证。一个架构中的敏感点意味着某个架构决策或架构模块,它们都和质量属性直接相关。而权衡点则是指至少两个质量属性的敏感点(某架构决策或架构模块)。理解敏感点和权衡点非常重要。虽然它们都是架构师能够使用的工具,但要小心使用。
刚刚我们所了解到的是CMU SEI所称的ADD(属性驱动设计)。如果您对此想了解更多,请访问它们的 网页。
泡沫不会破灭
在实际操作中,处理质量属性时仅仅考虑架构方面是远远不够的。Bertrand Meyer曾说过:“泡沫不会破灭”“我们所需要的就是代码”。
技术决策对于达成质量要求有很重要的影响。所用的应用服务器的种类、持续储存、或信息插件也有很紧密的关联。
因此,架构设计应当由具有可行性的范例或模型加以补充。有了可行的范例,我们就可以对某特定质量属性进行评估,来看它们是否能够达到这些属性。当某些部分缺少时,可以使用仿真来代替,比如在传统的系统工程中,硬件开发周期比软件开发周期要慢。
小结
诚然,功能性的要求是富有挑战的,质量数据的实施难度更高,因为它们往往代表了多方面的需求。因此,这些要求都需要仔细去处理。任何特别处理都不可避免地会导致设计失败,就像很多项目中会过早进行性能优化描述一样。
为了更系统化地处理质量属性,这些属性就需要得以恰当地描述、理解、排列好优先次序、并对应到架构决策中,由QA确认。其中一种有效的系统化设计就是利用基于场景的方法,从效用树开始着手,利用场景建立质量属性模型。只要方法得当,项目就会从可追溯的两方面:架构驱动因素和架构决策,尤其是其灵敏度和权衡方面得以成效。场景同样也有助于定义基于风险的测试方法,从而验证质量属性的成果。
想了解更多信息,请阅读相关文章如 《架构实战》等。
关于作者
Michael Stal 是 西门子公司的首席工程师,同时还兼任荷兰格罗宁根大学的教授。他主要从事培训和指导有关软件架构及大型系统的分布式系统技术方面的客户。Michael在实例和平台编程方面也颇有资历。在西门子他负责为那些资深的软件架构师提供教育培训项目。他参与编著了系类丛书Pattern-Oriented-Software-Architecture (POSA)的前两卷。目前,他正乐此不疲地从事函数式程序设计,并担任德国 JavaSPEKTRUM杂志的总编。平时,Michael喜欢跑步、骑车、文学、以及数码摄影。
原文链接: Faster, Better, Higher – But How?
感谢 侯伯薇对本文的审校。
给InfoQ中文站投稿或者参与内容翻译工作,请邮件至 [email protected]。也欢迎大家通过新浪微博( @InfoQ)或者腾讯微博( @InfoQ)关注我们,并与我们的编辑和其他读者朋友交流。