很多人不理解 NPM 上 Nodejs left-pad 这样的模块的意义

发布于 1周前 作者 gougou168 来自 nodejs/Nestjs

很多人不理解 NPM 上 Nodejs left-pad 这样的模块的意义
给那些也许还不理解 one-line module 意义的人

https://github.com/sindresorhus/ama/issues/10

76 回复

看完还是不太懂


谁简单翻译一下重点?

如果大量的基础函数可以通过外部依赖解决,那么自己的程序的代码行数就可以减少很多,程序员可以专注于发明一些新的不同的东西。

当然,这只是一种假设的、部分实现了的理想情况。

没看太懂。不过之前用过一个库,用来去除字符串中包含颜色信息的特殊字符的,实际上就是一行正则匹配,但是自己写的可能有遗漏,用库的话还有人维护,何乐而不为。

我还是不大理解 left-pad
如 x === 0 && 1 / x === -Infinity 这种行数虽少,但信息量不小,或者包含了大量经验及测试的我没意见
left-pad 的这种,不应该是张嘴吃饭伸手穿衣一样,随手就写的么,难以想象一个写软件的人,尤其是维护这么大的项目的人,不知道如何 pad 一个 string

大概是
你可以專注如何使用小齒輪
理想情況下其他用戶可協助優化
假若小齒輪有一天進化了
各個使用了該小齒輪的專案也可以獲得更新
而不需要自己憑記憶去找出來優化

mark ,支持

模块化本身就是这样啊。。。难道我知道做饭的步骤就一定要自己做饭嘛?

It doesn’t matter if the module is one line or hundreds.

It’s all about containing complexity.

Imagine if PC manufacturers all made their own CPUs.

Before Node.js and npm. I had a large database of code snippets I used to copy-paste into projects when I needed it.

Do you make your own shoes? No, you buy them in a store.

I want programming to be easier.

redefine 专注

It doesn’t matter if the module is one line or hundreds. It’s all about containing complexity.
By making small focused modules you can easily build large complex systems without having to know every single detail of how everything works.

用这个模块的人根本不会关心这个模块是一行还是十行还是一千行,只要用就是了,这样就可以把注意力集中到用这些模块构建大型的、复杂的系统中去

Do you make your own shoes? No, you buy them in a store. Most don’t care how the shoe is made. Just how good it fits.

你会制造自己的鞋子么?不,你只会去商店买鞋子。多数人不关心鞋子是怎么制造的,只关心鞋子合不合脚。

就是老程序员们喜欢说的不要重复造轮子吧

补位呗,如果用过 aes 或者 des 加密应该知道

你们都不怕齿轮没了,坏了的情况?

这有点因噎废食,你担心的话可以指定 package vesion x.x.x 而不是 ^x.x.x

怎么看待只有四个螺丝的桌子也要买现成的,不能自己组装吗
怎么看待去饭店吃饭点番茄炒蛋这种行为

螺丝不是你买的吗

我觉得主要问题是不应该把 one-line code 与单独实现功能的模块直接混淆掉。

如果是实现单一功能,缺少更多的模式变化,其实很多时候没必要拆出来一个单独的包作为功能。

反倒是一类功能的集合作为不同项目适配我觉得更适合模块功能的定义。

否则写代码更多时候只是拼积木,没有任何意义可言。

我觉得这背后的问题是 node.js 缺少一个优秀的 stdlib 。 TJ 老师也说过这个问题。 https://twitter.com/tjholowaychuk/status/665308077420183553

其实我的理解不就是 OOP 的东西么?把所有东西都一个个做成模块,然后需要的时候就可以用,尤其是哪些常用的东西。

这些东西是一行还是几行,放模块里调用起来肯定比你自己再写一遍要方便的多。

当然,这些东西是自己写一个模块在那还是调用现有的,我觉得这部是重要的。不重复造轮子固然重要,但是去找这些轮子也比较花时间的(除非你已经知道的或者很流行的)不过我觉得这部是讨论的重点。

重点是,这个东西好用,可以完成我需要的功能,我不需要重新写了,而且我可以反复利用,正好还被我知道了。

模块和 OOP 有什么必然联系?

function noop() {}

把 one line 变成 two lines 就可以完美避开这个问题了。机智不。

优秀的 stdlib 也不能完全覆盖所有的边角问题,就像很多其他语言程序员写多了之后都有自己的一个 stdlib-exts 一样。

然而一个 stdlib-exts 拆成几十个包的做法确实让人理解不能。

我觉得这不是懒的问题,而是程序就应该这样写。一段代码,一种方式是自己写,另一种方式是用第三方库,并且是被广泛应用且证明可靠的库,那么必然要用第三方库。
如果第三方库看起来不是那么可靠,那么如果可能,就去 improve 这个库,然后再用。
如果人人都这样做,那将会产生个完美的社区,和完美的开发环境。
软件的成本中,写代码的成本是比较小的,调试和测试才是占大头,既然已经有可靠的代码可以复用,那为什么还要自己写呢?不管多短的代码,自己写都有可能犯错不是?
回想一下,你难道没有犯过让自己捶胸顿足的低级错误?

这次的事件,不是 do one thing and do it well 原则出了问题,而是社区管理的问题。不能因此而不让小的包存在。

这么短的代码,是直接复制过来,还是引入外部依赖呢?
我觉得引入模块就一个好处:标准化

解决的方案可以是多人维护一库,像 underscore 一样,把这些功能集成进去,包引用也减小不少

然而那已经让 underscore 闲得很臃肿了,现在 lodash 的做法是自己本身包含所有功能但是每个功能同时以 lodash.xxx 的名字发布。

根本就是 js 缺乏一个像样的标准库,发展出这种畸形的依赖,还能衍生出一套理所应当的设计哲学出来,那句话怎么说来着,不以为耻,反以为荣?

那是因为 js 作为一种要优化到最小的包存在,却缺乏有效的只集成需要的 function ,所以在工程上智能自己做拆分。

如果是可以使用 require(‘lodash’) 的同时处理优化,谁在开发的时候还会喜欢去依赖一堆 lodash.xxx ?目前有一些工具在做,但是还是尝试性的。在正式项目中使用还有点担忧。

如果可以那样的话,为什么不直接只需要一个标准库 require(‘all’) 然后自动分析用到的代码,然而不是做不到吗

P.S. 你可以尝试 rollup/webpack2 的 tree shaking 功能,但是依赖 ES6 的 import 特性。

我最后不是说了么,有一些工具在做了… 所以我不是很理解你说的做不到是什么意思… 不管依赖什么,终归还是有人在特定条件下尝试性做了…

我的意思是始终要依赖构建工具

开源是把双刃剑

说到底就是专业级地实现轮子并维护轮子麻烦 有人帮你搞了何乐而不为?

如果是产品依赖这种库也没有什么问题. 和几行代码没关系, 只关乎你自己是否觉得这样 ok.

但是如果我是 library vendor, 一般如果不是真的非常必须的话, 我不会加入任何第三方的依赖进去. 如果一定要依赖的话, 那也会直接把源码 embed 到我的 library 里面去.

当然, 我这是在有着非常不错的 std library 支持的情况下. JS 的世界好像很不一样的感觉.



如果你说的是标准函数库的问题,当然是 JS 引擎提供的更多更好,这点我也同意是语言上提供更加舒服,比如 trim 或者最近的 left-pad ,但是也保不齐有兼容性问题,就算是客户端,面对某些兼容性问题的时候也要自己提供 dll ,所以最后你可能为了兼容还是要提供一些标准化的库,当然你可以使用 UA 来判断是否加载。

如果你说的是模块合并最优化,个人觉得是废话,以我肤浅的语言知识,目前没有见过不经过构建就能自己最优化的语言, C 和 Java 也有 gcc 和 javac ,与 JS 不一样的是,服务端和客户端语言可以不用在意体积最优化,而 JS 的执行过程是需要经过用户下载的(暂时不谈缓存和 service worker ),因此体积当中有任何 unused 内容都是对流量的损耗,不然就只能增加请求来减少体积了…

其实我觉得是 npm 机制的问题

你可能并不是 100 个 library 的 author 😂

一个引用的包本来就不应该算是自己包的一部分,通过外部依赖解决可以让使用者专注于包本身所实现的功能。
如果每个小包都自己写,势必很多包里都有一套重复性很高的 util 。而别人尝试 debug 时又不得不去研究是否是你自身的基础件实现有问题。

根本原因还是 node 没一个像 Apache Commons, Guava 一样的标准库

怎么还有人说标准库的事情啊

问题的根源在于 js 没有一个标准库,别的语言有这么多一行的包吗?

说标准库的同学真的看了帖子吗😂

好处是不用自己维护啊,前提是对这个 package 有信心

即使有标准库,也没可能囊括所有的需求吧。

标准库最后越来越大,变得越来越 bloated 真的好吗 😂

> tl;dr You make small focused modules for reusability and to make it possible to build larger more advanced things that are easier to reason about.

More proof that the Node.js developer community is cancer.

之前 NPM 3 后随便构建一个项目,点开 node_module 的时候卡了一下, 自习一看,超过 600 个目录。。
100M+ 的大小,真有点过了,不说维护什么的,如果第三方库分散成这样,你找个文档都是个费劲的事
当然这个趋势下去肯定会有个把 node_module 下所有包的文档打包成一个 Dash 的项目出来

看完还是觉得相同领域的 one line module 应该把功能合并到一起,一个小功能对应一个模块名,记忆地太多会把人逼疯的

this English is that bad

确实。没引入一个新的包,就存在别人更新更残了拖累自己的风险。所以好多情况下,我宁可 fork 别人一份代码用自己的这份,而不是 git clone 他的。就是怕别人更新了……我不知道啊……

你可以在 package.json 里限定使用哪个版本

你可以选择构建的时候不更新啊,或者去寻找其他的能够代替的包,风险这种东西哪个产品没有,依赖库的风险没有想象的这么严重,就比如你敢说自己的代码百分百完美?要是这样还需要什么测试哦。我个人是支持 npm 这种库管理的模式,每个人都可以自由地提供自己觉得很棒的代码(轮子),至于使用者是否愿意使用这个轮子或者选择其他的轮子都交给对方选择,一个轮子坏了,大不了找另外一个轮子代替嘛,总比自己去选木材造轮子还要判断这个轮子是否标准要省事得多吧。这次事件个人觉得是管理方的错,跟其他的并无关,所以看到上面强行把话题扭到 js/标准库 /模块化 /自己造轮子 的时候感觉真的是醉醉的,就好比一个国家闹了个小事情被人强行放大成一个大新闻,然后一众的人开始找历史根源,剖析社会制度,批判者和支持者争辩不休。冷静一下好么,事情或许没有我们想象得这么复杂。

我的理解是你自己写这样一个函数的话,虽然不难写,但是要在你的代码库里找一个地方来存放,可能还要为它写测试。既然如此,直接 require 一下是最方便的方法了。

人家不是提供了 custom build 吗,很多库都可以

可以,但是过了

不就一个小函数吗,有找的时间加看文档的时间,早就撸完了

我就知道我引入了一个 md5 模块因为不想 crypto.createHash… 写很长一行 /w\

there’re bullshits in every package manager, don’t take the extreme case as a general one.

理想情况是 所有轮子都完美实现功能
而实际情况却不是这样

也是跪了,这种一行的功能都要弄一个 module ,为什么其他语言都没这样的问题,只有这些有包管理的才有呢?比如 python , nodejs 这些有一个比较统一的包管理的语言,感觉包管理有点像是被滥用了。

有没有是一个问题,用不用是一个问题,用着好不好是另一个问题

只用一行代码做模块是各个人的自由,但是还是想吐槽:
很多简单的小功能,又不是处理用户的未知输入(基本没有所谓的类型之类的坑),还要去 npm 找模块,为啥不自己撸一个函数?这就是所谓的『流程正确』么?

那么这些加在一起呢

在Node.js社区中,left-pad这样的模块虽然看似简单,却体现了模块化编程的精髓。left-pad模块的主要功能是将字符串左侧填充指定的字符,直到达到指定的长度。尽管这个功能可以通过原生JavaScript代码实现,但使用NPM上的模块有几个显著的优势:

  1. 代码复用:通过模块化,开发者可以复用其他开发者编写的代码,避免重复造轮子。例如,left-pad的实现可能非常高效或包含额外的功能,直接使用现成的模块可以节省开发时间和精力。

  2. 维护性:当left-pad模块更新时,所有依赖它的项目都会自动受益,无需手动更新代码。

  3. 社区支持:NPM上的模块通常有广泛的社区支持,这意味着如果遇到问题,可以更容易地找到解决方案。

下面是一个使用left-pad模块的示例代码:

// 首先安装left-pad模块:npm install left-pad

const leftPad = require('left-pad');

let str = '5';
let paddedStr = leftPad(str, 10, '0'); // 将字符串'5'左侧填充'0',直到长度为10

console.log(paddedStr); // 输出:0000000005

这段代码展示了如何使用left-pad模块将一个字符串左侧填充字符'0',直到字符串的长度为10。这种简单而有效的功能在许多场景下都非常有用,比如格式化日期、生成固定长度的字符串等。因此,尽管left-pad模块的功能看似简单,但它在实际开发中却具有广泛的应用价值。

回到顶部