結合自己經歷聊聊注重實效的程序員應該掌握的幾個原則


本篇文章是《程序員修煉之道》第二章的筆記,總結了高效程序員需要遵守的一些原則和常用的開發模式,對我們有非常重要的指導意義。建議每個程序員都應該學習並掌握這些原則。如果大家覺得這個系列文章有價值,我們可以組織一次抽書的活動,鼓勵大家從原文學習。

DRY 原則

軟件開發過程無時無刻都伴隨着維護,如果項目中有大量的重復代碼會對我們的維護工作造成很大的麻煩。比如:一段代碼在多個地方出現, 一旦要修改就需要我們同時修改多個地方,如果某個地方忘記修改就可能導致一些不必要的錯誤。因此作者提出 DRY原則 - Don't repeat yourself(不要重復你自己)

我們平時有不少重復的場景, 同時也有避免重復的解決方法,下面舉幾個例子。

  • 代碼與注釋:我們經常被說教要在代碼里加注釋。但注釋並不是越多越好,我們應該把注釋留給高級的說明,對於比較低級的說明用代碼代替注釋即可。否則,就存在重復的知識,每次修改代碼都要想着修改注釋
  • 代碼與文檔:文檔的更新是永遠滯后於代碼的,經常更新了代碼但忘記更新文檔。我們可以采用一些輔助技術或者自研的技術,比如:API doc、Java doc 之類的工具,代碼更新后,文檔會隨着更新
  • 設計中的重復:假設某個類中有個起始坐標和結束坐標兩個屬性,這時再加一個兩點間距離的屬性就有點重復了,因為我們可以根據起止點計算出距離
  • 臨時性的重復:有時候我們臨時做一些需求可能用到了項目中某段代碼,我們一般會直接復制過來用,這時候也存在重復。更徹底的做法是我們可以把一些比較常用的計算邏輯抽象成接口,形成自己的工具包,需要的時候直接引用即可,無需拷貝代碼。比如:一些常見的求和,求最值等需要 for 循環的處理邏輯是不是可以抽象一個 reduce 函數
  • 開發者之間的重復:這個是比較常見的重復,如果一個項目的兩個組同時開發很容易造成同一個小的邏輯在兩個組的成員有各自的實現,這種重復不太好避免。但我們可以增加團隊之間的交流,可以組織一個平台,把一些比較好的組件開放出來。我做數據開發時經常會用到一些 udf 處理數據,如果我當前項目中沒有,我會到公司的公共平台去搜相應的關鍵詞, 一般都能找到現成的 udf。我比較建議團隊內部開源不同的項目代碼,當然是不涉及機密代碼的前提。我在開發中經常會問上游同學數據怎么處理的,經過了什么邏輯,這樣做一方面增加溝通成本,二來畢竟耳聽為虛。所以我就經常反編譯上游的代碼,以后需要看邏輯不需要問別人,直接看代碼節省非常多的時間。當然開源也有個好處是我們可以學習別人代碼中優秀的地方。

正交原則

正交性就是不相互依賴性或者解耦性。如果兩個或多個事物中的一個發生變化,不會影響其他事物,那么這些事物就是正交的。對應到編程,就是我們常說的高內聚、低耦合。正交的系統好處非常多,正交的系統可以降低風險,當系統中某個組件修改時,只要對外的接口保持不變,該組件就可以任意修改而整個系統不會受到影響。正交的系統能提高生產率,因為系統組件是解耦的,因此各個組件可以獨立地、並行地進行開發。比如最近幾年比較火的前后端分離技術就是很好的代表,以前后端的同學經常需要寫一些套頁面的前端代碼,前后端同學的代碼交織在一起相互依賴。但前后端分離后,只需要把協議確定好,前后端技術就可以解耦,開發同學就可以並行開發,提高生產率。下面列舉幾種維持正交性的方法

  • 設計:設計系統時我們可以采用基於組件的分層架構。每層提供一級抽象,每層只是用其下面的層次提供的抽象,層與層之間的協議/接口穩定且可擴展,下層組件的改動對上層透明
  • 編碼:為了讓代碼保持解構,我們可以開發 “羞怯” 的代碼,對於不需要開放出來的邏輯,可以控制其訪問權限,不被其他組件引用。避免使用全局數據,全局數據涉及多個使用方同時更新,導致組件耦合度較高。避免編寫相似的函數,相似的函數往往有重復的代碼,使得修改代碼要同時更新多處
  • 測試:在進行單元測試時,如果某個單元牽扯系統其余很大一部分,說明該單元與系統其他部分耦合度較大,需要引起開發同學的重視

可撤銷原則

可撤銷原則是說,當系統中某個部分需要改變時,我們能不能很好的撤銷已有的代碼,靈活的適應新變化。因為需求無時無刻都在變化,因此可撤銷性就一直存在。舉個栗子:假設我們開發一個數據庫可視化軟件,最開始的需求是基於 Mysql 的,如果我們不做分層設計,凡是需要增刪改查的地方我們直接寫 JDBC 代碼。但是某一天我們底層數據要支持 MongoDB 怎么辦,因為我們的 JDBC 代碼分布在項目的各個模塊的代碼中,幾乎無法撤銷,這時候系統只能重寫。如果我們設計之初將數據訪問層作為一個組件抽象出來,那么上層只需要調用抽象出來的接口來操作數據庫。這樣做的好處是當需要支持其他數據庫時,只需要為該數據庫編寫支持我們抽象接口的數據庫訪問代碼即可,因此系統就具備可撤銷性的。其實,我們在 Web 項目中經常使用 ORM 框架也是基於可撤銷原則的,ORM 可以將數據庫表映射成對象,底層的增刪改查對上層透明,所以可以靈活地調整底層數據庫。

曳光彈與原型

在黑暗中需要打擊軍事目標時通常會使用曳光彈,它在槍與擊中的地方之間留下一條煙火般的蹤跡,用來指示彈道和目標,從而協助射手修正彈道。其實,黑暗中的目標就像我們開發中面對的未知系統。面對未知系統,如果我們制作大量文檔,逐一列出每項需求,嘗試確定所有未知因素,就猶如在黑夜中對目標未知預先進行大量計算然后射擊,很顯然這種情況需要消耗大量計算力並且不一定能擊中目標。而注重實效的程序員往往更喜歡使用曳光彈。曳光彈的核心優勢就是反饋是及時的。比如:我們要開發一個支持多種序列化格式的 RPC 框架,最開始我們是不是可以先用簡單的系統默認的序列化方式先將整個系統框架搭建起來,先讓系統能夠運行起來。運行后我們可以及時地得到使用方的反饋,修復已有問題、增加多種序列化框架、不斷迭代完善。

介紹完了曳光彈再來說說原型,記得在大學學習《軟件工程》時就接觸了原型開發。原型更像是一個 Demo,不注重代碼的實現,而是能夠快速出一個能夠與產品確定需求的東西。比如:我們需要確定某個系統的 UI 需求,我們可以用最快的開發語言,開發出一個 Demo,它的代碼不需要規范,交互界面也不需要太美觀,因為原型大概率不會在后續實際的項目實現中使用。

接下來簡單總結一下這兩種開發模式的區別。曳光彈強調的是明確需求后,我們能不能開發出一個麻雀雖小、但五臟俱全的系統來快速獲得反饋,從而指導我們進一步迭代。在曳光彈開發模式下,后續代碼是依賴於第一版的代碼。而原型開發更側重明確需求這個階段,快速開發一個 Demo ,目的是為了能夠基於原型確定系統的需求。這個階段不在乎用什么代碼、不在乎系統的完整性、健壯性以及正確性,因為原型代碼基本不會用在真實的系統開發中。

領域語言與估算

這節內容我覺得平時應用不多,理解的不深刻,因此就簡單總結。領域語言我的理解就是使用(創造)一門規范的偽代碼,為什么是偽代碼呢?假設我們與產品溝通需求,我們可以使用文字,但我們都知道中華文字博大精深,別人表達的意思跟我們的理解可能不一致,否則的話我們也不需要這么苦逼的加班,當然直接用編程語言溝通更不可行。那么就需要一個中間層的偽代碼,既能清晰的表達出需求,又能讓產品或者使用不同編程語言的程序員都能看懂。

對於估算這一節,作者介紹了一些常見的預估問題(估算項目時間、流量)的一些指導性意見,但感覺比較偏理論,實操性不強。但給我印象最深的一句話是:在咖啡機旁給出的估算將像咖啡一樣回來糾纏你。也就是說估算不等於不假思索的回答,我們可以用 “這個問題我現在答復不了,我回去想下” 之類的話術先應付一下,后續再詳細地思考。

小結

本章主要介紹了三個原則中,這三個原則如果在開發中加以總結和利用將對我們高效地開發非常有幫助。DRY 原則避免重復勞動,正交原則避免改動一個組件時牽扯整個系統的維護,可撤銷原則避免更換系統某個組件時導致系統崩潰。最后,介紹了曳光彈和原型開發兩種快速開發模式,尤其是曳光彈,我比較喜歡用,先小規模、小成本搭建骨架並跑起來,后續再不斷地豐富骨肉,希望以上介紹的內容對你日后開發有幫助。

 

歡迎關注公眾號「渡碼」,我將分享更多優秀書籍的內容,組織定期抽書活動

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM