歡迎光臨
每天分享高質量文章

程式常用的設計技巧

精品專欄

 

原文:https://mp.weixin.qq.com/s/y4DNrH3iqWns25__kFAQpQ


一、背景

程式的定義:程式=資料+演演算法+介面

二、常用技巧

技巧1 – 按標的設計介面做冪等設計

– 場景

背景:做任務賺積分。前端發出增加積分請求,如果收不到響應會重試。

後臺開發人員:怎麼判斷是重試還是另一次請求?

解決方案:介面定義中需要傳入原來積分是多少,增加到多少。開發人員直接將標的結果入庫。

疑問:那實際生產環境發現了原來積分一樣,增加到多少不一樣的結果怎麼辦?

答疑:這說明上線的產品中肯定有漏洞或bug。怎麼辦?改bug唄!

– 解析

冪等性設計的定義:一次和多次請求某一個資源應該具有相同的副作用。直白點講就是多次重試可以多次查詢,但是修改更新應該只進行一次。

作為開發正確的觀念應該是外部呼叫失敗是常態,並且失敗之後必然有重試。

不要靠巧合程式設計  –《程式員修煉之道》

技巧2 – 多版本併發控制解決併發問題

– 場景

背景:上文中的做任務賺積分,後臺收到了增加積分請求。

開發人員:為了避免重試,我該怎麼寫程式碼呢?

解決方案:update XXX set score=XX where score=X

– 解析

多版本併發控制MVCC(MultiVersion Concurrency Control)的定義:該策略主要使用update with condition(更新帶條件來防止)來保證多次外部請求呼叫對系統的影響是一致的。這也是「樂觀鎖」的主要思想。

樂觀鎖的定義:假設最好的情況,資料在變更的時候不會被別人更新,如果更新了,某個值就會改變。所以就用這個值來作為判斷條件,只有條件為真才更新成功。

總是為併發進行設計  –《程式員修煉之道》

技巧3 – 預判斷準入控制避免「箭頭型」程式碼

– 場景

背景:上文中後臺收到了增加積分請求,傳入了一個負數的積分。

開發人員:我就if 正數 才往下執行就好了呀?

結果:一層層的判斷下來,程式碼變成這個樣子。

疑問:怎麼解決這種複雜的「箭頭型」程式碼問題呢?

答疑:「衛陳述句」在預判斷時做準入控制。

– 解析

衛陳述句(guard clause)的定義:先對異常情況做檢查,異常則直接傳回。

最終一個請求被完美的分成預判斷檢查和正式執行兩個部分,邏輯清晰,簡單明瞭。

早重構,常重構  –《程式員修煉之道》

技巧4 – 非同步設計分離響應和執行

– 場景

背景:上文的增加積分,併發量太大,因此採用了佇列設計,大量請求排隊等待資料庫變更。

開發人員:這樣後臺介面部分很容易都在等著響應,服務被拖死。

解決方案:準入校驗做充分,請求放到佇列裡後直接給使用者傳回操作成功。

疑問:萬一最後失敗了呢?

答疑:知道失敗了還不修資料嗎?資料補償保證最終與對使用者承諾一致撒。

– 解析

1/3/5秒原則:在1s以內得到響應,使用者會覺得系統響應很快,體驗非常好;1-3秒得到響應,使用者可以接受,體驗還不錯;3-5秒才響應,使用者就感覺慢了,體驗有點糟糕;一旦響應超過5秒,使用者就會認為是個失敗的體驗,選擇離開或重新發起請求。

三、總結

思考!你的工作!  –《程式員修煉之道》

利用策略樣式最佳化過多 if else 程式碼

關於爛程式碼的那些事(下)

關於爛程式碼的那些事(中)

關於爛程式碼的那些事(上)

深入解讀zookeeper一致性原理

阿裡雲Redis開發規範

10分鐘看懂!基於Zookeeper的分散式鎖

Core Java 併發:理解併發概念

分分鐘解決 MySQL 查詢速度慢與效能差

Java 必須掌握的 20+ 種 Spring 常用註解

END


>>>>>> 加群交流技術 <<<<<<