火山引擎A/B測試平臺的實驗管理重構與DDD實踐

字节跳动数据平台發表於2024-05-08
本次分享的主題是火山引擎數智平臺VeDI旗下的A/B測試平臺 DataTester 實驗管理架構升級與DDD實踐。這裡說明的一點是,程式碼的第一目標肯定是滿足產品需求,能夠滿足產品需求的程式碼都是好程式碼。而本文中對程式碼的好壞的評價完全是從架構的視角,結合程式碼的可讀性、可維護性與可擴充套件性去分析的。
在一個產品或者程式碼倉庫的發展過程中,如果不對程式碼的質量加以控制、不引入原則與規範的約束、不及時的採取手段,那麼隨著時間的流逝,大概的發展軌跡將會如下圖所示。
  • 早期
在專案的早期迭代非常迅速,一個需求可能一週就可以完成開發測試與上線,研發效率也保持在較高的水平。此時一切還都是有序的狀態。
  • 中期
隨著功能的迭代,模組與模組之間、功能與功能之間可能會出現聯動與複用的邏輯,如果不加以重構,可能就慢慢變成了技術債。加上人員投入增加與人員流動,新人可能對原來的設計思路並不瞭解,會出現僅看程式碼無法瞭解功能的情況,認知負荷開始上升,慢慢的會發現雖然投入的人力增加了,但是研發的效率開始越來越慢。系統混亂開始慢慢增加。
  • 後期
雖然效率降低,但是功能的迭代還在進行。但即使只是一天就能搞定的小需求,涉及到的改動也會有多處,且不確定要改多少個地方才能保證系統的正常執行。此時整個系統的認知負荷已經過載,僅僅寫好程式碼還不夠,還需要清晰地瞭解歷史程式碼的功能邏輯,否則稍加不慎就會引入oncall或者投訴。隨著oncall的增多,研發的人力又被佔用,進一步降低了研發效率,需要額外的時間償還技術債。此時系統已經變得非常混亂,即將變為無序狀態。
  • 末期
隨著混亂的進一步惡化,團隊的戰鬥力幾乎歸零,僅能夠維護現有功能,新增需求很難在短時間內完成開發上線。產品的發展技術陷入停滯,效率幾乎降為零。此時系統已經變為完全混亂的狀態。

與“複雜”程式碼的鬥爭

在 DataTester 專案早期,由於需求簡單直接,功能估期基本準確。但是隨著產品規模擴大、場景複雜度增加,能明顯感覺到功能的開發依賴和需要考慮的東西越來越多。
下面簡單羅列了功能模組與系統熵遞增的關係。可以看出從最初的程式設計實驗,到後邊的視覺化與多連線實驗,又到後邊的父子實驗、push實驗,再到最後的內外合併,整個系統的複雜程度越來越高,如果不及時採取措施,那麼後續的維護與擴充套件將會耗費非常非常多的人力。
回顧軟體工程的歷史發展,包括物件導向、微服務以及各種領域模型等,它們都代表了針對系統複雜性的不同應對策略。正如John Ousterhout教授在他的著作《A Philosophy of Software Design》中所強調的,複雜性可以定義為那些使得軟體變得難以理解和修改的因素,而軟體技術的發展史也是與“複雜度”鬥爭的歷史。
那到底什麼是複雜度?John Ousterhout教授在書中明確指出,複雜度是指那些使得軟體難以理解和修改的因素。複雜的系統通常具備三個明顯特徵,由John教授抽象為以下三個方面:
  1. 變更放大(Change amplification): 這指的是看似簡單的變更需要在許多不同地方進行程式碼修改。在此情況下,開發者可能未能及時地進行程式碼重構或提取公共邏輯。相反,他們可能採用了快速複製貼上的方式來開發程式碼,以節省時間和減小影響已存在的穩定模組的風險。然而,當需求變化時,就需要在多個地方進行程式碼修改。
  2. 認知負荷(Cognitive load): 這表示系統的學習和理解成本相當高,因此降低了開發人員的生產效率。高認知負荷意味著開發者需要花費更多的時間和精力來理解系統的結構和工作方式。
  3. 未知的未知(Unknown unknowns): 這意味著開發者不知道必須修改哪些程式碼才能確保系統正常執行,也不知道對程式碼的更改是否會引發線上問題。這是複雜性中最令人頭疼的表現之一,因為它帶來了不確定性和風險。
導致複雜性的原因可以概括為兩個方面:依賴性與模糊性。過多的外部依賴導致功能變更的放大,並會增加認知負荷,而資訊的模糊會增加未知的未知。而這些表象又會反過來提升系統複雜性,以此往復加速系統的“衰敗”。
系統從有序到無序是必然的,那隻能任由程式碼變壞而束手無策嗎?
幸運的是答案是否定的。軟體工程已經發展了60多年,我們遇到的問題,前輩們肯定也遇到過,我們有充分的理論和方法來對抗系統的逐漸混亂。如下圖所示,雖然系統複雜度上升是無法避免的,但是適時的重構可以減緩系統混亂的速度。
隨著時間的推移,DataTester 開發經歷了多個階段的發展,每個階段都伴隨著不同的技術、方法和挑戰,每個階段也有各自的主要矛盾與次要矛盾。團隊的發展過程中,也需要適時的進行組織架構調整,以適應新環境新的挑戰。只有變化才是唯一不變的東西。和團隊管理也非常類似,在這個不斷變化的環境中,適時的重構變得至關重要。重構是指在不改變軟體外部行為的前提下,對程式碼內部結構進行調整和最佳化的過程,目的是提高程式碼的可讀性、可維護性和效能。在不同階段,重構都有其獨特的意義和價值。
比如在 DataTester 迭代初期,我們的目標可能是儘快上線功能,提高產品競爭力,那麼此時應優先業務迭代。而隨著反饋越來越多、需求越來越多,會有更多新的功能上線。沒有人可以預知未來會有什麼功能加入,會有什麼業務場景,所以如果不能隨著產品的迭代及時調整程式碼與架構,那麼混亂的速度增加是必然的。
產品的交付需要從人力、時間與質量三個維度去進行評估,其中的時間即經常所說的“能不能按期交付”。產品的研發與上線需要PM\BE\FE\UX\QA一起協力,而這裡主要關注BE視角遇到的一些問題。每個雙週都是對一些工作進行估期,但是排期卻很難進行準確評估。導致該問題的原因可以分為以下幾類:
  • PRD描述不夠周全,往復討論無形中拉長了開發週期
  • 技術方案考慮不夠嚴謹,忽略了一些相容與適配問題
  • 歷史包袱導致新功能的開發,需要在很多地方做適配與調整,並且會影響其它功能
上述第三個問題的出現,就意味著程式碼中的”壞味道“已經很嚴重了。評估出來的工作量和實際的工作量大相徑庭也是在意料之中的。如果這時候的開發同學對原有功能瞭解的不夠深入,那麼結果可想而知。樂觀的情況下,新功能的開發只需要完成該模組需要的開發工作,這就對程式碼的封裝與隔離性要求非常高。
那麼既然重構如此重要,那為什麼沒有被重視或者沒有及時執行呢?我們可以嘗試從常見的理由來發掘深層次的原因,可歸為以下三類:
  • 不是我不想做,而是不知道怎麼做
    • 程式碼腐化嚴重,缺少相關規範的沉澱與指導
    • 人員流動導致原始設計思路無法繼承
  • 不是我不想做,而是別人都是這樣做的
    • 業務耦合嚴重,無法進行封裝與隔離
  • 不是我不想做,而是沒有時間做
    • 缺少長遠視角,認為重構是浪費時間的事情,對無業務幫助
    • 重構短期無法從業務側看到明顯的收益
    • 程式碼質量未受到重視
隨著混亂的增加,團隊生產力也持續下降,趨向於零。當生產力下降時,管理層就只有一件事可做了:增加更多人手到專案中,期望提升生產力。對於可以拆解的任務,增加人力確實可以縮短交付時間提升效率。但對於複雜的系統,新人並不熟悉系統的設計,他們搞不清楚什麼樣的修改符合設計意圖,什麼樣的修改違背設計意圖。而且,他們以及團隊中的其他人都揹負著提升生產力的可怕壓力。於是,他們會製造更多的混亂,驅動生產力向零那端不斷下降。因此,可以說補充人力在一定條件下是可以提升整體的進度與效率,但這並不絕對,特別是對於混亂的系統。

架構設計的思考

網上有一張比較有意思的圖片,如下,評價程式碼質量的唯一標準即code review會議室中,每分鐘傳出的WTF次數。
The only valid measurement of code quality: WTFs/min
當然程式碼的好壞要從可擴充套件、可維護、可測試、可讀性等多方面綜合考慮。雖然有很多規範與法則,但是如果過度設計也並不見得是好的程式碼。因此在業務需求與規範之間如何權衡,也是一門“藝術”。
程式碼是思維活動的產物,不同的開發者有著不同的思維模式,因此需要好的原則與規範的約束。"道法術器"是古代中國哲學思想中的概念,常用於描述宇宙和人生的基本原理和法則。那是不是也可以用於指導軟體的開發呢?
對於軟體的架構設計,同樣可以從以下四個層級進行思考,從上到下依次遞進:
"道"是指宇宙萬物的根本原則,也可以理解為事物執行的規律和基本法則。不以人的主觀意願而轉移。熵增定律可以被視為一條使整個宇宙變得絕望的法則,它被理解為事物結構不可避免的逐漸衰退。熵增定律無法避免,就像生老病死無法避免,但是我們可以透過一些手段,延緩“最終無序”的到來。
"法"是指宇宙和人生的治理法則與方法論,對應到程式碼開發中可以歸類為一些經典的原則與思想。軟體工程經過60多年的發展,沉澱了很多有指導意義的方法論。比如SOLID原則、各種設計模式,以及大道至簡的架構設計思想:抽象、封裝與隔離。這些方法論都可以助理我們進行程式碼重構,及時降低系統的複雜程度。
"術"指的是技能、技術和實踐方法。在軟體開發中,"術"可以表示程式設計技術、框架的使用、程式碼架構等。方法論往往都是思想上的指導,不同的人可能也有著不同的理解,真正落地的時候還需要一些業務框架與程式設計正規化,比如有領域驅動設計、MVC架構、依賴注入與物件導向等。這些原則都可以幫我們更好的進行程式碼分層與依賴反轉,進而實現高內聚、低耦合的業務程式碼。
"器"是指工具和資源,用於實踐和應用"道法術"的原則。在軟體開發中,"器"可以包括開發工具、版本控制系統、自動化測試工具等,採用微服務架構可以更好的實現功能的隔離,而單元測試與CI/CD則可以更好的加速功能的迭代與系統的重構。
無論是方法論層面還是工具層面,目前都已經很成熟了。在寫程式碼的時候多加一步思考,在功能完成之後對業務程式碼進行適當的重構,就會達到很好的效果,也應當成為一種習慣

程式碼可能存在哪些潛在問題?

下面將羅列一些專案中實際存在問題,這些雖然從規範與架構視角看是有問題的,但是從滿足業務需求的視角看都是好的程式碼。其實大家都能意識到這些程式碼存在的潛在問題(不是我不想做,而是別人都是這樣做的),但是模組”牽一髮動全身“,且不斷有新的業務加進來,不是簡單的改動就能完成的,因此”壞味道“只會慢慢惡化。

無業務分層

目前python的後端程式碼沒有層級關係,整體屬於標準的過程式程式碼,一個功能函式可能成百上千行,所有的功能都在一個函式里面堆積完成。雖然做過一些功能函式的拆分,但是整體還是過程式的邏輯處理。業務邏輯的封裝與隔離幾乎沒有。

迴圈/重複查庫

目前在koi中,django的使用大大方便了外部資料的獲取,但是也導致了外部呼叫的泛濫。比如在不同的函式中可能都需要Application得資料,但是傳參只傳了app_id,那麼就很可能導致再一次查表的操作,這種邏輯在koi中是非常多的。另一方面由於django的封裝很容易讓大家忽略這是一個外部呼叫,因此很容易寫出在迴圈中查庫的場景。

邏輯冗餘/分散

不同的校驗函式都堆積到了一起,這就導致一方面校驗函式的單測很難編寫,另一方面校驗功能難以複用,以至於出現很多校驗邏輯存在重複編寫的情況,導致邏輯冗餘。

函式職責複雜

接上述例子,在這個校驗函式里還有業務邏輯或者資料轉換的操作,後續的改動將更加難以維護與測試。資料校驗與業務邏輯應該分開,做好隔離才能方便後續擴充套件與測試。

未做抽象

未做足夠抽象表現為不同實體在做著類似的操作,但是沒有對操作進行統一的封裝與隔離處理,比如下方程式碼中實現開啟介面,涉及很多實驗型別的開啟操作,都是透過if else插入自己的邏輯。如果抽象合理的話應該是不同實驗都去實現一個實驗開啟的介面,在主業務流程裡看不到差異化處理,這樣才能做到比較好的業務隔離。將複雜的功能隱藏在簡單的介面後邊,才是更好的抽象。

耦合嚴重

目前功能的外部呼叫與業務邏輯完全混在一起,這裡不作舉例。因此業務邏輯對外部依賴非常嚴重,一個介面的變更或者欄位的修改可能就會導致業務邏輯出現問題。外部依賴應該是服務於業務邏輯的,外部依賴的變更不應影響到業務邏輯,這樣才能實現依賴反轉。
透過重構解決上述提到的問題。基於現有業務場景對實驗管理模組進行重構,解決問題,構建高內聚低耦合的業務程式碼,提升程式碼的可讀性、可維護性、可擴充套件性與可測試性。
透過提高可擴充套件性,大大縮短後續內部功能開發所需的開發時間;透過封裝實現程式碼的複用;透過隔離減少功能間的相互影響,減少bug出現的機率;透過依賴反轉與關注點分離實現高內聚低耦合的業務程式碼。
透過架構重構提升整體團隊的架構與規範意識,提升整體技術水平,增強團隊戰隊力。

如何進行實驗管理重構?

接下來將對實驗管理重構的具體工作進行介紹。DDD主要解決程式碼“寫在哪裡”的問題,但是具體的實現細節還是需要根據業務的具體場景做相應的處理。本次重構從資料結構定義、業務校驗、業務邏輯與領域物件構建等方面對重構的具體工作進行介紹。

模組梳理

目前產品現有及後續部分新增功能梳理如下圖所示。

領域建模

按照 DataTester 的實驗功能,可以將實驗域細分為四個領域模組:日誌、實驗、實驗層管理和工作流程。其中實驗層管理和工作流程分別由其它服務模組接管,因此在實驗倉庫下需要重構與完善的即日誌模組與實驗核心模組。而層管理僅做了對內部署的適配,對外部署仍未完成適配,因此在此次重構過程中會對層相關的邏輯做一定的功能抽象,方便後續內外統一後的對接。

日誌域

日誌域主要對外暴露獲取操作日誌的介面,對內提供領域物件的change-tracking能力,生成所需格式的操作日誌檔案。具體的,日誌目前有操作日誌和全域性操作歷史兩部分。除此之外,期望能夠透過ChangLog域提供的change tracking能力,最佳化資料庫操作,減少不必要的save與update操作。

實驗域

實驗域相比日誌域的業務邏輯更為複雜一些。基於可擴充套件與可複用的原則,對實驗的功能拆分成三個部分,分別為BaseExperimentExperimentExtension與ExperimentPlugin。模組的拆分其實都是在

  • BaseExperiment
BaseExperiment功能如其名是實驗最基礎且通用能力,除了常用的實驗與版本的一些操作外,還包括實驗收藏、Demo實驗的特殊處理、郵件通知、版本管理、指標管理與目標受眾等部分。這些功能後續是否需要統一抽象到IExperimentPlugin介面中,可以後續迭代而定。
版本管理
版本管理作為實驗比較核心的模組,也可以看做是基礎能力,因為實驗的本質就是管理一系列不同的差異化配置,然後結合線上流量看效果。和實驗版本相關的功能都可以在該實體中實現或者擴充套件,比如關閉單個實驗組、視覺化實驗下頁面資訊編輯等。其中,白名單和版本息息相關,因此將白名單相關處理邏輯放到該版本管理模組下進行統一處理。另外對於穿山甲特殊場景,需要載入預置版本配置,這種場景在實際設計的時候需要注意其通用性。
實驗層
實驗層管理部分後續會統一放到實驗倉庫裡面維護。目前實驗中只有對層的一些簡單操作與校驗功能。
指標管理
指標管理和版本管理類似,都是實驗過程中比較重要的模組。在該模組中主要處理指標的增刪改查與關聯關係的維護,比如實驗指標關聯關係、實驗與指標組關聯關係等。
目標受眾
目標受眾也即實驗模組中的filter條件,用於對請求的使用者做路由配置。由於其涉及到的業務邏輯較多,因此單獨抽出TargetRule實體對這部邏輯進行處理。後續還將負責過濾條件的引數轉換(backend)與一些關聯條件的建立,比如過濾條件與分群、服務端過濾引數的關聯關係等。

業務流程

對實驗的主流程進行總結,可以發現任何實驗的操作都可以抽象成三個步驟,即資料校驗、特定邏輯處理與資料持久化。這也為設計可擴充套件與可插拔的程式碼架構提供了可行性。具體的實驗建立的主流程如下圖所示,按功能型別可以大概分為三個部分:validator、process與save。
  • validator對資料進行校驗,如有不符合的資料將會直接返回錯誤。
  • process處理業務邏輯,包括資料轉換與構建聚合根等操作,出現問題也會直接返回並報錯。
  • save為最後的持久化邏輯,當資料持久化報錯也會返回,並取消事務。


在系統分層中,各個模組負責的主要功能大致如下圖所示。不同層各司其事完成業務邏輯,下面示例示例程式碼為實驗開啟介面對應領域服務的具體實現。

去除步驟依賴

在實驗建立的互動上,通常需要幾步完成元資訊的建立,並且在第四步時會將實驗從草稿態轉為除錯態。但從restful規範來講,資源的建立、更新與部分更新(狀態修改)應該是透過不同的操作來實現。並且如果將建立的操作與實驗操作的步驟進行繫結,將會大大限制可擴充套件性。目前koi程式碼中已經實現了部分資源建立、更新與步驟的解耦,但是還是存在與步驟強繫結的操作。此次實驗RPC服務重構將徹底摒棄步驟依賴,與步驟進行完全解耦。
具體的業務邏輯變更如下圖所示,可以看出對於實驗建立的過程,可以選擇一次完成所有欄位的建立,也可以自行分多個步驟完成整體資料的構建,除錯前會對資料完整性進行驗證。
為了實現上述功能,需要對實驗idl中的欄位型別進行調整,將所有的欄位除了id均改為optional欄位,這樣服務就可以獲取此次介面呼叫需要更新的欄位,除此以外,基於這些資訊還可以實現資料的按需校驗,下面將對自動校驗的實現進行介紹。

自動資料校驗

資料校驗在業務邏輯程式碼中作用比較重要,關係整個後續業務邏輯能否正確執行。對引數的校驗根據其具體業務邏輯與場景,可以分為欄位校驗、依賴校驗、功能校驗與邏輯校驗四個部分。
  • 欄位校驗
    比較常見的校驗型別,比如實驗的名稱不能超過多少個字元,實驗型別是不是合法等。
  • 依賴校驗
    依賴校驗顧名思義,在業務邏輯中依賴了其它模組,比如指標,需要校驗下指標是不是合法的等。
  • 功能校驗
    功能校驗,比如使用者是否對某個資源有許可權,又比如實驗裡面的配置衝突等。
  • 邏輯校驗
    邏輯校驗主要是一些具體的業務邏輯,比如父子實驗中子實驗開啟與父實驗結束時,會涉及時間範圍的校驗等。
首先看下通常資料校驗是如何實現的,以下是在tob側老版本feature flag中的校驗方法。如果一次請求包含的實體或者值物件不完整,那麼就會出現很多是否設定某些欄位的判斷;且建立需要的校驗與更新所需的校驗需要分開處理無法複用。這種校驗雖然能夠實現校驗的功能,但是新增校驗欄位可能需要在建立與更新等校驗函式里面做同步改動,如果有遺漏就會出現問題。那麼就需要考慮一種機制能夠按需校驗,根據設定欄位自動構建構建函式完成對引數的校驗。
通常校驗邏輯會寫在正式的業務邏輯之前,但考慮到資料有依賴關係以及校驗需要完整的領域模型,因此此次 DataTester 重構將資料校驗作為聚合的一部分。為了實現業務邏輯與資料校驗的完全解耦以及更好的支援後續的擴充套件,本次透過Validator物件實現了

透過一個json資料結構對需要構建的模組進行配置,每增加一個模組或者模組的子元素,需要自行在建構函式中做對應的實現,下面透過一個實驗開啟需要配置的模組示例來做說明。
如上圖所示,此時構建的領域物件包含應用資訊、實驗基礎與擴充套件外掛四個部分。其中應用資訊主要是常用的app_id和product_id等;實驗基礎資訊構建了實驗版本資訊、實驗所在層的traffic資訊與同層實現列表;擴充套件部分需要父子實驗中父實驗的基本資訊、版本資訊與所在層的traffic map資訊,智慧實驗部分需要獲取traffic map資訊;外掛模組中獲取了平滑生效與實驗工作流程兩部分資訊。其中每一個key需要有對應的實現。具體到實現部分,為了統一函式簽名,採用閉包的方式封裝repo實現,舉一個獲取extension模組的例子如下所示:

業務邏輯處理

業務邏輯部分按照實驗域的劃分,分為三個部分。
  • BaseExperiment部分業務邏輯比較簡單,可以視情況增加業務邏輯,原則上這些entity或者value object在構建聚合的時候均已完成建立。
  • ExperimentExtension部分主要是根據不同實驗型別做一些擴充套件,可以根據實際場景做各自的業務邏輯操作。
  • ExperimentPlugin部分主要是實驗粒度的高階功能擴充套件,這裡透過職責鏈模式進行擴充套件,在抽象的介面中完成不同操作下的業務邏輯。
下面用實驗開啟的業務邏輯為示例作說明。由於採用了物件導向的程式設計方式,業務模型也叫程式設計“充血模型”,每個實體都擁有豐富的方法。而對實驗開啟的操作,也按照上面的劃分從三個模組進行操作,每個模組直接或者間接的提供了Start方法,進而完成整體的業務。具體到extension與plugin部分,在聚合中依賴統一抽象的介面,不關注其具體實現,具體是程式設計實驗還是視覺化實驗,亦或是加入了精準熔斷或者實驗審批,都將透過統一的方法呼叫完成相應的業務邏輯。
另一方面,由於不同的擴充套件和外掛透過介面的方式做了隔離,後續新增模組或者修改部分模組的操作,將會變得非常容易,只需要關注當前的修改即可,不用擔心影響到其它模組。
在業務執行的過程中,整體業務邏輯呈現從上到下、逐級劃分的一個過程。一個功能將層層拆分最終落到一個單一職責的函式或者方法中,這與組織管理有著異曲同工之處。這樣一來函式或者方法將盡可能的複用,單一功能的函式或者方法將更容易測試。這種從上到下的實現方式,和滑鐵盧程式設計風格中所屬的關注資料流動非常類似,上層只需要做好任務的拆分,底層按照要求實現即可。最終開發者只需要關注單個功能的實現,將大大降低認知負荷,更容易規避潛在的bug。
我偶然發現了一種極其強大的程式設計哲學,那就是你應該忽略程式碼,那只是計算機要遵循的一大堆指令。相反地,你要專注於資料,弄清楚它如何流動。 --《滑鐵盧程式設計風格》

外部服務呼叫

業務呼叫

在一些 DataTester 的業務場景中,業務邏輯執行結束後需要呼叫第三方依賴完成一些操作,對於比較統一的處理比如實時生效需要傳送的訊息佇列,在領域服務中統一處理介面。而對於一些特殊的case,比如視覺化實現在開啟的時候需要呼叫圈選模擬器建立熱力圖,並把熱力圖的id存到version表中,而其它實驗型別可能又不需要類似的外部操作。為了差異化處理這種業務需求,在領域服務中增加了外部服務呼叫模組。
目前有兩種外部服務呼叫型別,一種是基於業務場景(tob或者internal)的差異化處理,一種是基於實驗型別的差異化處理,相關UML類圖如下所示。後續如果有新的業務場景可以在此處進行擴充套件。

資料持久化

資料持久化的實現還是還是參考架構規範中的實現形式,將事務放到領域服務層。另外,除了對資料庫的呼叫,相關依賴方的呼叫比如微服務間的呼叫均統一封裝在repo層,如需新增新的依賴只需進行依賴注入即可,方便統一管理。

總結

雖然目前這套拆分開起來能夠支撐 DataTester 的業務場景與業務需求,但是並非是一個“終極架構”。很多細枝末節的差異化處理仍存在。隨著後續業務場景的持續豐富,當前架構可能還需要做進一步擴充套件。目前的架構設計預留了一定的伸縮空間,如果後續增加了比較特殊的實驗型別,在實驗建立過程中沒辦法與目前的主流程複用,就可以將相關邏輯上升到extension模組等。
現在架構重構到了攻堅階段,沒有產品形態的重新設計,沒有產品功能的完全統一, 技術重構就不可能進行到底。已經取得的重構成果還可能得而復失,架構上產生的新的問題也不可能從根本上進行解決,合併也就可能變成了“縫合”。
目前重構工作已經結束並且已經上線到各環境,並高效支撐了數十種實驗型別的日益迭代工作。後續會對領域物件做歸類細化操作,確保能將領域物件作為工具庫使用,透過不同的組合排列實現新的功能,支援新增業務場景與需求;更進一步會將服務能力透過外掛進一步開放,沉澱為外掛市場,實現中臺能力與BP業務方的共贏。
重構效果:
  1. 需求開發效率提升30%
  2. 效能提升約50%
以上就是火山引擎A/B測試平臺 DataTester 實驗管理架構升級的實現,希望對大家有所啟發。
火山引擎DataTester作為火山引擎數智平臺VeDI旗下的核心產品,源於位元組跳動長期的技術和業務沉澱。目前,DataTester已經服務了上百家企業,包括美的、得到、博西家電、樂刻健身等知名品牌。這些企業在多個業務環節中得益於DataTester的科學決策支援,實現了業務的持續增長和最佳化。

相關文章