從技術債務到架構升級,滴滴國際化外賣的變革
背 景
商家營銷簡述
圖片
在外賣平臺的運營中,我們致力于通過靈活的補貼策略激勵商家,與商家共同打造良好的合作關系,也會提供多樣化的營銷活動,幫助商家吸引更多用戶下單。通過這些活動,不僅能夠提高商家的銷量,還能讓用戶感受到實際的優惠,從而增強他們對平臺的粘性。
前端技術特點
業務特點:營銷場景玩法多、活動類型多、活動鏈路長、活動規則復雜。
中后臺技術特點:活動配置表單規則多、聯動復雜。
前臺技術特點:終端類型多(PC/EXE/PAD/PHONE)、代碼重復度高、用戶輸入校驗規則復雜。
業務技術架構
圖片
活動鏈路
圖片
商家營銷相關項目迭代時間較長,積累的歷史技術債務越來越多,結合業務背景和以上的技術特點,之前對歷史項目進行過一波代碼治理,比如:多端代碼復用、后臺復雜度治理等。
2023年的治理更多解的是代碼重復及腐化相關的問題,而外賣商家營銷活動的配置能力還處于非常基礎的階段,2024年,我們結合業務新訴求的契機,從系統架構治理維度,對商家營銷前端項目做了一個全面的升級。
現狀
外賣商家營銷活動,按活動來源區分主要有四大類:平臺招商、代運營、品牌代建、商戶自營銷,按類型區分主要有四大類:特價菜、買贈、免配、滿減。前后端底層區分這些活動渠道及類型都是case by case的形式,以招商活動創建為例:
不同活動類型,優惠信息都放在不同的字段里,特價菜是specialItemRule,免配是freeDeliveryRule,滿減是reductionRule,買贈是buyGiftsRule,且規則rules字段層級嵌套冗余,字段屬性沒有規律可循,以下列舉了兩類活動的部分字段。
特價菜活動規則字段示例:
"specialItemRule": [{
"rulePurposeType": 0,
"rules": [{
"type": 3,
"content": {
"discountValueRange": null,
"discountValueList": [10, 11, 20],
"discountType": 1
}
}],
"selectItemNumRange": {
"min": 1,
"max": 10
},
"itemPromoRangeValue": {
"min": 1,
"max": 50
},
"picLimit": 1,
"priceLimit": null,
"itemType": 0,
"checkItemPriceDay": 7
}]
滿減規則字段示例:
"reductionRule": [{
"rulePurposeType": 0,
"rules": [{
"type": 1,
"content": {
"threshold": 10,
"discount": 5
}
}, {
"type": 1,
"content": {
"threshold": 20,
"discount": 8
}
}]
}]
面臨的挑戰
2024年隨著國際化外賣營銷業務需求明顯增長,比如:需要從0到1搭建連鎖品牌商家自運營能力、拓展新的營銷活動類型(商家券),按照現有的架構及配置能力來看,存在以下幾個問題:
- 產品需求迭代支撐效率低:涉及通用字段,需要重復修改,特價菜+免配+滿減+買贈,4種活動類型改4次,如果再算上活動渠道修改,需要再翻倍,4種渠道??4類活動 = 16 次。
- 開發遺漏:活動鏈路長,以當前最為復雜的招商活動為例,從運營后臺配置招商計劃=>商戶前臺報名招商活動,是一個較長的鏈路,由于系統數據模型不夠靈活,導致修改字段及UI展示時無規律可循,經常需要梳理遺漏點。
- 可拓展性差:當前架構下,如果新增活動類型,則涉及全鏈路所有接口改動,可復用性低。
由于業務發展的契機,國際化外賣商家側需要新增一個連鎖品牌管理端,借助這個項目,我們進行了商家營銷架構的升級。
解決方案
問題分析
商家營銷配置能力薄弱主要體現在底層數據結構缺乏通用性和擴展性。
從全局配置維度來看:
圖片
從數據結構現狀來看:
圖片
- 同一類活動,在不同平臺(端、后臺)數據結構不一致。
- 同一類活動,在不同活動來源場景下(自營銷、招商、代運營、品牌),數據結構不一致。
- 四類活動,活動規則數據結構不一致,創建需要case by case拼裝,詳情需要case by case渲染。
- 差異化分支共有:自營銷創建4 + 招商報名4 + 招商計劃4 + 代運營1 + 品牌4 = 17。
整體思路
架構治理最重要的一環就是設計出一個統一的活動數據模型,涵蓋所有平臺和活動來源場景。
圖片
- 抽象活動實體信息
- 統一差異化配置
- 按活動信息維度拆分組織字段,而不是按業務維度拆分(收斂類型、來源)。
- 按通用字段概括優惠類型,而不是按業務概念枚舉(收斂規則)。
- 支持靈活拓展
項目成果
在抽象出活動配置模型后,為保證后續需求或者人員變更能夠按照規范持續迭代,通過對應的配置模型的API文檔,配套前端JSON Schema校驗工具,約束后續拓展。
底層數據結構完成治理后,在新項目中,我們也對配置表單方案進行了優化,使得項目的數據流轉更加清晰,確保數據的一致性和可靠性。
而在前后端交互層面,對接口字段進行了運行時校驗,做到了接口安全約束,避免因數據缺陷而導致的前端錯誤。
數據結構對比
新版活動數據結構是一個面向對象的設計架構,采用組合式領域模型設計,通過策略模式實現業務規則的動態裝配。
基礎活動模型(ActInfoModel)可以被視為一個父類或者超類,定義了通用的屬性和行為,而其子類(如自營銷活動模型selfOpsModel)繼承了基礎特性,并可以實現或者重寫一些特定的功能,以滿足不同渠道的具體需求。
當出現新的渠道或者活動類型時,只需要創建新的子類,遵循現有的父類結構。而基礎模型的修改也不會影響所有子類,只需要確保子類能夠適應父類的接口變化即可。
圖片
配置表單方案優化
在之前的項目里,表單間的組件通信,是傳統多層組件的數據傳遞形式,通過父子組件層層傳遞。
圖片
數據流:自上而下,每個組件都需要通過props接受和傳遞數據。
缺點:增加了代碼復雜性,每個組件都需要顯式傳遞數據,容易出現冗余代碼和數據同步問題。
這種形式對于簡單的表單場景來說,比較直觀,但是對于商家營銷活動配置場景來說,在過往需求迭代中出現了維護困難和數據同步異常的問題,在新項目里,我們使用了配置模型+依賴注入的表單方案。
圖片
數據流: 數據通過依賴注入在組件樹的各層之間傳遞,子組件直接獲取所需數據
優點: 降低了組件之間的耦合性,減少了多層傳遞的冗余性,數據更加集中且易于管理
數據流轉對比
圖片
使用配置模型 + 依賴注入的方式不僅可以簡化數據流轉,還能實現集中管理,減少代碼冗余,提高數據一致性,更容易進行維護和調試,特別是在需要動態配置或復雜業務邏輯的場景下表現尤為突出。
接口安全保障
當前數據安全問題
為了避免接口數據異常,導致前端頁面白屏,我們通常會在代碼中加一些字段兜底邏輯,這樣帶來的問題:
- 冗余的兜底邏輯:在組件中,使用“||“操作符、可選鏈和解構默認值等方式進行兜底處理,導致同樣的邏輯在多個地方反復出現。
- 復雜的數據結構處理:對于復雜的數據結構,通常為了某個字段兜底會出現一大坨繁瑣的代碼,影響代碼可讀性與代碼效率。
- 數據類型安全問題:常規兜底形式無法保證數據類型安全,可能造成不符合預期的類型錯誤,進而引發應用程序中的邏輯錯誤或頁面崩潰。
在抽象出活動配置模型后,活動配置的定義是由標準的JSON Schema描述組成的,在這個基礎上,我們定義一些校驗及默認填充規則,并引入集中式的兜底機制,在接口數據返回時,調用一個校驗工具函數,實現統一的兜底策略。校驗工具函數是借助zod這個工具庫去實現的。
招商活動配置描述示例
// 招商活動規則
export const SignUpActRuleSchema = ActRuleSchema.extend({
selectNumRange: z
.object({
min: z.number().default(0),
max: z.number().default(0),
})
.default({ min: 0, max: 0 }),
actType: z.union([z.number(), z.string()]).default(0),
rule: z.array(SignUpRuleSchema).default([]),
})
export type SignUpActRule = z.infer<typeof SignUpActRuleSchema>
// 招商活動詳情頁接口信息
export const SignUpDetailSchema = z.object({
actRule: SignUpActRuleSchema.default({}),
actInfo: SignUpInfoSchema.default({}),
shopJoinInfo: z.array(ShopJoinInfoSchema).default([]),
})
接口返回處理示例:
// 招商活動詳情接口
// useApiSchema是統一的返回數據校驗工具函數
export async function getSignUpDetail(params: object = {}): Promise<SignUpDetail> {
const response = await post(GET_SIGN_UP_DETAIL, params, { returnData: false })
return useApiSchema<SignUpDetail>(SignUpDetailSchema, response.data, response.traceId)
}
useApiSchema函數功能包含:數據校驗、兜底數據填充、埋點上報。
接口返回字段中若出現返回數據類型錯誤或者未返回的情況,將返回自定義的默認值從而保障頁面正常展示,對于錯誤數據也做了埋點上報,當到達一定閾值時會進行報警。
效率提升
日常迭代
活動配置模型通過字段的抽象和整合,大幅提升了字段擴展的效率。原本因各活動類型和場景的數據結構差異,需要在多處修改數據結構和組件邏輯的場景,現在只需在一處進行修改即可,大大提高了開發效率。
以前臺項目活動規則相關迭代為例:
圖片
開發實例
以近期需求為例,我們需要新增一種券活動類型,通過采用活動配置模型和集中式狀態管理的開發形式,使得開發過程中對于數據相關的處理邏輯與狀態管理要比之前簡易很多,開發效率提升約40%。
后續規劃
以上架構治理都是針對新的項目去做的實踐,而對于國際化外賣商家營銷前端的其他項目同樣需要做架構升級改造,后續我們計劃收斂運營后臺的活動配置,將最為復雜的招商活動鏈路進行標準化,后臺配置=>前臺應用,引用同一套數據模型。
國際化外賣商家營銷前端架構預期
圖片