如何設計投放系統系列—-靈活的欄位對映補全機制
引言
我們知道搭建系統跟投放系統是兩個緊密關聯的系統,搭建產出的是頁面的結構,投放產出的是頁面的資料。搭建產出的頁面包含各式各樣的模組,這些模組包含的欄位也沒有太多規律可言,那麼投放系統怎麼為這些模組補全資料呢?
在回答這個問題之前,我們先嚐試解決一些簡單的業務 case
。
幾個案例
案例一
有一個商品模組,欄位包括:商品的標題、商品圖片、購買連結、商品價格、商品描述,想要投放某個選品集的商品,請問投放系統應該怎麼設計以補全這些欄位資訊?
拿到這個需求,最直觀的解決方案就是,直接去商品庫取選品集對應的商品列表,把商品庫裡的欄位塞到對應的模組欄位上。
// 商品選品集
var goodSet = [1,2,3,4,5];
// 從商品庫獲取對應的商品實體資訊
var entityMap = goodService.fetch(goodSet);
var output = [];
for (var i = 0, l = goodSet.length; i < l; ++i) {
var goodId = goodSet[i];
var entity = entityMap[goodId];
if (!entity) {
continue;
}
// 欄位對映
output.push({
`商品名稱`: entity[`goodName`],
`商品圖片`: entity[`goodImg`],
`商品連結`: entity[`goodLink`],
`商品價格`: entity[`goodPrice`]
...
});
}
return output;
案例二
有一個店鋪模組,欄位包括:店鋪的名稱、店鋪的照片、店鋪連結,想要投放某個選品集的店鋪列表,請問投放系統應該怎麼設計以補全這些欄位資訊?
這個需求跟上面一個類似,依然是最直觀的解決方案,直接去店鋪庫取選品集對應的店鋪列表,把店鋪庫裡的欄位塞到對應的模組欄位上。
// 店鋪選品集
var shopSet = [1,2,3,4,5];
// 從店鋪庫獲取對應的店鋪實體資訊
var entityMap = shopService.fetch(shopSet);
var output = [];
for (var i = 0, l = shopSet.length; i < l; ++i) {
var shopId = shopSet[i];
var entity = entityMap[shopId];
if (!entity) {
continue;
}
// 欄位對映
output.push({
`店鋪名稱`: entity[`shopName`],
`店鋪圖片`: entity[`shopImg`],
`店鋪連結`: entity[`shopLink`]
});
}
return output;
案例三
同樣一個商品模組,欄位包括:商品的標題、商品圖片、購買連結、商品價格、優惠價格,想要投放某個選品集的商品,請問投放系統應該怎麼設計以補全這些欄位資訊?
這個 case 我們發現單純的從商品庫取不到優惠價格資訊,必須去另外一個服務獲取商品的優惠價格。
對應的虛擬碼為:
// 商品選品集
var goodSet = [1,2,3,4,5];
// 從商品庫獲取對應的商品實體資訊
var entityMap = goodService.fetch(goodSet);
var output = [];
for (var i = 0, l = goodSet.length; i < l; ++i) {
var goodId = goodSet[i];
var entity = entityMap[goodId];
if (!entity) {
continue;
}
// 欄位對映
output.push({
`商品名稱`: entity[`goodName`],
`商品圖片`: entity[`goodImg`],
`商品連結`: entity[`goodLink`],
`商品價格`: entity[`goodPrice`],
// 去優惠券服務獲取商品的優惠價格
`優惠價格`: couponService.fetch(goodId).price
});
}
return output;
到了這裡,我們發現模組只要一變,程式碼就得跟著變,有沒有辦法能模組變化,程式碼不變呢?
終極解決方案
相信聰明的你已經可以看出,隨著需求的變化,我們的程式碼變化的都是欄位的補全來源以及欄位的對映關係,不變的是整個程式碼的流程。如果我們可以把這些變化的部分做成可配置的,似乎程式碼就不需要變動了。
我們試著寫了這樣一個介面
function get(id, field);
這個介面只需要傳實體的 id
,以及需要返回的欄位名,就可以返回對應的值。
每個欄位的具體補全邏輯都是 get
的具體實現,我們把實現做成可配置的形式
商品資料來源配置
{
`goodName`: {adapter: `goodService`, param: [`id`, `goodName`]},
`goodPrice`: {adapter: `goodService`, param: [`id`, `goodPrice`]}
`couponPrice`: {adapter: `couponService`, param: [`id`, `couponPrice`]}
}
店鋪資料來源配置
{
`shopName`: {adapter: `shopService`, param: [`id`, `shopName`]},
`shopImg`: {adapter: `shopService`, param: [`id`, `shopImg`]}
}
接著我們再新增一些配置,配置的是模組素材欄位跟資料來源中的欄位ID的對映關係。
商品欄位對映
模組素材欄位編碼 => 資料來源欄位 ID
{
`商品名稱`: `goodName`,
`商品圖片`: `goodImg`,
`商品連結`: `goodLink`,
`商品價格`: `goodPrice`,
`優惠價格`: `couponPrice`
}
店鋪欄位對映
{
`店鋪名稱`: `shopName`,
`店鋪圖片`: `shopImg`,
`店鋪連結`: `shopLink`
}
最後我們再修改下虛擬碼:
function get(id, field) {
var param = configService.getDatastoreConfig(field).param;
return adapterFactory.get(field).apply(param);
}
// 選品集
var entitySet = [1,2,3,4,5];
// 實體型別
var entityType = model.entityType;
// 獲取欄位對映配置
var fieldMappingConfig = configService.getFieldMappingConfig(entityType);
var output = [];
for (var i = 0, l = entitySet.length; i < l; ++i) {
var entityId = entitySet[i];
var entity = {id: entityId};
// 遍歷模組的欄位列表
for (var j = 0; j < model.fields.length; ++j) {
// 模組欄位編碼
var field = model.fields[j];
// 補全該欄位的值,get 會用資料來源配置的類和引數補全該欄位的值
entity[field] = get(entityId, fieldMappingConfig[field]);
}
output.push(entity);
}
return output;
上面其實也是我們 UTCP
系統目前的設計思路。
get
get
介面對應的就是 AbstractEntity.get
方法。
欄位對映配置
資料來源配置
相關文章
- JPA實體中欄位對映補充和嵌入物件物件
- 【Mybatis系列】從原始碼角度理解Mybatis欄位對映-AS&ResultMapMyBatis原始碼
- 裝備屬性欄位設計和投放詳解
- 將多個JSON欄位對映到單個Java欄位JSONJava
- JPA關係對映系列五:many-to-many 關聯表存在額外欄位關係對映
- 揭秘!閒魚拉新投放系統如何設計
- 【Mybatis系列】從原始碼角度理解Mybatis欄位對映-駝峰式命名MyBatis原始碼
- resultMap 和 resultType 的欄位對映覆蓋問題
- PAT-B 1021 個位數統計【對映】
- 超硬核解析!Apache Hudi靈活的Payload機制Apache
- laravel使用save與update方法靈活操作updated_at欄位Laravel
- windows域控裡,屬性和欄位對映表Windows
- mybatis 實體類排除資料庫欄位對映MyBatis資料庫
- 二進位制檔案記憶體對映記憶體
- 讀懂框架設計的靈魂—Java反射機制框架Java反射
- 計算機二進位制中的原碼,反碼,補碼計算機
- 如何透過模組/外掛機制,靈活組織Laravel工程Laravel
- 如何通過模組/外掛機制,靈活組織Laravel工程Laravel
- LeetCode 642 號問題:設計搜尋自動補全系統LeetCode
- Windows是如何將64位Ntdll對映到32位程式的Windows
- [計算機基礎] 計算機進位制轉換:二進位制、八進位制、十進位制、十六進位制計算機
- ThinkPHP3.2.3 欄位對映/自動驗證/自動完成PHP
- 高可用高可靠系統設計中的重試機制
- Ubuntu系統 git命令補全UbuntuGit
- 移動端支付系統如何設計有效地防重失效機制?
- sql 統計多個欄位的和(如果欄位中含有 null 的處理)SQLNull
- 【作業系統】頁表對映作業系統
- 將list型別對映到資料欄位 @TableField(typeHandler = StringListTypeHandler.class)型別
- 補充行業程式碼欄位行業
- win10系統下如何對映共享資料夾Win10
- 創業者需要的品質:靈活!靈活!靈活創業
- Python如何設定自動補全?Python
- win10系統mac的dock欄怎麼設定_win10系統mac的dock欄如何設定Win10Mac
- java併發程式設計系列:wait/notify機制Java程式設計AI
- WebSocket系列之二進位制資料設計與傳輸Web
- 計算機中的二進位制計算機
- Yarp 讓系統內排程更靈活
- 計算機基礎進位制轉換(二進位制、八進位制、十進位制、十六進位制)計算機