Skip to content

《程序员必读之软件架构》——本是朋友买的书,却将电子优惠券送给了我,于是,我顺手买了此书的电子版。当这本书的前半段几乎磨损尽我的耐心时,终于在后半段发现了所谓的干货,以至于我认为有必要整理成一则笔记。

一、软件系统的结构:

“假设一个软件使用了面向对象的编程语言,我喜欢用如下方式来思考它的结构:软件系统由多个容器构成,容器又由多个组件构成,组件由一个或多个类实现。大多数软件系统都可以用这种简单的逻辑结构单元的层级关系来建模。”

1.抽象结构:

  • 类:对我们大多数人来说,在一个面向对象的世界里,类是软件系统的最小结构单元。

  • 组件:组件可以想象成一个或多个类组成的逻辑群组。比如,其他组件可以使用审计组件或认证服务,来确定对特定资源的请求是否放行。组件通常由多个类在更高层次的约束下组合而成。

  • 容器:容器是指一个在其内部可以执行组件或驻留数据的东西。它可以是从网络或应用服务器直到富客户端应用或数据库的任何东西。作为整个系统的一部分,容器通常是可执行文件,但未必是各自独立的流程。比如,我把每个Java EE网络应用或.NET网站都看作一个独立的容器,不管它们是否运行在同一个物理服务器流程中。从容器的角度理解一个软件系统的关键在于,任何容期间的通信可能都需要一个远程接口,比如SOAP网络服务、RESTful接口、Java RMI、Microsoft WCF、报文,等等。

  • 系统:系统是最高的抽象层次,代表了能够提供价值的东西。一个系统由多个独立的容器构成,例如金融风险管理系统、网络银行系统、网站等。

2.静态视图:

  • 语境:设定场景的高层次图,包括关键的系统依赖和参与者。

  • 容器:容器图显示了高层次的技术选择,容器如何分担指责、如何通信。

  • 组件:组件图可以让你看到每个容器的关键逻辑组件及之间的关系。

  • 类:这是一个可选的细节层次。如果想解释某个模式或组件将(或已经)被怎样实现,我会画少量高层次UML类的图。促使我给软件系统的部分分类画图的原因包括软件的复杂性,团队的规模和经验。我画的UML图通常会是草图而非综合性的模型。

*由上述4部分构成的软件架构图被作者称为C4。原书后面对于语境图、容器图、组件图的详解,以及“软件文档即指南”的思想,条理清晰,层次分明,对于项目管理工作非常有帮助。例如:软件指南中可以包含的内容:语境、功能性概览、质量属性、约束、原则、软件架构、外部接口、代码、数据、基础设施架构、部署、运营和支持、决策日志。

二、风险风暴:

与“软件系统的结构”一样,本书用作风险识别的方法:“风险风暴”也是一种可以被其他行业所借鉴的方法,至少在我看来,这种方法是相当有趣的——我们完全能够以此建立一种“风险识别模型”。

“风险风暴是一项快速、有趣的技术,提供了一种识别和可视化风险的协同方法。另一方面,这种技术可用于任何能够可视化的东西:从企业架构到业务流程和工作流。它可以在一个软件开发项目的开始阶段使用,也可以一直使用,或者在迭代计划或回顾中使用。”

步骤1:画一些架构图

第一步是在白板或大张的活动挂图纸上画一些架构图。C4是一个很好的起点,因为它提供了一种获得一组抽象层次各异的图的方法,其中一些可用来标出架构中的不同风险。图越大越好。

步骤2:分别识别风险

风险可以是主观的,所以请团队中每个人(架构师、开发者、项目经理、业务人等)都站在架构图前,各自写下他们能够识别的风险,一个风险用一张便利贴。此外,请他们根据概率影响量化每个风险。理想情况下,用不同颜色的便利贴来表示不同的风险优先级。你可以将这部分练习划分为5~10分钟的时间段,以免拖延,这一步应该保持沉默,每个人收好各自的便利贴。这里是一些要寻找的风险的例子:

  • 第三方系统的数据格式意外变更;

  • 外部系统不可用;

  • 组件运行过慢;

  • 组件无法伸缩;

  • 关键组件崩溃;

  • 单点故障;

  • 数据被破坏;

  • 基础设施故障;

  • 磁盘填满;

  • 新技术未按预期工作;

  • 新技术使用过于复杂;

  • 等等。

有了软件开发评估,根据人们的经验,他们对风险的看法可以是主观的。如果你计划使用一种新技术,但愿团队中有人能识别出相关的风险。另外,有人可能会对使用新技术的风险量化得比较高,而其他人如果已经用过同一种技术,可能感觉就不一样。各自识别风险让每个人都可以为风险识别流程作出贡献。你将更好地了解团队感知的风险,而不仅仅是那些设计软件或领导团队的人的看法。

步骤3:汇总图中的风险

接下来,请大家把自己的便利贴贴在架构图上,邻近风险被识别出的区域。举个例子,如果你识别出一个组件会有运行过慢的风险,就把便利贴贴在架构图中那个组件的上方。

这种技术的这个部分是视觉的,一旦完成,你就能一眼看到风险最高的区域在哪里。如果有人识别出类似的风险,随着大家想法的汇总,图的上方会贴满便利贴。

步骤4:对风险设定优先级

现在你们可以拿下每一张便利贴(或一堆便利贴),就如何量化已识别的风险达成共识。

  • 单张便利贴:问识别出风险的人他们的理由是什么,并就其概率影响达成共识。经过讨论,如果概率或影响是“无”,就从架构图上把便利贴拿下来,但别扔掉它(确保你保留了识别风险的记录,包括那些后来被认为概率或影响是“无”的)。

  • 成堆的便利贴:如果每张便利贴的概率和影响都相同,那就完成了。如果不是,则需要用与规划扑克或推广德尔菲法环节中相同的评估方法,就如何量化风险达成共识。看看哪些与众不同,并相应地了解人们量化风险背后的根据。

“想起大学老师曾经画过的一幅图:一个矩形(或者说“黑盒”),左边一个箭头指向矩形(“输入”),右边一个箭头从矩形指出(“输出”),现在想来,这图的确简单,却是现实中许多复杂系统的极简表达。

所谓的产品设计,无非也就是如此:一些输入量经过系统的处理,产生一些输出量,站在系统层面,我们所需要做的就是确定输入输出量,然后通过“人机接口”(UI,也就是矩形接触输入输出的两条边)将其转换为机器所能识别的量,这其中,人机接口的友好程度即是“用户体验”(UE,系统前台的工作),黑盒将输入量高效、可靠地转换为输出量即是系统的“性能”(系统后台的工作)……

将开头提到的系统扩展一下,缺少输入量的系统就是“无进有出”,可以理解为“无私奉献”;缺少输出量的系统则是“有进无出”,可以理解为“不断索取”,但是,我对于以上这两种系统的认识还比较模糊,有待继续深化……”

——以上文字就是对我近日思考的总结,当我试图细化这种思考时,偶然找到了两本书:《系统之美》、《系统思考》。一口气将其读完,我发现在细化老师那幅图时,还要添加“反馈”这样的元素,基于“反馈”的“调节回路”和“增强回路”则与电路知识中的“负反馈”和“正反馈”产生了共鸣……我相信,这两本书所涉及的思想,非常有利于从整体角度进行系统认识、系统分析和系统设计性质的工作。

以下是我粗略的阅读感受:

  • 《系统之美》深入浅出,可读性很强,但是,作者的图表并不能很好地表达某些概念,例如:使用存量-流量图(“水管图”)对“调节回路”的描述并不清晰,原文(第一章,系统之基础,42页)是:“这一类反馈回路具有保持存量稳定、趋向一个目标进行调节或校正的作用,我们称之为“调节回路”。”但是,对于“咖啡散热”这个模型(43页),调节回路并不是用来保持“咖啡的温度”这一存量的稳定(除非这样理解:保持咖啡温度稳定在室温),真正的作用是保持“咖啡的温度与室温一致”,而这其实是“咖啡散热”模型的“目标”。

  • 《系统思考》比《系统之美》要深入,提供了“系统循环图”这一工具,但是可读性也差一些,作者的言语则显得罗嗦,某些地方可能还有错误(也可能是译者、校对的错误),例如:第8章,刺激增长,原文(127页)是:“这就意味着需要引入一个从“市场份额”指向“满意的客户群”的连接,而且是一个O型连接,见图8-3。”结合原文和原图:“然而,大多数业务的正常特征是,随着“市场份额”的上升,吸引新客户的工作逐渐变得困难起来。”,我认为“满意的客户群”应该写成“新增的客户群”,至少在对汉语的一般理解上,我觉得“满意的客户群”和“新增的客户群”还是不一样的。又如:第12章,加速系统思考,第240页中有一处“年出生人数”明显应该是“年死亡人数”。此外,作者对于特定领域的系统流程进行剖析的文字也有点令人乏味。

将我的阅读收获归纳一下,主要有如下几点——这也是对我自身所思考问题的补充:

  • 1.任何一个系统都包括三种构成要件:要素、连接、功能或目标。例如:一支球队是一个系统,它的要素包括球员、教练、场地和足球等;它们之间通过游戏规则、教练指导、球员技能、球员之间的交流以及物理法则等产生连接;而球队的目标是赢球、娱乐、锻炼或赚钱等。(收获自《系统之美》)

  • 2.理解系统行为的动态性需要至少两个概念:“存量”,是指在任何时刻都能观察、感知、技术和测量的系统要素;“流量”,是一段时间那改变的状况。(收获自《系统之美》)

  • 3.系统具备的三大特征:适应力、自组织、层次性。(收获自《系统之美》)

  • 4.“时滞”,系统流量变化后,系统存量需要经过一定的时间才能反映出这种变化,系统存量缓慢变化而产生的时滞往往是系统稳定性的根源所在,但也让人们有了余地去利用反馈调整那些不奏效的策略。存量的“时滞”也会导致存量随时间呈现振荡变化。(收获自《系统之美》)

  • 5.“反馈”,当某一个存量的变化影响到与其相关的流入量或流出量时,反馈回路就形成了,反馈回路只有两种:“调节回路”和“增强回路”。“调节回路”在于调节校正维持稳定、保持系统目标,在电路系统中称为“负反馈”;“增强回路”是为了增强系统原有的变化态势,并且是让系统按照指数方式变化,在电路系统中称为“正反馈。”(收获自《系统之美》、《系统思考》)

  • 6.“悬摆”,系统循环图中,那些位于对于闭合回路之外,但是仍然连接在闭合回路之上的元素被称为“悬摆”。“悬摆”定义了我们所感兴趣的系统的边界。悬摆分为“输入悬摆”和“输出悬摆”。“输入悬摆”一般用来表示期望达到的目标、隐含的标准、政策,或者系统外部的驱动、限制因素,以及用来确定外部变量数值的参数等;“输出悬摆”表示整个系统运行的结果。(收获自《系统思考》)

  • 7.“模糊变量”,系统分析中某些非常重要的变量,无法用具体数值刻画,只能用“强”、“弱”定性描述的那些变量。(收获自《系统思考》)

  • 8.“存量-流量图”,又称为“水管图”,用水管图标形象地表示系统“存量”、“流量”变化的图形;“系统循环图”,又称为“影响图”,用箭头连接起来的表达系统各要素之间因果关系的图形。(收获自《系统之美》、《系统思考》)

此外,两本书中有关各类系统思考的法则、方式、基模(系统思考者将产生常见问题行为模式的系统结构称为“基模”),图形绘制准则等,都不是我所感兴趣的——至少目前不是。关于这些内容,我更喜欢《系统思考》作者丹尼斯·舍伍德先生在前言对话中的观点:“我相信,与其花费力气去了解和掌握基模,还不如把基本概念理解得更深刻,并能熟练地使用它们。”