Day 25 - 追蹤使用者行為
常常我們在開發完功能之後,UX 設計師可能會想知道使用者如何使用這些功能,並建立漏斗來觀察每一個步驟的使用量。一種常見的方式在各個頁面中埋下分析追蹤碼,由此就可以追蹤使用者在每個頁面的使用晴望。為了完成這個功能,Flutter 開發者們常常會需要在各個頁面開啟時,埋下紀錄 Firebase Event 以紀錄使用者打開了這個頁面。
舉個例子
假設我們有一個頁面,我們可能會把追蹤碼埋在這個頁面的 initState 中。

但是當我們頁面一多時,就會發現需要每一頁都要埋,著實有些麻煩。當我們想修改頁面的顯示或者 Event 紀錄方式時,都會修改到這個類別,也暗示這個類別違反了單一職責。頁面工作應該是負責顯示使用者需要的資料,而不是紀錄 Event。
使用 FirebaseAnalyticsObserver
所幸,Firebase Analytics 套件提供了一個稱為 FirebaseAnalyticsObserver 元件,使用這個元件,當頁面切換 Route 路徑變化時,元件就會幫我們紀錄事件。

如此一來,我們就不需要辛苦的在每個一個頁面的 initState 紀錄事件,能把紀錄事件的職責交給 FirebaseAnalyticsObserver 元件,每個頁面的的職責也回歸單一。當我們想要排除一些頁面的事件紀錄時,也可以使用 routeFilter 來解決。

但是使用什麼服務來紀錄事件有許多選擇,甚至是自己實作。在這些情況下,我們就沒有好用 FirebaseAnalyticsObserver 元件可以使用了。
Route Observer
為了解決這個問題,我們可以仿造 FirebaseAnalyticsObserver 使用 Flutter 提供的 Route Observer,建立一個 EventLoggingRouteObserver 來幫助我們紀錄事件,並把它放進 MaterialApp 中。

使用客製的 RouteObserver,還能讓我們有機會針對不同的頁面,增加不同的參數,讓我們能準確紀錄使用者行為。

當我們今天不需要紀錄頁面開啟/關閉事件時,我們也可以直接移除掉 RouteObserver 就好,而無需到每個頁面去移除紀錄事件的程式碼,也符合開放封閉的原則。
將事件紀錄封裝
大部分的 Firebase 套件,都使用 Singleton 模式。當我們想使用時,只要使用 FirebaseAnalytics.instance 就能使用方法。
FirebaseAnalytics.instance.logEvent(name: "event_name");但是如果我們直接程式碼中呼叫 FirebaseAnalytics.instance,會讓使用的類別直接與 FirebaseAnalytics 相依。相信讀者們一定知道這會產生什麼問題,當我們想更換事件紀錄的方式時,就會忙著到所有使用到的類別修改。除此之外,當我們想進行單元測試時,也會因為 FirebaseAnalytics 而無法測試,因為會造成執行測試時,還是嘗試去尋找 Firebase 設定,但單元測試不會有這些東西,所以測試就壞了。
為了解決這些問題,我們可以使用前幾天提到的技巧:依賴注入。我們可以寫一個類別封裝 FirebaseAnalytics 並繼承 Analytics 介面。

然後把實作放進依賴注入框架中。

最後使用 Service Locator 取得 Analytics,並使用其紀錄事件。

結論
紀錄頁面開啟/關閉的事件是一種常見的事件紀錄,將紀錄事件的程式碼與畫面渲染的程式碼分開,能有效提升程式的可維護性。另外除了上述的事件之外,還有另外一種常見的事件紀錄情境是:當使用者點下某個按鈕時,我們也希望紀錄使用點擊了哪個按鈕,此時如果我們直接使用 FirebaseAnalytics.instance,會讓程式碼逐漸僵化,同時也失去可測試性,此時我們可以使用依賴注入解決,避免軟體漸漸變成硬體。
— 全文完 —
如果這篇對你有幫助,可以分享給朋友,或追蹤後續更新。我在 Threads 也會貼一些零碎想法。