程式設計師們,這些「坑」你熟悉嗎?

2019-11-14     指尖上的代碼

嚴謹如程式設計師,時間久了還是會有一些"想當然"。不知不覺中就會掉進很多陷阱里。看看這些陷阱,你都中招了嗎?

譯文:

我對誤解很感興趣。以前我經常在酒吧里主持猜謎遊戲(我們這裡有的地方叫做「冷知識之夜」),參加過幾次的人都知道,如果一道題看上去像是陷阱,那通常它就是陷阱。我的題目里有相當多的「似真似假」的題目,其中所有問題的答案都是假,但幾乎沒有任何人注意到這一點,因為每道題都是人們平常深信不疑的錯誤的事情。

等等,這跟編程有什麼關係?別著急,繼續讀下去。

在Hacker News或Proggit上評論的程式設計師並不是從計算機行業隨機選取的,而是這個行業中的精英部分。就像參加任何會議一樣,參與評論的這些人都比一般程式設計師對編程更有熱情。

然而,從許多評論中可以看出,許多很厲害的程式設計師也會有各種信仰和誤解,這些信仰和誤解雖然錯得離譜,但卻廣為流傳。下面是我收集的一些很有意思的誤解,附有我的解釋。

C語言就是快。

如果說哪個誤解會招致差評、導致認知差異、甚至引起口水戰?那很可能就是這一條了。

就像其他的誤解一樣,我對這一條完全不理解。

估計是因為我學C語言的那個時代,人們普遍認為C語言用於遊戲編程等很慢,而彙編才是王道。或者是因為,程序都要編譯成機器語言,而就像什麼順勢療法一樣,彙編語言仿佛是水,能記住自己從哪兒來,從而使得CPU能執行得更快……於是就有了下一條誤解。

垃圾回收語言就是慢。

這裡說的垃圾回收指的是「跟蹤式垃圾回收」。許多人都評論說,在真正的系統中編程時,跟蹤是垃圾回收是多麼不能忍。要是每條評論我能收一分錢的話,我現在就有好幾塊錢了。

我大概能理解這一條,因為四年前我也相信。

我還曾經相信後台會有小仙子自動幫我清理那些「明顯」會導致程序變慢的代碼。以後我會寫一篇文章專門講這個問題。

Emacs是個文本模式的程序。

每次有人說文本編輯器比不上IDE,就必然有人跳出來問,為啥非要用文本模式的編輯器。

我是個Emacs用戶,我也不知道為啥他們都要用。類似地還有……

文本編輯器沒辦法也不應該擁有自動完成、查找定義等功能。

這一條通常會在討論Emacs是終端程序的帖子裡出現。通常還會伴隨著一些人說IDE的上述功能是必要的。我也不用IDE編程,估計以後也不會。同樣,我很少看到用編輯器用得很溜的人。

不記得多少次看到某人用vim打開一個文件,發現開錯了,關掉vim,再打開另一個文件,再關掉……啊啊啊啊啊啊啊啊啊啊。

還有人「喜歡Eclipse」卻不知道「查找定義」功能的……簡直是奇蹟。

由於C ABI是編程的通用語言,所以實現應該也用C語言。

在討論二進位代碼時C語言是真正的膠水語言。

這是有歷史原因的,但不可否認在這方面C語言就是王者。但令我大跌眼鏡的是,很多人把這句話理解為,如果API是C語言的,那麼實現它的唯一語言就是C語言。也不想想Visual Studio的libc是用C++寫的。

C和C++是同一種語言,真正的名字是C/C++。

而且沒人把Objective C算進去(其實Objective C跟C++不一樣,它實際上是C語言的超集),因為……啥原因呢?

C和C++有太多共通的地方,有時候當你想說一些適合兩種語言的東西時,寫成C/C++是有道理的。但許多時候人們並不是這樣用……

在並發編程的容易性方面Rust是唯一的選擇。

我估計所有使用Pony、D、Haskell、Erlang等語言的人都不明白這句話。Rust是不是比C++更安全?當然是,但這個標準也太低了。

我第一次用Rust時花了30分鐘就死鎖了。我感覺並不容易,或者應該說「不考慮數據衝突的話很容易」?反正是很容易上當.

內核只能用C語言。

顯然Haiku和Redox被無視了,以及其他一切unikernel框架。

平台的位元組序很重要。

這又是一條讓我迷惑不解的理論。

我甚至都不知道為啥還有htons和ntohs這兩個函數。完全搞不懂,而且更悲慘的是,我跟別人解釋這個時,似乎他比我還明白。

我並不是說位元組序不重要,而是說99.9%的情況下,人們認為它很重要,實際上卻完全無所謂。我肯定會讀一次IEEE浮點數的定義,但這並不意味著寫任何程序都必須記住哪一部分才是尾數。

Haskell代碼能通過編譯就能跑!

嗯……不是的。

簡單的語言能避免複雜性。

也稱為「清掃地毯下面的塵土」迷信。

我並不明白這句話。我的意思是,一項任務的複雜度並不會因為使用了簡單的語言而消失,甚至會變得更複雜。有許多負責搞笑的語言極其簡單,但真用來寫代碼就簡直是噩夢。

代碼覆蓋率是測試質量的標準。

我認為覆蓋率很重要。我覺得,閱讀一份漂亮的HTML覆蓋率報告確實能夠幫助書寫高質量的軟體。但我十分確信,追逐代碼覆蓋率的目標是有害的,而且毫無意義。下面是個很無聊的函數:

int divide(int x, int y) { return x + y }

然後是測試套件:

TEST(divide) { divide(4, 2); }

100%的覆蓋率。函數甚至連返回值都不對。好吧,其實應該assert點啥東西:

TEST(divide) {
assert(divide(4, 2) == 2);
assert(divide(6, 3) == 2);
}
int divide(int x, int y) { return 2; }

100%覆蓋率。嗯……要不這樣?

TEST(divide) {
assert(divide(4, 2) == 2);
assert(divide(9, 3) == 3);
}
int divide(int x, int y) { return x / y; }

測試成功!當然,別給y傳0……

應該測量測試覆蓋率,閱讀報告,然後決定下一步該做什麼。之前我也寫過著跟問題。

C能最接近地映射到硬體。

如果「硬體」的意思是PDP11或微型嵌入式設備,那麼沒錯。但寫內核不能只用C不用彙編是有理由的。

而且還有這一堆東西:SIMD,多CPU核心,緩存層次結構,緩存管線,內存預取,亂序執行,等等。至少現在有原子性了。

我不知道人們給量子計算機寫代碼的時候還會不會說C最接近硬體。聽起來似乎很傻,但我還見過更傻的。

另外,Lisp機器從來沒存在過,FPGA/GPA也不是硬體(別忘了Poe定律!Poe定律:只要不明確表明是諷刺,那麼不管諷刺得多麼誇張,總會有人信以為真)。

做某件事只能用某個語言。

不管你說的某件事是啥,Lisp估計都能做。

文章來源: https://twgreatdaily.com/-qbda24BMH2_cNUgNL4z.html