友快網

導航選單

一些賊好用的開發原則

點選載入圖片

我是一個著迷於產品和運營的技術人,樂於跨界的終身學習者。歡迎關注我喲~

每週五12點 按時送達~

我的第「197」篇原創敬上

大家好,我是Z哥。

不知道在看這篇文章的程式設計師夥計們平時是如何寫程式碼的?有參照什麼原則嗎?還是說寫到哪算哪?

如果你在搜尋引擎裡搜一下「軟體開發原則」,可以搜到N多種原則,每一個原則看上去都很有道理,很對。

下圖就是我之前整理的一個與設計原則相關的思維導圖。

點選載入圖片

但是不管你整理的多好,很多人到實際寫程式碼的時候完全想不起這些原則。不用自我懷疑,大多數人都是如此,你並不是特例。

之所以會有這樣的情況,是因為總結後的原則大多都太抽象了,往往只有一句話,甚至只是一個詞,自然不會有太多深刻的印象。

我們今天不聊這些刻板的名詞,來聊聊Z哥在工作中常用到的一些“原則”,以及它們的適用場景,幫助你更好地記住它們。另外,我還給它們做了一下分類,更便於你記憶。

/01 耦合/

01避免迴圈依賴

這個原則不管是在單體應用,還是分散式應用裡都是非常重要的一個原則,它可以避免「big ball of mud」專案的產生。而且,如果專案裡存在著過多的迴圈依賴,也更容易一不小心寫出迴圈呼叫的程式碼,讓整個系統陷入死迴圈。

02儘量單向依賴

在滿足「01」的前提下,儘量做到單向依賴可以大大降低閱讀程式碼、排查問題時的複雜度。如果實在對上游有依賴的話,儘量透過IOC的思路來處理,用隱性依賴代替顯性依賴。

如果實在沒法透過IOC來解決的話,可以將依賴上游的資料在當前系統冗餘一份,然後透過MQ來保持資料同步,在業務處理的時候直接使用本地的這份冗餘資料。當然,這個方法的複雜度明顯比上面的更高,所以還是優先考慮上面的方案。

03避免跨層呼叫

在滿足「1」和「2」的前提下,儘量做到避免跨層呼叫,可以很起到更好的封裝效果。

舉個最簡單的反例,就拿三層架構來說,如果應用層的程式碼可以直接訪問資料訪問層,那麼業務邏輯層自然會形同虛設。而且,後續一旦涉及到某資料表增加一個引數,要修改的相關呼叫程式碼可多了……這也是為什麼很多維護不善的老專案越往後大家就越不敢亂動程式碼的主要原因之一。

/02 物件設計/

01單一職責原則

其實我在後面會提到SOLID原則,這裡為什麼將單一原則單獨拿出來說呢,因為我覺得它是SOLID的六大原則裡最重要的,雖然它看上去最簡單。

單一職責原則規定一個類應該有且僅有一個引起它變化的原因,否則類應該被拆分。

——Robert C. Martin《敏捷軟體開發:原則、模式和實踐》

只有深刻理解這個概念,你才能真正發揮面向物件程式語言的最大優勢。並且,這個思路也可以運用在模組的劃分上。

遵循這一原則最關鍵的地方在於職責的劃分,很多人其實並沒有掌握好正確的劃分思路。因為這個的確很難,需要你對業務有深入的瞭解,因為職責存在於業務裡。

比如,在電商系統裡體現「一個商品在某個平臺銷售」這個業務,你可以既在「商品」類上設定「銷售渠道」屬性,也可以在「銷售渠道」上設定「在售商品列表」屬性,還可以單獨設計一個「商品繫結銷售渠道」的類。但是我們從單一職責原則來考慮的話,就應該選擇最後一個方案。為什麼呢?因為在不同的渠道銷售商品,其實對商品和銷售渠道本身都沒有什麼影響,商品還是那個商品、渠道還是那個渠道,因此這個業務不是它們的職責。

02減少if else

這一點可能算不上傳統意義上的原則吧。但是我覺得這是很容易體現開發水平高低的一點。所以也列了一下。

大部分的 if-else 都可以合理運用設計模式來消滅掉。比如, 狀態模式、策略模式、命令模式、責任鏈模式、代理模式。

如果對這些設計模式的形態有些模糊了,那麼趕緊去回顧一下。

03資料冗餘

冗餘資料的確可以帶來很多便利,比如減少RPC請求查詢其它程式內的資料。但是副作用也是很明顯的,付出了需要解決資料一致性問題為代價。因此僅當存在效能要求時,才考慮資料冗餘。

在平時的程式碼設計中,你可以有很多方法來降低不必要的資料冗餘,比如:

給每一個API或者Function區分必要引數和可選引數。如此一來,對呼叫方來說能夠減少為了傳入可選引數而做的不必要的資料冗餘以及RPC請求。

如果是會對外提供訪問的API,一定要最小化引數,可以自行獲取的資料儘量在內部自行獲取,不要求外部傳入。目的同1。

我覺得能意識到上面的這些設計原則,已經算得上是一個合格的程式設計師了。如果想要更近一步,還可以在以下這幾個方面考慮。

/01 物件設計/

01SOLID原則

這個原則鼎鼎大名了,應該大家都知道,就不展開說了。

Single Responsibility Principle:單一職責原則

Open Closed Principle:開閉原則

Liskov Substitution Principle:里氏替換原則

Law of Demeter:迪米特法則

Interface Segregation Principle:介面隔離原則

Dependence Inversion Principle:依賴倒置原則

我為什麼將它們放到進階裡面呢,因為我覺得這裡面除了單一職責,其它幾個原則還兼顧著在可擴充套件性上的考量。所以,除了單一職責以外的原則沒做到位,最多犧牲了可擴充套件性和一定的耦合度。但是單一職責沒做好,可會存在非常大的耦合問題。

/02 資料準確性/

01可重試

這點可能在單體應用中感受不明顯。但是在分散式系統卻重要得多。因為網路是不可靠的,如果設計的程式碼不可重試,那麼會存在大量的資料不一致問題需要手動去處理。可頭疼死你。

02冪等

重視「冪等」的原因和「可重試」一樣,在單體應用中作用不大,最多對瞬時的重複點選有作用。但是在不可靠網路的分散式系統中,某個請求被重複提交的可能性大大增加,如何保證多次請求的結果是一致的就至關重要了。

03CAP、BASE

前面的「可重試」和「冪等」更多是在程式碼級別的資料準確性設計。如果在整個大系統層面考慮資料準確性,需要基於經典的CAP定理、BASE理論去設計。什麼業務場景需要保證強一致性,什麼業務場景可以接受存在延遲的最終一致性,是需要仔細考量的。

多提一句,如果採用最終一致性方案的話,儘可能地增加一個後續的核對機制,以解決某些非同步訊息在中途丟失、長期異常掛起等等導致的資料不一致問題。

/03 資料儲存/

01資料安全

其實,要在程式碼設計上考慮資料安全,只需要一些非常基礎的業務意識就夠了。你只要能識別到哪些資料是敏感的,針對這些資料做一些保護機制,防止資料洩漏。比如,加密、脫敏、避免越權、減少非必要傳輸等等。

以上的這些是我目前暫時想到的在工作中最常用的開發原則。如果後續再想到什麼我會補充在評論區,也歡迎你在評論區發表你的經驗之談。

還是總結一下,這篇呢Z哥與你分享了一些我在工作中常用的開發原則。總體來說,他們分為4類。

耦合:避免迴圈依賴、儘量單向依賴、避免跨層呼叫。

物件設計:單一職責原則、減少if else、資料冗餘、SOLID原則。

資料準確性:可重試、冪等、CAP、BASE。

資料儲存:資料安全。

希望對你有所幫助。

“大道理都懂,但還是過不好這一生”。這句話也能適用在這裡,“開發原則都懂,但發現眼前的專案還是如此不堪”。

之所以如此,我覺得是因為很多時候,我們假裝沒看到專案裡的程式碼壞味道,認為與自己沒啥關係,孰不知,它很有可能在不久的將來給你一擊“反噬”,讓你不得不硬著頭皮面對它。

推薦閱讀:

這麼簡單的bug,你改了2天?

我是如何保持長期寫作的

也可以「關注」我,帶你以技術思維看世界~

內容包括:架構設計丨分散式系統丨產品丨運營丨個人深度思考。

上一篇:探索: 古生物是怎麼滅絕的
下一篇:百猛獁象怎麼死的? 科學家發現人類與猛獁象廝殺, 有直接證據證明