iOS響應式架構

2021-08-21 18:16:12 字數 3514 閱讀 6877

自2023年起,移動端的架構中開始漸漸的融入了響應式的元素。時至今日,融入響應式的架構已經在很多產品的多次迭代中經受住了考驗。十年後,再回首現在這一時間點,很可能會被認為是乙個新的移動端架構時代的開端。很多文章中都提出了針對自己產品研究出來的一套架構,卻鮮有文章單獨對架構中的響應式元素進行討論。筆者就寫下了這樣一篇關於ios響應式架構的文章來闡述響應式架構的歷史、響應式架構的本質、響應式架構的優點以及如何在現有架構中融入響應式架構這幾個值得**的問題。

首先,重中之重。界定一下響應式架構與響應式程式設計和其他架構的邊界。響應式架構與frp(響應式程式設計)有必然聯絡嗎?沒有的,響應式架構並不需要引入rx等frp正規化方案。響應式架構與mvc、mvvm有必然聯絡嗎?沒有的,mvc中可以很愉快的融入響應式架構,mvvm也可以。不過,響應式架構與immutability倒是密不可分,畢竟不可變才能「響應」。

2023年facebook開源了immutable.js,react、flux等以immutability作為核心元素的方案,可以說是席捲了前端。這看上去是在前端的浪潮之中,facebook提出了這一概念。事實並非如此,immutability的概念早在物件導向程式設計誕生的階段就已經有了。而facebook的工程師是這個時代發現珍珠的人。

這裡也不打算長篇大論,簡要的回答這幾個問題。不可變性是啥?可變資料與不可變資料有什麼區別?

不可變性就是不可變資料具有的不可變性質,而可變資料和不可變資料的區分就在是否具有狀態,可變資料具有,而不可變資料不具有。首先來思考一下這個有趣的問題,現實世界中有鐘錶反映時間的流逝,那在計算機世界中如何反映時間的流逝?同一資料發生了變化就可以,比如說,計時器的本質不就是同一資料一直在遞增,即狀態反映了時間的流逝。其實,狀態是對現實世界時間流逝的隱式表現。引入了狀態,也就向計算機世界引入了時間。

那我們為什麼要關心狀態,狀態有什麼危害嗎?資料本身改變其狀態實際上沒什麼危害,而且是必需的,任何對本身狀態的修改都是可**的。而多資料共享的狀態則不同,任何一方的修改對其他方來說都是不可**的。這也就是平時程式設計bug的源泉。(可變資料帶來的同一性問題)

除此了共享狀態,狀態帶來的時間,也同樣帶來了語句的時序問題,cpu流水線執行的讀寫狀態的語句就變得至關重要,影響了程式的正確性。其中最令人頭痛的就是執行緒安全問題。

狀態帶來這兩點危害,在gui程式設計中尤其顯著。為了縮短平時與bug爭鬥的時間,前端和客戶端的工程師們開始了immutable之旅。然而從程式設計的模型中剝離狀態是不現實的,那麼就從架構的乙個層面上剝離狀態吧,很顯然,model贏得了頭獎。

首先,在日常業務編寫model的時候,工作無趣而且繁重,很多任務作量就是將後端提供的api轉換成model,根本不需要動腦進行抽象,這是個要解決的問題。

其次,在平時物件導向編碼過程中很容易將多個物件共享的狀態混在其中乙個物件的行為裡更改。比如說,多個物件的共享狀態,在其中任何乙個物件的方法裡更改。實際上,應該再單獨抽象乙個物件(single model)去做對共享狀態的修改,這使共享狀態的**隔離出來,提高了維護性,也使共享狀態的修改更加可**。

這種方法確實會減少bug,讓**更加可**,然而每次要警覺到這一點再建立個新的single model聽上去就是個無法「實施」的方案。唯有繼續上下而求索,後來摸索出的方案就是本文的主題,直接讓model immutable化。將model設計成與其他immutable資料nsarray、nsdictionary一致。model生成後不可以修改其內容,如果要修改再重生成乙個新的model。

facebook和pinterest提出的方案都是將model的屬性宣告為readonly。並用builder設計模式,抽象乙個model builder,model builder通過原model生成,生成後,model builder可以自由修改資料,然後再由model builder生成修改後的新model。

本來編寫model就是比較枯燥的工作,如果再將model immutable化,要花更多的時間寫樣板化(boilerplate)**,更加加重了平時編寫model的負擔。為了將model immutable化還不給平時工作加重負擔,remodel就橫空出世了。

要想理解響應式架構的本質,還是要把facebook提出的響應式架構元老flux請出來。聽說過flux的都知道,flux有三個重要部件,view、dispatcher、store,並且flux是單向data flow。

flux將data的狀態變動從view中隔離出去,view同樣也immutable化了?實際上,還沒有,因為不管是瀏覽器,還是ios、android,view都是有狀態的。這就輪到react出場了,ios中則是componentkit作為花旦,當view有狀態變動,重新生成view。如果還按照以往的render邏輯,很明顯會產生效能問題。所以,react就會對view層進行重構,將每個view抽象為乙個component,component又巢狀component,模擬樹的層級結構,抽象的粒度盡量小,當view的狀態變動,react將diff出所有變動的地方,然後重新生成涉及到的component。

那什麼是響應式架構的本質?這裡就下個定義吧,並不是通過工具生成immutable化model,也不是固定的幾個抽象部件,而是將軟體的檢視當做data狀態的乙個響應呈現。

響應式架構有以下三個明顯優勢:

固定data flow,易於人腦理解,也讓data flow更可**。

從架構層面上消滅共享狀態,讓多方共享的資料可**。

共享資料線程安全。

那如果不用響應式架構,可不可以同樣的學習其思想?我們可以盡量寫出更可**的**,比如swift對於optional的引入,就是讓可能為nil更可**。

首先,你要足夠了解產品現有的架構。其次,請盡量融入,而不「重造」。融入響應式架構不只有一種方式,盡量選擇較溫和的那一款。

使用或開發一套自動生成model的工具,將model immutable化。通過觀察者設計模式,在需要得知model改變的地方註冊觀察者。任何model的修改,無論是網路請求、互動等原因,都新生成乙個model並把model push出去,具體設計可以參考consistency-manager。業務編碼要在controller-views裡observe,在資料層介面獲取model和互動改變model的地方push model。

引入rx等frp正規化方案,結合mvvm,具體設計參考limboy的這篇文章。

無論如何選擇,請一定要參考產品的複雜度和已有架構。畢竟,重要的是寫出更可**的**,形式只是表達。而以筆者業務開發的經歷,自動生成model是很有必要的,自動生成的**,更少的錯誤、更統一的規範,這都是我們寫**的崇高追求。不過,國內外開發環境不一樣,國外開發的工具確實不能生搬硬套到國內,這就是另外乙個話題了,後期有機會筆者會開源正在使用的自動**生成工具。

除了將model immutable化,那view要immutable化嗎?這是乙個值得好好權衡的問題,矽谷的科技公司對view的immutable化做的很徹底,從gmtc大會上airbnb分享的**實踐裡將view起名為component就能猜測出一二了。但是國內確實是不溫不火,究其原因還是學習成本成了攔路虎,國內公司的迭代速度是矽谷無法匹敵的,在快速的試錯、迭代中,view層的變化始料不及,公司對技術的要求必然是可讓新手快速上手、迭代,將view immutable化,要整體重構系統view層,對於沒有接觸過的新手很不友好。如果讓新人入職第二天開始寫需求,而他都沒法在新專案中好好寫個view,這就是不可接受的了。

iOS響應式架構

自2014年起,移動端的架構中開始漸漸的融入了響應式的元素。時至今日,融入響應式的架構已經在很多產品的多次迭代中經受住了考驗。十年後,再回首現在這一時間點,很可能會被認為是乙個新的移動端架構時代的開端。很多文章中都提出了針對自己產品研究出來的一套架構,卻鮮有文章單獨對架構中的響應式元素進行討論。筆者...

ios響應式程式設計Racsignal

signal和subscriber,limboy把signal比作插座,吧subsciber比作插頭,插座負責取電,插頭用於用電,乙個插座可以插任意數量的插頭,沒 頭時,不會去取電,只有插了插頭才能去獲取電。signal獲取到資料後,會呼叫subscribe的sendnext,sendcomplet...

ios 函式式程式設計與響應式程式設計

ios函式式程式設計 響應式程式設計概念 如果想再去呼叫別的方法,那麼就需要返回乙個物件 如果想用 去執行,那麼需要返回乙個block 如果想讓返回的block再呼叫物件的方法,那麼這個block就需要返回乙個物件 即返回值為乙個物件的block 在網上流傳乙個非常經典的解釋 響應式程式設計的概念 ...