為什麼我看不懂你的代碼

2020-12-11 開源中國

「我到底在想什麼?!?」

凌晨1:30分,我正盯著不到一個月前我寫的一段代碼。當時它看起來像是件藝術品,全部是可理解的,優雅、簡單、讓人嘆為觀止。這一切都不再了,明 天是我的最後期限,數小時前我發現了一個bug。當時看起來的簡單和邏輯再也說不通了。可以肯定的是,如果我寫代碼,我應該足以聰明到理解代碼?

經過了多次這種經歷以後,我開始認真思考,為什麼我的代碼在我編寫的時候很清楚、而當我數周或數月後回頭看的時候,它們卻那麼費解。

問題1,過度複雜的邏輯模型

為了理解當你間隔一段時間返回到你的代碼、卻發現代碼難以理解的第一步,就是理解我們如何從心智上建立問題模型。你寫的幾乎所有代碼都是儘量解決現實世界的問題。在你寫代碼之前,你需要理解你正試圖解決的問題。這常常是編程裡最難的一步。

為了解決現實世界的問題,我們首先需要形成該問題的心智模型【注1】,以此作為編程意圖。接下來你需要形成實現編程意圖的方案模型,我們姑且稱為語 義模型(semantic model)。從來不要混淆你的編程意圖和此意圖的方案。我們傾向於主要考慮方案方面的東東,而常常忽略意圖的模型。

你接下來的步驟是形成可能最簡單的語義模型。這是容易搞錯的第二步。如果你不花時間去真正理解你正試圖解決的問題,你將在寫代碼時被絆倒在模型上。另一方面,如果你真正考慮了你正儘量做的事情,你經常得到一個非常簡單的模型,這足以讓你掌握最初的意圖。

如果你想容易地維護簡單的代碼,就儘可能多些地消除意外的複雜性。我們正試圖解決的問題是足夠複雜的。如果你不必那麼做,就不要把意外的複雜性增加進來。

問題2,笨拙的把思想轉化成代碼

一旦你盡全力形成了最好的語義模型,那麼就到了把它轉化為代碼的時候了。我們稱之為句法模型(syntactic model)。你正試圖把你的語義模型的意義轉化為計算機能夠理解的句法。

如果你有非常不錯的語義模型、而在轉化為代碼時搞砸了,那麼在你需要在以後某個階段回頭修改代碼時,你將比較痛苦。當你腦子裡還有語義模型時,把你 代碼映射到語義模型是容易的。回憶起變量「x」實際上代表一條記錄被創建的日期、而「y」代碼記錄被刪除的日期,這是不難的。當你3個月後再回來看代碼, 你的腦子裡將沒有這個語義模型了,因此無法理解同樣的變量名字。

把語義模型轉化為句法的任務就是儘量多地留下線索,讓你在今後返回時,能夠重建當初的語義模型。

好了,你該怎麼做呢?

類結構和命名

如果你在使用面向對象語義,請儘量讓你的類結構和命名靠近語義模型。領域驅動設計(Domain Driven Design)【注2】是在這種練習上投入了相當重要性的一種運動。即使你沒有相信完全的DDD方法,你也應當非常小心地考慮類結構和命名。每個類都是你 留給自己和其他人的線索,它幫助你在將來返回的時候重建你的心智模型。

變量、參數和方法命名

儘量避免普通的變量和方法命名。不要把方法命名為「Process」,因為「PaySalesCommision」更有意義。不要把變量命名為 「x」,因為它應當是「currentContract」。不要把參數命名為「input」,因為「outstandingInvoices「更好。

單一功能原則(Single responsibility principle,簡稱SRP)

SRP【注3】是面對對象設計原則的核心之一,關聯著好的類和變量命名。它認為,任何類或方法都應該完成一個單一的功能,只能是一個單一的功能。如 果你想為類和方法給出有意義的名字,那麼它們需要有一個唯一的較好定義的目的。如果一個單一類從資料庫讀和寫、計算營業稅、通知交易客戶並生成帳單,那麼 你就可能無法給出合適的名字。我常常停留在重構類上,因為我總是努力取一個足夠短的名字,以描述它做的每個功能。為了更多地討論SRP和其它面向對象原 則,可以參考我的博文《面向對象設計》。

適當的注釋

如果因為某種原因,你不能讓代碼變得清晰,你同情將來的自己,需要不得不做些事情,那就留下注釋來說明你為什麼不得不那樣做。注釋傾向於快速地變得陳舊,因此我寧願儘可能讓代碼自描述,注釋用來說明為什麼你不得不那樣做,而不是它如何做。

問題3,沒有足夠的組塊

心理學上的組塊被定義是,把信息組塊定位為單一的實體。那麼這該如何應用到編程上呢?作為一名開發者,在你積累經驗時,你開始發現你解決方案裡反覆 出現的模式。極具影響的設計模式:《可重用的面向對象軟體》是第一本整理和解釋一些模式的書。儘管如此,組塊不僅僅用在設計模式和面向對象。在函數式編程 (FP)裡,存在大量的著名標準函數具備這同樣的目的。算法是組塊的另一種形式(後續會更多)。

當你合理地使用組塊(設計模式、算法和標準函數)時,它讓你停下來思考,你編寫的代碼是如何運行的、而不是考慮它做了什麼。這縮短了你的語義模型(你的代碼)和句法模型(你腦子裡的模型)的距離。這個距離越短,你就越容易重建你的心智模型。

如果你有興趣了解更多FP裡的函數,請移步到我的文章面向web開發者的函數式編程。

問題4,費解的用法

目前,我們主要討論了如何結構化你的類、方法和變量命名。心智模型的另一個重要部分是理解這些方法應該怎樣被使用。再次強調,當你最初形成心智模型 時,這是相當清晰的。當你後來返回時,就非常難以重建你的類和方法的、所有有意圖的用法了。通常這是因為不同的用法散布在你的程序其它地方。有時候甚至出 現在很多不同的項目中。

我就是在這種情況下發現測試用例是非常有用的。除了相應地知道一個修改是否破壞了代碼的明顯好處,測試為你的代碼提供了一整套的用例。你不必搜遍100個文件,只需看測試就能得到引用的全景。

注意為了達到這個目的,你需要有一整套完整的測試用例。如果你的測試僅僅覆蓋了一部分、而你認為測試是完整的,那麼你後來將陷入困境。

問題5,不同的模型之間沒有清晰的途徑

你的代碼從技術角度看,常常是優秀的、非常優雅,但是從程序意圖到語義模型、再到代碼存在非常不自然的跳躍。考慮你選擇的一堆模型的透明性是重要 的。從程序意圖到語義模型、再到代碼的過程需要儘可能平滑。你應當能夠看透對應到問題的每個模型的所有方面。多數情況下,最好選擇特定類結構或算法不是為 了它在隔離方面的優雅,而是可以連接各種模型,為你重建的目的而留下 一條自然的途徑。當你從抽象的編程意圖走到具體的代碼時,你做的選擇應該受到 你能夠表現更為抽象模型 的清晰度驅使。

問題6,發明算法

作為程式設計師,我們經常認為,我們在為了解決問題而發明著算法。事實很難是這樣的。幾乎所有情況下,已經有現成的算法可以被組合在一起解決你的問題 了。像最短路徑搜索法、字符串相似度算法、粒子群算法等。大部分編程是以正確的組合、選擇現存算法來解決你的問題。如果你正在發明新算法,那麼,要麼你不 知道合適的算法、要麼你正忙於你的博士論文。

總結

最後總結:作為一名程式設計師,你的目標是建立能夠解決你問題的、儘可能簡單的語義模型。把語義模型儘可能靠近地轉化為句法模型(代碼),儘可能多地提供線索,便於你之後無論哪個人看你的代碼,都能重建像你最初腦子裡的、相同的語義模型。

設想一下,當你走過你代碼的被照亮的森林時,你在身後留了麵包屑。相信我,當你需要找到回去的路時,森林將充滿了黑暗、朦朧和不詳的預感。

聽起來容易,實際做起來是很難的。

原文出處:www.labazhou.net

相關焦點

  • 程式設計師:為啥我寫的代碼幾個月後自己也看不懂?
    不要寫「太牛逼」的代碼!"傻瓜式代碼" != "低性能代碼」=========華麗的分界線==========程式設計師同志們大多都會有這樣的經歷,就是要看別人的代碼。比如說公司有同事離職了,他的那塊業務就需要有其它的小夥伴們給接下來繼續維護。這對好多程式設計師來說是種折磨,邊看邊罵,這寫的是什麼東西呀。相信好多人都有這種經歷。
  • 為什麼我要垂直對齊代碼(你也要如此!)
    上周在 HackerNews,關於 Linux Kernel 代碼風格展開了有趣的討論。在討論中,我就應不應該垂直對齊代碼發起了一場小小的聖戰。我完全支持!讓我細說端詳。什麼是垂直對齊?我不用多費事,就輕鬆地看出來它們都是整數。這條意見還沒被廣為分享,因此我打算解釋一下,為什麼很多人認為這是一種有用的風格指南。理解90% 的編程工作是為了解決問題,剩下的 10% 的工作需要再用 90% 的時間用來理解問題是怎樣被解決的。注1閱讀代碼和閱讀散文,有著極大的不同。
  • 不懂代碼,如何一小時免費建立個人網站
    不懂代碼,不懂網頁設計能建網站嗎?  前幾天面試了一個小夥伴,交談的過程中他告訴我,他目前最大的夢想就是擁有一個個人網站,但時讓筆者小小驚訝的同時也非常感慨。
  • 是個狼人:你讓我聽不懂聽力,休怪我讓你看不懂翻譯
    是個狼人:你讓我聽不懂聽力,休怪我讓你看不懂翻譯!,那它在我眼中就是個弟弟。」我又確認了一下,發現周圍的同學都在翻頁,然後我小心翼翼地打開了我的試卷,OMG,原來答案選項都在裡邊,我塗了個寂寞……(估計監考老師都懵了,還有這麼牛X的同學?卷子都不看撲哧撲哧塗啥呢?)我的閨蜜:天知道我為什麼把運輸方式記成了傳統習俗,好傢夥,人家寫火車高鐵飛機,我在寫月餅湯圓餃子,怎麼說呢?重在參與吧!
  • 程式設計師曬出實習生的一段代碼,表示看不懂!網友:out了,新寫法
    技術總是在不停的更新迭代,這就是程式設計師為什麼要保持學習能力的原因了,與其他行業相比,程式設計師不學習新知識,只是保持現有的技術,幾年後再回頭看看,就可能與同行落下去一大截,當然,對於技術的更新也是徐徐漸進的,只要有一定的技術嗅覺,多留意一些技術官方網站的最新發布, 多留意一下發展的動向就不會那麼輕易落後
  • 我不懂你的高尚,正如你不懂我的矯情
    我終於還是鼓起勇氣拿起飯盒去打飯了,不希望認識我的人看見,更怕別人問我為什麼一個人,我的步子走的很快,原來這就是自卑的我,但看到自己可以吃到熱氣騰騰的飯,也是心情不錯。  不想去吶喊什麼,也絕對吶喊不出什麼,反正註定我就是這樣高調,這樣需要自嘲。  你說一個人沒什麼,是啊,沒什麼,畢竟我不是你,你不是我,我不懂你的高尚,你不懂我的矯情一樣。
  • 不懂技術的HR如何看技術人員的簡歷
    最開始我是把簡歷當成一個個小說來看,有長得很漂亮的,還有的會有一些很奇葩的經歷,比如有參加過非誠勿擾的、中過什麼獎的,但合上簡歷後,我還是不知道這是一個什麼樣的人,以至於我真正拿起電話和他聊的時候,我發現和每個人聊的都一樣:「你好,您為什麼從上一家公司離職,你在上一家公司做的是什麼東西,遇到過什麼問題,有沒有什麼讓你印象深刻的,你是怎麼解決的,有沒有沒有解決的問題
  • 抖音24萬人點讚的微信表白代碼,心動了
    講真今天這個代碼系列我期待好久了這次的代碼都是複雜的符號最近在抖音上非常火我截圖的時候有24.8w贊>一般人都看不懂,超級神秘了直接複製使用, (寒冷的天氣多穿衣服你知道我愛你) , (我想告訴你
  • 為什麼你寫的代碼糟透了?
    就好像你想成為一名演員,但又懷疑自己是否擅長表演。作為一名教授全棧 Web 開發的教育工作者,我教過很多「初次進入這個領域的程式設計師」。好消息是,我很少會遇到無法學會編程的學生。我認為編程是人類的一項基本技能,就像閱讀、寫作和算術一樣。任何人都可以做到,它是人類能力的一部分,但確實需要進行有意識的學習。
  • 程式設計師的呆萌表現:外行人看不懂,內行人笑一天
    有句話叫做「內行看門道,外行看熱鬧」,但在程式設計師這一行,這句話反過來的機率很大,往往是外行人看門道,內行人看熱鬧。外行人總是覺得那些腦袋亮的程式設計師是技術高的程式設計師,認為代碼寫得多的是高手,看到一頁代碼,就要用有限的英語水平去看一下,說什麼需求什麼功能,頭頭是道。
  • 淘客的苦衷:不懂代碼沒有網站 如何做淘寶客
    首頁 > 評論 > 關鍵詞 > 淘寶客最新資訊 > 正文 淘客的苦衷:不懂代碼沒有網站 如何做淘寶客
  • 遺留代碼寫的爛,我能怎麼辦?
    聽到這,相信寫過代碼的同學都會產生一個質疑:「為什麼要隨機休眠?」是的,這就是他們倆爭論的原因。先別急著吐槽,如果只站在 「執行通過」 的角度,你覺得這代碼有問題嗎?粗糙的說,這代碼不但能運行,而且作為一個企業內部系統,只要並發不達到一定規模的情況下,是絕不會出現異常的。既然如此,那為什麼還要爭吵?
  • 3D遊戲編程:遊戲代碼的整體結構是什麼樣子的?
    也就是說,你能把前面17節的內容完全掌握了,你的3D遊戲編程基礎就有了,接下來再講解代碼,你就很容易明白了。從這一節開始,我們將要把整個3D遊戲示例程序的代碼講解一遍。由於有Direct3D的幫忙,我的程序代碼只有1000來行,所以,即便你是初學者,也是可以學明白這些代碼的。
  • 雅思閱讀你為什麼總是讀不懂?
    那為什麼雅思閱讀很多學生總是讀不懂呢?這個問題的答案似乎很簡單,因為幾乎所有雅思閱讀讀不懂的學生都會說是因為單詞量太差,還是得補單詞。的確,詞彙是很多同學讀不懂的原因之一。很多學生的硬傷是詞彙量比較小,詞彙量小讀起來味同嚼蠟。不背單詞,做雅思閱讀就是以下這種感覺:我們知道賢鑜是在生活中很重要的。
  • 「女人為什麼要練瑜伽,你懂不懂?」我好像懂了!
    女人為什麼要練瑜伽,你懂不懂?哈哈哈哈哈我好像懂了!!這真的是一年級的入學測試嗎,小愛感覺自己的9年義務教育好像是白學了,根本啥就不懂。各位厲害的網友們,你們知道這些題到底是怎麼做的嗎???????看看這設計,張開手掌對著你,仿佛再和你告白一樣。就是晚上開車要注意了,一不小心就能被嚇著第一張圖就像你們剛戀愛時候的樣子,男生一直在找女生說話,女生覺得自己應該保持高傲,不理男生。等到後來真的愛上了男生,去找男生說話,可是這時男生已經不愛她了,變成了女生一個人自言自語。
  • 論文讀不懂怎麼辦?
    可你非得拖到截止日期的前一天晚上才打開看,希望畢其功於一役…… 這顯然是態度問題。但是,不可忽略的,有些同學,卻真的不是態度問題,而是方法不當。他們喜歡跟論文死磕。讀不懂,就一遍一遍反覆讀,試圖從字裡行間,悟出精髓。
  • 面試官問:請拿出一段體現你水平的代碼,我該如何回答?
    把這段代碼給他看,既有多線程的知識,又有排序方法。第一種是有備而來的面試者,你最好去面試的時候帶一個百寶箱:兩份簡歷,一兩張紙印了你最擅長的代碼,如果更準備充足點,帶上你的筆記本,或者平板,兩者都要能上網、或者已經緩存了你的作品。如果你沒準備,孤身去了被問這個問題。那麼你要看你的面試官了。那種一看就是技術派,會在問你的時候,糾纏技術細節的面試官,你無論寫下什麼代碼,都會被挑刺的。
  • async,await執行流看不懂?看完這篇以後再也不會了
    昨天有朋友在公眾號發消息說看不懂await,async執行流,其實看不懂太正常了,因為你沒經過社會的毒打,沒吃過牢飯就不知道自由有多重要,沒生過病就不知道健康有多重要,沒用過ContinueWith就不知道await,async有多重要,下面我舉兩個案例佐證一下?
  • 《我的世界手機版》創世神代碼是什麼 創世神代碼詳解
    《我的世界手機版》是一款自由度很高的創意類沙盒遊戲,但是在遊戲中我們就只能做普通人了麼?那麼今天小編來給大家介紹一下創世神代碼,這是一個能一口氣成神的代碼哦,希望大家喜歡!~slippery [SLIPPERYNESS]讓某個塊變得很滑(像冰)longerlegs讓腿更長,可以跳2格等atlantis亞塔蘭迪斯模式spawnportal製作一個地獄傳送門clone [QUANTITY]複製你正在看的npc (滑鼠對著的)
  • 醫生的處方,為什麼完全看不懂,原因在這裡!
    正文有人去醫院就診,當醫生開好藥方,發現完全看不懂,大多數人很想問「醫生寫的是什麼啊?我怎麼看不懂呢?」不只是國內,國外醫生的字同樣讓人看不懂。美國醫學會曾經在7年內頒布了三條政策,就是為了讓醫生們改進挺潦草的處方筆記。