工程师是怎样对待开源 qt
工程师如何对待开源
本文是笔者作为一个在知名科技企业内从事开源相关工作超过 20 年的工程师,亲身经历或者亲眼目睹很多工程师对待开源软件的优秀实践,也看到了很多 Bad Cases,所以想把自己的一些心得体会写在这里,供工程师进行参考,希望能帮助工程师更好的成长。
概述
作为一个在科技企业内部进行技术工作的工程师,工作任务就是用技术手段支持和实现公司所关注的商业目标。 实际工作过程中,需要主动或者被动的使用和维护大量的开源软件。 据统计,每个工程师在企业内部进行研发和运维等工作的时候,每年会接触到上千款开源软件, 如果是以 Java 或 JavaSciprt 为主要程序开发语言的工程师,则接触到的开源软件数量更多,在万级别甚至十万级别。 (数据来源:《2020 State of the Software Supply Chain》由 Sonatype 发布)
那么如何选择开源软件? 这么多开源软件中,如何根据个人需求和业务需要来选择合适的开源项目来进行投入,是需要综合考虑的。
选择了开源软件之后又如何进行定制和长期维护? 这也是一个很大的问题。因为在企业内部开发软件,跟个人开发软件不一样的是,维护一个计算机软件系统的成本远远大于开发该系统或软件的成本。选择开源软件之后,如何从长期的视角进行定制和修改,后续的长期维护如何进行,才能做到高效和节省成本,业内有很多很好的经验,也有不少不太成功的案例成为教训。
最后回到个人,工程师的成长是在不断的学习和实践中进行的。如何来利用开源来提升自己能力,扩大自己的眼界,提高自己技术口碑和业内影响力,对于工程师本人也是非常重要的。
本文将从如下三个部分来分别阐述:
工程师如何选择开源软件
工程师如何定制和维护开源软件
工程师个人成长如何利用开源
1. 如何选择开源软件
首先要明确对开源软件的态度,在现阶段是不可能离开对开源软件的使用的。 使用开源软件有各种各样的风险,包括开源合规、安全、效率的问题。 简化为一句:在企业内部使用开源软件,需要遵守该企业对开源软件的内部规定,包括如何引入和如何维护,以便达到高效、安全、合规的使用。
回到具体如何选择特定的开源软件的问题上,有如下几个纬度可以进行参考。
根据需求
根据技术发展趋势
根据软件采纳周期的不同阶段
根据开源软件的成熟度情况
根据项目的质量指标
根据项目的治理模式
1.1 根据需求来选择开源软件
选择开源软件,首先要明确需求,即选择这个开源软件的目的究竟是什么。 工程师选择一个开源软件,究竟是它用来做什么的,是用来进行个人学习的; 还是用来满足 ToB 客户的需求的;还是用来满足内部服务开发的需求的。 这三个不同的目的下,选择开源软件的导向完全不一样。 (注意:后两个场景是需要先考虑企业开源合规的需求的,参见第三章)
先说说选择开源软件来进行个人学习,那么需要看看个人学习的具体目的究竟是什么。 是想学习一种比较流行的技术来完善个人的技术知识结构扩大个人技术视野;还是想看看相应的开源技术项目的具体实现,来作为内部项目技术开发的参考;还是想为了下一份工作进行有针对性的技术准备。不同的目的会导致不同的选择。针对前者,显然是什么技术最流行选什么,自己缺什么选什么;针对第二种目的,一般是对该技术领域的知名开源软件或者创新性软件进行有针对性的选择,即某个特性是我当前需要的,或者是我当前项目实现不好的,我需要看看别人是如何实现的。最后一种,显然是按照下一份工作的职位需要和技术栈要求进行准备,并根据技术栈要求的门槛高低进行选择。但是注意,从个人需求出发选择开源软件,一般都需要写个小项目练练手,比如一个 Demo 程序或者一个测试服务,因为不用考虑后续的长期维护,所以尽可以按照个人的想法和个人研发习惯进行各种练习,不用遵循企业内部的开发流程和质量要求,也不用考虑该开源软件的稳定性和社区成熟度等情况,只需要尽情的学习和参考代码就好了。
然后看下一个需求,选择开源软件进行研发的软件是需要提供给客户的,往往可能还是以私有云的方式进行交付。基于此类需求来选择开源软件,注意作好平衡,即客户的需求和企业自身技术规划或产品的长期规划需要。以私有云方式进入客户的 IDC 环境,是需要跟客户开发和运行环境的上下游项目进行集成的。这时候要看客户的需要,可能某些客户对开源软件有特定的要求,例如要求使用 HDFS 而且是某个特定版本。对这类指定软件名字和指定版本的要求,有可能是因为客户当前比较熟悉这个版本,也有可能是因为之前其他软硬件供应商提供的软件和版本,指定的目的是方便集成和后续的使用与维护。如果这种需求是符合企业项目或者产品的长期发展需求的,则是可以完全满足的。如果甲方非常强势,除了满足他的要求之外没有别的办法,那就选择客户所指定的软件和版本好了。但是如果跟自身项目或产品的长期发展需求不一致,而且具体项目或者版本是可以跟甲方进行协商的,那么需要跟客户协商出一个双方都能接受的结果出来,即选择特定的开源软件和版本既要做到客户满意并买单,又要做到自身的交付成本可控,还要做到符合自身项目或者产品的长期发展需要。例如客户使用 Java 的某个老版本,但是企业的 toB 交付的软件要求使用 Java 的较高版本。那么需要跟客户协商,要么切换到企业希望的版本上,还需要帮助客户完成已有系统的升级工作;要么只能降低自身软件的 Java 版本需求,可能还需要对某些自身代码进行修改,还可能对软件中的某些依赖组件进行修改。这个场景下是带有很多客观约束条件下的选择,是需要跟客户,自身的产品经理和架构师一起协商的。
最后,如果场景是为了满足内部服务的需求,即选择开源软件来搭建的服务是给内部业务或者最终用户来使用的,常见于国内各大互联网公司的互联网服务系统和各种手机上的 App。这时候项目的开发和维护方有较大的自主权,跟 toB 的交付业务完全不一样。此时选择开源软件,就一定要综合考虑开发和维护成本,还要考虑使用该服务的业务所处的阶段。
(1)如果提供的服务是给创新业务使用的,创新业务一般都是试错业务,随时需要根据市场情况的变化和当前执行的状态进行调整,很可能三个月后这个项目没了,即被取消了。这种情况下 “糙快猛” 的开发方式是比较合适的,不用太多考虑系统的可维护性和可扩展性,就用研发团队最熟悉的软件技术栈,然后用底层技术支撑团队比如基础架构团队提供的成熟而且经过验证后的底层基础技术平台就可以,最重要是尽快把系统搭建出来,然后随着产品进行快速的迭代。这个时候需要尽量降低现有研发运维团队的学习成本和开发成本,不用太多考虑可维护成本,因为需要糙快猛的把系统堆出来,验证产品需求和商业模式是最重要的,时间最重要。如果发现有市场机会,就快速跟进,站稳脚跟之后可以采用省时间但是费资源的方式(俗称 “堆机器”)来进行扩展,或者采用 “边开飞机边换引擎” 的模式进行重写都是比较划算的。对于处于创业阶段的企业或者项目来说,速度胜过一切。
(2)但是如果选择开源软件搭建出来的计算机软件系统或者服务,是需要长期维护的,比如是给公司内成熟业务使用的,或者是针对公司内成熟平台的缺点进行系统升级并要替代原有产品的,那么在满足业务需求的前提下,考虑系统的可维护性变成最重要的事情。选择对应的开源软件,它是否成熟,是否稳定;二次开发是否友好;运维成本是否比较合算即比较省机器和带宽;运维操作是否方便,例如常见的扩容和缩容操作是否可以高效、自动、无损的完成;Upstream 到上游开源社区是否容易等等,这些都成为需要重点考虑的事情。这种情况下,开发一个系统的成本,可能只占整个系统生命周期内的成本的 1/10 不到。所以在满足需求的前提下,重点考虑可维护性。
1.2 根据技术发展趋势来选择开源软件
如上图所示,现代计算机软件或者服务的研发,是一个不断运行的循环和迭代过程。从市场分析开始,然后进入到创意阶段,再到编码阶段,最后到上线阶段完成应用的部署和生效,上线之后根据得到的数据反馈,继续进行分析。这个循环迭代的过程,显然对于一个身处竞争激烈的行业的企业来说,迭代的速度越快越好,同时也需要具备快速弹性、低成本伸缩的能力,即产品方向对了,那么赶紧进行系统扩容,承接快速增长的流量,做到快速增长;如果产品方向不对,需要赶紧缩容,把相关硬件和人力资源节省出来,投入到新的试错方向上去。身处同一个行业内的企业,如果企业 A 能以更低的成本,更快的速度的进行各种产品和策略的迭代,显然它是能比迭代速度慢,成本高的企业 B 是有更好的竞争优势的。
现在的开源软件数量非常多,几乎每一个分类下面都有很多的开源项目。针对某一个具体的需求,如何进行选择?一个建议是根据技术趋势进行选择。即现在的计算机系统迭代的方式是 Agile(敏捷) + Scale(扩展)。显然,能够支持计算机系统进行快速迭代,并能够很方便进行低成本弹性伸缩的开源软件是值得进行长期投入的。而对一个新的开源软件的学习和使用,学习者是希望该软件的学习门槛越低越好。一个流行的开源软件,内部实现可以尽可能的复杂,但是对于用户来说一定是需要用户友好的。不然即使创新度再好,易用性不好,只有极客才能学习和掌握,创新的鸿沟是很难跨越的。
例如 Docker 的出现之后,以极快的速度风靡全球,非常多的工程师喜欢上了 Docker。就是因为 Docker 的特性,在传统的容器系统之上增加了新特性,包括把应用程序和底层依赖库封装为一个容器镜像,容器镜像有版本,而且可以通过集中的镜像仓库进行存储和大批量分发。Docker 首先解决了长期困扰工程师的开发、测试、上线环境标准化的问题,能够支持开发者进行快速的迭代。同时使用了统一的镜像仓库来进行镜像的分发,而且底层采用了轻量级虚拟机即容器的技术,可以非常快的被拉起,所以采用 Docker 的系统可以很方便的进行弹性扩展。同时,因为把应用 App 封装在一个镜像里面,可以在逻辑上根据 Domain Model 的设计原则进行更好的抽象和复用。显然,这样的技术是值得每一个开发计算机系统的工程师学习和掌握的。因为他能带来极大的方便。相反,在 Docker 产生之前,虽然 Control Group(简称 cgroup) + Namespace 的技术早就已经出现,并早就集成在 Linux 内核中,Google 的 borg 相关的论文早就已经发表,但是一般的技术研发团队不是很容易就能驾驭容器并把容器系统在公司内部大规模进行部署的。印象中 borg 论文出现后,国内只有 BAT 级别的互联网公司,才有一小撮精英研发团队来研发和使用容器管理系统,例如百度负责 Matrix 系统研发的团队,阿里负责 Pounch 系统研发的团队,腾讯也有一个小团队负责容器系统的研究。但是除了那一小部分团队,更多的工程师因为相对较难的学习难度而没有把容器大批的用起来。而 Docker 这种技术,就是非常好的顺应了敏捷和弹性扩展的技术趋势,而且提供了非常好的用户易用性,然后一出场就被非常多的工程师迅速使用上了,而且成为市场的默认标准。
这些顺应潮流的开源软件是值得选择和投入的。
另外一个例子是 Spark,Spark 的出现解决了 MapReduce 在分布式计算过程中因为需要频繁进行 IO 操作导致的性能比较低下的问题,同时在易用性上有较大的提升,所以才取代了 MapReduce 在分布式计算领域内的主流地位。
1.3 根据开源软件采纳周期的不同阶段进行选择
软件作为智力活动的产物,他有他的生命周期,一般用软件的技术采纳曲线表示。
开源软件也是软件的一种,也都是遵循软件的技术采纳规律的。
一个开源软件从创建到衰亡一般会经过 5 个阶段。 从创新期(Innovators,占比 2.5%),到早期采纳期(Early Adopters,占比 13.5%),然后跨越鸿沟(chasm),进入到早期大众期(Early Majority,占比 34%),再进入后期大众期(Late Majority,占比 34%),最后进入衰退期(Laggards,占比 16%)。绝大部分的开源创新项目,没有能成功的跨域鸿沟,即从早期采纳阶段进入到早期大众阶段,就消亡掉了。 所以,如果是选择一个需要长期使用并维护的开源项目,选择处于早期大众或者后期大众状态的项目是比较理智和科学的。
当然如果只是个人想学习一个新的东西,可以看看处于创新者状态的开源项目,或者看看处于 “早期采纳者” 状态的项目。
注意不管是从长期研发系统的角度,还是从个人学习的角度,都不要再去看处于衰退期(Laggards)的项目了。 例如现阶段即 2022 年,是不用再去选择 Mesos,Docker Swarm 之类的项目了。自从 Kubernetes 成为容器调度技术分类的默认标准,这两个项目就已经处于衰退期,他们的母公司都已经放弃了。这个阶段如果还投入较多精力来开发和维护,除非真的是非常强势的甲方要求,把钱砸在工程师面前逼的不得不用才会选择。