HarmonyOS开发者限时福利来啦!最高10w+现金激励等你拿~ 了解详情
写点什么

一张主流编程语言的变迁图,讲清程序员迁移模式

  • 2019-05-08
  • 本文字数:6454 字

    阅读完需:约 21 分钟

一张主流编程语言的变迁图,讲清程序员迁移模式

我绘制了一个主流编程语言的变迁图,用以表示程序员在不同语言之间的切换路径。


关于编程语言,还有很多类似的图可以表示它们相互之间的演进。不过我并不想从语言设计者角度来说明这个问题,而是想从程序员本身来看待语言演变。虽然两者间有些接近,但并不完全相同。


从该图可以看出,如果开始使用的是编程语言 A,下一个最有可能切换过去的是哪种语言。这种推测不是非常科学。不过如果你需要精确的科学,就不会在这里阅读这篇文章了,对吗?也许这张流程图对我来说,能揭示更多的内容。


声明:在此处,不考虑程序员最喜欢的是什么语言。人们可以在任意两个语言之间切换,也可以学习很多种语言、然后选择最适合工作的一种语言。本文中的观点有一定的倾向性。


在接下来的篇幅里,我所阐述的均为个人观点。为了不影响读者阅读,就不再一一做出声明了。



程序员迁移模式


我想强调下最普遍的“终极节点”。在这些节点上,人们在他们所处的维度找不到更好的可替代编程语言。这些终极节点包括:Rust、 Java、 Go、 Python 3、Javascript 和 node.js(node.js 作为一种特殊的 Javascript,在这里特别指出)。


几年前,我认为 C 也是一个终极节点。可能现在也还可以这样认为,因为有大量的重要项目(如 OS 内核)仍使用了 C,而且可以认为它无可替代。不过有迹象表明 C 其实是可以替代的。我最喜欢的例子就是有趣的空指针。Linux 内核有个编译器带来的致命弱点,即 NULL 值“不可能”出现,因此没有对函数进行空指针检查。C 也是一团糟,其规格里有几个新编程语言所没有的致命错误。也许某天这些错误能被修复。


让我们回退几步。如果从顶部开始,根据人们进入编程的不同规格,可以看到四个主干:


  1. “低级”编程,包括 asm 和 C。

  2. “商业型”或“学习型”编程,从 BASIC 开始。

  3. 计算类/科技类编程,如 Fortran,MATLAB 和 R。

  4. 脚本/胶水编程,如 shell 和 perl。


(我们也会谈到“数据库查询语言”,比如 SQL。它是一枝独秀,所有替代它的尝试都以失败告终。数据库语言从上世纪六十年代开始就停滞不前了。甚至到现在,其关键字仍使用大写,因为(他们认为)这样能更好的理解代码。)


(我还忽略了 HTML 和 CSS。他们是真正的语言,不过现在大家都开始学习这两种语言,图上无法用相应的箭头来标识。Lisp 也没有考虑在内,因为它一直没有流行过,虽然有一小部分人一直希望它能流行起来。我还建议添加第五个分类,“配置编辑”)


(该图也忽略了 Haskell。它可以在旁边用一个独立的框来表示,和其他语言之间没有出入的箭头,不过这没关系。Haskell 是个自嘲式的大笑话,除非涉及到 Monads,它不再使用 I/O 概念。)


不管怎么样,让我们回到上世纪九十年代。假设那时编程世界很简单,(1)初级程序员使用 C,asm 或者 Turbo Pascal,(2)商业程序员使用 VB,(3)数值计算人员使用 Fortran,R 或 MATLAB,(4)胶水编程者使用 sh 或 perl。


那时,编程语言就是这么严格划分的。画该图时,我才意识到这一点。显然,我们不会用 perl 来写操作系统内核,不会用 MATLAB 来写胶水程序,不会用 VB 来写大型矩阵相乘算法。


现在则变化很大。选择什么样的语言已经不再像过去那样明确了。

语言的变化主要是风格的变化

我们先来看树起点 asm(汇编语言)。用 Asm 来写程序是相当困难的。不过即使到现在,它仍是写某些程序最好的方式(如电脑启动后的最初几个指令,或是中断处理的入口代码)。不管是在 App Store 里还是手机上的 JIT 里,每个编译语言最终都会将代码编译成汇编或机器语言。


基于 asm,出现了两个分支:C 类型分支和 Pacal 类型分支。(Algol 出现的更早,不过此处忽略掉。宣称自己是 Algol 程序员的人并不多。Algol 对其他语言影响很大。)


Pascal 风格分支语言的特点是有"begin…end"。C 风格语言的特点则是有括号。当然,C 影响了很多的编程语言设计,这点在图中没有体现。因为我们现在讨论的是程序员,而不是语言设计人员。


首先来看看 C。很奇怪,一旦人们开始使用 C,就习惯用它来处理各种情况。不管实现优劣与否,它是为数不多的能合理实现所有四类编程问题的语言之一。这四类都有些难度(除了低级编程,它正是 C 擅长的领域),不过 C 都能搞定,速度也还可以。


如果你是个 C 程序员,接下来会使用那种语言呢?这取决于用它来做什么。


显然,C++是一个选择。虽然其名字与语法和 C 很像,但它其实和 C 风格迥异。除了 BeOS,其他操作系统内核不会使用 C++。在极具潜力的 Rust 使用前,操作系统基本都使用 C 编写。


但是商业(“大型程序”)和数值计算(“快速程序”)领域的人员喜欢 C++。说喜欢不一定准确,但他们别无选择,只能使用 C++。


对于胶水程序,很多人会直接从 C(或 C++)转到 python 2。我最近也这样做过。和怪异的 perl 不同,Python 2 类似 C 语言风格,其语法更简单。C 程序员很容易理解 python C 模块(并可以编写新的 python 模块)。从 python 里调用 C 函数比其他语言更简单。如果在 Java 里调用,就需要处理非引用计数的垃圾回收问题。python 的“os”模块提供了 C 系统调用及该调用能工作的环境。程序员可以访问 C 语言中的错误码并设置相应信号处理程序。唯一的问题就是 python 有些慢。不过只把它作为胶水语言,则可以不考虑python的慢速。速度慢时,可以写 C 模块或调用 C 的库或子程序。


另外,Java 面世后,很多 C 和 C++商业软件的程序员非常快地切换到 Java。C++编译时间长,头文件繁多,可移植性差,有释放后重用的错误问题。因此,虽然 Java 运行的很慢(和 python 不同的是,Java 宣称“理论上运行很快”),人们还是更愿意使用 Java。


我记得有篇文章讲过,Go 的设计者最开始认为 Go 可以和 Java 或 C++媲美,但实际没有做到。Java 就像知名酒店,或是门洛帕克(Menlo Park),一旦入住就不想离店。同时,程序员没有从 C++切换到 Java 主要是因为:a)Java 速度比 C++慢,b)Java 仍有垃圾回收的经典问题。


Go 在之前已经切换到 python 2 的胶水程序人员中流行起来。事实证明 python 的慢速是其痛点所在。计算机复杂度急剧增加,python 胶水程序规模也越来越大。相较其优势,动态类型带来的麻烦更多,因此人们开始使用预编译二进制。python 2 占用很多内存,因此 Go 做了 RAM 改进,避免了从 C++迁移到 Go 带来的问题。Go 的难度和 python 差不多,但它运行更快,占用 RAM 更少。


我们现在称 Go 是一种“系统”语言,因为提起胶水程序,我们更多的是想到 perl 和 ruby,不过它们的作用是一样的。(试试告诉一个 C 语言内核开发者,Go 是“系统”语言,看看他们的反应)Go 是粘合剂,可以把各个组件组合到一起成为一个系统。

Hejlsberg 因素

我们接下来看 Visual Basic 和 Pascal 分支。人们有不同的想法:明显正确的(“我为什么会使用与 C 或 Java 一样让人痛苦的语言呢?”),或明显错误的(“可视化的…Basic?开玩笑吧?”)。二十世纪八十年代和九十年代,一些人仍认为编程应该让新手可以方便使用,因此在个人电脑上预装了免费的编程语言,大部分都是 BASIC。


另一方面,大学教授编程时,则避开了 BASIC(“如果学生前期使用过BASIC,就不能对学生很好的进行编程授课”),也没有选择 C。他们更倾向于 Pascal,认为 Pascal 易于学习。就像 Algol 的学术论文里提到的一样,而且它的语法适合教学,能让每个学生都能听懂。因此就有了学术分支和个人电脑分支,不过它们有个共同点,那就是都和 C 不像。


基于 PC(DOS)的 BASIC 演变为基于 Windows 的 Visual Basic,这可能是 javascript 出现前使用最多、最受欢迎的编程语言。(现在,它仍是在 Excel 中使用的“宏”语言。目前有很多 Excel 的程序员,虽然他们并不认为自己是程序员。)


同时,Pascal 也在努力往 PC 转。因为 Turbo Pascal 的出现,它变得流行起来,并一度成为最快的编译器。在速度上,Pascal 的确没有夸张。甚至有一些 C 程序员也喜欢用 Pascal,不是因为喜欢其类 C 的语法,而是因为它的速度很快。(Turbo C 也可以,但速度还不够。它比其他 C 编译器都快。)(大学里,Pascal 学术性越来越强,后来演变成 Modula 和 Ada。如果不是美国军方在其高可靠系统中采用了 Ada 语言,这个分支早该终结了。现在我们可以忽略 Ada。)


那时还有两个“商业”开发分支:BASIC 和 Pascal 分支。Windows 问世后,出现了 Visual Basic。基于 DOS 的 Turbo Pascal 有点过时,基于 WIndows 的 Turbo Pascal 也并不出众。为了竞争,Turbo Pascal 的设计者Anders Hejlsberg创建了 Delphi。Delphi 和 Visual Basic 一样,有可视化的编程环境,但它基于 Turbo Pascal 语言,也极少出现找不到或不匹配实时动态链接库的烦人问题。


Delphi 很好,但它不属于 Microsoft。掺杂商业因素后,局面变得有些困难。在一系列出人意料的事件之后,Hejlsberg 离开了 Microsoft,但仍继续 C#的开发,发布了 Microsoft .NET 平台,并包含 Visual Basic.Net(这是个很可怕的产品)。据称 C#统一了两个分支。


不幸的是如前所述,VB.NET 很可怕。它和 Visual Basic 几乎没有共同点,更像是 C++的一个慢速版本,披了件有点非典型 Basic 的语法外衣,还带着一个更糟的 UI 设计工具。C#也不是 Delphi。不过这几种语言都销声匿迹了,Microsoft 尽力推动了这一点。(除了 Microsoft Office,它到现在仍在使用最开始的 Visual Basic 语法,称为"Visual Basic for Applications", 即 VBA。比起.NET,它使用的更广泛,更受用户喜欢。)


我不清楚怎样才能叫做一名 Visual Basic 程序员。微软致力于让他们改用 VB.NET,但大多数人并不愿意。我想在图中画一条“他们实际的选择”的箭头,不过老实说我也不知道应该指向哪里。也许他们成为了 web 开发者,或者编写了 Excel 的宏。


从现在看,如果写基于微软主推的基于.NET 平台的 Windows 软件,是件很有趣的事。可能使用的语言都会深受 Hejlsberg 的影响。Hejlsberg 的语言在反击之前被微软和 Visual Basic 所遏制,于是 Hejlsberg 转向写 Typescript,这个留待以后讨论。

胶水语言的简要介绍

最初的胶水语言是 Unix shell,它因引入“管道”概念也很著名。“管道”连接简便的工具来完成复杂的工作。


啊,就是那些日子


那些日子一去不复返,perl就是献给它们的悼词


– Rob Pike


事实证明,设计小而简单的工具是困难的,通常我们没有足够的时间来做这个。能够让我们跳过这些轻便工具,致力于编写奇特的、能够粘着很多乱七八糟的小程序的语言变得越来越流行。(它对 shell 语言的缺陷,尤其是与引用和通配符扩展规则相关的缺陷并没有帮助。)


第一个是 awk,它是语法和 C 类似的解析语言,可以用在 shell 的管道上。那时,在一种语言(sh)的一行中里使用另一种微语言(awk)有点奇怪,庆幸的是我们适应了,因为现在的 web 程序都是这样的。(我们略过 csh,它是另一种与 C 语法不兼容的语言,存在不同的致命缺陷,可以被 sh 替代。)


接下来是 Perl。awk 没有足够多的标点符号,从而促成了 Perl 的产生。(好吧,这只是个玩笑。)


Perl 开始到 perl 5,越来越受欢迎。现在,Perl 停止改进语法,在 perl 6 上倾尽全力,从零开始打造。(在图中并没有标出 perl 6,因为还没有人切换过去。)


这样的配置给在几个方向断层进行“粘合”留下了空间。如果程序员觉得 perl 的语法差劲,可能会切换到 python。如果他们认为 perl 的语法很神奇有效力,只需要一些调整,则可能会切换到 ruby。如果使用 perl 来运行 web 的 CGI 脚本,则可能会保持原样,也可能会转而切换到 PHP。


ruby 很快成为 web 服务器支持的语言(进而是 Ruby on Rails)。Python 也同样在演进。


现在有趣的是:整整一代程序员摒弃了命令行方式(这也是胶水语言运行的方式),希望在 web 端可以做任何事情。从某方面来说,这样更好,比如在一个胶水程序中可以超链接到另一个胶水程序。从另一方面来说,则更糟糕,因为现在所有的 web 程序都很慢,不能使用脚本,而且安装 Electron 的另一个副本需要 500MB 的 RAM 空间等等。这就引入了 web 语言这个话题。

Web 语言

图中,集中在 javascript 的“胶水”分支有很多的箭头指向,这并不奇怪。Javascript 最初只使用于前端。当 node.js 出现后,这种情况完全改变了。现在,只需要学习一种语言来写前后端和命令行工具。Javascript 最初的设计是将其作为最终的胶水语言,试图融合 HTML、CSS、面向对象编程、面向函数编程、动态语言、JITs 以及其它一切能通过 HTTP 请求得到的东西。


但是这样不太好,因为后向兼容对于 web 的成功至关重要。要保证这一点,就无法修复一些严重错误。1995 年,经过 10 天的设计,Javascript 发布了。对于 10 天的成果而言,它相当优秀,但同时它也存在一些问题,无法对其进行修复。


这就是图中唯一一个有双向箭头的地方:javascript 和 python 3 之间。我们把它叫做脚本语言的阴阳两面。


大部分出现过的胶水+web 语言正在消失,python 不在其列,至少目前还不会消失。我猜是因为 python 本身是合理的。使用 javascript 编程时间足够长的话,过段段时间后就会变得不大正常。这时为了缓解压力,程序员有可能会切换到 python。


同时,如果长时间使用 python,最后准备编写 web 应用程序时,前端代码和后端使用完全不同的语言是很烦人的。一个的语法是[‘a’,‘b’,‘c’].join(’,’),而另一个则变成了’,’.join([‘a’,‘b’,‘c’]),这让人完全记不清谁是谁了。


一种语言有 JIT,可以让其一旦运行起来就会速度很快。而另一种则是启动快,运行慢。


一种有合理的命名空间系统,而另一种则没有。


我不清楚从长期看,python 3 是否能打败 javascript。但至少目前看,它不会被击败。


同时,对于编程事实分支从不满意的 Hejlsberg,看到了 javascript 的很多问题,引入了 TypeScript。与此同时,微软突然停止了对 Windows 应用程序的大力推进,开始大面积推广 web 和开源。这意味着 Microsoft 第一次将其开发者推向 web 语言即 javascript。在此基础上,他们有自己的 TypeScript,我觉得这是一种很好的语言。这个分支存在有数十年,开始和其分支融合,可能不久后会消失。


TypeScript 和 javascript 比,能胜出吗?这是个有趣的问题,我也不知道。我以前赌 Hejlsberg 能赢,不过我一般容易赌输。

Python 2 和 Python 3 的对比

综上所述,我对 python 2 和 3 有了结论。它们很相似,但不尽相同。我认为,这是因为他们在整个程序员语言迁移图中所处的位置不同。Python 2 开发者来自 C 和 perl 开发人员,希望编写胶水代码。Web 服务器是后续添加的一个应用场景。我的意思是,python 2 出现后,web 程序变得流行起来,这并不出人意料。很多 python 2 的开发者转到 Go 的开发,因为他们想写的某些“系统胶水”代码使用 Go 正合适。


Python 3 的开发者是从不同的语言切换而来的。事实证明,python 3 问世后,python 的使用得到很大的发展,不过新加入的人群和以前的人群有所不同。由于带有模块 SciPy 和 Tensorflow,从科学类和数值类处理转过来的新程序员占了其中很大的比例。老实说,在高吞吐量的数值处理中,Python 是一个相当怪异的选择。但不论如何,这些库的存在是我们选择它的一个原因。我猜 python 的另一个优势则是易于和 C 模块集成。当然,python 3 本身就是网络编程。


想要理解 python 2 和 3 的区别,只需看看其不同的字符串类型。Python 2 中,字符串是一组字节,因为操作系统、Unix 管道处理、网络 socket 的处理均以字节为单位。对于系统程序而言,python 2 是胶水语言,其处理以字节为单位。


在 python 3 中,字符串是一组 unicode 码。因为人们不擅长 unicode 码的转换,而和网络交互时,都是以 unicode 为基础。做科学数值计算的人不关心字符串,做网络编程的人更关心 unicode,所以 python 3 使用 unicode。如果要用 python 3 来编写系统程序,就会一直疲于 unicode 的转换,即使最简单的文件名也需要进行转换。这也正是有其因,必有其果。


相关文档


Misunderstanding Exceptions (2007)


You can’t make C++ not ugly, but you can’t not try (2010)


原文链接


https://apenwarr.ca/log/20190318


2019-05-08 15:03120493

评论 1 条评论

发布
用户头像
Rust其实蛮受函数编程影响的,特别是trait的概念基本直接照搬了Haskell,所以应该多一个从Haskell到Rust的箭头。ES6的destructering assign其实也有点pattern matching的意思,Erlang程序员会觉得很熟悉。现在小众函数式语言程序员成为主流程序员也越来越容易了。
2020-07-13 10:46
回复
没有更多了
发现更多内容

利用Vim和Github Copilot打造一款强大IDE!

Jackpop

从 DFS 到回溯法,再看 N 皇后问题

掘金安东尼

前端 9月月更

Java实现SM3加密和验证

共饮一杯无

Java 9月月更 SM3

保障系统安全

源字节1号

软件开发 信息安全 系统安全

如何实现数据库读一致性

京东科技开发者

数据库 读写锁 事务 MVCC 一致性

什么是架构,什么是架构师?

源字节1号

软件开发 软件架构

视频直播+小程序,打破物理空间的电商卖货时代!

Speedoooo

小程序 小程序生态 直播带货 电商营销 小程序容器

从零开始 - 50行代码实现一个Vuex状态管理器

茶无味的一天

JavaScript Vue vuex

大数据ELK(五):Elasticsearch中的核心概念

Lansonli

ELK 9月月更

被裁后半月面试8家公司无果,凭借这份Java面试指南成功入职阿里

Geek_0c76c3

Java spring 程序员 架构 面经

阿里P8手写Spring Cloud Alibaba实战学习手册,架构师养成必备

Geek_0c76c3

Java 数据库 开源 程序员 架构

Javaweb之会话技术

楠羽

技术 笔记 9月月更

如何解决 Angular custom library module 在 ng build 时无法被识别的错误

汪子熙

typescript 前端开发 angular web开发 9月月更

【文本检测与识别-白皮书】第二章:文本检测与识别技术发展历程

合合技术团队

人工智能 文字识别 OCR

三三复制公排互助系统开发技术详情

开发微hkkf5566

小程序化:系统集成行业降本增效的破局思考

Speedoooo

小程序 数字化转型 小程序容器 生态平台

【数据结构与算法】8道链表面试真题超详剖析,带你领略算法思想【附思路、动图、源码】

Dream-Y.ocean

链表 数据结构与算法 9月月更

关于加密数据的模糊查询

知识浅谈

9月月更 加密数据

开发者有话说|用成长治愈所有迷茫

法医

程序员 个人成长

苏州市大数据集团成立!博云成为首批数商代表

BoCloud博云

云计算 数字化 云平台

现代化车企——零束科技DevOps研发数字化体系建设实践

嘉为蓝鲸

#DevOps #研发 #汽车 #科技

易周金融分析 | 银行融资青睐可转债;苏州市手机银行应用活跃人数规模发布

易观分析

金融 银行

docker与gosu

程序员欣宸

Docker 9月月更 gosu

HowTo:Pipy 如何统计关键指标

Flomesh

Service Mesh 服务网格

通过Thread Pool Executor类解析线程池执行任务的核心流程

华为云开发者联盟

后端 开发 企业号九月金秋榜

ShareSDK HarmonyOS集成指南

MobTech袤博科技

sdk HarmonyOS

从零开始 - 40行代码实现一个简单Promise函数

茶无味的一天

JavaScript Promise

极客时间—架构实战营—第九期—模块一作业

阿梁

Dubbo 泛化调用在vivo统一配置系统的应用

vivo互联网技术

dubbo 中间件 配置管理

新来个阿里 P7,仅花 2 小时,撸出一个多线程永动任务,看完直接跪了,真牛逼!

程序知音

Seal 软件供应链防火墙 v0.2 发布,提供依赖项全局洞察

SEAL安全

DevSecOps 开源安全 软件供应链 软件供应链安全 软件供应链防火墙

一张主流编程语言的变迁图,讲清程序员迁移模式_编程语言_apenwarr_InfoQ精选文章