iOS架構設計之」冗餘性」思考

作者:一水流年

原文鏈接:iOS架構設計之」冗餘性」思考

該系列文章是2016年折騰的一個總結,對於這一年中思考和解決的一些問題做一些梳理和總結

做客戶端開發的同學都了解業務需求千變萬化,你永遠不知道他未來會變化成什麼樣子。而作為開發人員也絕對不喜歡需求變更。本來說好的,都快做完了,產品經理突然變卦了:咱們不這樣搞了,你看我七十二變。

我們極不情願跟在這紛繁複雜的變化屁股後面,疲於奔命。天下沒有那麼容易偷的懶,若不想應對這變化。就需要走到變化前面。技術往前走一步,領先於業務,而不是被業務趕著屁股走。這就需要冗餘性思考,在做業務開發的時候,作為Coder就需要往後思考,業務可能會怎麼變,當前程序結構是否足夠靈活,方便調整。當業務需求調整的時候,能夠以最小的代價來滿足。而這就是『冗餘性』思考。

針對變化進行設計而不只是針對需求。

這裡說是『冗餘』,是因為開發測多想了幾步,為未來可能的變化也做了鋪墊。與一些同學堅持的程序設計滿足當前需求,不進行過度設計的理念多少有些不符。而我認為進滿足當前需求進行設計是傳統軟體開發的路數,在互聯網軟體開發過程中,已經不適用。互聯網軟體產品,尤其是終端上的,版本迭代頻繁,功能更新迅疾。已經很難有穩定的需求存在,變化是其本質特徵。於是要求我們在開發的時候,就需要針對這種變化做出一定的設計。

探尋變化的規律

設計機制而不是僅僅滿足需求

機制與策略分離

我們首先要說一個觀點就是機制與策略分離。我們希望設計的是一整套能夠滿足當前需求的機制,其次才是針對當前需求的產品策略。這也是我這一年來的一個非常重要的總結。並且在逐漸開源出來的一些庫中也體現著這個設計。具體說一下,所謂機制即是抽象出來的規則,比如:

f(x)=x^2 x屬於Rn

所謂策略即是在具體場景中的應用,比如當x=2的時候:

f(2)=4 x=2n

面對需求,我們需要首先投過表層的的東西,深入一步探討一下在需求之下在變化的東西。舉個例子來講,我們都有處理過TableView相關的需求。

在版本1.0的時候,產品告訴你我們要做Feed。展示樣式嗎有目前是這個樣子的:

當沒有深入思考的時候。我沒有區分什麼機制那些變化的規律,什麼是需求產品的當前的訴求。然後就開始動手了。寫UITableViewCell的子類,往上面加Label和UIImageView,一起都是固定的。然後載入數據展示。。。。。

而1.0沒發布幾天,產品說咱們的Feed展示樣式太簡單了。現在我們需要支持鏈接跳轉,Coders你們看UI給到的樣式是這樣的:

於是我們又開始增加新的UITableViewCell的子類。。。。。版本1.1發布了。

後面還有版本1.2,1.3,1.4……終於有一天忍無可忍

這個時候於是就有了重構,我們開始抽離Feed的公共部分放在基類裡面,通過類繼承等技術手段來控制工程的複雜度,同時提高開發效率。這個時候,我們反問一句:

這些重構的工作是否可以提前到1.0版本的時候開始做呢?

這裡當然會有兩方觀點,

一方認為:代碼腐敗是伴隨著項目推進必然產生的現象,何必多花費勞工去提前設計,兵來將擋水來土掩就好了。

另外一方認為:我們堅信事物背後都有一定的規律可以依循,雖然代碼腐敗是必然現象,但是依舊可以通過一定的技術手段來極大的減速這個過程。

先說一點,這裡沒有對錯之分。要是爭對錯了,估計又是一場罵戰。只能說我更傾向於認同第二種觀點。在項目設計初期,我們可以通過去預判功能走向,來進行軟體設計。透過表面UI和業務邏輯,去看背後的底層變化邏輯。而這也正是我一直比較看好的:機制與策略分離比較好的應用。

首先透過表層的業務邏輯,去深度思考業務或者功能背後的底層變化規律。真對這些規律設計類庫,然後再在當前的業務中選取適當的策略進行應用。再次強調一個理念:

針對變化進行設計而不僅僅是需求

幾種針對變化進行設計的Case

說完乾巴巴的理念的東西,我們來看一些大家喜聞樂見的具體的應用。

Talk is cheap, show me your code.

增加Client端的動態性或增加CS之間交互性

一般我們認為iOS客戶端是固體,給人的感覺是很硬的,一旦發版之後很多修改將變得異常困難。尤其是iOS的客戶端,由於AppStore審核的限制,發版也相對難一點。一個很「硬」的東西,不如一個很「軟」的東西更容易應對變化。這種變化有可能是業務需求,有可能是軟體的BUG,有可能是系統突發危機…..

金以剛折,水以柔成。 ——晉·葛洪《抱朴子·廣譬》

所以為了應對這些變化,需要讓我們的Client變得像水:容萬物而不折。我們就需要給其相應的能力。這裡有兩種策略:

  1. 增加CS之間交互性,通過Server下髮指令來操作客戶端
  2. 增加Client端的動態性,比如JSPatch,還有OCScript這類的方案。

讓客戶端變得像是一個可以接受指令的機器人,能夠在伺服器的配合下,靈活應對各種需求和突髮狀況。

動態性

先說動態性,這一塊是業界一直在探索的東西,遠的有Hybird等基於WebView的方案,近的有RubyMotion和ReactNative,還有阿里團隊的Wexx,都是非常優秀的嘗試。尤其是ReactNative和Wexx,最近一段時間很多團隊將其引入到了技術棧,讓自己的客戶端可以支持動態發版,也就是常說的插件化。

去年下半年滴滴和手Q團隊也分別拋出了兩個非常驚艷的方案,一個是滴滴的DynamicCocoa,一個是手Q的OCScript。在編譯器級別進行修改,通過下發中間語言,在客戶端上跑對應語言的虛擬機來解釋執行對應的語言。讓客戶端變得像是一個容器,可以承載下發的業務邏輯。

如果我們單純的從業務需求的角度去思考,可能這些方案很難會出來。這些方案背後的大神們,也是深入思考之後,把這些機制性的方案設計並構建出來的。把動態性的支持做到如此的深入,也是極牛逼的事情。非常期待他們開源。

互動式客戶端

互動式的客戶端這種策略,更像是一個縮水版的「動態性」策略。我們在客戶端中預置一些能夠響應的指令。在需要的時候,通過伺服器下發具體的指令,來觸發執行客戶端對應的邏輯。讓客戶端能夠被動的應對一些業務需求和突髮狀況。下面我們說幾個具體的應用:

命令式緩存

在我們構建了伺服器與客戶端命令式交互的架構(伺服器向客戶端發送指令,執行特定的動作)之後,我們做了一些有意思的事情。就比如命令式緩存:伺服器向客戶端下發文件緩存指令,客戶端收到指令後進行文件緩存操作。

這套簡單的系統構建起來之後,我們在這上面做了很多有意思的事情。

利用預緩存減小安全包體積

界面開發中往往用到很多的圖片資源,尤其是PNG格式的資源,雖然可以進行壓縮,但是某些尺寸比較大的北京資源圖片還是可能會達到上百KB。這對於一個ipa包來說,也是舉足輕重了。

最開始,可能為了包體積,我們犧牲了用戶體驗。對於這樣的圖片使用網路資源。這樣就很難保證用戶跳轉到界面的時候,能夠第一時間看到正確的背景圖片。甚至有些網路差的時候,圖片壓根就下載不下來。

於是,我們做了這樣的設計:

  1. 2.1版本將引入A,B,C三張大體積的圖片
  2. 在2.1版本沒有發布之前,就向全量客戶端下發預緩存指令:緩存A,B,C三張圖片。
  3. 然後發布2.1版本,用戶升級之後進入對應頁面時,將直接從本地緩存中讀取對應的圖片進行展示。

這樣即兼顧了用戶體驗也減小了包體積。

利用預緩存減少CDN壓力

在活動運營的時候,尤其是重大的節假日,一旦活動發布之後的段時間內,用戶訪問量激增,將會導致CDN過載。大量用戶初次訪問頁面,大量下載文件資源。這個時候,就完全可以在活動之前,下發預緩存指令,來緩解CDN過載的問題。

染色日誌上報

在我們客戶端支持的指令列表中,日誌上報也是一條非常有意思的指令。當客戶端發生問題的時候,我們最開始的時候是手足無措。後來有了Crash上報,但也只是能夠上報Crash這種極端情況。有很多沒有Crash的情況,可能只是用戶某個用法不當,或者產品邏輯本身有問題的時候,就比較難以追蹤。這個時候我們就需要去查看生產環境上的日誌。這個是在伺服器開發中是比較常見的策略。

於是我們就構建了這樣的一條指令,當指令被觸發的時候,會將用戶本地打的生產Log使用非對稱加密之後上傳到制定的地址。這種指令是和用戶掛鉤的,我們是根據UID針對單一用戶下髮指令。

然後我就可以,通過管理端拿到對應的Log,解密後查看。來看生產日誌中可能存在的問題。

構建可運營的客戶端

可運營的概念來自於別人的文章。意思是讓自己的客戶端能夠支撐運營人員的需求,動態的更改展示的內容,甚至是功能點。雖然我們不進行發版,但是可以支持內容的動態替換,支持功能點的動態上線下線。甚至當某些功能上線之後,能夠動態的增加其對應的保障性功能(例如日誌,數據上報這樣的保障性功能)。這裡要說一下數據部分。

對於數據上報功能的設計,重點需要考慮擴展性,因為對於數據種類的需求無法一次就確定,往往隨著產品的迭代會增加新的數據需求。這時候如果能夠通過不修改上報模塊,只在目標監控點增加采數據集代碼就能完成新增需求,這就說明上報系統已經具有不錯的擴展性了。當然這只是在客戶端增加了數據上報的基礎設施,真正運營的工作還要靠團隊建立一個強大的大數據分析平台了,數據上報之後其實只是一堆數字垃圾而已,而真正賦予這些數字垃圾信息化價值的過程是分析。試想作為產品經理的你每天一到公司都會收到關於產品的數據郵件,可以看到新鮮的數據報表,曲折的線圖,躍動的燃燒圖等,這些都將為你的工作和負責的產品提供非常有價值的支撐,你應該感謝有這麼好的運營團隊。

閱讀原文


推薦閱讀:

大的golang工程都是怎麼從0開始構建的,代碼又是怎麼組織的?
哪些互聯網公司在使用領域驅動設計?
AI 公司該如何設計基於微服務的 AI SaaS 架構丨硬創公開課
未來會出現96位計算機么?
庫,框架,架構,平台,有什麼明確的區別?

TAG:iOS | 架构 | 机制设计 |