程序員們?yōu)槭裁礋嶂杂诎l(fā)明輪子?
“重復(fù)發(fā)明輪子”這句話原本用于比喻無(wú)謂的重復(fù)勞動(dòng),但這個(gè)比喻似乎也不那么恰當(dāng),因?yàn)樵谌祟?lèi)的歷史長(zhǎng)河中,輪子已經(jīng)被重復(fù)發(fā)明了無(wú)數(shù)次。
如果把“重復(fù)發(fā)明輪子”這個(gè)比喻放到計(jì)算機(jī)領(lǐng)域,也不見(jiàn)得太恰當(dāng),因?yàn)橛泻芏鄰V泛流傳的軟件本身就是被重復(fù)發(fā)明的“輪子”,不能說(shuō)它們是無(wú)謂的重復(fù)勞動(dòng)。
- Linux 是對(duì) Unix 的重新發(fā)明;
- MariaDB 是對(duì) MySQL(MySQL 是對(duì) PostgreSQL 和 Oracle 的重新發(fā)明,而 PostgreSQL 是對(duì) Oracle 的重新發(fā)明)的重新發(fā)明;
- 現(xiàn)代 C++ 是對(duì)老版 C++ 的重新發(fā)明,C++ 是對(duì) C 語(yǔ)言(C 語(yǔ)言是對(duì) B 語(yǔ)言的重新發(fā)明,而 B 語(yǔ)言是對(duì) BCPL 的重新發(fā)明)的重新發(fā)明,Rust 是對(duì) C++ 和 C 語(yǔ)言的重新發(fā)明;
- Clojure 是對(duì) LISP 的重新發(fā)明,LISP 是對(duì) IPL 和 Lambda Calculus 的重新發(fā)明;
- Haskell 是對(duì) System FC 的重新發(fā)明,System FC 是對(duì) System F 的重新發(fā)明,System F 是對(duì) Labmda Calculus 的重新發(fā)明;
- DOT 是對(duì) OO 的重新發(fā)明;
- Kotlin 是對(duì) Java 的重新發(fā)明;
- Vim 是對(duì) Vi 的重新發(fā)明;
- Wayland 是對(duì) Xorg 的重新發(fā)明;
- Ubuntu 是對(duì) Debian 的重新發(fā)明……
我可以舉無(wú)數(shù)個(gè)這樣的例子。
很多優(yōu)秀的軟件并不只是簡(jiǎn)單地往已有代碼庫(kù)中添加新特性而已,而是通過(guò)不斷迭代,創(chuàng)造出比以往更好的東西。GitHub 上很多流行的代碼庫(kù)都有數(shù)百個(gè)分支,而對(duì)于每一類(lèi)軟件工具,我們又有很多不同的選擇。
人們經(jīng)常說(shuō)“不要重復(fù)發(fā)明輪子”,但他們忽略了這樣的一個(gè)事實(shí):大部分優(yōu)秀的計(jì)算機(jī)軟件實(shí)際上就是被重復(fù)發(fā)明的輪子,而并非是全新的東西。這些變化是循序漸進(jìn)的,我們基于已有的概念逐步迭代,慢慢修改它們,讓它們變得更好。這是個(gè)無(wú)窮盡的過(guò)程,甚至我們忘記了自己是從哪里出發(fā)的,也不知道終點(diǎn)在哪里。我們只要付出時(shí)間,也許這就是計(jì)算機(jī)編程的神奇之處。在這里,沒(méi)有所謂的資源短缺,也不管我們?nèi)绾委偪?,我們總能?chuàng)造出一些東西。
重復(fù)發(fā)明輪子不是罪,只是我們要知道在何時(shí)以及如何重復(fù)發(fā)明輪子。
沒(méi)有合適的輪子?自己造!
在找不到可用的工具時(shí),就自己開(kāi)發(fā)一個(gè),而不是基于已有的庫(kù)開(kāi)發(fā)一個(gè)不那么好用的“次品”。或許其他人也有同樣的需求,那么就可以把你開(kāi)發(fā)的工具分享給他們。自己開(kāi)發(fā)可能需要更長(zhǎng)時(shí)間,但會(huì)更有趣,而且開(kāi)發(fā)出來(lái)的工具可能更好用。當(dāng)然,具體要怎么做,完全取決于你自己。你可以“勤快”得像某些 C 語(yǔ)言開(kāi)發(fā)者一樣,連 list 和 vector 都要自己實(shí)現(xiàn),也可以“懶惰”得像某些 JavaScript 開(kāi)發(fā)者一樣,連最簡(jiǎn)單的判斷奇數(shù)的函數(shù)都要從網(wǎng)上下載(比如日下載量超過(guò)十萬(wàn)的“is_odd”包,地址是https://www.npmjs.com/package/is-odd)。
以 Julia 為例,Julia 是一門(mén)與 Python 非常像的編程語(yǔ)言,只是它更容易部署,不需要虛擬環(huán)境就可以運(yùn)行,它運(yùn)行更快,而且支持大規(guī)模的并發(fā)。Julia 就是一個(gè)被重復(fù)發(fā)明的輪子,因?yàn)閺睦碚撋险f(shuō),它所能做的事情,Cython 也能做到,只要使用恰當(dāng)?shù)?C/C++ 庫(kù),修改一點(diǎn)代碼,再加上一點(diǎn)耐心就可以。但 Julia 與生俱來(lái)就提供了便利性,為開(kāi)發(fā)人員節(jié)省了大量時(shí)間,還讓開(kāi)發(fā)變得更有趣。或許,它會(huì)是 21 世紀(jì)最讓人矚目的編程語(yǔ)言之一。
現(xiàn)有輪子停滯不前?造!
當(dāng)很久沒(méi)有人重復(fù)發(fā)明輪子,就可以考慮重新發(fā)明一個(gè)。出現(xiàn)這種情況,可能是因?yàn)楝F(xiàn)在的輪子已經(jīng)夠好了,沒(méi)必要做出大的改進(jìn),但更有可能是因?yàn)榇蠖鄶?shù)人希望有更好的輪子,只是他們沒(méi)有時(shí)間去做。比如,有些問(wèn)題雖然暫時(shí)得到了解決,但并不是沒(méi)有缺陷,因?yàn)楫?dāng)前的技術(shù)或框架無(wú)法提供更好的解決方案。這就留有余地,等待更好的時(shí)機(jī)出現(xiàn)。數(shù)年之后,或許技術(shù)發(fā)展到可以更好地解決這些問(wèn)題。
以圖像識(shí)別為例,圖像識(shí)別屬于經(jīng)典的分類(lèi)器問(wèn)題。人們?cè)诜诸?lèi)器問(wèn)題上不斷努力改進(jìn),直到 2010 年,通過(guò)使用 Fisher Kernel 這類(lèi)算法才讓分類(lèi)器得到了非常精確的結(jié)果。當(dāng)然,這些成果還不足以用于檢測(cè)腫瘤或汽車(chē)自動(dòng)駕駛,從精確度和訓(xùn)練時(shí)間方面來(lái)看,它們的水平還只是處在鸚鵡和大象之間。直到有人重新發(fā)明了并不太流行的卷積神經(jīng)網(wǎng)絡(luò),還使用了現(xiàn)代的 GPU 來(lái)訓(xùn)練那些早在 90 年代就開(kāi)發(fā)出來(lái)的圖像識(shí)別模型。2012 年出現(xiàn)了著名的 AlexNet&Co,而幾年之后,圖像識(shí)別技術(shù)發(fā)展到令人驚詫的地步,在中型數(shù)據(jù)集上訓(xùn)練出來(lái)的分類(lèi)器甚至可以打敗人類(lèi)。
輪子所有權(quán)遭到限制?造!
比如 Linux、GCC 和 Git,它們都是對(duì)已有版權(quán)軟件系統(tǒng)的重新發(fā)明。在某些方面,它們比版權(quán)軟件更好,而且它們是開(kāi)源的。這意味著有更多的人在使用,有更多的人參與開(kāi)發(fā),這讓它們能夠以驚人的速度發(fā)展演化。
單純覺(jué)得好玩?造!
對(duì)一個(gè)已經(jīng)很強(qiáng)大的軟件來(lái)一次重新發(fā)明,這樣做也沒(méi)什么錯(cuò)。你可能會(huì)失敗,但你會(huì)從中學(xué)到很多。盡管別人已經(jīng)解決了大部分問(wèn)題,但你仍然能夠從解決同樣的問(wèn)題中獲得有趣的體驗(yàn)。數(shù)百萬(wàn)人想證明勾股定理或重新發(fā)明新的 LISP,雖說(shuō)他們最終不過(guò)是在重復(fù)發(fā)明相似的輪子,但他們所做的并沒(méi)有什么錯(cuò),只要他們能夠從中獲得樂(lè)趣。而如果你重新發(fā)明的輪子哪怕只是比原先的好那么一點(diǎn)點(diǎn),都算是在造福人類(lèi)。
想造就造!
盡管放手去做吧,重復(fù)發(fā)明輪子不是罪。
如果有人說(shuō)重復(fù)發(fā)明輪子是無(wú)用功,就把馬斯克造火箭的故事甩他臉上。
或許,你也可以開(kāi)發(fā)出一個(gè)更直觀、更優(yōu)雅的 JavaScript 庫(kù),或者一個(gè)更快的 Python 編譯器,或者一個(gè)更便宜的計(jì)算單元,或者一個(gè)更好的 Spotify,或者一個(gè)更高效的查找表……
因?yàn)槟闶菬釔?ài)創(chuàng)造的程序員呀~






















