農林漁牧網

您現在的位置是:首頁 > 農業

程式設計師有哪些丟不掉的程式設計“陋習”?

2022-06-27由 CSDN 發表于 農業

編譯程式絕大多數時間花在什麼上

擺脫這些壞習慣可以帶來意想不到的效果:編寫出更優質精簡的程式碼。

程式設計師有哪些丟不掉的程式設計“陋習”?

作者 | Peter Wayner

譯者 | 譚開朗,責編 | 郭芮

以下為譯文:

我們都有過這樣的經歷:在媽媽不注意的時候偷吃一塊餅乾;聚餐時過量飲酒;把車停在超時停車的停車位上——我們甚至在死亡邊緣瘋狂試探。是的,我們違反了許多程式設計的基本規則,那些大家都認為是不好的規則,而我們卻偷偷地使用著。

我們對好的程式設計規則嗤之以鼻,輸出的程式碼也一塌糊塗——但我們做出來了。沒有來自程式設計之神的五雷轟頂,我們的桌面也沒有爆炸。事實上,只要我們的程式碼可以編譯並交付,客戶似乎就很滿意了。

這是因為糟糕的程式設計不像安裝電路或者摸老虎屁股那樣有直接的危害性。大多數情況下,它也是可以執行的。規則通常是作為一種指導或格式上的建議,並沒有硬性規定一定要遵守,也不會導致程式碼出現問題。當然,你的程式碼可能會被人恥笑,甚至可能大家公開嘲笑你。不過,這種挑戰慣例的行為可以讓人增加一點顛覆傳統的快感,哪怕是在不經意間。

讓事情變得更復雜的是,有時候違反規則反而更好。(噓!)輸出的程式碼會更乾淨,甚至可能會更快更簡單。規則通常顯得太過於寬泛,有技巧的程式設計師可以透過打破這些規則來最佳化程式碼。不要告訴你的老闆,這對你的編碼生涯會很有意義。

下面這十條編碼習慣常常是被駁斥的,但我們很多人就是會不由自主地使用它們,覺得好用且實用。

程式設計壞習慣一:複製

在學校裡,複製是不對的。而在工作中,規則不是很明確。當然有一些程式碼塊不應該被竊取。如果它來自私有程式碼,不要將它複製到你的堆疊中,特別是標記了版權資訊的。請編寫自己的版本,這是有報酬的。

更棘手的問題出現在原創者想要分享的時候。可能是在一個線上程式設計論壇上;也可能是具有許可證的開放原始碼(BSD、MIT),它允許竊取其中一到三個函式。你無需承擔法律責任。你的工作是解決問題,而不是重新發明輪子。

大多數情況下,複製的優點是不可抗拒的,而缺點可以稍加限制。從一個可靠來源處獲得的程式碼已經至少經過一輪思考與實踐。最初的作者尋找解決方案並找到新思路,給出了迴圈不變數和資料流。

複製的棘手問題是,是否存在一些未發現的bug,或者關於角色或底層資料的一些不同假設。也許你的程式碼混合了空指標,而原始程式碼卻從未檢查出來。如果你能解決這些問題,就好比你的老闆能從兩個程式設計師那裡得到輸入一樣。這是結對程式設計,沒有華麗的鋪陳。

程式設計壞習慣二:非功能性程式碼

在過去的十餘年裡,功能正規化一直在提升。研究表明,在呼叫巢狀函式的基礎上構建程式,程式碼會比老式的變數和迴圈更安全、更少bug,所有這些都足以使程式設計師滿意。狂熱者義憤填膺地譴責程式碼審查和拉取請求中的非功能性請求。這可能是真正的優勢。

但有時你只需要複製貼上。精心設計和優雅規劃的程式碼不僅需要時間來想象,還需要時間來構建和導航。所有這些層都增加了複雜性,而複雜性就是金錢。寫出漂亮函式程式碼的開發人員需要提前規劃,並確保所有資料都沿著正確的路徑傳遞。有時候改變一個變數更容易,這也許可以寫個評論來解釋一下。即使在評論中向未來幾代人註上一長串真誠的道歉,也比以正確的方式來重構整個系統要快得多。

程式設計壞習慣三:不標準的間距

軟體中的大多數空格對程式的執行沒有影響。除了像Python等少數使用空格表示程式碼塊的語言外,大多數空格對程式的行為沒有影響。儘管如此,仍有一些執迷於此的程式設計師,他們計空格數並堅持認為這很重要。曾有人義正言辭的向我老闆控訴我在寫“非標準程式碼”,且他一眼就看出來了。我的錯咯?沒有在等號兩邊都加上空格,違反了ESLint space-infix-ops規則。

有時你必須考慮比空間位置更深層次的東西。或許你擔心資料庫超載,又或許你擔心一個空指標會使你的程式碼崩潰。幾乎程式碼的任一部分都比空格更重要,即使挑剔專橫的標準委員會已經制定了諸多關於空格或製表符位置的規則。

令人驚奇的是,有幾個很好的工具可以自動地重新格式化程式碼,以遵循任何規定的linting規則。我們不需要花時間去思考這個問題,如果它如此重要,我們可以透過執行工具來清理問題。

程式設計壞習慣四:使用goto

禁止使用goto可以追溯到許多結構化程式設計工具尚未面世的時代。如果程式設計師想建立一個迴圈或跳轉到另一個程式中,他們需要輸入GOTO再在後面加上一個行號。幾年後,編譯器團隊允許程式設計師使用字串標籤而不是行號。這在當時被認為是一個熱門的新功能。

有些人認為這會導致“義大利麵式的程式碼”。程式碼會變得不可讀,並且很難理解程式碼的執行路徑。那是一團亂麻,永遠纏繞在一起。Edsger Dijkstra用一篇名為“Goto語言害人不淺”的滑稽手稿建議禁止goto命令。

但絕對分支是沒有問題的。這就讓人糾結了。通常,巧妙的break或return將提供一個非常清晰的宣告,說明程式碼在該位置正在做什麼。有時候,將goto新增到case語句中會更容易,而不是一組結構更合理的層疊if-then-else塊。

也有反例,蘋果SSL協議棧中的“goto fail”安全漏洞就是最好的例子之一。但是,如果我們小心避免case語句和迴圈的一些棘手問題,我們可以插入良好的絕對跳轉,讓讀者更容易理解。我們可以插入一個break或return,這對每個人來說都更乾淨簡明——可能除了那些goto厭惡者。

程式設計壞習慣五:沒有宣告型別

那些熱愛型別化語言的人認為,如果為每個變數新增明確的資料型別宣告,就可以寫出更好、沒有bug的程式碼。在程式碼執行前,花一段時間來拼寫出型別,可以幫助編譯器標記出愚蠢的錯誤。這可能不容易做到,但它是有幫助的。這是程式設計中阻止bug的一種有備無患的方法。

但是時代變了。許多較新的編譯器足夠智慧,可以透過檢視程式碼來推斷型別。它們會前後反覆的檢視程式碼,直到確定變數是string,int或其他型別。如果這些推斷的型別不成佇列,那麼編譯器就會丟擲一個錯誤標誌。因此就不再需要我們輸入變量了。

這意味著現在可以透過省略一些最簡單的宣告來簡化程式碼。程式碼變得更簡潔了,而且讀者通常能夠猜到在for迴圈中名為i的變數是一個整數。

程式設計壞習慣六:溜溜球程式碼

程式設計師喜歡稱之為“溜溜球程式碼”。一開始先將值儲存為字串,然後又解析成整數,接著又轉換回字串。這是非常低效的。你幾乎可以感覺到CPU在所有額外負載下的掙扎。聰明的程式設計師之所以能快速的編碼,是因為他們事先會設計架構,以儘量減少轉換。因為他們的良好規劃而使得程式碼更快的執行。

但是不管你信不信,有時候這種溜溜球程式碼是有道理的。比如你有一個很棒的庫,在其專有的黑盒子裡能做無數智慧的事情。又比如,老闆會開一張七位數的支票,賦予黑盒子所有傑出功能。如果庫需要字串形式的資料,那你就給它字串,即使你剛將其轉換為整數。

當然,你也可以重寫所有程式碼以儘量減少轉換,但這需要時間。有時,程式碼多執行一分鐘、一小時、一天甚至一週都沒有問題,因為重寫程式碼會花費更多的時間。有時候,積累技術債務比一開始就把它建好要便宜。

有時,這個庫不是私有程式碼,而是你很久以前自己編寫的程式碼。有時,將資料轉換一次比重寫庫中的所有內容更快。所以,就繼續寫溜溜球程式碼吧,沒關係的,我們都經歷過。

程式設計壞習慣七:編寫自己的資料結構

其中一個標準規則是,程式設計師在大二時修完資料結構課程後,絕不應該編寫用於儲存資料的程式碼。其他人已經編寫了我們需要的所有資料結構,他們的程式碼經過了多年的測試和重新測試。它與語言捆綁在一起,而且可能是免費的。而你寫的程式碼可能只有bug。

但有的時候,你會發現資料結構庫有點慢。有時它們迫使我們進入一個可能是標準的但對我們的程式碼來說是錯誤的結構。有時,在使用結構之前,庫會要求我們重新配置資料。有時庫包含一些所謂有備無患的保護功能,而我們的程式碼不需要它們。

如果遇到這種情況時,我們就該編寫自己的資料結構了。這可能會更快更好。有時它使我們的程式碼更簡潔,因為我們沒有包含所有額外的程式碼來精確地重新格式化資料。

程式設計壞習慣八:老式的迴圈

很久以前,有人建立了C語言,希望將所有抽象的可能性封裝在一個簡單的結構中。某些事情在開始時就要做,某些在每次迴圈時要做,還有一些方法可以告訴你什麼時候完成。當時,它似乎是一種捕捉無限可能性的完美語法。

然後,現在一些現代的責罵者只看到其不便性。太繁瑣了。所有這些好的可能性也同樣可能是壞的。這使得閱讀和拓展變得更加困難。他們喜歡功能範型,沒有迴圈,只有應用於列表的函式,計算模板對映到一些資料。

有時,無查詢方式更簡潔,特別是只有一個整潔的函式和一個數組時。但有時老式的迴圈要簡單得多,因為它可以做更多的事情。例如,如果您可以在找到第一個匹配項時立即停止,那麼搜尋它就會變得更簡單。

此外,當需要對資料執行多個操作時,對映函式會鼓勵更草率的編碼。假設你想取絕對值然後取每個數的平方根。最快的解決方案是對映第一個函式,然後對映第二個函式,對資料進行兩次迴圈。

程式設計壞習慣九:中途跳出迴圈

規則制定小組宣稱,在程式碼行中的某個地方,每個迴圈都應該有一個“常量”,即在整個迴圈中邏輯語句為真。當該常量不再為真時,迴圈結束。這是考慮複雜迴圈的一種好方法,但它會導致愚蠢的禁令——比如禁止我們在迴圈中間使用return或break。這也包含在禁止goto語句規則中。

這個理論很好,但是它通常會導致更復雜的程式碼。考慮這種簡單的情況,遍歷陣列,將找到的元素傳給test函式,並將該元素返回:

while (i

。。。

if (test(a[i]) thenreturn a[i];

。。。

}

迴圈常量愛好者會要求我們新增另一個布林變數,命名為notFound,然後這樣使用:

while ((notFound) && (i

。。。

if (test(a[i])) then notFound=false;

。。。

}

如果這個布林值命名正確,它就是一段很好的自文件化程式碼,更易於大家理解。但它也增加了複雜性。它還意味著分配另一個區域性變數並阻塞暫存器,而編譯器可能不夠智慧,無法修復這些問題。

有時,一個goto語句或一個跳轉會更乾淨利索。

程式設計壞習慣十:

重新定義運算子和函式

一些最有趣的語言可以讓你做一些尤為曲折的事情,比如重新定義看起來應該是常量的元素的值。例如,Python允許輸入TRUE=FALSE,至少在2。7版之前是這樣的。這並沒有造成某種邏輯的崩潰和宇宙的終結;它只是交換了TRUE與FALSE的意義。你也可以用C預處理器和其他一些語言玩類似的危險遊戲。還有一些語言允許你重新定義運算子,比如加號。

這是一種延伸,但是當要更快速的重新定義一個或多個所謂的常量時,其在程式碼塊中意義非凡。有時候,老闆希望程式碼做一些完全不同的事情。當然,你可以遍歷程式碼並更改每個事件,或者重新定義。它會讓你看起來像個天才。不需要重寫一個龐大的庫,只需稍微翻轉一下,它就會執行相反的操作。

也許在這裡劃清界限比較好。你不應該在家裡嘗試做這個,不管它有多聰明和有趣。這太危險了——真的……

原文:https://www。infoworld。com/article/2992566/10-bad-programming-habits-we-secretly-love。html

本文為 CSDN 翻譯,轉載請註明來源出處。

【End】