駁《我不是很懂 Node.js 社區的 DRY 文明》

今天在群里有人議論方先生的文章《我不是很懂 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

    原文作者:justjavac
    原文地址: https://segmentfault.com/a/1190000014480379
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞