驳《我不是很懂 Node.js 社区的 DRY 文化》
今天在群里有人讨论方老师的文章《我不是很懂 Node.js 社区的 DRY 文化》,我也看了一遍,槽点太多,不知道如何下笔。
方老师分析了几个依赖最多的 npm 包,每个都只有不到百行代码。
比如 is-odd,每周下载 300 万次,但是只有核心 5 行代码。而且依赖了每周下载 1000 万次的 is-number 库。
得出了一个结论:
- 原来有这么多 JS 程序员不会判断奇数
- 只要 markdown 写得漂亮,就能迷倒 JS 程序员
1 + '1'
的问题一直在困扰 JS 程序员,我要不要写一个add()
库解决这个问题呢
首先第一条:
原来有这么多 JS 程序员不会判断奇数。
其实不仅仅是 JS 程序员,大部分程序员都不会准确的判断奇数。
你写
const isOdd = x => x % 2 === 1;
这是小学的知识,除以 2,如果除不尽(有余数)那么就是奇数。正因为知识点很简单,所以给人一种随便一个程序员都会判断的错觉。
现在我们假设用户传入的参数一定是数字。
即便如此,这个函数依然不能正确判断奇数。因为 -3 % 2
的结果是 -1
。
有人说那就这么写:
const isOdd = x => x % 2 !== 0;
随便一个小数就被判断为奇数了。更不用说浮点数中的妖怪 NaN
和 Infinity
了。
那么是不是对 NaN
和 Infinity
直接返回 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
看似很简单的一个需求,但是真正自己写一个却不简单。
- 查找“=”字符,然后截取后面的?
- split("="),然后去第二个
- ……
不到 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 文化》的更多相关文章
- 程序员的复仇:11行代码如何让Node.js社区鸡飞狗跳
来源自:http://www.techug.com/node-js-community 几天前,一名 NPM(Node.js Package Manager)社区的贡献者 Azer Koçulu 出于 ...
- 从发布订阅模式入手读懂Node.js的EventEmitter源码
前面一篇文章setTimeout和setImmediate到底谁先执行,本文让你彻底理解Event Loop详细讲解了浏览器和Node.js的异步API及其底层原理Event Loop.本文会讲一下不 ...
- 看完我的笔记不懂也会懂----Node.js
Node.js 学习 - 命令行窗口 - 进程与线程 - ECMAScript的缺点 - Node模块化 - Node中的全局对象 - 包 package - NPM包管理器 (Node Packag ...
- 国内最大的 Node.js 社区将 New Relic 的监控产品换成了 OneAPM
国内最知名的 CNode 社区把 New Relic 的监控产品换成了 OneAPM .难道 APM 的老大 New Relic 已经被 OneAPM 超越? 毋庸置疑,在全球应用性能管理 SaaS ...
- node.js+mongodb 爬虫
demo截图: 本demo爬瓜子二手车北京区的数据 (注:需要略懂 node.js / mongodb 不懂也没关系 因为我也不懂啊~~~) 之所以选择爬瓜子二手车网站有两点: 一.网站无需登录,少做 ...
- [转载]Node入门 » 一本全面的Node.js教程
http://www.nodebeginner.org/index-zh-cn.html 作者: Manuel Kiessling 翻译: goddyzhao & GrayZhang & ...
- Node.js 中开源库探秘 object-assign | 全栈之路
这篇内容呢,讲的是另一个技术栈 Node.js 系列,虽然和咱们这里的主题不是特别吻合,不过嘛,汲取多样性的养分是快速成长的好方法,也是现在流行的全栈工程师的必经之路. 由于这篇内容涉及的是 Node ...
- Node.js 给前端带来了什么
在软件开发领域,前端工程师曾经是一个比较纠结的职业.在Web技术真正发展起来之前的相当长一段时间里,由于技术门槛很低,前端工程师行业一直是鱼龙混杂的状态.其中很多号称是Web开发者的人实际上并没有什么 ...
- Node.js Web框架收集
原文地址:http://geek.csdn.net/news/detail/4020 框架列表: http://nodeframework.com/ 与其他很多语言一样,Node.js也有很多Web框 ...
随机推荐
- (第三章)TF框架之实现验证码识别
这里实现一个用神经网络(卷积神经网络也可以)实现验证码识别的小案例,主要记录本人做这个案例的流程,不会像之前那么详细,主要用作个人记录用... 这里是验证码的四个字母,被one-hot编码后形成的四个 ...
- Centos部署Loki日志聚合系统
关于一些日志聚合由来及原理科普见我的另外一篇 <编程入门之日志聚合系统> https://www.cnblogs.com/uncleguo/p/15948763.html Loki日志聚合 ...
- LeetCode-026-删除有序数组中的重复项
删除有序数组中的重复项 题目描述:给你一个有序数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度. 不要使用额外的数组空间,你必须在 原地 修改输入数组 ...
- 线上| 10万奖金!Greaterwms/DVAdmin插件开发者现金激励活动
为激励广大开发者创作精神,Greaterwms/DVadmin插件开发者现金激励活动现已上线! 什么是GreaterWMS 完全开源仓储管理软件,遵循Apache License 2.0协议,前后端分 ...
- python+pytest接口自动化(6)-请求参数格式的确定
我们在做接口测试之前,先需要根据接口文档或抓包接口数据,搞清楚被测接口的详细内容,其中就包含请求参数的编码格式,从而使用对应的参数格式发送请求.例如某个接口规定的请求主体的编码方式为 applicat ...
- JavaScript面向对象—对象的创建和操作
JavaScript面向对象-对象的创建和操作 前言 虽然说在JavaScript编程语言中,函数是第一公民,但是JavaScript不仅支持函数式编程,也支持面向对象编程.JavaScript对象设 ...
- myBatis plus 去除生成 controller
由于我在网上没有找到答案, 所以分享给大家学习, 我也是第一次用 mybtis plus 的新生成器生成代码, 所以基础代码都是在官网复制所得. 在这里也支持大家在解决不了问题时, 可以试着看看源 ...
- MySQL 查询处理
当腰删除或者更新数据时,首先要雪薰出这些记录,然后再对其进行相应的 操作. 每一个操作都会产生一个虚拟表,该虚拟表作为处理的输入,这些虚拟表对用户的透明的,只有最后一步生成的虚拟表才会返回给用户.
- Linux 中如何使用 Htop 监控工具?【网络安全】
镜像下载.域名解析.时间同步请点击阿里云开源镜像站 一.Htop 界面展示 "Htop 是一个用于 Linux/Unix 系统的交互式实时进程监控应用程序,也是 top 命令的替代品,它是所 ...
- 3D视觉 之 线激光3D相机
1 3D 视觉 常见的三维视觉技术,包含双目.ToF.激光三角.结构光等,如下图: 1)毫米级 双目.ToF.结构光(散斑)的精度为 mm 级,多见于消费领域,如:导航避障,VR/AR,刷脸 ...