當前位置:
首頁 > 知識 > 我的if else代碼純凈無暇,一個字也不能簡化

我的if else代碼純凈無暇,一個字也不能簡化

機器之心報道

機器之心編輯部

參與:劉曉坤、王淑婷、李澤南

「我曾接手過一個代碼,裡面是幾十個 if else 模塊……」對於程序員們來說,遇到這樣的事情應該是苦不堪言的——很多人認為這種寫法非常難看、分支眾多、容易出 bug。最近,網友們在容器管理平台 Kubernetes 的 GitHub 上發現了這樣一段代碼,其中的 1700 行 if else 語句卻讓人嘆為觀止。

為了防止「頭鐵」群眾真的去重構它,在這段代碼的開頭,有這樣一段注釋:

不要嘗試簡化此代碼。

請看著它起飛。

這個控制器是故意以非常詳細的方式編寫的。你會注意到:

1. 每個『if』語句都有一個匹配的『else』(除了客戶端 API 調用的簡單錯誤檢查)

2. 在這裡我們要明確地解釋一下

我們把這種代碼叫做『太空梭風格』。太空梭風格是為了確保每個分支和條件都得到考慮——就像在 NASA 編寫太空梭的航天器應用程序代碼一樣。

最初,這個控制器的工作被分成了三個控制器來做。該控制器是為簡化 PV 子系統付出巨大努力的結果。在這種努力中,很明顯我們需要確保在代碼中處理和計算每個條件,即使它導致了無操作代碼分支。

因此,控制器代碼可能看起來過於冗長,有太多注釋和「分叉」。但是,這裡記錄了大量的業務知識和內容,以確保未來的維護者能夠正確地推理綁定行為的複雜性。因此,對此文件的更改應保持太空梭風格。

該文件的 GitHub 地址:https://github.com/kubernetes/kubernetes/blob/ec2e767e59395376fa191d7c56a74f53936b7653/pkg/controller/volume/persistentvolume/pv_controller.go

1700 行的 if 嵌套語句。

作為流行的開源系統,Kubernetes 常被用於自動容器化應用程序的部署和管理。其開發者稱,Kubernetes 擁有 15 年承擔 Google 生產工作負載的經驗。對於人工智慧領域的開發者來說,Kubernetes 可以幫助我們部署深度學習模型(參見:如何使用 Kubernetes 輕鬆部署深度學習模型)。

太空梭的風格

聽說它是美國航天局 NASA 的代碼風格?在 Hackernews 上,眾多網友們在通讀全文代碼後給出了一致好評。

@Klathmon 表示:

我愛死這個了!這簡直就是軟體開發里的「爵士樂」。它打破了所有的固有「規則」,但目的明確,比按照「規則」來的結果要好得多。

乍一看,你會覺得這個文件太大了,裡面充斥著許多分支和嵌套 if 語句,還有很多「無意義的注釋」,僅描述周圍一行或幾行代碼是做什麼的。注釋里還有很多 logic,與實際代碼相比,這些 logic 很快就會過時或者出錯。

但同時,這樣做使得維護和管理代碼變得簡單多了,因為你不用把 logic 拆分成幾十甚至上百個文件。它包含了大量對這個文件需要進行的固有複雜工作,而它的注釋做得又好又多,做任何改變都可以輕易讓注釋一起更新。

@munchbunny 說:

不能更同意了。我日常要處理的代碼不是這個級別,但也有低級別的特點,同樣也比典型的後端代碼更接近 metal,被許多的前端和後端代碼調用。如果有「甚至更後端代碼」的東西,這就是個不錯的例子。如果你忽略了一個細微的差別,一群憤怒的開發人員會在部署代碼時衝到你辦公桌前,而如果你沒有快速修復它,就會出現一群憤怒的顧客。

對於任務關鍵型代碼內部循環中的代碼來說,主要的時間成本並不是寫代碼或者理解代碼,而是根據所服務場景的細微差別進行優化,檢查更改代碼帶來的直接影響,然後檢查更改的二階和三階影響。

當你的代碼非常細化,以至於你做的每個改變都有三階影響時,帶有精心注釋的代碼會更容易維護。因為假如你拼湊了十個不同的文件,需要花費精力弄清正確的路徑,就更有可能忽略其中的細微差別。

關於注釋

很多網友對於帶大量注釋的代碼表示很有用、不反感,並且那些不帶注釋的代碼會帶來很大的麻煩。

@EB66 說:

我完全同意。對於那些不可避免很複雜的代碼,我也喜歡這種風格。

我非常喜歡簡潔且語句/命名是表達性的代碼,但有時候注釋是必要的,以便清楚地闡明邏輯或使用案例。表達性代碼能直接傳達的含義有限。精心設計的注釋可以大大地減少其他開發人員在不熟悉的代碼基礎上所耗費的時間。

關鍵是要更新注釋。沒有比不準確的注釋更噁心的事了。檢查代碼時一定要檢查修改過的代碼行的注釋。

@ascar 說:

解釋使用案例或目的的過時注釋還是比沒有注釋強。它能給你提供背景信息,比如代碼的演變及其目的。

只讀注釋可能比讀沒有注釋的代碼更糟糕,所以一些開發人員反感過時的注釋,因此就有了一般化(過於簡略)的注釋。

注釋是關於代碼的附加信息,沒有事實來源,所以,要同時閱讀代碼和注釋。

@nickharr 說:

我有 25 年以上用多種語言編寫、查看、注釋和檢查代碼的經驗,所以我會說這的確是一個好東西——不管編程的「風格」(或者廣義上來說的語言)如何。

好的代碼注釋可以對生產力產生巨大的影響——無論是對個人、團隊還是企業來說都是如此。它有助於存儲知識(當前和之前的團隊/個人之間容易丟失的信息)。

我個人花了太多時間對那些沒有注釋的代碼進行逆向工程。有時候,經驗豐富的程序員或開發人員會走捷徑:壓縮程序和函數,這些程序和函數是基於他們明確了解的語言和/或領域,但沒有對它們進行註解……

在基本層面上,注釋應該告知、教育、概述和幫助他人理解我們寫代碼時創造的有時很複雜的路徑和函數。

有些人認為好的代碼不需要注釋,某種程度上這是對的,但這一點並不適用於每個代碼庫。有些代碼很複雜、笨拙,就像義大利面,有時甚至難以理解。

我一直努力教經驗較少的開發人員以帶點幽默(可能的話)的方式作出高效的好注釋——讓我們能夠快速理解代碼,欣賞前人所做的努力,並笑對複雜的挑戰。

我個人並不真正關心代碼和注釋的比率。有時,代碼注釋可能比代碼本身更有價值。而有時,它們只是幫助你完成工作;只要快速、高效、沒毛病,就是不錯的代碼。

文件大小

@Klathmon 說:

我從事前端網頁應用開發,其中最複雜的問題在於如何實現代碼庫的快速迭代,大部分情況下都不是實際的業務問題。但儘管「deep functionality and small interfaces」聽起來很不錯,大多數情況下,導出的僅有少量函數的大型文件是不容易維護的。將所有代碼放到同一個文件中,需要你在做出任何修改之前確保透徹地理解它們。

@taneq 說:

他們是有目的地這樣做的,為了確保開發人員在修改之前能理解整個文件,因為其功能非常關鍵,很容易被混淆。此外,將一個邏輯嚴密的文件分割成小型文件(而不是改寫成更小的邏輯模塊)只會導致不必要的文件管理問題。

新手的膜拜

@jml7c5 說:

作為一個初學程序員,我非常震驚這竟然不是編程的標準慣例。一般的源文件應該提供語境、主題背景、解釋概念的參考資料/博客/書籍指南、關於代碼如何匹配程序整體的信息,以及(最重要的)文件中體現的思考過程(即為什麼選擇這種做法而不是其它,面臨的挑戰,權衡等等)。

我還是想不通,每一位程序員都需要從零開始學習使用一個代碼庫。除非肯花費數小時來做測試,想改善一個 non-trivial 的程序是不可能的。致開源開發者:如果你想要讓人們對項目做出貢獻,這些類型的注釋是很基本的,更不要說它們能幫助節省非常多的時間。

@qlk1123 說:

「作為一個初學程序員,我非常震驚這竟然不是編程的標準慣例。」我同意這一點,如果這能成為社區標準,當然會有很多人受益。但是,你不認為一個好的社區文化可以讓人們為此保持良好的習慣嗎?

我的日常工作是 Linux 內核開發人員。我發現源代碼僅僅是「What」部分,注釋中應該聲明「How/Why」部分。並且如果這些還不能使我搞明白源代碼,我會直接電郵作者問更深層次的「Why」部分。大多數情況下信息都是足夠的。

模仿需謹慎

Kubernetes 之外,最近另一個因為代碼而被熱議的程序可能就是在 Steam 上火起來的獨立國產遊戲《太吾繪卷》了。據好奇的程序員介紹,其早期版本中內含數千個 if 語句。由於遊戲主創是中文系出身,隨後又投身建築行業,半路出家寫遊戲代碼——最後居然玩起來沒有什麼大問題,代碼的「糟糕」樣式成為了一個梗,為遊戲的流行起到了助推作用。

這些著名的案例雖然可以運行,但沒有強大的邏輯(運氣)是玩不轉的。科班出身的程序員們一般就不要模仿了。

參考內容:https://news.ycombinator.com/item?id=18772873

2018 人工智慧期末考試正在進行中,衝擊「最高段位:王者機器」即有機會獲得「華為雲獎學金」:66666元。

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 機器之心 的精彩文章:

理解隨機森林:基於Python的實現和解釋
來自谷歌首席的靈魂追問:想當研究科學家,一事無成你受得了嗎?

TAG:機器之心 |