程式設計師如何寫出更好的程式碼

infoq發表於2016-06-08

  Martin Thompson是Java Champion稱號獲得者,同時也是一名高效能運算科學家。他說,為了寫出更好的程式碼,程式設計師需要運用基本設計原則,閱讀已有程式碼。在QCon London 2016大會上,他做了題為“挖掘你的工程師屬性(Engineering You)”的演講。InfoQ在會後採訪了他,內容涉及軟體行業面臨的挑戰及程式設計師如何應對那些挑戰成為更好的軟體工程師。

 

  InfoQ:您在演講中引用了1968年第一屆NATO大會上有關軟體工程的一些內容,它們仍然成立。軟體行業為什麼還是在苦苦掙扎?

Martin Thompson:1968年的NATO大會有好幾個主題。他們認識到,軟體行業存在交付危機。他們也看到了一些成功的專案,並且希望弄清楚如何吸取好的經驗,進行更廣泛地應用。在我看來,其中有幾點比較突出,就是認識到軟體開發是一個迭代過程,注重試驗/學習,需要專門人才領導,並且最好是在小型團隊內完成。他們在幾十年之前就從許多方面描述了TDD和敏捷這些在當時並不常見的做法。

作為一個行業,我們已經取得了很大的進步,但是我們仍然有很長的路要走。軟體開發是一個非常年輕的學科,我們仍然有很多東西要學。我喜歡Dijkstra對它的描述,“煥然一新(radical novelty)”,而使用一些很不恰當的隱喻和類比,會註定我們的失敗。軟體構建是在之前活動基礎上的躍變。這些活動和約束與之前的活動截然不同。有些人有這方面的天賦,有些人需要學著做,而大多數人很掙扎。在土木工程學方面,我們耗費了幾個世紀才具備了現在的能力,因此也就不奇怪軟體行業當前的掙扎。

  InfoQ:您為什麼認為理解基本設計原則,如耦合和內聚,很重要?

Thompson:軟體開發面臨的其中一個最大的挑戰就是處理應用程式規模增長帶來的複雜性。物件、元件、模組或系統之間的耦合程度越高,我們需要承擔的後果就越多。這些後果包括但不限於修改困難、故障蔓延、由於爭用而無法擴充套件、由於關聯操作而導致的效能問題。時間、空間和實現上的鬆耦合對於擴充套件性和彈性而言至關重要。“共生性(Connascence)”可以很好地描述耦合,一個模組/元件的變化會導致另一個模組/元件的變化。

我發現,內聚比耦合更微妙。我喜歡將內聚理解為統一性。當我們考慮在不同的方面使用同一個元件時,就失去了統一性,這會導致不必要的行為和特徵。軟體設計中的低內聚常常是一個很好的需求或團隊狀況指標。通常,內聚設計很容易跟蹤,由於相關的函式和特性都進行了分組,相互關聯,所以可發現性很高。

如果我們希望成為更好的軟體工程師,那麼提高我們運用基本設計原則的技能應該成為我們日常活動的核心。在訓練和實踐中不斷重複是讓技能成為第二天性的最好方法。

  InfoQ:您能舉幾個例子說明下,如何運用分解和抽象幫助開發人員寫出更好的軟體嗎?

Thompson:我認為,抽象是軟體開發領域被人誤解得最深的話題之一。Dijkstra將抽象描述為一種建立“新的語義層次”的方式,“在這個語義層次中,一個人可以做到絕對精確”。大多數開發人員都完全是亂用這個術語,建立他們所謂的抽象來掩飾他們不懂的東西。Joel Spolsky甚至發明了“抽象洩露(leaky abstractions)”原則,拙劣地想為這種誤解正名。我們有些很棒的抽象示例,如Linux核心或裝置驅動中的塊裝置,但遺憾的是,大多數軟體抽象通常是源於某種形式的精神自慰,導致弗蘭肯斯坦怪獸的誕生,讓程式碼更難以處理,而不是更嚴密更容易理解。糟糕的抽象比重複的成本更高。

我們需要更擅長將業務目標分解成可衡量的具體成果,然後以高質量、低耦合的可組合元件為基礎構建軟體。商業公司希望我們在他們的框架內完成構建,那樣他們可以鎖住客戶。這些框架是錯誤的示範。它們是商業壓力催生的產物。商業壓力與交付高質量的可維護軟體往往是矛盾的。

如果看一下其他工程學科,我們就會看到,工具的使用是為了支援交付流程,而不是強加一個流程。我們似乎展現了這個時代的一個特徵,商業廣告聚焦於人天價格、per-CPU許可及鎖定維護合同。現在,類似Amazon這樣的公司提供了實用計算,讓我們可以根據需要使用。非常有趣的是,雲端計算很好地支援了持續整合和交付模型。這改變了市場格局,推動了更好的行為。我們也可以從工具方面看待這個問題,類似Jetbrains這樣的公司將你鎖定在他們的產品合同上;他們是通過提供可以提高生產力的優秀產品把你鎖定的。

  InfoQ:您提到,把重讀程式碼作為發現缺陷或改進程式碼的方式。您能詳細地闡述下嗎?

Thompson:任何創造性的嘗試都可以從不斷地審視和完善中受益。你曾經回過頭來閱讀已經寫好的郵件、論文、部落格或報告等等,然後覺得某些部分可以做得更好呢?這是一件很自然的事情。當我們回過頭來看時,情況不同了,我們會有新的認識。從最簡單的層面來說,我們的寫作初衷已經從我們的短期記憶中消失了,我們必須真正的重讀和思考。換句話說,我們有了更多的資訊,世界發展了,我們的知識也豐富了。

我喜歡將程式碼視為一個可以捕獲當前看法的地方。我們都會犯一些回過頭來看時可以糾正的錯誤,除了糾正這些錯誤外,我們還可以記錄我們更深入的理解。一般而言,應用程式是業務流程的軟體模擬。如果軟體沒有捕獲當前瞭解的業務流程,那麼開發人員就必須做一個心理對映。在任何專案中,心裡對映都是一個很大的負擔。這是我認為領域驅動設計是一個重要的軟體開發工具的原因之一。

定期閱讀所有的程式碼,而且不只是你自己的程式碼。閱讀他人的程式碼是一種很棒的學習方式。正如作家Stephen King所言,“讀其他人的書是讓你成為一個更好的作家的最好方式。”這同樣適用於程式碼,開源是我們這個行業採取的最好的措施之一。通過公開開發軟體,我們可以分享理解,獲取反饋,向其他人學習。參與開源是讓你成為一名更好的工程師的最佳方式之一。

  英文原文What Programmers Can Do to Write Better Code

相關文章