开源,是个真正的王者,一项真正意义上的软件行业生产力革命。
本书没有足够的篇幅来仔细地讲开源,为了体会开源对软件行业的价值,感受开源项目的魅力,本节分享的是开源管理平台GitHub的诞生史,希望可以由此窥知那段软件行业发展的黄金年代。
林纳斯·托瓦兹(Linus Torvalds)是技术宅们心中的英雄,他作为Linux之父而广誉天下,Linux既是免费的又是开源的,年轻时的我是无法想象的,真正的原因当然是自己太渺小而无为。然而Linux并不是托瓦兹对软件行业做出的唯一巨大贡献。20世纪90年代,托瓦兹就绞尽脑汁地想将开源社区的贡献融入操作系统中,这个过程其实就叫作“版本控制”,托瓦兹因此成为Linux的“集中守门员”,对开发者做出的变更最终负责。集中式管理当然不可持续,一个人无法完成所有变更的管理,大量有完善可能性的代码因此被永远湮没。2005年,托瓦兹开发了一个开源软件来解决这个问题,为其取名为Git,Git让各个项目所有者(或是任何能“拍板儿”的人)进行项目的管理,还让任何人能够轻松地创建Linux分支,拥有属于自己的版本。
有趣的是,Git在英文俚语中的意思是“讨厌的人”,指的是那些如同守门员一样的开源项目管理者们。
故事还未到精彩之处。Git存在一个问题,作为一个命令行工具,使用起来令人头疼。对于程序员而言,或许不是特别严重的障碍,但的确限制了程序的易用性和吸引力。因此,直到2007年,Git依然没有被Linux社群之外的人们广泛知晓。在这之后,出现了GitHub,在硅谷人的眼中,它具备Facebook、维基百科、Twitter这三者的先进基因,是名副其实的集大成者:GitHub是程序员的社交网络平台以及内容的维基百科,让他们能编辑档案、追踪变更内容,任何人都可以评价他们的代码或者添加、完善。通过跟踪特定的代码,可以在有变更时得到通知,这就像在Twitter上关注某人,当他发布新的推文时,关注他的人就会被通知一样。GitHub具有用户界面,大多数人可以轻松与其互动。GitHub就此成为托管和发掘开源代码的全球平台,是寻找开源项目的第一选择。用经济学的词汇来说,GitHub极大地缩减了人们在软件项目合作的交易成本,这个交易成本,包括了用户搜索和获取信息的成本、多方之间谈判和合作的成本、每个参与方工作执行的成本。
除了缩减交易成本,GitHub价值主张的另一个关键部分是为用户提供一个管理并编辑代码的环境。这个平台被设计来鼓励用户去创造,而不仅仅是交易。承载创造成果的,正是代码仓库。GitHub提供基础设施,使得软件开发者托管和管理开源项目更容易,包括版本跟踪、编辑和沟通。
为何用GitHub来谈开源呢?在有限的篇幅内,作为开源革命的催化剂,我们很容易以GitHub掌握开源项目的实际面貌。开源将软件生产者的范畴,由顶尖的一小部分人扩展到千千万万的软件从业者,全民参与性使得各类软件的生产力得到空前绝后的发展。
从GitHub的2023年年度报告中可以看到:93%的开发人员用Git来开发和部署软件;项目(或称为代码仓库)总数超过4亿
;全球开发者账户增长迅速,总数超过1亿。在某次技术交流中,笔者听到这样一句话:我国软件的创新项目,至少有一半来自GitHub。
这些数字足以说明GitHub市场占有率之高,还有一个数字值得关注,私人项目占据了GitHub活动的80%以上。之所以强调私人项目的活跃性,原因在于私人项目更能反映技术创新的热度。
一个领域的发展,通常是由0到1的孵化,再由1到100的过程。开源产业至今仍是软件生态中的主角,还在迈向100的旅途上。关于开源产业的全面、翔实的信息,上到白皮书、下到某个项目情况,在网上很容易搜索到。但是,笔者更加关注那段确立其价值和市场地位的(由0到1)过程,这才称得上是革命,也是最具启发意义的,这个过程正是发生在第二个时期。认识这个过程,对于深耕于这个行业、在激烈竞争中保持韧性,是一种自我赋能。
对软件从业者来说,不好好地理解开源的前世今生,容易像是一个门外汉。成为开源参与者会带来更强烈的、属于软件人的一种归属感。即使普通的软件开发者,尽可能地了解开源,也会极大地提升自己的底蕴。这种底蕴难以言表,可以将其理解成一种无形之中的实力和内涵。
本节要谈的是开源革命与软件架构发展两者之间的关系话题。
开源提供了一个全球项目的代码存储中心和流通中心,源源不断地提供各种实际可用的软件原型,这些原型内置了各种模式的架构,普通从业者更多是通过直接阅读开源文档的方式来反向学习架构,不再自己费劲地创造。这就好比开汽车的人,可以先学会驾驶汽车,进而掌握发动机、变速箱和底盘(意指汽车的架构)的知识,拿着成品学习,当然比从基础理论开始研究要容易得多。这就是很多人眼中的“弯道超车”之法。
开源增大了软件架构量子的体积,结果自然是系统更加臃肿。封装了各种设计模式的技术框架成为软件开发者的必需品,早期使用过的JMX、OSGi技术框架,至今印象深刻,我不再追求精细化,而是只能一股脑地拿来用,在上面叠加自己的应用程序。软件系统的发展,好像是从赤道到西伯利亚的旅行
,层层封装、层层加码。
系统臃肿会诱发一种趋势,即“代码如同浮云,重构不如重写”。这当然不能都怪罪于(因引入开源造成)系统体积膨胀、体量太大而无法承接,在实际工作场景中,或许还与文档越来越少、工作交接不充分、职场团队帮派之间明争暗斗等多种问题有关。这样的趋势有利有弊,但总体来说,我更愿意用“只要存在的,即是合理的”这样的哲学观点来理解这些变化,顺其自然地承认它。
开源软件是安全漏洞问题的重灾区,谈此话题,我头脑中更多的印象是黑客们对于攻入开源漏洞的津津乐道。除此之外,开源还可能与(企业自身的)统一架构规划格格不入,开源软件中使用自己的接口网关、服务注册、消息队列、数据库,无法将其拆解开纳入到企业的技术栈和架构管控体系。从管理与维护视角看,对于使用者而言,开源软件更多情况下是一个无法打开的黑盒,技术决策者则要考虑“开源软件与企业已有架构”异构问题的长期影响。
没有什么是真正免费的。在开源社区中,人们可能会看到“TANSTAAFL”这个缩写术语
,意思是“天上不会掉馅饼,世上没有免费的午餐”。当用户下载并使用开源软件之后,他们会开始发现它的局限性。有时,代码只需要一些小改进;有时,开源软件根本没有适合的功能。开源软件在免费提供时即使功能不全也很少有用户抱怨,但要补齐开源软件缺少的功能,对开发者来说是一个巨大的负担。即使免费开源软件实现了99%的目标,最后1%的开发工作对于开发人员来说也可能是一个非常艰难的过程。虽然开源以免费著称,但如果真实计算投入,使用开源项目通常高于市场化采购,两个中级开发人员的年(人力)成本会达到100万元,这个价钱已经足够买到大多数的商用软件。
每个企业都希望复用代码,因为软件看起来模块分明,如同电子元器件。然而,真正模块化软件很难实现。这些言论绝非危言耸听,著名的技术类反模式——代码复用和滥用,正是讽刺复用问题。虽然软件开发者们对外承诺的是“可随意组合的乐高积木”,但是现实世界中充斥的是“从其生长环境中单独拿出来就会死亡的组织器官”。例如,在SOA架构中,最佳实践是找到公共的部分尽可能地复用,但事实远非如此,即便公司多个业务系统中都有名为Customer(客户)的领域模型,欲将它们整合为一个公共、共享的Customer服务,结果也常常适得其反。为了实现复用,需要引入额外的选型和决策点以适应不同的用途,开发人员为实现可复用添加的定制化内容(或者说特性)越多,对代码的可用性损害越大。
有一点需要说明,使用开源包括使用开源框架、开源库,从工程实践来看,上述所述的主要风险主要针对开源框架,开源库对架构耦合性影响较小,自然更为可控。
建设软件系统有三种方式:完全自研、开源+自研、商业化采购。在开源的基础上进行自研,已成为主流的技术决策路线,引入开源的几个评价标准无外乎是功能成熟度、所用语言和技术栈优劣、社区活跃度情况。对创新类项目,笔者鼓励如此,例如本人最近参与建设的交互式安全测试平台、基于联合建模的隐私计算平台。然而对于核心、传统的项目,则是另外一回事,例如资金交易系统,或是数据库系统,商业化服务的保障是必要的。
被开源项目所吸引,但是未深入评估的情况下,不能被其迷惑。从另外一个讽刺的视角来看这个问题,技术决策者面临的左右为难的话题,被谁绑架(或者说是控制)对自己更为有利?是付出更大的员工(工资)成本进行自研,还是指望开源软件及框架,抑或是依赖供应商服务?三个答案各有利弊,正确的答案只能根据自己的需求和现实情况而定。
如果将自研比喻为自力更生,那么适合形容使用开源软件的成语应该是拿来即用。拿来即用这个词,其实与意味着工匠精神的精耕细作一词并不相悖,但总是给人“粗制滥造或是(以不合理方式)据为己有”的感觉。的确,软件设计无比推崇复用思想,这听起来貌似无懈可击,但知识复用本身也是一种反模式,仔细想想这和公开抄袭好像是一回事。拿来即用可以推进生产力发展,其弊端是“以抄袭为家常便饭”而导致的文化问题,其结果是:过于向往能够快速达到目的、获得利益,从而淹没了对于真实创造力和原生力,以及技术纯粹性的追求。
开源给软件生产力带来巨大提升,必然使得拿来即用的开发方式成为潮流。1.1.2节中讲道,软件设计与开发的核心原则和方法,20多年并未发生根本性改变。如果非要在其中找一个最大的变化,那么应该是“重用”似乎比“耦合和内聚”更为重要。“低耦合、高内聚”在架构中的地位不可动摇,但是设计人员在此方面投入的精力在减少。更加注重复用的价值,无形中降低了耦合的可设计空间。无论是桥接的外部服务接口,还是引入的开源框架或组件,均提供了(或者说是界定了)天然的耦合点。
有句行话叫作“二次架构”,隐喻的现实情况是:今天的架构师似乎有太多“捷径”可走,因此不再需要架构知识,例如借助云平台从丰富的工具和基础设施中做些选择,或是在已有的开源项目上进行二次开发,抑或是找些免费的类库做些拼装,即可以完成工作。原创性的缺乏,令人对架构师行业的未来看淡。这需要我们真正回到问题的原点,扎实地掌握软件架构的底层逻辑。
综上所述,拿来即用思想的负面影响在于软件系统建设的粗糙化、功利化。这样的做法看似抢滩登陆,实则涸泽而渔。敢对人人称道的开源如此诟病,大家可能觉得笔者是鸡蛋里挑骨头,无理取闹。因为对于个人的职场发展并无影响,所以对个体而言,拿来即用思想问题是潜在的、不重要的。但是放大到整体格局层面,提升基础技术的研发意愿、关键技术的研发投入,避免软件应用同质化,降低软件建设重复化,是行业决策者们应该真正思考的问题。与软件发达国家相比,这是我们的薄弱之处。目前,我们缺少打造Transformer这种现象级软件产品的核心实力。值得欣慰的是,这样的差距在不断缩小。
是否使用开源软件还有一个因素需要考量,那就是“有效利用率”问题。开源软件普遍是泛而不精,因为基本不依赖商业化运营资金的支持,存在这样的问题是必然的。但是我们需要的软件多是细分领域上专而精的。因此,使用开源软件搭建自己的系统,经常出现的现象是,为了能够让开源软件跑起来,首先要部署和配置整个框架,但其实只有一小部分功能是业务需求所必需的。然后,剩下的精力就是花费时间去完善这部分功能,做大量的增量开发,精耕细作。这样看来,如果隐私计算最终投产应用的业务场景只是隐私求交,自动化测试仅用于作为发包器进行系统服务可用性探测,那么,其实从零开始借助函数库自研的效果也不会差太多。
问题归问题,不要看到问题就让阴暗面占据上风,演变为偏激的贬低和抱怨,更无须将二次架构视为是反面教材。本节内容更重在体现思辨精神,在完整的架构思维体系中,批判性意识是不可或缺的。将这样的问题解读为“成长的烦恼”,让工作始终保持螺旋式上升的态势,才是良性的认知。
开源是商业世界中的奇迹,很难从其他行业中找到类似案例。除了借力行为
背后隐藏的深层次弊端之外,我几乎找不到开源的任何吐槽点。开源许可证像是一条大河,架构设计则如同顺水行舟,两者的加持,令软件系统的建设势头空前高涨。开源,更像是软件行业进入了共产主义。