正文
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 的原因。
Webpack 确实解决了很多问题,比如可以像处理 JavaScript 依赖那样处理 CSS、图片和许多其他的资源。
前端框架确实有点复杂,但是由于它们的存在,使得我们写代码时减少了同步加载,如此一来,我们就不必担心 DOM 操作,甚至也不用和那些乱七八糟的浏览器 API(JQuery 已经解决了这个问题)直接打交道,众所周知,浏览器的兼容性处理错误百出,而且效率低下。