从 Vim 与 IDE 的讨论说起

缘由

十一假期,在家 review 一位朋友的代码,发现不少低级错误。这位朋友是位熟手,用 Vim 四五年了,看她写代码,如行云流水,是种享受。但最后产出的代码,却常常很容易让我发现问题。这种糟糕的经历,在不同的人群里,我碰到过很多很多次。有一个共同点是,容易发现低级问题的代码,经常是用 Vim、EditPlus 等编辑器写出来的。这里面一定有些东西值得思考。

我自己用 Vim 也有八九年了。大概四年前,偶然的一次机会尝试了 IntelliJ IDEA,后来正式的项目代码就首选 IDEA 了。当然也还一直用着 Vim,比如临时编辑一个文件,或者快速修改一个非常明确的 bug,这些场景下,在 console 里直接 vim 编辑,简单快捷,很舒服。然而正式的代码编辑,或比较复杂的重构,我现在会毫不犹豫的切换到 IDE 下操作。IntelliJ IDEA 的 slogan 是 Develop with pleasure,这句话一点也不广告,我真心感受到了这种愉悦、乐趣,不仅仅是编码(coding)阶段,而是整个开发(developing)过程。

为什么会有这么多人坚守在 Vim 阵营呢?我尝试过给身边的人推荐 IDEA,成功率大概在 30% 左右。这是件很有意思的事情,为了写这篇文章,为了收集更多想法,于是我在微博上“不淡定”了:

再次抨击使用 Vim 编写代码的兄弟们,投身 IDE 吧,IntelliJ IDEA、Eclipse、Visual Studio 等等都可以,请别再用上古的神器了。Vim 是冷兵器时代的强者,但现在早就是热兵器时代,甚至是玄幻兵器时代了……

发这条微博时,还挺担心会立刻被人问候祖宗的,不过后来的评论和转发比我预料了好很多很多(程序员们的素质普遍比其他行业的高呀)。为了让讨论更有针对性,我后来又发了几条:

Vim 等文本编辑器粉丝们,经常拿出的论据是:Linux 是用 IDE 写出来的吗?问题是你确认自己是 Linus?还有一个前端界的论据是:写 JavaScript 又不用编译,Vim 足够了。足够个屁呀,正因为 JS 不用编译,才更容易出错,更需要 IDE。前端界里,能把 Vim 用得比 IDE 还好的,我至今还没发现,谁自爆下?

首先抱歉,因为微博字数限制,未能把语境说全。这段话,是针对前端工程师说的,写 C/C++/Lisp 等等的,爱用啥用啥啊,我不懂不评论。但如果写 JavaScript,如果没尝试过 IntelliJ IDEA,我强烈推荐下,学学不会死人的,觉得好就继续用,不好就继续用 Vim 吧,但得用好呀,别搞出 var a = b = 1 来。

好了,微博上的讨论,缘由已经交待清楚,我们进入正题。

前端工程师请留步

这篇讨论是针对前端工程师写的,非前端工程师们,请嘴含微笑,抱着散散步看看风景的心情到此一游就好。

缘由里我有一个很大的疑惑:

前端工程师的代码里,容易发现低级问题的,经常是用 Vim、EditPlus 等编辑器写出来的。这里面一定有些东西值得思考。

因为平时要做不少 code review,上面这个问题对我而言是个不得不去思考的问题。我所在的团队,编辑器一直是百花齐放、各用所爱的。大体上可以分为两个阵营:Vim 和 IDEA(含 WebStorm 等),还有用 ST2 的,不在这里讨论。我的疑惑可以分解为两个问题:

  1. 为什么前端工程师的代码,比较容易出低级问题?
  2. 为什么 Vim 阵营的前端代码,比 IDEA 阵营的更容易出问题?

前端工程师的挑战

进一步聚焦,前端工程师的代码,我们这里就只谈 JavaScript,对于 HTML 和 CSS,道理相同,就不混着说了。

与传统静态语言比如 C、C++ 相比,JavaScript 是门动态语言。在静态语言里,运行之前必须通过 compile,有啥低级错误,一般编译阶段就发现了,所以 Vim、Emacs 等等编辑器,在这些场合没什么弊端,并且能与 CLI 很好的结合在一起,用好了非常强大。这是大部分编辑器论战的结论,我完全同意。

静态语言里,还有一类是 Java、C# 等,这类语言的最佳编辑器是 IDE,有意见的去找 @老赵 讨论,这里就不多说了,呵呵。

动态语言里,Python、Ruby、Lisp、PHP 等等,这里争论就多了。就我了解,Python 和 Lisp 开发者偏好 Vim 或 Emacs,Ruby 的有 TextMate、RubyMine 等等。这类动态语言,在我看来,都还是挺幸福的,因为虽然是动态的,但无论怎么动态,最后还是得编译。这类动态语言的 compiler 都挺严肃的,在开启了错误提示时,有错就会抛错,一丝不苟。因此用什么编辑器,对这些语言来说,更多是个人爱好,不好比较。

JavaScript 也是动态语言,但与 Python 等动态语言有着很大的不一样。Python 的编译器是开发者自己控制的,但 JavaScript 的编译器却是由用户控制的。为了强调,加粗重复一遍:

JavaScript 的编译器不由开发者掌控,而是由用户控制。而且很悲催的是,JavaScript 的编译器很宽容。

编译器由用户控制,意味着我们写代码时要特别小心,要默认兼容。比如,天知道用户是在吃蕃茄还是吃苹果呢,一个典型问题,在苹果(Mac)下没问题但在蕃茄(XP)下有问题的代码:

var STATUS = {
  'fetching': 1,
  'fetched': 2,
  'compiling': 3,
  'compiled': 4,
}

这个问题,在 Vim 写的 JavaScript 代码里,我发现过不下 20 次(实际次数肯定比这个多),有些甚至是上线后才发现的,因为前端们喜欢在 Chrome / Firefox 等自己选择的 compiler 中写代码。这个问题,稍后再详谈。

再来看后半句:JavaScript 的编译器很宽容。编译器其实都很严谨的,这句话的意思,是说 JavaScript 语言本身的宽容性。比如:

var a = b = 1

上面这段代码,在所有浏览器下都不会报错,一般情况下也不会触发 bug。但这就是个地雷,一旦出了问题,就很诡异,要排查许久才能定位出来。不是我危言耸听,这是一个个真实案例。在淘宝,因为这种低级错误导致的线上 bug,据我所知就出现过 4 次!上面的代码,等价:

var a = 1
window.b = 1

变量 b 是全局共享的,这会导致踩雷的地方,闭包的状态进入非预期,从而有可能产生诡异的问题。

Vim 与 IDEA

前端代码的 compiler 不是由开发者控制的,这个事实,给前端工程师带来了很大挑战。回到刚才的第一个例子:

var STATUS = {
  'fetching': 1,
  'fetched': 2,
  'compiling': 3,
  'compiled': 4,
}

Vim 使用者的解决方案有:

1)、 使用 jslint 。这个问题,jslint 在默认配置下检查不出来。即便能检查出来,我发现实际操作中,Vim 用户也会经常偷懒而不检查。偷懒是人的天性,我鼓励偷懒,但我们还是得想办法避免低级错误。怎么办呢?每次保存时自动运行 jslint?Git 提交代码时自动运行?到集成测试环境时定期检查?有很多很多种方案,但为何我们不能在写代码时就避免掉呢?

2)、 修改编码习惯。比如:

var STATUS = {
  'fetching': 1
  ,'fetched': 2
  ,'compiling': 3
  ,'compiled': 4
}

这的确能解决“手误”了,不过这始终是一个不得已而为之的解决方案,背离了天然本性的写法,迟早会被淘汰(我经常预言失误,但这一条绝不会)。

3)、自己编写 Vim 插件。据我所知,Vim 用户里,会主动给 Vim 编写插件的寥寥无几。如果你通过这个方案来解决,记得将你的插件共享并传播出来,让更多人受益。

好了,再来看 IntelliJ IDEA 的解决方案:

inspection

一图甚千言,不多说什么。估计有 Vim 的超级粉丝会说,通过 Vim 插件也可以做到即时提示。可是,为什么在我接触到的所有 Vim 用户里,从骨灰到小白,都没这么用的?可能还会有 Vimer 争辩:Vim 的哲学不是这样的,Vim 的哲学是让你编码时关注于编码…… 问题是,明显错误的编码也到等到事后不靠谱的插件执行来检查吗?

var a = b = 1 的问题也类似,不赘述。

类似的,还有 HTML 。典型的标签不闭合问题,在 IDE 下你想不闭合都难,但在 Vim 下,我经常看到粗心大意。粗心大意没有错,可为何在 Vim 下会经常忘记检查呢?

别跟我提程序员的素养,偷懒是优良品质,粗心大意是人之常情。在直面人性特征的情况下,至少我们可以通过 IDE 去避免,为何不呢?

保持自己的思考

回到那条倍受争议的微博,我其实是一个无工具论者,从 EmEditor、Visual Studio、FrontPage、Dreamweaver 到 Vim、ST2、IntelliJ IDEA、TextMate 等等,都装过用过。就连写这篇文章的 Markdown 编辑器,我都同时装了 Mou 和 Byword,并且这两款软件我都喜欢。Mou 可以让我在编辑带大量格式的文本时一目了然,Byword 则可以让我在写博客时非常专注、安静。

下面针对一些典型回复,择一二说说我的想法:

这个话题没啥好争论的,顺手的武器才是好武器,好的工具肯定会因人而异。

这代表着一类人的想法,不过武器顺不顺手,你得尝试了才知道。如果你真正尝试过各种工具,然后依旧选择 Vim,我没任何反对意见,这是你的选择。但我见到的实际情况,是很多程序员们,会有很强的先入为主思维,或者尝试也仅仅是浅尝辄止。保持开放的心态,勇于尝试新事物,这是我想表达的。

这有什么好争的?决定一个程序员是不是牛人,不是看他用什么工具,而是看他写出来了什么程序。

同意。不过选刀不误砍柴功。对于前端工程师,由于编译器是由用户决定的,以及 JavaScript 的宽容性,选用什么样的工具还是蛮重要的。一个优秀的程序员,绝不会忽视自己所用的工具。

IDE 很像“记住密码”这个功能,用起来很爽,用多了密码就忘了。

这个回复是非常有意思的。不过从产品的角度讲,我们真需要密码么?或许在不久的将来,密码就会像软驱一样成为回忆。

IDE的确提高了编程效率,但同时也抹杀了Coder对底层原理的理解。如果一开始就依赖于IDE那么他对于Coding的理解是停留在逻辑层而难以深入对内存、操作指令、编译链接。用valgrind gdb这些debugger同样提高作为一个coder的素养。总而言之,coder必须熟知这些神器但真正搞开发依然更倾向于IDE了。

对于 C、C++ 等程序员而言,上面这段话也许有道理。但对前端来说,不是这样。反而 IDE 可以让前端工程师了解到一些自己忽视的东西,比如认真去关注 JavaScript Inspections,很多细节受益匪浅。用 IDE 的过程,也是一个学习的过程。各种提示一开始会很烦,但当你认真去对待去定制提示时,提升和成长就在里面。

你切西瓜用火枪么?

这个回答挺好,切西瓜用刀就好,但你想切一辈子西瓜吗?

我知道这些编辑器的优点,很强大,精通后无敌。关键是我不想一天换4个编辑器来完成工作。我需要的是一款跨平台,能在DOS/Windows NT/Linix/BSD/Android/iOS,CLI或GUI上都能用,而且不仅仅可以编辑程序,也能编辑文本、LaTeX或者二进制文件的跨平台编辑器。

为什么要找通杀的神器呢?

好像很多程序员喜欢把自己的个人喜好强加给别人,像一个喜欢吃榴莲的人滔滔不绝跟人说榴莲的营养价值,要世上所有人都喜欢才罢休。虽然看这些争论可以得到一些知识,但还是感觉很蛋疼。

我从来不把个人喜好强加于别人,但对个人反感的东西,不说不舒服。用 Vim 的,太多装 B 的了(当然也有不装 B 的,用得非常帅气的,可惜好少好少),而且很多甚至不知道自己在装逼,看不惯这种现象。

vim用的熟练的话,效率的确比ide要高,毕竟ide要鼠标移来移去

又是一个误解,谁说用 IDE 就要用鼠标?IntelliJ IDEA 的一大亮点就是全键盘操作,非常爽。在我接触到的人里,用 IDE 的大都会用 Vim,但会用 Vim 的经常对 IDE 充满着各种臆测和误解。

长期依赖IDE,提高水平不太容易哦

这个是我极力反对的,长期依赖 Vim,提高水平才难。因为老忙于修改那些低级或晦涩的 bug 去了。用 IDE 的话,可以把你从低级问题中释放出来,有更多的时间去思考代码本身。

没错,一定要keep open mind,我现在也在用sublime text。

嗯,Open your mind 是我一直提倡并奉行的,无论是前端类库还是编辑器。我抨击的是那些还没了解 IDE 就拒绝尝试的人,拿着 Vim 就以为看到了所有天空的人,殊不知很多 Vim fans 看到的很可能只是一口井。

我挺想看看 @玉伯也叫射雕 用IntelliJ IDEA到底有多帅,能截个视频么?

很抱歉呀,我用 IDEA 就像老年痴呆一样,经常需要停下来在用笔在纸上画画。流不流畅,在脑而不在于手。另外,编辑器这种工具从来就不会影响程序员的效率,只会影响码农的。对程序员来说,效率不在写代码上,而在写代码之外。

思考过程就是结论

编辑器论战,永远不会有定论,关键是思考。就如生活在中国,千万不要不小心习惯了这种闰土一般的生活。保持开放,不受各种权威的羁绊,随时准备好去接受、去怀疑,并对所有的可能性敞开。我喜欢并欣赏这种心态,这是我们的初心、本性。

就如之前激烈讨论过的分号一样。你可以不 care,但如果你 care,你就有可能创造出 LESS、Stylus、CoffeeScript 等新事物出来。创新往往来自细节,然后走很远很远。如果你第一步都不愿意尝试,你就等待别人做好,然后推广给你用吧。

开放、自由、好奇心、勇于尝试,只要在这些点上让你能有所思考有所行动,而不是仅仅说一句无所谓或脑残之类的评论,那么我写这么多就值当了,甚至你可以继续用 Vim,而丝毫不去看看 IntelliJ IDEA 是什么。