正文
我们努力避免 bug 不是说我们重视正确性,而是
我们的客户
重视正确性。如果你曾经遇到过一个 bug 成为了一个特性的话,那么你就知道我在说什么了。这个 bug 确实存在,但是我们不会去修复。出现这种情况并不是说我们的目的就是制造 bug,我们的目的是创造价值。但是如果我们的 bug 能够使客户开心,能够提升他们的收益,我们也能达成我们的目标,如此皆大欢喜,何乐而不为呢。
可重复使用的太空火箭、自动驾驶汽车、机器人、AI:这些东西之所以存在,并不是因为我们觉得它们很酷,而是因为在它们的背后有商业利益存在。我并不是说这些东西背后的那群人只在乎金钱,我确定他们也认为这东西很酷,但事实是,如果没有经济利益或者说没有潜在的经济价值,这些东西是不会存在的。
也许我不应该将这一章节取名为“我们行业的真相 101”,也许应该取名为“资本主义真相 101”。
说到我们的目标——减少支出提升收益——我认为作为程序员的我们应该更加关注需求和设计,积极思考,积极参与业务决策,这就是为什么了解我们正在开展的问题领域变得极其重要。之前你有多少次在你的经理或商务人士没有考虑到的某些边缘案例中想到应该发生什么?
1975 年,Boehm 做过一项研究,研究发现,软件中 64% 的错误都是由设计引起的,只有 36% 的错误是代码错误。另一项叫做 “高阶软件——软件定义方法论” 的研究也显示:
在 NASA 的阿波罗计划中,73% 的错误都是设计错误
。
设计和需求存在的唯一目的就是定义我们将要解决的问题,而解决问题就能创造收益。
没有了需求或设计,编程就是往一个空的 text 文件里面添加 bug。—— Louis Srygley
这个原则同样适用于 JavaScript 生态系统的工具。Babel、webpack、react、Redux、Mocha、Chai、Typescript,所有这些工具之所以存在就是为了解决对应的问题,我们要理解它们要解决的是什么问题,要仔细思考什么时候需要这些工具,否则,我们就会感到 JS 疲劳,因为:
当我们使用我们不需要的工具来解决根本就不存在的问题的时候,JS 疲劳就出现了。
正如 Donald Knuth 曾今说的:“过早优化是万恶之源”。请记着,软件的存在是为了解决相应的业务问题,大部分的软件其实都挺令人厌烦的,既没有多强的扩展性,也没有高性能约束。要专注于解决业务问题,专注于减少支出、提升收益,这才是需要关注的焦点。只有在当你需要优化的时候才去优化,否则,软件可能会增加一些不必要的复杂性,而这些复杂性会增加支出,并且不能产生足够的收益来抵消这些支出。
这就是为什么我认为应该在我们的工作当中应用 测试驱动开发 原则。我说的测试驱动开发并不是说仅仅去做测试。
我说的是在问题暴露之前将其扼杀在摇篮里。这才是 TDD 要做的
。正如 Kent Beck 说的“TDD 减少了恐惧”,因为它能够指导你的开发节奏,允许你慢慢地逐步解决你的问题,一步一个脚印,一次解决一个问题。当我们要使用新的技术时,这样做同样也会减少恐惧。
一次解决一个问题同时也降低了 分析麻痹,举个栗子,就好比你打开了 Netflix,你本可以看一些视频的,但是却花了三个小时来决定看什么。一次解决一个问题的方式可以缩小我们做决定的范围,缩小了做决定的范围我们的选择就会相对减少,选择减少了我们就降低了分析麻痹。
不知道你有木有想过,如果只有几个可看的电视频道,决定看哪个频道会变得多么简单?如果家里只有几张游戏盘,决定玩儿哪个游戏会变得多么简单?
那么对于 JavaScript 而言呢?
截止到我写这篇文章时,NPM 上有 489,989 个包,第二天将会有差不多 515 个包在上面发布。
我们使用、抱怨的这些包都是有一个历史出发点的的,为了理解我们为什么需要这些包,我们必须理解这个历史出发点:
它们是用来解决问题的。
Babel、Dart、CoffeeScript 和其他转义器之所以会出现,是因为我们不仅仅使用 JavaScript 写代码,但是我们又想使其能够在浏览器中正常运行。Babel 甚至能够使我们使用 JavaScript 新版本语法写的代码在旧版本浏览器中运行,因为众所周知,不同版本的 ECMA 规范在各个浏览器中的兼容是一个很大的问题。尽管现在 ECMA 规范已经越来越可靠,但是我们仍然需要 Babel。如果你想了解更多关于 Babel 的相关知识,我强烈推荐你读读 这篇由 Henry Zhu 写的很赞的文章。
像 Webpack 和 Browserify 这样的模块化打包工具也有它们存在的理由。想必你们依然记得,曾几何时,我们使用大量的
script
标签将脚本引入使其能够正常运行。这样做的结果就是污染了全局命名空间,当一个脚本依赖另一个脚本时,很难合理地将它们整合起来。为了解决这个问题,
Require.js
诞生了,但是它仍然有它自己的问题:它不够简单,语法也会引起其他问题,正如你在这篇文章中看到的。然后 Node.js 借鉴了
CommonJS
的 import,这种 import 是同步的,简单整洁,但是我们仍然需要一种可以在浏览器中运行的方式,这就是为什么我们需要 Webpack 和 Browserify 的原因。