程式碼中的奧卡姆剃刀原理
如無必要,勿增實體。
過早的優化是萬惡之源。
背景
一個抽獎活動,要求在展示獎品股票時,顯示股票價格。開發在實現這個功能的時候,用redis快取每隻股票的價格,每兩小時呼叫行情服務更新一次。
問為什麼要做個快取,而不是直接訪問行情服務直接讀取,給出了幾個理由:
- 減少對行情的請求,直接訪問redis一次就能查很多。
- 用快取速度快。
- 獎品展示、獲獎排行榜都要用行情資料,防止不一致。
- 用行情的地方很多,不用每次請求行情服務。
- 前端需要拉取的資料,在需求範圍內,可以接受兩小時不變,不用每次重新計算。
但是這些理由都站不住腳,直接訪問行情服務並不會有問題。
優化過渡,過早加了快取,增加了程式碼的複雜度,產生了資料的不一致性。
沒有解決具體的問題,看到的只是一些表象,看似解決了問題。
思考
逐條思考下上面的幾點理由。
理由1. 減少對行情的請求,直接訪問redis一次就能查很多。
說法是對的,確實減少了對行情的訪問。但是為什麼要減少對行情的訪問呢?
行情的服務很穩定,而且效能也很好,並沒有什麼問題。沒有解決具體問題。
理由2. 用快取速度快。
如果直接訪問行情資料來源速度是瓶頸嗎,有遇到效能問題嗎?沒有。行情也是記憶體訪問,速度不一定比redis慢的。而且開發也沒有資料支撐。
理由3. 獎品展示、獲獎排行榜都要用行情資料,防止不一致。
為什麼要一致,不一致有什麼問題?對於排行榜,大家都有預期,是一定時間才更新一次的,只要在排行榜介面有說明即可。就像遊戲的排行榜,很多都是24小時更新一次。沒有必要為了和排行榜資料一致,而修改程式碼。這個問題在產品形態上就能解決,也是個偽問題。
理由4. 用行情的地方很多,不用每次請求行情服務。
同理由1,多怎麼了?正常訪問就可以了,如果效能瓶頸再優化。
理由5. 前端需要拉取的資料,在需求範圍內,可以接受兩小時不變,不用每次重新計算。
具體的產品形態,可以有加快取的餘地,但不意味著必須要加快取。除非遇到有效能問題,否則程式碼的可維護性、穩定性是最重要的。
再換個角度,如果行情的介面效能真的很慢,要怎麼優化呢?
不是直接暴露redis介面的,有更好的方法。
把行情獲取部分單獨封裝成為一個獨立函式,對外不依賴具體的內部實現。
不管是直接訪問行情服務、讀快取,還是訪問一個單獨封裝的優化行情服務模組,對外介面都不變。
整理下常見的避免過渡優化場景:
1、能同步實現的程式碼,就不要用非同步;
2、能實時實現的程式碼,就不要用定時;
3、能用資料來源讀取的,就不要用快取。
先保證程式簡潔,滿足效能要求,等遇到問題的時候,再去優化,避免過早優化,引入問題。
總結
解決問題前,先思考是否有問題,問題是什麼,而不是直接去做。
「如無必要,勿增實體」程式碼模組中,在沒有遇到問題時,不要引入過多的模組,快取,增加程式碼的複雜性。既不易於閱讀,也不易於維護。
遇到效能優化,不優化有問題,優化過渡,即使沒產生問題,也是浪費。
轉載請註明來源: 程式碼中的奧卡姆剃刀原理 本文連結地址: https://www.owenzhang.net/blog/188.html