精华 我不是很懂 Node.js 社区的 DRY 文化
发布于 6 个月前 作者 FrankFang 6640 次浏览 来自 分享

我去掉吐槽,重新写了一篇:请 Node.js 社区正面回答

原文在知乎,欢迎交(tu)流(cao)

我终于知道为什么 npm install 总是动不动就下载 300 Mb 的东西了,Node.js 社区强调的 DRY 文化使得 node_modules 臃肿不堪,因为有的库引用了 is-object,有的库引用了 isobject,还有的库引用了 isObject,每个包看起来很 DRY,但是合起来就 wet 得不行了,呵呵。

我一直以为 npm 里下载量较大的 package 是 React 这样不错的包。

今天我才知道我错了。

目前 React 每周下载量是 240 万次。

然而下面我要说的几个包的下载量全都大于 React !


is-odd,每周下载 300 万次

源代码如下:

'use strict';

var isNumber = require('is-number');

module.exports = function isOdd(i) {
  if (!isNumber(i)) {
    throw new TypeError('is-odd expects a number.');
  }
  if (Number(i) !== Math.floor(i)) {
    throw new RangeError('is-odd expects an integer.');
  }
  return !!(~~i & 1);
};

你没有看错,五行核心代码,还依赖了一个 is-number 库。


这个 is-number 库更厉害,每周下载 1000 万次

源代码如下:

'use strict';

module.exports = function isNumber(num) {
  var number = +num;

  if ((number - number) !== 0) {
    // Discard Infinity and NaN
    return false;
  }

  if (number === num) {
    return true;
  }

  if (typeof num === 'string') {
    // String parsed, both a non-empty whitespace string and an empty string
    // will have been coerced to 0\. If 0 trim the string and see if its empty.
    if (number === 0 && num.trim() === '') {
      return false;
    }
    return true;
  }
  return false;
};

后来我发现这两个库的作者是同一个人(该作者水平很高),这个人还写了另外几个库:

  • is-plain-object,每周下载量 330 万
  • is-primitive,每周下载量 350 万,源代码你自己可以看看
  • isobject,每周下载量 750 万

需要指出的是

  1. webpack、babel 等库都有「间接地」依赖上面的一些包。
  2. 这些包的 markdown 代码远远多于 JS 代码,可能它们的 markdown 更值得我们学习

这件事对我的启发:

  1. 原来有这么多 JS 程序员不会判断奇数
  2. 只要 markdown 写得漂亮,就能迷倒 JS 程序员
  3. 1 + ‘1’ 的问题一直在困扰 JS 程序员,我要不要写一个 add() 库解决这个问题呢

我终于知道为什么 npm install 总是动不动就下载 300 Mb 的东西了,Node.js 社区强调的 DRY 文化使得 node_modules 臃肿不堪,因为有的库引用了 is-object,有的库引用了 isobject,还有的库引用了 isObject,每个包看起来很 DRY,但是合起来就 wet 得不行了,呵呵。

Node 社区跟我想得不太一样,说不上好也说不上坏,反正不是很适合我。


以下是扯淡。

我是看到 Medium 上的一篇《混乱又危险的 Node.js 生态》才知道这些的,这篇文章里的一个评论我很赞同:

如果你不能在十秒钟内写出一个判断奇数的函数,要么你是一个糟糕的打字员,要么你就不应该当程序员!

还有一些颇为搞笑的评论:

53 回复

第一次在 CNode 社区发帖,希望不要被喷 : )

@FrankFang 写的挺好,库引用多了不易阅读。 我读代码有这种感受- -。

太自由,发布成本太低,各种链式引用也有些蛋疼

来自酷炫的 CNodeMD

估计很多人都没有考虑过你的问题,你的问题确实挺有意思的,哈哈

来自酷炫的 CNodeMD

把函数发布到npm我觉得没毛病,引用一个包肯定比再写一边函数快,只不过以前npm没有org命名空间,所以只能发布到统一命名空间,发一个少一个,现在好了,如果你想发布一个自己的包,可以创建一个org再发布你想要发布的函数库,比如我创建了一个org:shylog, 然后 is-number 可以发布到 @shylog/is-number 下,这表明这个包是经过我自己检测的,是可信的,再次引用的时候就不会有包的质量担心了

对于链式引用我只想说: 不以成熟稳定的包或库为基础,难道是从零开始的吗?

用这么多库,就是为了提高开发效率

总感觉别人的包靠谱点(自己懒得写)

神仙打架、、

能少引用就少引用

用这种库的都是些什么人

个人实际使用的时候,并没有遇见一个问题就想办法找库,当然也会使用一些比较成熟,功能实用的库,比如 momentaxios 等等。赞同 @shynome

=。= 假如你想,你可以实现一套自己的基础函数库,比如 lodash、ramda,问题是大多数人达不到那个健壮性。而且做重复的事情并不是好事,说到底还是工具而已。我只能说想法比较程序员思维,施主你着象了。

同感。 node模块的设计 当初是借鉴unix单一职责的原则 一个包做一件事 导致现在出现文档、用例等非核心代码远多余核心代码 这增加了node_modules的管理复杂度,以及严重影响了代码阅读效率。 确实值得反思。

@shynome 这个 不错 很棒

可以, 都找到大本营来了.

围观群众对事态发展表示关切和忧虑,呼吁有关各方着眼大局和长远,以和平方式妥善解决有关问题,维护论坛的和平稳定符合各方共同利益

@zengming00 有营养的话题,撕撕不挺好的嘛。

坐等打脸。

markdown 写得漂亮什么样的程序员不能迷倒~ 文档是用来给人提供帮助的,难道“和颜悦色”的告诉一个人一件事儿,使人愉悦是一件有问题的事情咩~ 试问非 js 工程师是宁愿看到“面目狰狞”的文档咩~ 这应该说是一个推广技巧,在几乎垄断的技术下,文档质量再差也得看,况且近年来的新技术新文档不都是往良好阅读体验的方向靠拢,至少没人出来说:“我就要把文档写得只有我自己看得懂” 而在竞争激烈的环境下,靠“表面功夫”脱颖而出,这当时所有人都认可的道理。

经常也有这样的困惑,就是相似的包总有好几个。到底哪一个最靠谱?

A little copying is better than a little dependency.

我终于知道为什么 npm install 总是动不动就下载 300 Mb 的东西了,Node.js 社区强调的 DRY 文化使得 node_modules 臃肿不堪,因为有的库引用了 is-object,有的库引用了 isobject,还有的库引用了 isObject,每个包看起来很 DRY,但是合起来就 wet 得不行了,呵呵。

======== 上面的主题很明确啊,但是下面举的例子不切题。其实你可以直接把这三个包的代码拿出来举例。

这类文章加精是不是有点过了?

2233今天好热闹

@dengnan123 这是只是分战场,知乎上才是热闹

npm的确要改进,javascript语言本身也要改进,有些东西的确要从语言库的层面去解决,这些东西其实大家都心里门清。

撕逼不解决问题,也许我们需要更好的语言,Dart,Typescript,Swift。。。

作为吃瓜群众来说,看了各方的观点和一些评论。 我的看法是: npm 包的自由度,带来了包管理的复杂性,每天的新包,各种质量的包很多,难于区分优势劣汰。 导致问题如下:

  1. 包多了选择困难。
  2. 包多了下载慢。
  3. 非常占存储空间。
  4. 良品中容易掺杂次品。 这些都是客观问题。

npm 自由度带来的好处: 高度自由的市场。从来没有一个代码贡献发布的平台能如此方便和亲民,哪怕你是个小学生都可以写半行代码发布出去。 没错这是个高度自由的市场,哪个包好不好用,市场说了算。 带来的好处不要多,一种就够,生机勃勃无限可能(这就是开源的价值所在)。

对于小颗粒一行代码库的存在,实际上是语言本身有待完善的一个过程 (包裹一个方法,换的名字嘛,代码的本质是什么呢,是一种的表达或描述,好的代码并是更好的描述或表达,名字是很重要的。如果一个一行代码的包存在并广泛使用,那么必定这个名字抽象的很好)。 npm 换句话说,某种程度也是个实验场,如果类似的东西多了,说明javascript 本身需要更迭改进,这个是社区的反馈 (这一反馈是需要有个过程的,理想情况我们想要一个大神把所有这些包办了【出个社区标准包】, 但问题是大神在哪里, 如何做这都是问题【大神们会为了一个判断奇偶的函数,写那么多测试用例,和性能评测吗? 某个大神能超过社区所有人的智慧比拼吗?】)。

综上, npm 现状是一种选择下当前的结果. 楼主提的确实是存在的不足、社区也需要更多的讨论和智慧来解决它。

@FrankFang 没有时间去知乎,工作严重饱和,过来才看到这个,说的也不是完全没有道理,我的观点如下: 1、有些问题是普遍存在的,也不是js独有的,你去问问java程序员有几个会写奇数?语言特质导致了关注点不同,基础不同,不同的语言导致了思维模式不同,C/C++ 程序员估计完美实现,而java 程序员只要@就可以了。。 2、整个社会急功近利,说的不好的,就是拿来主义,能用就用,管他好坏!有个java程序服务的压测始终不过关,后来仔细打磨,重新改了jdbc部分就一切OK了。很多人拿来package 就是用。。也不考虑效能。只不过nodejs 比较年轻,package良莠不齐,比较明显罢了,你觉得其他社区这个问题就不存在吗? 3、文档很重要,非常重要,我认为有时候比程序本身更重要,程序是给人用的。等到哪一天,你遇到一个需要维护的程序,没有文档,没有注释,密密麻麻几千行,程序员离职了,程序在线上跑,你要去改功能。。。。。 4、nodejs 相对年轻,发展过程中,很多package 品质不高,很正常,相对比较自由,所以对程序员约束比较少,对个人的代码修养比较高。很多都要自己选择去使用,很多人不注重执行效能,很多package 其实很坑的,只是相对自由的环境,容易体现,其他程序社区比较规范,不容易表露。。。java 的package大坑一点都不少。。。cpp 奇葩问题。。。。哎。。 5、你的问题,我觉得是缺乏最佳代码实践的引导,导致因为开发者水平良莠不齐,实现方式好坏差异极大。我是没空啊,有闲有心的人可以写个最佳实践指南,支持某些package 就是垃圾,那些是五星级package,那些可以自己实现,那些可以用cpp 插件实现,做功能区分,最佳实践。。。。很多人上传的package其实不知道已经有了比他更加优秀的实现或者其它原因。。。 6、nodejs 就像一个自由市场,我觉得挺好的,你去菜场买菜也可能买到几根烂菜叶呢。大家凭自己水平,该怎么办就怎么办,总体来说,是优秀和不断上升的一个社区开发环境。 简单扯扯,继续去填坑了。

@vellengs

赞同,方老师写的这篇文章,指出的问题是实实在在的,大家工作中都会碰到,也都因此郁闷过,社区本身要经得住不同的声音。现在Javascirpt可能看起来在前端领域占据绝对统治地位,但没准哪天就被革命了,WebAssembly,GraaIVM,Dart等等,这些技术都给出了一些可能性。后端更不要说了,说了必引战。

@cnlile 缺乏最佳实践我很赞同,现在 Node 基本就是瞎写,没有人知道怎么写是好的,怎么写是坏的。所以我这篇文章主要就是讽刺一种坏的思潮:什么函数都搞成一个包。现在这种思潮在 Node 几乎就是主流了。虽然大家没有嘴上说,但是就是这么做的。很多库都不到20 行代码。

其实又回到一个老问题了, JS需不需要一个官方的标准库。 如果有标准库,很多基础函数就可以直接拿来用了。 国外这个问题被讨论过了很多次了,目前的看法依旧是维持JS函数的精简: https://www.infoworld.com/article/3048833/open-source-tools/brendan-eich-javascript-standard-library-will-stay-small.html

@ycczkl 根据现在 ES 每年的新增的 API,ES 是有在更新标准库的。http://2ality.com/2016/02/ecmascript-2017.html 一年才加这么点 API,不知道怎么规划的。这么小的 标准库跟没有差不多,不好用啊。

感觉选包也是系统技能,我一般是:star多,依赖少,还在维护的

[CNodeMD]

感觉选包也是一项技能,我一般是:star多,依赖少,还在维护的

[CNodeMD]

想找輪子 也不是那麼容易的 關鍵詞搜來搜去都不一定找的到對的輪子

常有一些奇怪的名字

is-number 的实现是错的。

搞培训的不要误人子弟了。

我被各种库坑过无数次,有时候一个版本用的好好的,突然就不行了,细查下来,原来是他的依赖包更新了,然后整个系统崩溃了。 有些是这个包的1.x版本有问题,联系作者得到的回复是,我已经升级到3.x,1.x不再维护了,你更新到3.x吧,好吧,我心累,你3.x的各种方法改了一大圈,升级的话,我代码就要重写了,更甚的是,这个1.x也不是我引用的,是我的依赖库引用的,然后崩溃了,我到底还用不用。

思前想后,最终我决定自己建个私有库,有bug能自己改就自己改,有些工具还可以写好放到上面去,对于引用乱的情况,还可以自己手动调整一下各个包的引用关系,虽然烦了点,但至少不用完全被npm限制住。 我用的是verdaccio建的私有库。

@ugrg 如果你写一个库开源给其他人,经过 3 年,你已经升级到了 10.x 版本了,然后有一个远古玩家还在用 0.x 版本,然后找你要你升级支持,尽管你在这 3 年间已经通知无数次升级了,但别人就是不愿意,而且指着你的鼻子说:我不管我不管,谁让你开源的,你要负责到底,就算死了,也要从棺材里面爬出来帮我免费解决。

@atian25 说实在的,大多情况下,我是找到问题,甚至连代码怎么改都改好了,发过去,只是想让他更新一下,发布一个新版本而已,我从来没想着让别人来帮我找bug。 更多的情况是,只要修改一下package里引用的版本号就行了,而且我都是会告诉他应该改成什么样。

现在我已经解脱了,他不改,我自己改,改进我自己的私有库中,对作者,我现在只是通知一声,他爱改不改,我已经不关心了。

@ugrg 我指的是你作为一个类库开发者时候会怎么样

@atian25 我写库会尽量少引用别的库,除非这个库非常独特,我写起来很麻烦。 想 is-object is-number 这种功能我肯定是自己写一些帮助函数。 我只要保证我提供的库 API 通过测试即可。

我现在主要在 Ruby 社区,Ruby 社区的库维护者非常靠谱,很少出现这种情况,非常少。

@FrankFang

什么函数都搞成一个包。现在这种思潮在 Node 几乎就是主流了。虽然大家没有嘴上说,但是就是这么做的。很多库都不到20 行代码。

不赞同这个观点,函数即服务怎么说?

@dayuoba 服务不是包……

作为新人说说我的感受吧。 作为一个年轻的东西,肯定存在一些问题,但是我相信逐步成长的过程中,肯定会有改进的。 有时候想想,正式因为各种的选择,各种的可能,才使得Node或者说js散发出巨大的魅力与无限的可能性,见证一个人的成长甚至提供帮助矫正方向,这是一件多么美妙的事情啊,我相信这也是大部分Noder愿意做的事情,这也是我选择js选择node的原因之一。 并没有否定您说的问题,这也正是我们开发者需要考虑的,也无所谓引战之说。。。

来自酷炫的 CNodeMD

这个挺不错额,正在学习NodeJS

引用别人的模块之前最好先动动脑子,经常看到别人的代码里面引很多很偏门的模块,最终结果就是: 半年或一年之后坑一堆人 所以我的观点是,模块发布者想怎么发我管不着,模块使用者要对结果负责

我用过这个,感觉是挺好用的

不要重复造轮子啊

回到顶部