最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

軟件開發(fā)為啥強調(diào)“單向數(shù)據(jù)流”

2021-07-18 12:17 作者:屋頂頭牌  | 我要投稿

Bug的出現(xiàn)

? ? ? ??先來看1個筆者在實際開發(fā)中遇到的Bug。

? ? ? ??因業(yè)務(wù)需要,需要在某個頁面創(chuàng)建很多輸入框(UITextField),來接受眾多不同類型的參數(shù),如下圖:

擁有很多輸入框的界面

? ? ? ??等用戶填寫完整所有數(shù)據(jù)后,點擊“完成保存”,程序會在此時將輸入框中的數(shù)據(jù)逐個寫到一個data model上,隨后再做數(shù)據(jù)持久化,如下圖:

統(tǒng)一收集UI數(shù)據(jù)回填到data模型

? ? ? ??需要提到的是 dataModel 以及 眾多輸入框控件都被同一個視圖控制器持有。為什么不在輸入框完成編輯的時候通過delegate立即將數(shù)據(jù)變化同步到dataModel?因為頁面上的輸入框?qū)嵲谔嗔?,一個個的都通過delegate來傳遞數(shù)據(jù)給視圖控制器,意味著在delegate里要出現(xiàn)大量的if-else分支來判斷數(shù)據(jù)變化是來自哪個輸入框,這將是異常笨拙凌亂的代碼,所以作罷。

? ? ? ??索性編輯的時候就讓用戶愛怎么弄就怎么弄,我們等最后完成保存的時候再統(tǒng)一將數(shù)據(jù)從UI控件中更新到dataModel,之后愛干嘛干嘛好了。怎么樣?這種做法看起來是不是非常nice,省時省力不折騰???

? ? ? ??萬萬沒想到,bug出現(xiàn)了。

? ? ? ??它的癥狀是這樣,無論用戶修改多少個UI輸入框中的信息,點擊保存后,最多只有1個變動能夠被成功保存,有時甚至連1個變動也沒法保存!

原因分析

? ? ? ??在花費了幾個小時的盤查分析后,終于發(fā)現(xiàn)了問題的原因所在,如下圖:

錯誤的調(diào)用地點

? ? ? ??圖中的refreshUI()函數(shù),作用是將dataModel的各項屬性數(shù)據(jù)應(yīng)用到UI上,包括那些眾多的輸入框。而這個refreshUI()函數(shù)本身是沒有任何問題的,之所以出問題,是因為千不該萬不該地在dataModel的 didSet() 方法里去調(diào)用它。

? ? ? ??這個didSet方法是Swift語言提供的一項便利語法糖,作用是某個屬性被修改時會觸發(fā)調(diào)用,然后開發(fā)者可以在里面做些想要的事情,如保存數(shù)據(jù)之類的,類似OC中手寫的Setter方法。

? ? ? ??筆者在構(gòu)建該頁面的時候心想,既然頁面要呈現(xiàn)傳入的dataModel,那就索性在dataModel發(fā)生變化的時候去調(diào)用refreshUI刷新各種UI控件,這樣多好,關(guān)鍵是有現(xiàn)成的didSet方法可以用!

? ? ? ??于是就出現(xiàn)了上面提到的問題,dataModel本質(zhì)上是Struct,里面的屬性propA, propB, propC ....對應(yīng)著UI上的輸入框A、B、C....。設(shè)想用戶修改了眾多輸入框信息后,點擊保存,觸發(fā)統(tǒng)一的寫數(shù)據(jù)邏輯writeInfoToData(),在該方法運行到第一行代碼時


? ? ?data.propA = textFieldA.text

? ? ? ??

該dataModel的didSet方法被觸發(fā),進(jìn)而refreshUI()被觸發(fā),其中的代碼被悄無聲息地執(zhí)行 ? ??

? ?

? ? ?textFieldA.text = data.propA

? ? ?textFieldB.text = data.propB

? ? ?...

? ?

? ? ? ??老天!data.propB可是修改前的舊數(shù)據(jù)~ ?

? ? ? ??這樣執(zhí)行下來的結(jié)果,就是輸入框B,C,D....中的內(nèi)容都被強制更新成了用戶修改之前的舊值,等于用戶的修改除了輸入框A,其他的全部被強制撤銷了!

怎么補救?

? ? ? ??可以看到,造成問題的原因在于,筆者嘗試在dataModel數(shù)據(jù)變動的回調(diào)方法(didSet)里去刷新UI控件,之后企圖在用戶點擊保存的時候從UI控件中將數(shù)據(jù)寫回到dataModel,而這個寫回操作又會觸發(fā)dataModel的數(shù)據(jù)變動回調(diào)方法,形成了相互調(diào)用。進(jìn)一步講,數(shù)據(jù)一會兒從dataModel流向UI控件,一會兒又從UI控件流向dataModel,最終釀成了Bug。 ?

? ? ? ??加上執(zhí)行完writeInfoToData()后,頁面就立即銷毀了,看不到輸入框中的修改值被強制重置為舊值,這又增加了發(fā)現(xiàn)Bug的難度。

? ? ? ??最后的解決辦法是將refreshUI從dataModel 的didSet方法里摘除,放到ViewDidLoad中執(zhí)行,隨后問題消失了。

感想

? ? ? ??之前做RN項目的時候,官方文檔一直在強調(diào)一個術(shù)語“單向數(shù)據(jù)流”(貌似搞Web前端的朋友對這個概念更熟悉,奇怪App端開發(fā)知道這個的并不多)。但當(dāng)時也只是按照規(guī)定做事,具體為什么要保證“單向數(shù)據(jù)流”卻沒有弄清楚。這次算是真的碰到了實際Bug,才知道單向數(shù)據(jù)流之于程序穩(wěn)定性的重要,因為不這么弄容易出Bug。 ? ?

? ? ? ??再有就是,新的高級語言會提供很多語法糖之類的東西,使得相對于之前的語言,會有很多非常省事方便的操作來使用鍵值觀察、信號傳遞之類的特性。這就導(dǎo)致很多開發(fā)者濫用這些語法糖、操作,因為它們可以讓代碼寫的更少,相對于開發(fā)者老老實實地用代理,自定義函數(shù)方法來實現(xiàn)。 ??

? ? ? ??后者雖然繁瑣,但調(diào)用邏輯清晰,利于代碼維護和Bug定位。而這又得扯到開發(fā)效率和代碼健壯性之間的平衡,是另外一個話題了。


P.s: ?用作Bug分析的源碼可以從下面的地址獲取:

https://gitee.com/BeiTianSoftware/bugdemo.git


軟件開發(fā)為啥強調(diào)“單向數(shù)據(jù)流”的評論 (共 條)

分享到微博請遵守國家法律
肃宁县| 嘉黎县| 尼勒克县| 张家界市| 萨迦县| 沾益县| 马关县| 紫金县| 信丰县| 仪征市| 虎林市| 临夏市| 盐亭县| 岱山县| 沁源县| 兴文县| 织金县| 鹿邑县| 淮南市| 正宁县| 衡阳县| 巴林右旗| 红原县| 盐城市| 同德县| 福鼎市| 台中市| 林州市| 嘉义市| 柏乡县| 河南省| 旬阳县| 东辽县| 株洲县| 同心县| 黄大仙区| 西和县| 琼结县| 乌什县| 桦川县| 许昌市|