我想探讨一个微妙的话题,但这个话题将对抗脆弱(anti-fragile)IT系统的进展方向和PaaS(Platform-as-a-Service,平台即服务)提供商将做何抉择产生深远的影响:上下文型和组合型这两者在系统的可扩展性和可编程性方面的不同之处。我一直在探索,在云计算的时代,如何将DevOps、复杂适应系统(Complex Adaptive System)以及抗脆弱性这三者中的概念应用到软件开发和IT运营之中。该话题就是我这个探索中的一个非常重要的部分。
Neal Ford自称是系统集成商ThoughtWorks公司的“主管、软件架构师以及文化基因辩手” ,他最近所发的文章对这两种模式描述的很透彻:
在我的主题演讲中,我定义了在软件开发界很流行的两种类型的可扩展性/可编程性抽象机制:组合型和上下文型。基于插件的体系结构就是个使用上下文型抽象机制的很好的例子。插件API提供了一堆数据结构以及一些其它的上下文,开发者或者继承或者调用已有的方法。但为了使用这些API,开发者必须熟悉上下文提供了些什么,有时要熟悉这些东西所付出的代价比较高昂。。。 要进行看似微不足道的改变,所需掌握的知识和所需花费的精力却成了让改变发生的障碍,让开发者空有一个永远笨拙的工具。上下文型的工具并不总是很糟糕,没有上下文型这种方式,Eclipse和IntelliJ将不复存在。上下文型的工具提供了大量开发者可以直接使用的基础设施。只要你能掌握好,复杂的Eclipse的API就为你提供了大量封装好的功能。。。问题的难点来了:这些都是怎么封装的?
在20世纪90年代后期,4GL还在大行其道,那些语言就是上下文型方式的例证。它们将上下文内嵌到了语言本身之中:dBASE,、FoxPro、 Clipper、 Paradox、 PowerBuilder、 Microsoft Access等等这类相似的语言和工具直接都具有了数据库所具有的一些功能。最终由于Dietzler定律,4GL失去了人们的宠爱。在我所写的书《卓有成效的程序员》(Productive Programmer)中,基于我同事Terry Dietzler的经验, 我定义了该定律。那时他正在我的老板那里干着许多各种Access项目:
Dietzler的Access定律
每个Access项目最终都将失败。这是因为,尽管用户想要的东西当中有80%在创建起来很快并且也很简单,还有10%也能做到但有难度,但最终会由于谁也无法超越内建的抽象机制,那剩下的最后10%不可能完成,可用户总是想要得到100%的他们所想要的东西。
最终,Dietzler定律消灭了4GL的市场。尽管它们使得创建简单的东西变得容易了也快了,但它们没有上升到能满足真实世界里的很多需求。我们都回归到了通用编程语言。
组合型系统往往是由更细粒度的部件组成,各部件间以特定的方式进行连接。这种抽象机制比较强大的例子出现在各种*-nix操作系统的shell当中,这些shell能够将互相独立的行为串联起来产生一种新东西。 1992年的一个著名的故事说明了这种抽象机制是多么的强大。有人请Donald Knuth写一个程序来解决这个文本处理问题:读入一个文本文件后找出其中n个使用率最高的单词,并将这些单词以及它们出现的频率排序后打印出来。 他用Pascal写了一个十几页的程序,并在此过程中设计(并记录)了一个新算法。后来,Doug McIlrov演示了一个用不超过一条Twiiter博文的长度写的shell脚本,以更加简单、优雅和更容易理解(如果你能看懂shell命令的话)的方式解决了同样的问题:
tr -cs A-Za-z '\n' | tr A-Z a-z | sort | uniq -c | sort -rn | sed ${1}q
我猜即使是Unix shell的设计者也常常会对开发人员利用Shell那简单但强大的组合型抽象机制搞出来的别出心裁的用法感到惊奇。
Ford继续非常详细地描述了每种方式的利与弊,但我认为,对于理解应该如何开发能够驱动新IT模型的工具和工具链来说,他所得到的主要结论非常关键。
这些抽象机制同样适用于工具和框架,特别适用于必须在功能和复杂性方面要向上适应的工具,比如build工具。 通过来之不易的经验教训得知,组合型的build工具比上下文型的(在时间、复杂度和可用性上)能更好的向上适应更复杂的项目。就象Ant和Maven这类上下文型的工具可以通过插件API进行扩展,对于原先作者预想到的扩展做起来就很容易。然而,要是想以一种并没有在API设计范围之内的方式进行扩展,不是非常难就是不可能。Dietzler定律又回来了。这一点对于那些其内部功能实现的关键部分,比如各项任务的排序,不通过很特殊的手段就无法控制的工具来说更是如此了。
Ford的对比最终帮我理清了我这段时间以来我一直所关心的同PaaS有关的一个关键问题。在我的心目中,目前市场上主要有两种类型的PaaS系统(现在用Ford术语说非常清晰)。一种是上下文型的PaaS系统,它提供了编码框架,按照此框架编写的代码可以很少或者不用特殊的配置或者定制自动化就能得到这种PaaS所提供的功能。另外一种是组合型PaaS,它的主要功能是通过可以按需组装以支持不同的应用程序的部件(包括运维自动化)来实现的。
上下文型PaaS的例子有Google起初发布的App Engine、Heroku以及其它一些“第一代”PaaS系统,这些系统要求开发者遵从特定的体系结构,要在应用中使用各PaaS系统专有的类。 在创建这些框架本身设计中就考虑到的各种变化范围内的应用程序时,这些框架惊人地强大,但一旦出了这个范围,它们马上就不行了。
Google的App Engine对后台请求的处理时间有个30秒的限制,这就是一个最有代表性的例子。这对想写个Facebook游戏的人来说没问题,但这个限制使得大家无法用它创建很多的涉及多个步骤的事务处理型应用。当然,也有办法处理掉这些问题,但多数情况下这些办法都比较复杂,而且也会给系统平添一些风险。
Ford在他的文章中还谈到,在20世纪90年代后期,4GL也出现过类似的问题。那时我还在Forte软件公司(1999年被Sun微系统公司收购)工作,我们为分布式应用程序的开发建立了一个开发运行环境。 我们的业务模型非常依赖于做系统集成的合作伙伴,这些系统集成商帮助我们的客户编写很多都非常复杂的应用程序,而且每个系统集成商最后都创建了各自的框架环境,力求让编写那些复杂应用程序变得“更加的简单”。
问题是什么?几乎使用这些框架中的某个框架的每一个客户都有该框架不能完美处理的一个(或多个)需求。造成的结果,要么是系统集成商为了满足那些需求去胡乱修改他们的框架,从而不可避免地导致框架用起来不那么“容易”了;要么就是客户为了实现需求完全跳过了框架,结果得到的应用程序运行、调试起来更困难了。
组合型PaaS系统站在另一个角度,对基于其创建的应用程序的体系结构或功能并不作太多的考虑,它考虑更多的是,要对包括基础设施自动化、数据源、专业的数据工具等等在内的服务的装配进行简化。我认为,Cloud Foundry是组合型PaaS的一个最有代表性的例子,它是来自VMWare的开源的PaaS,现在Cloud Foundry是VMware公司 拆分出来的Pivotal Initiative的一个组成部分。当下最新的Heroku、EngineYard、CloudBee以及一些别的PaaS也都比“第一代”PaaS系统越来越多的展现出这种新思路了。
然而,可能最重要的是,现在有一些为建立和发布应用程序而直接部署在基础设施服务中的开源build工具链(tool chain),完全体现了很纯的组合型思路。将GitHub同Jekins、Gradle、AWS、CloudFormation、Autoscaling等等工具都结合起来,就能得到一个完全自动化的、领会的应用程序开发和运行“平台” —— 这正是你想从PaaS中获得的东西。当然,美中不足的是,在未来的时间中将需要你来装配和维护这个工具链(而不是让PaaS供应商为你做这些事情)。
现在把概念再往前推一步。想象一下这样的部署环境,它提供了非常广泛而大量的单个的工具和组件并为你简化了根据需要将它们组成你所需要的工具链的步骤。想象一下这样的环境,环境中的每个开发团队都允许从已知的工具链“模式”中进行选择,并能让他们针对每个项目对所选的工具链根据需要做出修改。这是我所认为的将会胜出的终极通用PaaS,而绝不会是那些难用但是上手容易的、基于框架的PaaS。
评论删除后,数据将无法恢复
评论(2)
引用来自“TX”的评论
本来想自己翻译的,你动作真快@fbm