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:对风险设定优先级

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

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

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

营业执照、税务登记证、法人代表身份证……这恐怕是最近与我的工作相关最多的证件,将以上搜集到的信息填到协议里,再由后台的信息录入员完成录入,我不止一次去想——为什么就不能简化?据说,这都是出于风险控制的需要,说得详细一点,就是控制交易/资金结算的风险。

想起前段时间,关于互联网金融的讨论,有人批评某宝不安全,风险很大,某宝则予以坚决否定。假设不充斥任何蓄意的诋毁,传统金融和互联网企业对于风险控制的理解显然是有差异的。

“如果你的规模做到很大,你是不可能跑赢市场的,因为你就是市场!”评价余额宝们的高收益率时,兴业银行一位经济学家的这句话简洁明了。当我就余额宝们的收益向一位银行行长请教时,他郑重表示:如果不设置准备金,随着余额宝们的长大,当面临大规模集中赎回时,必定会出现巨大的兑付危机。即使在互联网领域,某大佬也表示,互联网企业在金融领域还是新手。

同样,传统金融行业在面对互联网的冲击时,也是新手,当两个行业开始融合时,巨大的商机必然涌现,同时伴随着巨大的风险。我目前所供职的支付公司,就是穿着互联网行业的外套,却按照传统金融行业规则做事的形态。既然传统金融行业如此重视风险,那么试图优化流程的想法就必然要从风险控制开始。

查阅维基百科,风险是这样定义的:“风险是指事件发生与否的不确定性。”在百度百科中,“风险控制是指风险管理者采取各种措施和方法,消灭或减少风险事件发生的各种可能性,或风险控制者减少风险事件发生时造成的损失。”

维基百科中认为,风险具有如下特征:客观可能性,偶然性,可测性。前两条特征都不利于风险控制,但是对于“可测性”,维基百科中有这样的说明:“单个风险的发生虽然是偶然的,但是大量同质个体某一时期某种风险的发生又有其规律性。就大量风险单位而言,风险发生可以用概率加以测度。”

显然,事件发生与否必然是针对未来而言,而未来是不可预知的。那么,风险控制就应该从如下两个方面入手:

  • 1.基于过去、现在的信息。

  • 2.采取适当的措施和方法。

简言之,就是搜集信息,采取措施。

上述我们对于营业执照、税务登记证、法人代表身份证等材料的搜集,就属于搜集信息的环节。我们可以搜集的信息通常包含如下几个方面:

  • 1.商户(风险主体)自身的信息:商户的名称、营业照片等。

  • 2.支付企业(风险控制主体)可以查询到的信息:营业执照、税务登记证、法人代表身份证等。

  • 3.支付企业所积累的信息:同类商户的历史交易数据等。

现实中,由于监管机构信息化水平的不足,原本可以由支付企业查询的信息,却不得不由商户提供,再加上纸质协议的签订和录入,明显降低了支付企业的业务效率。

再看采取的措施,据说监管机构对于交易风险都有逐条的定义,所有接入支付网络的企业都要照此进行风险控制,例如:信用卡的大额整数交易往往就是套现的疑似特征。不得不承认监管机构对于风险交易特征的了解之深,但是,如果能将搜集到的信息整理输入到特定的数学模型,并赋予不同的权重,综合之后就可以得出是否套现的结论,而不必逐条判断是否疑似套现的特征,这样的风险控制模型,是不是会更好?这样一来,任何一位信用卡持卡人都无法通过规避单一的规则来套现,模型本身却可以随着积累的数据而进化,这就好像基于概率统计规则的邮件过滤器一样。

于是,我希望看到的基于风险控制的业务流程至少是这样的:

商户直接领取支付终端,然后自行注册登记(通过网站/手机皆可),可以提供包括姓名、年龄、性别、所从事行业等信息在内的各类信息(除了商户号和必要的结算信息,其他没有什么是必填的),支付公司的后台通过风险控制模型授予商户一定的交易额度(显然,商户能提供的资料越详细,所能获得的交易额度越高)。

此后,商户的所有交易数据都会被记录,并由风险控制模型决定提高还是降低交易额度。对于支付公司而言,则可以通过积累的数据不断优化风险控制模型,尽量减少所需要处理的商户信息。

这样的模型并不完美,考虑到风险的客户可能性、偶然性,以及可测性对于“大量同质个体”的要求,如果一类从未发生过的风险突然发生,由于模型中缺少“大量同质个体”的积累,风险演变成损失、甚至灾难的可能性仍然存在。这一点,对于任何模型都是无法避免的,就如同美国的次贷危机,各类评级机构基于历史上几乎没有发生过大量房贷违约的假设条件进行金融衍生品评级,一旦假设条件不成立,模型的结论显然会变得不可靠。

为此,采取适当的措施和方法来减少风险出现后的损失,这就成为风险控制的第二道保险,一个显而易见的条件是:减少损失所依赖的模型假设条件肯定不能与之前避免损失的模型条件一致。这第二道保险又是一个复杂的问题,我自认为还没有做好讨论的准备。