天天看點

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

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

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 原則避免重複勞動,正交原則避免改動一個元件時牽扯整個系統的維護,可撤銷原則避免更換系統某個元件時導緻系統崩潰。最後,介紹了曳光彈和原型開發兩種快速開發模式,尤其是曳光彈,我比較喜歡用,先小規模、小成本搭建骨架并跑起來,後續再不斷地豐富骨肉,希望以上介紹的内容對你日後開發有幫助。

歡迎關注公衆号「渡碼」,我将分享更多優秀書籍的内容,組織定期抽書活動

繼續閱讀