天天看點

程式員偷偷深愛的6個不良程式設計習慣

點關注,不迷路;持續更新Java架構相關技術及資訊熱文!!!

我們曾經都做過這樣的事情:當媽媽不注意的時候,偷偷地吃糖果零食,然後導緻有了蛀牙。同樣的,許多程式員都違背過一些程式設計的基本規則,并且偷偷愛着這些不良的程式設計習慣。

“我們對所謂的程式設計規則嗤之以鼻,輸出的代碼也很糟糕——但我們依然活着。程式設計上帝沒有下閃電劈死我們,我們的電腦也沒有爆炸。事實上,隻要我們能編譯和釋出代碼,客戶似乎就很滿意了。”

這是因為糟糕的程式設計不像安裝電路或者摸老虎屁股那樣有直接的危害性。大多數時間裡它也是可以工作的。規則通常是作為一種指導或格式上的建議,并沒有硬性規定一定要遵守,也不會導緻代碼馬上死掉。

為了讓問題變得更加複雜,有時候違反規則反而更好。(出來的代碼會更幹淨,甚至可能會更快和更簡單。規則通常顯得太過于寬泛,有技巧的程式員可以通過打破這些規則來提高代碼。

下面這6個編碼習慣,雖然在程式設計規則中是被駁斥的,但很多程式員就是會不由自主地使用它們。

程式設計習慣No. 1:使用goto//關于禁止使用goto可以追溯到許多結構化程式設計工具還未面世的時代。

如果程式員想要建立一個循環或跳到另一段程式中,那麼他們需要輸入goto後再跟一個行号。過了幾年之後,編譯器團隊讓程式員使用字元串标簽取代行号。這在當時被認為是一個熱門的新功能。

有的人認為這會導緻“意大利面條式代碼”。代碼會變得不可讀,并且很難了解代碼的執行路徑。線程混亂,纏纏綿綿到天涯。Edsger Dijkstra就三令五申地表示應該禁止這個指令,他有一份诙諧的手稿,題目為《Goto語句害人不淺》。

但絕對的分支是沒有問題的。這就讓人糾結了。通常,巧妙的 break 語句和return 語句可提供一個非常幹淨的關于代碼在那個時候執行什麼的聲明。有時候,添加 goto 到case語句會比更恰當的多級嵌套的if-then-else語句塊更易于了解。

也有反例。在蘋果的SSL堆棧中的“goto fail”安全漏洞就是最好的例子之一。但是,如果我們能夠仔細避免case語句和循環的一些尴尬問題,那麼我們就可以嵌入良好的絕對轉移,使閱讀代碼的人更容易明白這是怎麼回事。我們可以插入break和return 語句,讓每一個人感覺更清潔和更愉快——可能得除了goto的敵視者。

程式設計習慣No. 2:成功避開文檔//某程式員有一個非常精明的老闆

這位老闆雖然從來沒有寫過任何代碼,但卻秉持着每一個功能都必須包含在文檔中的理念。哪個程式員不提供注釋,那麼他就會受到懲罰。是以,這個程式員在他的編輯器中聯入了一個有點像人工智能的玩意兒,于是乎,他的每一個功能就都有幾行“文檔”了。因為這位精明的老闆還不夠聰明到能了解這些注釋其實啥意思也沒有,是以這個程式員逃過一劫。

許多函數方法,甚至一些類或多或少都能自文檔化。冠以insertReservation或cancelReservation或 deleteAll 等名稱的函數并不需要多此一舉來解釋它們的作用。為函數取一個正确的名字往往就足夠了。事實上,這比寫一段長長的注釋要好,因為函數名可以出現在代碼中的其他地方。而文檔隻能默默地呆在某個角落。自文檔化的函數名可以改進它們出現的每個檔案。

在有些情況下,寫文檔甚至會導緻情況變糟。例如,當代碼瞬息萬變,團隊像瘋了似的重構的時候,文檔會産生分歧。代碼是這樣寫的,但文檔解釋的還是四五個版本以前的情況。這類“過時”的文檔通常位于代碼頂部,有的人會在這裡對代碼應該發生什麼作一個美好總結。是以,盡管重構團隊已經仔細修改了相關的注釋,但還是會遺漏檔案頂部的這段“美好總結”。

當代碼和文本出現分歧的時候,注釋就變得毫無價值,甚至會産生誤導。在這樣的情況下,良好的自文檔化的代碼顯然勝出了。

程式設計習慣No. 3:不聲明類型//那些熱愛類型化語言的人認為

如果為每個變量添加明确的資料類型聲明,就可以寫出更好的、沒有錯誤的代碼。花一點時間來拼寫類型,能幫助編譯器在代碼開始運作之前标志愚蠢的錯誤。可能會讓人覺得痛苦,但很有幫助。這是程式設計中停止bug的一種有備無患的方法。

但是時代變了。許多較新的編譯器完全可以智能地通過檢視代碼來推斷類型。它們會向後和向前浏覽代碼,直到可以肯定這個變量是string 還是int,抑或其他。如果這些被檢視的類型不成隊列,那麼錯誤标志就會點亮。是以再也不需要我們輸入變量的類型了。

這意味着我們現在可以在代碼中省略掉一些最簡單的聲明。代碼更清潔,而且閱讀代碼的人也猜得出for循環中命名為 i 的變量表示一個整數型。

程式設計習慣No. 4:搖擺不定的代碼//有的程式員在代碼上特别優柔寡斷,猶豫不決

先是一開始将值存儲為字元串,然後又解析成整數。接着又轉換回字元串。這是非常低效的,你甚至可以感覺到CPU在咆哮這種浪費負載的行為。聰明的程式員之是以能快速地編碼,是因為他們事先會設計架構,以盡量減少轉換。他們的代碼能更快地運作是因為他們有一個良好的規劃。

但是,不管你信不信,這種搖擺不定的代碼有時候也是有意義的。比如說,你有一個非常棒的庫,在它專有的黑盒子裡能做無數智能的事情。如果庫需要字元串的資料,那麼你就給它字元串,即使你剛将這個資料轉換成為整數型。

當然,你可以重寫所有的代碼,以盡量減少轉換,但是這需要時間。而且,有時候讓代碼稍微多花點額外時間來運作也未嘗不可,因為重寫代碼需要耗費我們更多的時間。有時,背負這樣的技術債務比一開始就正确建構的成本要更低。

有的時候,庫不是專有的代碼,但那些你以前全部自己寫的代碼是你獨有的。有的時候,再次轉換資料比重寫庫中的所有代碼要快得多。是以,就讓它這樣吧,就讓代碼搖擺吧。

程式設計習慣No. 5:編寫你自己的資料結構//有一個标準規則

程式員在完成資料結構課程的第二年,不應該寫用于存儲資料的代碼。基本上我們需要的所有的資料結構,已經有人寫好了,而且其代碼已曆經多年的測試和再測試。它和語言捆綁在一起,而且常常是免費的。你的代碼隻能造就bug。

但有時你會發現資料結構庫有點慢。有時它們會迫使我們使用标準的,但于我們的代碼卻是錯誤的結構。有時庫會把我們推向在使用結構之前重新配置資料的地步。有時庫會包含一些所謂有備無患的保護功能,如線程鎖,但其實我們的代碼并不需要。

如果遇到這種情況,那麼就應該着手寫我們自己的資料結構。這或許能讓你做得更快,做得更多。而且代碼會變得更清潔,因為我們不會包括那些多餘的用于格式化資料來完成一些功能的代碼。

程式設計習慣No. 6:重新定義運算符和函數//一些最有趣的程式設計語言允許你去做一些特别詭異的事情

例如重新定義元素的值,就如同常量一般。例如Python,你可以輸入TRUE=FALSE(在Version2.7及之前的版本)。這并不會産生某種邏輯崩潰,或導緻宇宙終結——僅僅隻是互換了TRUE和FALSE的含義。你也可以在C預處理器和一些其他語言中玩玩類似于這樣的危險遊戲。還有一些語言允許你重新定義運算符,如加号。

當然這是延伸了,不過有一個觀點是,在一個大的代碼塊内,當重新定義一個或多個所謂的常量時,速度會更快。有時老闆會要求代碼做一些截然不同的事情。當然,你可以修改代碼的每個事件,或者,你可以重新定義。這讓你看上去像一個天才。不必重寫一個龐大的庫,隻需翻轉一下,就可以做相反的事情了。

對于以上這6種不良程式設計習慣,希望還沒接觸過的程式員不要做輕易的嘗試,不管它看上去有多牛掰,但對于程式員的工作來說,始終都是危險的!

轉載于:https://juejin.im/post/5ce947c9e51d455a694f9491