今天在群里有人讨论方老师的文章《我不是很懂 Node.js 社区的 DRY 文化》,我也看了一遍,槽点太多,不知道如何下笔。

方老师分析了几个依赖最多的 npm 包,每个都只有不到百行代码。

比如 is-odd,每周下载 300 万次,但是只有核心 5 行代码。而且依赖了每周下载 1000 万次的 is-number 库。

得出了一个结论:

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

首先第一条:

原来有这么多 JS 程序员不会判断奇数。

其实不仅仅是 JS 程序员,大部分程序员都不会准确的判断奇数。

你写

const isOdd = x => x % 2 === 1;

这是小学的知识,除以 2,如果除不尽(有余数)那么就是奇数。正因为知识点很简单,所以给人一种随便一个程序员都会判断的错觉。

现在我们假设用户传入的参数一定是数字。

即便如此,这个函数依然不能正确判断奇数。因为 -3 % 2 的结果是 -1

有人说那就这么写:

const isOdd = x => x % 2 !== 0;

随便一个小数就被判断为奇数了。更不用说浮点数中的妖怪 NaNInfinity 了。

那么是不是对 NaNInfinity 直接返回 falst,然后把 -1 的判断也加上去就行了:

const isOdd = x => x % 2 === 1 || x % 2 === -1;

也是图样

9007199254740991 % 2 === 1
9007199254740992 % 2 === 0
9007199254740993 % 2 === 0
9007199254740994 % 2 === 0
9007199254740995 % 2 === 0
// 后面的都是 0

为什么从 9007199254740991 开始呢?因为这个值是 Number.MAX_SAFE_INTEGER,是 2 ** 53 - 1

那回过头来看看 is-odd 库是怎么实现的呢?

!!(~~i & 1)

~~i 用于把字符串转换为整数,和 1 进行按位与运算判断最后一位是 1 还是 0

很遗憾,也有问题。 因为在字符串转整数的时候精度就丢失了。

如果有谁想造轮子,可以写一个 better-is-odd,可以把字符串 '9007199254740995' 判断为奇数,但是对于数字 9007199254740995 也是无能为力。等着 proposal-bigint 提案吧。

不仅仅是判断奇数,单纯的判断一个字符串是不是数字就可以难倒一大片 JS 程序员(其它语言程序员也一样)。

is-number 库核心代码不到 10 行。方老师只关注了库的源代码,但是我们如果看一看他的 test case,就决定要使用这个库了。

作者为这 10 行代码写了 108 行的测试用例,来保证这个函数的功能是正确的。

我在之前的文章百行代码,千行测试里面曾写过:

不要重复发明轮子。

很多大牛推荐我们“造轮子”,但是造轮子的目的是为了学习,而不是使用,尤其不要用在生产环境。

造个轮子很简单,但是你非要把自己的轮子安在汽车上,开上路,那肯定是一个安全隐患。

有很多人会说,“既然自己可以写一个,为什么非要用别人的?” 还有人觉得,有些非常小的功能不需要使用别人的。

很多人还会借此吐槽 leftpad 模块,但是平心而论,你自己能徒手这一个没有 bug 且高性能的 leftpad 函数吗?

前几天我们项目组就遇到了一次,其实功能很简单,一个页面分享出去,并使用 url 携带参数。比如:

aaa.html?id=123456

看似很简单的一个需求,但是真正自己写一个却不简单。

  1. 查找“=”字符,然后截取后面的?
  2. split("="),然后去第二个
  3. ……

不到 10 行代码就写完了。

第一次分享到微信是正常,把分享出去的页面再次转发分享,页面错误。

因为微信会在 URL 后面添加一些额外的参数,同样,不同的平台都会有不同形式的添加参数方式,有的加 &,有的加 #,不论加什么都会导致解析的失败。

归根结底是我们写的解析函数有 bug,我们重新造了一个有 bug 的轮子。

解决方式就是:

npm i qs

麻雀虽小,五脏俱全。看看 github 源码,“百行代码,千行测试”。绝对比自己写的代码靠谱。

我写这篇文章不是为了推荐这个 qs 库,而是告诉大家不要重复造轮子用在生产环境,平时大家多造轮子用来学习。

在回过头来看看 is-number 库,不仅仅有 100 多行的 test case,还有一个目录 benchmark。这里面的代码我没有数,但是光看文件数量就有 10 个以上。也就是说作者不仅仅保证了这个函数的运行结果没有问题,更保证了这个函数的性能。

我们为什么要使用这个库,因为作者为了他的 10 行代码,写了几百行的其它代码来保证质量。

作者 9 天前还发布了新版,20 天前还优化了字符串转数字的性能。

再看看方老师说的第二条:

只要 markdown 写得漂亮,就能迷倒 JS 程序员。
这些包的 markdown 代码远远多于 JS 代码,可能它们的 markdown 更值得我们学习

Redux 号称百行代码,千行文档,一共就导出了 5 个函数。

而且 markdown 写的漂亮也是很有必要的,否则你不知道下面的代码到底输出什么

isOdd(' 12')
isOdd('一')
isOdd('①')
isOdd('Odd')

第三条:

1 + '1' 的问题一直在困扰 JS 程序员,我要不要写一个 add() 库解决这个问题呢

不能。

我是认真的!因为 npm 已经有一个 add 库了,名字被别人占用了,所以你只能叫别的名字了。

虽然是一个小众的库,但是每周也有近一万的下载量。这个库实现了 JavaScript 中的浮点数加法的 Rump-Ogita-Oishi 算法。

比如有如下浮点数:

const nums = [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7]

把这些数累加

nums.reduce((a,b) => a+b);

结果是:

15.299999999999999

而使用 Rump-Ogita-Oishi 算法:

add(nums) === 15.3

再看看 benchmark (OS X 10.9.4, 2 GHz Core i7, 8GB DDR3 1600Mhz RAM):

add-precise x 1,400,712 ops/sec ±3.31% (89 runs sampled)
add-dumb x 24,268,034 ops/sec ±3.96% (80 runs sampled)
native x 94,957,251 ops/sec ±2.94% (85 runs sampled)
native is ~67.8 times faster than add-precise

最后再重申一般:Don't Repeat Yourself

驳《我不是很懂 Node.js 社区的 DRY 文化》的更多相关文章

  1. 程序员的复仇:11行代码如何让Node.js社区鸡飞狗跳

    来源自:http://www.techug.com/node-js-community 几天前,一名 NPM(Node.js Package Manager)社区的贡献者 Azer Koçulu 出于 ...

  2. 从发布订阅模式入手读懂Node.js的EventEmitter源码

    前面一篇文章setTimeout和setImmediate到底谁先执行,本文让你彻底理解Event Loop详细讲解了浏览器和Node.js的异步API及其底层原理Event Loop.本文会讲一下不 ...

  3. 看完我的笔记不懂也会懂----Node.js

    Node.js 学习 - 命令行窗口 - 进程与线程 - ECMAScript的缺点 - Node模块化 - Node中的全局对象 - 包 package - NPM包管理器 (Node Packag ...

  4. 国内最大的 Node.js 社区将 New Relic 的监控产品换成了 OneAPM

    国内最知名的 CNode 社区把 New Relic 的监控产品换成了 OneAPM .难道 APM 的老大 New Relic 已经被 OneAPM 超越? 毋庸置疑,在全球应用性能管理 SaaS ...

  5. node.js+mongodb 爬虫

    demo截图: 本demo爬瓜子二手车北京区的数据 (注:需要略懂 node.js / mongodb 不懂也没关系 因为我也不懂啊~~~) 之所以选择爬瓜子二手车网站有两点: 一.网站无需登录,少做 ...

  6. [转载]Node入门 » 一本全面的Node.js教程

    http://www.nodebeginner.org/index-zh-cn.html 作者: Manuel Kiessling 翻译: goddyzhao & GrayZhang & ...

  7. Node.js 中开源库探秘 object-assign | 全栈之路

    这篇内容呢,讲的是另一个技术栈 Node.js 系列,虽然和咱们这里的主题不是特别吻合,不过嘛,汲取多样性的养分是快速成长的好方法,也是现在流行的全栈工程师的必经之路. 由于这篇内容涉及的是 Node ...

  8. Node.js 给前端带来了什么

    在软件开发领域,前端工程师曾经是一个比较纠结的职业.在Web技术真正发展起来之前的相当长一段时间里,由于技术门槛很低,前端工程师行业一直是鱼龙混杂的状态.其中很多号称是Web开发者的人实际上并没有什么 ...

  9. Node.js Web框架收集

    原文地址:http://geek.csdn.net/news/detail/4020 框架列表: http://nodeframework.com/ 与其他很多语言一样,Node.js也有很多Web框 ...

随机推荐

  1. C#中?和:?和??代表什么

    ?代表可空类型修饰符    引用类型可以使用空引用表示一个不存在的值,而值类型通常不能表示为空.为了使值类型也可为空,就可以使用可空类型?:带便三元表达式    int a=b>c?b:c 如果 ...

  2. docker 搭建php 开发环境 添加扩展redis、swoole、xdebug

    docker-compose搭建lnmp 先决条件 首先需要安装docker 安装docker-compost 1.创建lnmp工作目录 #创建三个目录 mkdir lnmp && c ...

  3. LeetCode-049-字母异位词分组

    字母异位词分组 题目描述:给定一个字符串数组,将字母异位词组合在一起.字母异位词指字母相同,但排列不同的字符串. 示例说明请见LeetCode官网. 来源:力扣(LeetCode) 链接:https: ...

  4. Logstash-CentOS7单机安装测试

    目录 环境&准备 安装&启动 简单配置一下,看看效果 Conf配置文件参考 完成 环境&准备 下面所有操作都基于CentOS7 官网下载安装包 logstash下载 如官网打不 ...

  5. Nodejs在Linux环境安装

    一.下载安装包 http://nodejs.cn/download/ 二.解压 tar -xf node-v14.3.0-linux-x64.tar.xz 三.配置 1.编辑文件vim /etc/pr ...

  6. CAS 比较并交换

    简介 CAS 的全称为 Compare-And-Swap,他是一条 CPU 并发源语. 他的功能是判断内存某个位置的值是否为预期值,如果是则更改为新的值,这个过程是原子的. CAS 并发原语体现在 J ...

  7. laravel 框架 ajax无页面刷新删除

    ....................HTML页面<!doctype html><html lang="en"><head> <meta ...

  8. 在命令行运行 python 抛出 ModuleNotFoundError 的解决方法

    所要运行的 py 文件在子目录中,并且该文件引用了另一个子目录中的 py 模块.类似这样: 原因 在运行环境下, a.py 找不到 b.py 所以抛出 ModuleNotFoundError. 解决 ...

  9. virtualenv和virtualenvwrapper pipenv安装

    virtualenv和virtualenvwrapper pipenv安装 virtualenvwrapper工具 virtualenvwrapper是用来管理virtualenv的扩展包,用着很方便 ...

  10. DC-2

    环境搭建 下载地址: https://download.vulnhub.com/dc/DC-2.zip.torrent 从描述中得知有5个flag. 下载好后导入虚拟机 修改网络配置为NAT 探测靶机 ...