发布于 2026-01-06 1 阅读
0

谁杀死了 Tab?

谁杀死了 Tab?

是的……我就是要说这个。我知道我不应该说。我知道这是软件开发领域最不理性、最随意的话题之一。但自从我开始写博客以来,这个问题就一直萦绕在我的脑海里,迟早都会爆发出来。

不是一篇关于空格或制表符是否值得使用的论文。我也不是试图改变你在这个极具争议的话题上的看法。(我从痛苦的经验中得知,在这个问题上,没有人能改变自己的想法。)相反,我真诚地尝试弄明白:我们是如何走到这一步的


替代文字

一些轶事历史

我并不认为我对历史的看法会与对同一历史的看法完全一致。但我可以自信地说,我对历史的视角往往比大多数同事更长远。因为在这个行业,年近五十通常意味着你比大多数同事年长10到15岁。所以……以下是我(略显老派的)对此的看法:

虽然我在 80 年代就编写了我的第一个程序(用的是一台带磁带驱动器的GW-BASICColeco Adam电脑),但直到 90 年代后期,我才真正成为一名职业意义上的“程序员”。1997 年,我拥有了自己的第一个网络公司。直到 2001 年,我才真正开始从外部雇主那里获得报酬。但早在 1997 年,我就开始编写代码,每周工作时间超过 40 小时。

那时候,我所知道的开发人员只有两种类型,分别是:

  1. 专业人士通常只用几种语言中的一种编写代码:C、C++ 或 Java。(真正的“老前辈”用 COBOL 编写代码。)他们花费大量时间争论内存管理、指针和垃圾回收。据我所知,他们每个人都使用制表符

  2. 其他人,包括在互联网萌芽时期写作的所有人。那时还没有“JavaScript 开发者”这个概念,但肯定有一些更“硬核”的开发者在用 Perl。后来,PHP 催生了一个完整的生态系统,其中充斥着被“专业人士”嘲讽为“脚本小子”的人。但据我所知,所有 Perl/PHP 开发者都使用制表符

虽然我从事开​​发工作(自由职业)已有数年,但直到 2001 年才正式进入企业 IT 领域。由于一些奇特的因素,从 2001 年到 2007 年,我编写了大量的 ColdFusion 代码。(我并不为此感到特别自豪——但它足以维持生计,也让我积累了简历。)在我工作的 ColdFusion 开发团队(最多时有 90 名开发人员)中,我们都使用标签页

在某个神奇的时刻,JavaScript 终于发展成为它自己的“产物”。而当它做到这一点时,它显然是从 Brendan Eich 的脑海中诞生的,其唯一目的就是:彻底消除标签页。

我大概直到 2012 年左右才开始认真学习 JavaScript。那时,我已经意识到我的开发方式中存在一些过时的“问题”。即使在 2012 年,我也清楚地认识到,我偏好的标签页布局方式与其他固执己见的开发者产生了冲突。

但我当时很困惑——真的非常困惑。为什么一夜之间,缩进的“标准”就完全变了?而且这种改变竟然让全世界的开发者都群情激愤,恨不得举起干草叉和火把抗议!我完全无法理解。事实上……直到现在我仍然无法理解。


替代文字

语言难题

如果整个编程社区都一致认为“制表符不好,空格好”,那我或许更容易接受这种范式转变。如果你从事开发工作足够久,就会明白这种事情时有发生。标准会演变,“最佳实践”也会涌现。有时候……你用了多年的方法现在却被视为反模式。而且大多数情况下,这……也没什么大不了的。我理解

但就我所知,“空格取代制表符”的风潮远未普及。事实上,它似乎尤其根深蒂固于前端语言中。我当然可以只指出 JavaScript,但我认为它的普遍性远不止于此。

我觉得大多数“太空迷”都专注于前端技术。(很多前端技术都基于JS,但并非全部。)而大多数“标签页迷”则更专注于一些老派的、编译型的、类似后端的技术。

几年前,我曾在一家大型健康保险结算中心工作。他们有很多后端Java代码——我负责维护这些代码。他们也有很多前端JS代码——我也负责维护这些代码。

前端(JS)代码毫无疑问地始终使用空格缩进。后端(Java)代码毫无疑问地始终使用制表符缩进。也许你觉得这没什么“奇怪”的。也许你会点头表示赞同,“是啊……那又怎样??” 但对我来说,这简直……太随意了。

我的意思是,如果制表符真的被认为是“不好的”,那么为什么在我们的 Java 代码中仍然可以接受它们呢?(使用现代 IDE,只需几分钟就能转换整个代码库。)而且,如果更老旧、更稳定、“工业级”的 Java 代码使用制表符完全没问题,那么为什么在我们的 JS 代码中,空格作为默认选择就显得如此理所当然呢?

我越深入研究这个问题,就越感到困惑:在一种语言中,制表符似乎天生就是邪恶的;然而在另一种语言中,制表符不仅可以接受,而且还是标准用法

或许这个比喻不太恰当。但在我使用过的几乎所有面向对象编程语言中,过去十年左右的时间里都出现了一种趋势,即倾向于使用组合而非继承。这种趋势并非Java、C#或其他任何面向对象编程语言所独有

在 Java 中我们不提倡组合优于继承,在 C# 中也不提倡继承优于组合。如果你相信组合优于继承,那就应该在所有地方都使用它。这是程序员普遍接受的设计原则——无论你使用哪种面向对象编程语言。

但说到由来已久、备受争议的制表符与空格之争,最终似乎取决于语言标准和流行趋势。仿佛在一种语言中,制表符完全合理,但在另一种语言中却令人难以接受。

但是,我最终还是回到了我的核心问题:我们是怎么走到这一步的


替代文字

小额规则律师

有一段时间,我看到一些为空格优于制表符辩护的荒谬论点,感到非常沮丧。其中一些不成熟的观点包括:

  1. 效率——你可能看过一些这样的短片:一个程序员SPACE为了缩进代码,不停地按缩进条,而另一个程序员只按TabTAB键。最后,他们开始争吵,甚至摔家具、摔门。但事实是:我认识的人里,没人真的会用SPACE缩进条来缩进。每次我看其他开发者写代码,他们都只用TabTAB键。他们只是把IDE设置成每次按Tab键就插入一定数量的空格TAB。所以,“空格党”和“Tab键党”敲击的键数其实是一样的。(但是“空格党”坚信Tab键是邪恶的——尽管他们自己也一直用TABTab键。嗯……)

  2. 内存/带宽——在过去的二十年里,集成开发环境(IDE)和源代码控制系统几乎都能自动去除尾随空格。它们也能够存储连续字符,而无需为序列中的每个字符分配内存。因此,我实在无法理解,在这个时代,怎么会有人一本正经地认为这两种方法都会造成内存/带宽“问题”。

  3. 一致性——“空格控”每次都用固定数量的空格缩进代码块。嵌套代码块用 `\n` 表示indentSpaces = nestedLayers x standardSpacesPerIndent。这很一致。“制表符控”每次都用一个制表符缩进代码块。嵌套代码块用 `\n` 表示indentTabs = nestedLayers。这也很一致

我可以继续列举一大堆用来支持某一方观点的武断论据。但关键在于,这些论据似乎都无法真正说明人们为什么偏爱其中一方而非另一方。人们抛出这些站不住脚的论点——但很明显,他们实际上是在为自己的偏好辩护

到目前为止,我还没有听到任何人就这场辩论提出过任何基于经验且逻辑自洽的论据。当我意识到这场“圣战”双方所有所谓的“逻辑”论据实际上都……不合逻辑时,我开始从更广泛的层面寻找影响因素来解释这种转变。


替代文字

邪恶公司

有一段时间,我把这场分裂的圣战归咎于邪恶的公司。具体来说,我把矛头指向了Airbnb和谷歌。更确切地说,我抨击了他们无处不在的风格指南。这些风格指南规定(除其他事项外):

  1. 只能使用空格缩进。

  2. 缩进应为两个空格,且只能是两个空格。

此时,我或许应该坦白一个关键点。如果你想通过引诱我动手打你来让我丢掉工作,最有效的方法可能是告诉我:“ Airbnb 的风格指南上说我们应该……”或者“谷歌的风格指南上说我们应该……”

我倒不是对风格指南本身有什么意见。如果选择的是Airbnb风格指南或者谷歌风格指南,那……太好了!就用它吧!标准几乎总是好事

真正不能接受的是,一些原本很聪明的程序员放弃理性思考,把批判性思维的主导权拱手让给某些模糊不清的“标准”。我理解你可能懒得去仔细研究Airbnb/谷歌风格指南里的每个细节。但如果你做事的唯一理由仅仅是:“风格指南里就是这么写的”,那……你最好还是学学怎么自己系鞋带,动动脑筋吧。

我确信我在这里有点夸张了,但在 2010 年代中期的一段时间里,我真的感觉 JavaScript 中几乎所有关于美学编码的决策最终都会简化为“嗯,风格指南说我们应该这样做……”。如果有人设法黑掉了 Airbnb 风格指南网站,并插入一条规则,规定每隔一行代码都必须是注释,内容为:// fnord!!!,那么几周之内我们就会在生产代码中看到这些注释了。

唉,尽管我这老顽固总爱跟体制较劲,最终还是意识到空格和制表符之争早在 Airbnb/Google 风格指南发布之前就已存在。人们很容易把两个空格的缩进格式归咎于他们。但如果认为这场争论是他们发起的,或者说他们解决了这个问题,那就大错特错了。他们只是把早已在许多开发者社区中酝酿已久的讨论,用(数字)文字记录了下来而已。

如果我们不能把这场圣战归咎于邪恶的大企业恶霸,那么我们该如何解释这场无休止、无定形的争论的兴起呢?


替代文字

对抗混乱

当我把关注点从Airbnb或谷歌这些容易被诟病的“恶魔”转移到更广阔的领域时,我开始思考互联网的本质,以及JavaScript的成长历程和它迅速普及的方式。

还记得我之前说过,在我们上一份工作中,我们所有的 Java 代码都使用制表符吗?嗯……公司里几乎所有人都用 Eclipse 作为 IDE。你猜猜安装 Eclipse 后默认的缩进格式是什么?

C# 几乎总是使用 4 个空格的缩进。这与我们在 Eclipse 中看到的默认缩进截然不同。事实上,它与其他许多语言的缩进方式也大相径庭。但为什么 C# 会采用 4 个空格的缩进呢?原因在于……绝大多数 C# 代码都是在 Visual Studio 中编写的。(我们或许可以稍微提及一下 VS Code 的日益普及。但事实是,“老牌”的 Visual Studio 仍然是几乎所有专业开发团队编写 C# 代码的首选。)你猜猜安装 Visual Studio 时默认的缩进是多少?

现在我们来谈谈 JavaScript。尽管出现了几个主流平台(例如 VS Code),但从来没有一个“默认”的 JS 开发 IDE。现在依然如此。你公司里的开发人员可能都使用某个特定的工具,但世界各地的 JS 开发人员仍然使用各种截然不同的 IDE 来完成他们的工作。而且,每个 IDE 都有其独特的默认设置。

正如我将要解释的,我认为 Web(JS)开发的“混乱”和分布式特性并不能完全解释强制所有人使用两个空格缩进的趋势。但我认为这是一个很好的切入点。从 JS 语言诞生之初,就没有“默认”的 IDE 用于 JS 开发。因此,也没有默认的缩进设置。

但事情远不止如此。混乱或许可以解释早期 JavaScript 开发中缺乏标准,但却无法解释为何新标准会被如此严厉地强制执行。



替代文字

合作滋生从众心理

JavaScript 于 1995 年首次发布。我记得在 1995 年,没有争论过制表符和空格哪个更好。尤其不记得当时有任何关于 JavaScript 的此类讨论。

这很容易解释。在 JavaScript 诞生的最初十年左右,实际上并没有真正意义上的“专业”JavaScript 开发者。在它诞生的头十年里,自称“JavaScript 开发者”就好比自称“建筑师——专门在 Second Life 里建造虚拟房屋”。JavaScript 当时只是个玩具。它很少被用于“真正的”开发项目中,即使被用到,通常也是由某个与大型开发团队无关的孤胆开发者编写的。

这些限制在 2006 年开始逐渐消失。那一年 jQuery 发布了。诚然,在 2006 年,开发者们并没有蜂拥而至地拥抱 JavaScript。但 jQuery 的发布标志着 JavaScript 快速发展的开端——“JavaScript 开发者”从一个人们私下里的玩笑,变成了一条成熟的职业道路。

这一切跟制表符和空格有什么关系呢?嗯……问得好。

当你独自编写代码,使用自己选择的开发工具时,没人会在意你的代码缩进方式。说真的……如果你只是自己编写代码,甚至缩进与否都无关紧要。当你特立独行时,你想做什么就做什么。

但随着 jQuery 开始真正流行起来(我姑且把这个时间定在 2008 年),JS 社区出现了一种全新的现象。我们开始看到专业的JS 开发团队一起工作和协作。虽然这对于 Java 开发者来说并不新鲜,但对于所有那些 JS小白来说,这却是一个全新的发展

你可以把100个天才天才分别关进100个不同的山洞,让他们各自编写100套不同的代码库。既然他们都是天才,你当然可以假设他们写的代码都很精彩,甚至具有革命性。但这并不意味着这些代码会保持一致,甚至彼此兼容

即使是那些“疯狂的天才”,如果你强迫他们分享代码以便合作开发,也肯定会遇到一些问题。这就像让100位音乐新秀创作100首歌一样。她们可能都很优秀,但合在一起肯定不好看

所以,我猜想,当公司开始组建“真正”的开发团队时,新兴的 JavaScript 社区肯定遇到了不少难题。所有 C# 程序员都已经在使用 4 个空格缩进,所有 Java 程序员都已经在使用制表符。但是所有 JavaScript 程序员呢?嗯……他们却在使用……一大堆不同的方法。当所有这些“方法”都被提交到同一个项目中时,就会造成混乱。而混乱与协作是水火不容的


替代文字

为什么是两个空格???

如果你接受我上面的前提,这就解释了为什么JavaScript 社区觉得有必要制定某种缩进标准。世界各地的 JavaScript 开发者都在使用各种各样的工具,这些工具的默认设置也各不相同。没有人对“正确”的缩进方式有一个统一的认识。一旦开始协作编写代码,情况就会变得……一团糟。

但这并没有具体解释为什么最终是两个空格。不是四个空格,也不是制表符,而是两个空格。我的读者(或者其中任何一位)可以纠正我,但我不知道还有哪门语言采用两个空格作为事实上的标准。那么,为什么 JavaScript 会采用两个空格作为事实上的标准呢?

我要把罪责归咎于 Git,而不是 jQuery。Git发布于 2005 年,也就是说,它比 jQuery 早发布不久。对于 Web/开源社区而言,它迅速成为团队代码协作的首选解决方案。

但我更关注GitHub而不是Git。你看,Git本质只是一个命令行工具。(没错……现在它也有各种图形界面——但它的大部分时间里,几乎都是一个纯粹的命令行工具。)当你使用这个命令行工具时,你可能不会太在意哪些文件使用2个缩进空格,哪些使用4个缩进空格,哪些使用制表符。你只是祈祷不会出现合并冲突。

然而, GitHub完全是另一回事……

GitHub 是最早让分布式团队能够轻松浏览其他成员代码及其分支的工具之一,它就像一个永不关闭的窗口,我们现在都称之为“浏览器”。当时可能还有其他一些源代码控制工具也允许用户在网页上浏览他人的代码,但我并不了解。GitHub 是我记忆中第一次登录基于Web 的门户网站并浏览提交记录。

GitHub 于 2008 年发布。换句话说,当 GitHub 开始在数字精英中迅速发展时,jQuery 已经如火如荼地发展起来,真正的、货真价实的专业 JS 开发团队也开始通过网络进行协作。

为什么我会把 GitHub 的崛起与 2 个空格缩进的实现联系起来呢?嗯……你有没有看过 GitHub 上用制表符缩进的代码文件?作为一个基于 Web 的客户端,GitHub 使用的是 HTML 中制表符的默认表示方式。换句话说,GitHub 一直把制表符显示为占用8 个空格

此外,由于许多人过去(现在仍然)在相对狭窄的视口中编写 JavaScript 代码,我认为他们自然而然地会感到压力,希望代码尽可能“精简”。在宽度受限的网页门户中,即使是像 4 个空格缩进这样简单的操作也会让人觉得多余。

没人喜欢横向滚动。而且,网页经常被挤进狭窄的视口里。所以,从这个角度来看,作为 Web 的子民,JS 社区围绕着 2 个空格的缩进标准达成共识,似乎也顺理成章。

需要说明的是,我并不是要你同意我的观点。我非常希望有人能“纠正”我的错误。但就我所知,我真心认为,GitHub 比其他任何因素都更应该为如今在众多 JS 项目中看到的 2 个空格缩进标准的出现负责。



替代文字

2-空间挫败感

尽管我出了名的脾气古怪,像个老顽固,但事实上,我并不会为了制表符和空格哪个更好而夜不能寐、咬牙切齿。如果你还没看出来,我其实更喜欢用制表符。但没人真正在乎我的喜好。我理解这一点。所以大多数时候,在大多数项目中,我都会让editorconfig文件自动决定代码的格式——然后继续工作。

但这是我的博客。我的读者(他们俩)理应享受我抱怨和牢骚的乐趣。所以,仅供参考,我最后想指出一些关于两空格缩进标准的问题,这些问题常常让我忍不住想说出来。

可访问性
哦,天哪……我真不想解释清楚,因为这正好证明我老了。但我看的 JavaScript 代码越多,就越清楚地意识到这两个例子并不相同



// Example 1
const doSomething = (trials = 0) => {
  for (let i = 0; i < trials; i++) {
    const data = getTrialData(trial);
    if (data.length) {
      const filteredData = data.filter(datum => {
        return getConstant(datum.someProperty);
      });
    }
  }
}

// Example 2
const doSomething = (trials = 0) => {
   for (let i = 0; i < trials; i++) {
      const data = getTrialData(trial);
      if (data.length) {
         const filteredData = data.filter(datum => {
            return getConstant(datum.someProperty);
         });
      }
   }
}


Enter fullscreen mode Exit fullscreen mode

仔细观察这些示例,你会很快发现它们在功能上没有任何区别。它们的代码完全相同。示例 1 和示例 2 的唯一区别在于,示例 2 缩进了3 个空格,而示例 1 只缩进了2 个空格

这有什么关系呢?

嗯……可能对你来说并非如此。遗憾的是,我可以非常肯定地告诉你,相比例2,例1中的嵌套逻辑对我来说更难理解。

我已经尝试过上千次了。我在IDE里调整过上千种不同的设置。但无论我怎么调整,有时我的眼睛还是会“迷失”在试图追踪嵌套的2个空格缩进中。

当我接触使用制表符的代码库时,这从来都不是问题。因为我可以自定义 IDE 设置,让制表符以我感觉舒适的任何宽度显示。但是,当文件使用 2 个空格缩进时,我就只能完全相同的方式查看它。而且,我也只能无奈地花更多时间阅读和理解代码。

来说,缩进中多留一个空格真的能让阅读变得轻松很多。可惜的是,那些想强制我们所有人使用两个空格缩进的“当权者”根本不在乎。事实上,当我试图向同事解释这一点时,他们中的不少人甚至直接对我不屑一顾,甚至出言不逊。

过时的比较
当我愚蠢地和别人讨论制表符和空格的区别时,我数不清多少次遇到这种(完全过时的)观点:制表符看起来很糟糕。换句话说,他们潜意识里仍然停留在浏览器默认的制表符渲染方式上(比如,在 GitHub 浏览器窗口中查看代码时)。

尽管他们声称制表符在视觉上难以辨认,但他们却无法向我展示这些制表符在他们的屏幕上看起来究竟有多糟糕。这是因为他们是在集成开发环境(IDE)中查看代码——而他们的IDE并不会将制表符显示为占用8个空格。

事实上,多年来我注意到,几乎所有的代码阅读都是在开发人员的个人屏幕上,也就是他们的集成开发环境(IDE)中进行的。换句话说,他们几乎看不到用8个空格表示的制表符。但他们似乎仍然对如果选择在浏览器窗口中查看代码可能发生的事情抱有某种根深蒂固的抵触情绪。

工具无知
我知道在 GitHub 上,混用制表符和空格曾经会造成严重问题。具体来说,它会让你陷入合并冲突的泥潭。但我注意到,令人震惊的是,现在很多开发者对 Git 的内部运作机制一无所知。他们似乎认为任何空格的改动都会导致合并冲突,或者会搞砸他们的代码审查。当然,这些开发者通常也会错误地描述 Git目前的功能。

几年前,我和一个十足的吹毛求疵、极其讨厌的家伙共事。我提交了一个拉取请求(针对他根本不会的那段代码),结果他拒绝了

我犯了什么错?文件里有制表符。他(真的)举起双手,说:“我没法审查这个。因为差异比较器认为你把文件里的每一行都改了。”

我回复他:“差异显示,在你设置忽略空格之后,我修改了文件里的每一行???”他看着我,眼神里充满了恼怒、困惑和无奈。说实话,我觉得他应该是第一次意识到GitHub里还有这种选项。

但问题其实与 GitHub 的“忽略空格”选项无关。问题完全在于我的代码里有个制表符——他要给我点教训。

Stack Overflow 的诅咒
如今,我们都已看过相关报道。几年前,Stack Overflow 在进行一项面向全体开发者的广泛调查时,“发现”使用空格的开发者比使用制表符的开发者收入更高。

说实话,那项“研究”给我带来的麻烦远超他们的想象。突然间,每个以前用空格的毛头小子都能一副自以为是、高人一等的表情看着我说:“你知道吗……用空格的开发人员工资更高。”

问题是,这些自以为是的人根本说不出他们为什么薪水更高。他们只想当然地认为,仅仅在工作中使用空格而不是制表符就能提升你的价值。

过去十年左右,前端开发(曾经被认为“次要”的领域)在许多就业市场中已跃居前沿,这一点却鲜有人关注。而且,由于 JavaScript 早已将空格缩进作为标准,前端开发人员的薪酬更高也就不足为奇了。

他们收入更高并非因为使用空格缩进,而是因为他们掌握了一项市场需求更高的技能——这项技能恰好围绕着空格缩进而形成。但千万别试图向那些对双空格缩进顶礼膜拜的马屁精解释这一点……


替代文字

结论

最后,我认为这篇文章其实与制表符、空格其他任何缩进标准都无关。我真正感兴趣的是趋势如何萌芽、发展、扩散,以及最终如何成为“标准”——即便有时并没有实证依据。

我明白(我真的明白),有时候,你只需要选择一个“标准”——任何标准都行。因为这总比没有标准要好。但在这个行业摸爬滚打了四分之一世纪,我仍然会因为某些标准被随意采纳,而另一些标准却被草率抛弃而感到沮丧。

文章来源:https://dev.to/bytebodger/who-killed-the-tab-5287