前提
使用者行為驅動開發是什麼?
它是一種適用前端的面向使用者行為的開發思想,是一個使用者行為的產生到執行,驅動資料的產生,再由資料流驅動渲染的流程。我認為,前端要完成的工作就是接收使用者行為,解析使用者行為,到給使用者一個反饋。在各種使用者行為形成一個序列後,在之後的開發中可以得到很多方便。
使用者行為驅動開發是如何誕生的?
由於每個 App 都需要採集資料進行分析,需要進行資料埋點,這些資料往往都是一個使用者行為加上一些業務資料,如果使用程式碼埋點的方式,就會導致 UI 程式碼中總要摻雜著一些額外的埋點邏輯,比如一個 button 的 onClick 中有一段獲取業務資料併傳送埋點事件的程式碼,久而久之,程式碼就會變得臃腫不堪。現在雖然有無痕埋點的方案,但是成本過高,小公司去開發不是很現實。
出了上面的問題後,我意識到使用者行為是一個關鍵點,其實每一個需要採集的資料都由一個或幾個使用者行為拼湊出來的,比如使用者點選了登入按鈕,其實就是由兩個 Action 組成,ButtonClick 和 LoginAction。再比如,使用者上拉載入更多資料,其實就是產生了 PullUpToLoadMore 和 GetXXXDataAction 。
帶著這樣的思考,我就開始嘗試了面向使用者行為開發。
其他說明
- 我是 Android 開發,之後的一些例子可能更適用於移動端,但思路上適合各種前端的
- 觀察者(訂閱\釋出)模式,解耦利器,使用者行為驅動開發使用了大量的觀察者模式,讓每一個部分職責單一明確
- 本文不講程式碼的具體實現,只講思想,之後可能會寫其他的文章具體講實現
一、UserAction 的型別
如圖,展示的是移動端的一些基本操作,左邊四個是針對列表頁面的操作,分別為「下拉重新整理」「上拉載入更多」「Item 曝光」「Item 點選」。剩下四個為「PageView -> 瀏覽頁面」「UseDomainService -> 使用業務服務」「 ButtonClick -> 按鈕點選」「ComponentShowUp -> 元件展示」。這裡具體解釋一下「使用業務服務」和「元件展示」
- 「使用業務服務」可以看做是使用者在使用公司的業務,比如每個公司都會有登入註冊,再比如公司中特殊的業務,如看視訊或者獲取一組新聞資料等
- 「元件展示」是指一個控制元件或元件彈出,比如 Android 中的 Dialog\Toast\PopupWindow 以及自定義的 Window 等
二、UserAction 驅動渲染的過程
首先說說,在一個簡單的列表頁中,UserAction 是怎樣工作的
首先不考慮資料是怎麼獲得的,只想 UserAction 如何應用在 UI 程式碼中,就是圖中的 5 個步驟。 UI 只負責生產對應的 UserAction,然後觀察它,它在執行後會產生對應的結果,UI 只需要使用結果去渲染。
所以 UI 的職責很明確:
- 產生 UserAction
- 執行 UserAction
- 接收資料,進行渲染
UI 中的程式碼大概就像這樣:
//頁面開始顯示一個列表
start() {
observer = List<xxx> result -> {
render(result);
}
new GetXXXListAction().execute(observer);
}
//登入
loginBtn.setOnClickListener(v -> {
ButtonClickAction btnClickAction = new ButtonClickAction();
btnClickAction.enqueue();
LoginAction loginAction = new LoginAction();
loginAction.execute(observer, params);// observer 用於觀察登入狀態變化,引數為使用者名稱密碼
})
複製程式碼
三、UseDomainAction 的執行過程
使用者選擇使用我們的 app,就是在使用我們提供的業務服務,所以業務邏輯處理是我們平時開發精力投放最多的一部分,我具體說一下「UseDomainService」是如何工作的。基於模組化開發,我們每個業務應該對一個模組,所以 action 執行時就是呼叫我們的業務模組的介面,這裡針對業務模組的非同步請求會再次使用觀察者模式或是個 CallBack ,action 觀察業務模組,然後接收模組返回的結果,再將結果發給執行 action 的頁面。
下面是針對資料流向的一個圖,可概括為UI -> Action -> Data -> ViewModel -> Render
,UI 產生使用者行為,使用者行為驅動資料產生,資料驅動 UI 渲染
四、其他 UserAction 的使用方式
- 「PageView」:可在 LifecycleManager 的 onActivityResumed 方法中進行建立,然後取到每個 Activity 的路由 url 或是類名,存放到 PageViewAction 中。如果你有一個 BaseActivity,也可寫在 BaseActivity 的 onResume 方法中
- 「PullDownToRefresh/PullUpToLoadMore」: 可在列表重新整理控制元件的 callback 中,建立這個 Action,例如繼承 SmartRefreshLayout 然後重寫 refresh 和 loadMore 方法,在裡面加上對應的 Action
- 「ButtonClick」:和上面?類似,繼承 Button,在 onClick 中,新增 ButtonClickAction
- 「ComponentShowUp」:也是繼承基礎控制元件,然後再 show 的時候新增這個 Action
- 「ItemImpression」:這個比較特殊,是列表中每個 item 曝光的行為,我的做法是在 RecyclerView 的OnChildAttachStateChangeListener 中的 onChildAttached 方法中記錄,並且要繫結一些業務資料
這些 Action 在生成或執行時需要存放到一個列表裡,形成一個序列,下一節會具體介紹。
五、UserActionSequence 使用者行為序列
以下展示的是從開屏頁,跳轉到登入頁,然後點了登入按鈕的一個 UserActionSequence
假如資料需要我們在登入按鈕處埋點,我們只需要從序列中找到對應的 Action 組成事件發到後端即可。當然後端最好也抽象出一些通用事件配合前端,那樣使用者序列的威力就會發揮到極致,基本可以在 UI 程式碼中做到無痕。下一節會簡單說一下使用者序列如何配合埋點系統做到基本無痕的埋點方式。
六、淺談埋點
按職能解釋「EventTracker」的每一部分:- 「ProcessedActionBuffer」:
需要觀察 UserAction 入隊,當有新 Action 入隊時,就將其存到 ProcessedActionBuffer 中,並做一些特殊處理,比如「PageView」 我們是在 onResume 時生成的,但有時彈 Dialog 再回來的時候又會觸發一次「PageView」(Android Activity 生命週期決定的,其他平臺可能不會有這種問題),所以需要去重,保證傳送沒有冗餘的資料給後端 - 「EventActionMapper」:
用於對映 Action 和 Event,其實就是一套行為和事件的轉換規則(需要前後端配合) - 「EventBuffer」:
儲存轉換過的 Event,有一套自己的策略進行快取(例如大於100條存入本地資料庫),還有一套策略用於傳送(1分鐘輪訓一次 EventBuffer 進行傳送)
圖中還畫了 Logger 和 Other 兩個模組,Logger 可以根據行為序列記錄一些日誌,用於分析 Crash 和一些業務的異常,Other 大家就可以根據自己的腦洞和需要進行設計了,比如 UserActionSequence 是把 UserAction 序列化為 json 的過程,我們也可以把 json 反序列化成物件,然後再交給對應的 UI 去執行,這樣就可以完成 UI 自動化測試。
七、總結
原來常使用的 MVP 或者最近比較火的 Android Architecture Component 使用的 MVVM,都不能很好的用程式碼來表示使用者行為(程式碼可讀性不夠直觀),雖然 Presenter 和 VM 的職能也是用來解釋使用者行為獲取資料再到驅動渲染,但我覺得對於程式設計師來說還是不夠友好。但使用 UserAction 來貫穿整個前端的流程,一切看起來就變得自然了,UI、模組、資料的職責也都顯得更單一了。
重要的是這樣開發是我們獲得了使用者的操作序列,一切的資料來源於使用者。有了它對以後的分析和其他的開發都會有很大幫助。
本文為原創文章,如需轉載請註明出處,謝謝!
如有問題可留言討論~