本文原發(fā)表于《程序員》雜志9月刊,現(xiàn)將全文公開至此。前幾天的技術交流會上我也講了這部分內(nèi)容,配合著看會有更好效果。
此外我想再多幾句。《程序員》雜志在某些方面必須盡快做出調(diào)整。就拿我這篇文章來說,代碼除了被三欄的版式搞得支離破碎以外,其中必要的空格也莫名奇妙地少了許多。我認為《程序員》如今在內(nèi)容方面已經(jīng)有了顯著提高,但是在這種“表面”工夫上也得抓緊才好,這也是國內(nèi)同類雜志中“最專業(yè)者”所應有的風范。
前言
異步操作是強大的,它是許多高伸縮性架構(gòu)的基石。異步操作在許多情況下是必須的,例如在客戶端保持用戶界面的響應能力,以及在日益興起的云計算場景中。但是,異步編程又是十分困難的,它讓這讓許多程序員敬而遠之。因此,越來越多的編程語言都對異步編程提供了相當程度的支持,其中的典型代表便是F#中的異步工作流以及Scala的Actor模型。不過目前的一些主流編程語言,如C#或是JavaScript,它們在設計之時并沒有在異步編程上考慮太多,我們便會根據(jù)它們的語言特性,提供合適的異步編程模型及其實現(xiàn)。而本文介紹的便是其中一例:響應式編程(Reactive Programming)模型及響應式框架(Reactive Framework,簡稱Rx)。
異步編程的難點
異步編程之所以困難,主要有三大難點。
首先是對于狀態(tài)的維護。在普通編程中,我們已經(jīng)習慣了根據(jù)各種狀態(tài)采取不同做法的編程方式。在異步編程中,狀態(tài)對于操作的影響則往往更為復雜。例如,我們在編寫一個鼠標“拖動及繪圖”的行為時,一般會采用這樣的邏輯:
在MouseDown事件中將isDragging標記設為true,表示“拖動開始”,并記錄當前鼠標位置prevPos。
在MouseUp事件中將isDragging標記設為false,表示“拖動結(jié)束”。
在MouseMove事件中檢查isDragging標記,如果為true,根據(jù)鼠標當前位置currPos和之前記錄的prevPos進行繪圖,并將currPos的值寫入prevPos。
僅在這樣一個最基本的場景中,我們便需要編寫三個事件處理器(Event Handler),控制isDragging,prevPos等外部狀態(tài),并根據(jù)這些狀態(tài)決定事件觸發(fā)時的效果。這樣的例子數(shù)不勝數(shù),尤其是在各式拖放操作中,幾乎都會涉及大量狀態(tài)的控制(例如,判斷物體是否進入某個特定區(qū)域)。
異步編程的另一個難點,在于異步操作之間的組合及交互。例如在如上的簡單拖放操作中,我們便涉及到了MouseDown,MouseUp及MouseMove三個事件。從某些角度來說,客戶端的UI事件還是比較容易處理的,因為它們往往都是在單一線程上依次執(zhí)行。但是在另外一些場景中,如云計算時,我們往往會同時發(fā)起多個異步操作,并根據(jù)這些操作的結(jié)果進行后續(xù)處理,甚至還會有一個額外的超時監(jiān)控,這樣便很有可能會出現(xiàn)并發(fā)操作的競爭(Race)情況,這將會成為程序復雜度的災難。
此外,異步操作還會破壞“代碼局部性(Code Locality)”,這可能也是異步操作中最為常見的阻礙。程序員早已習慣了“線性”地表達邏輯,但即便是多個順序執(zhí)行的異步操作,也會因為大量的回調(diào)函數(shù)而將算法拆得支離破碎,更何況還會出現(xiàn)各種循環(huán)及條件判斷。同時,在線性的代碼中,我們可以使用“局部變量”保存狀態(tài),而在編寫異步代碼時則需要手動地在多個函數(shù)中傳遞狀態(tài)。此外,由于邏輯被拆分至多個方法,因此我們也無法使用傳統(tǒng)的try/catch進行統(tǒng)一異常處理。
推模型與拉模型
平時我們使用最多的便是“交互式(Interactive)”的編程方式,采用的是組件之間的相互調(diào)用來表現(xiàn)邏輯。例如,對象A向?qū)ο驜請求數(shù)據(jù)并等待返回,待對象B完成并返還數(shù)據(jù)之后A才繼續(xù)進行后面的操作。交互式編程的一個典型應用便是GoF23中的迭代器(Iterator)模式,它在.NET中的實現(xiàn)為IEnumerable及IEnumerator接口,例如:
void Traverse(IEnumerable<int> source) { var etor = source.GetEnumerator(); while (etor.MoveNext()) { Console.WriteLine(etor.Current); } }
出處:老趙點滴
責任編輯:bluehearts
上一頁 下一頁 異步編程與響應式框架 [2]
◎進入論壇網(wǎng)絡編程版塊參加討論
|