可配置化代碼快速響應客戶需求
1. 項目背景
快速響應客戶需7求是企業(yè)成功的關鍵之一。在現(xiàn)代競爭激烈的市場中,客戶需求不斷變化,企業(yè)需要快速響應這些需求以保持競爭優(yōu)勢。常見的快速響應并滿足客戶通常有如下方案:
采用敏捷開發(fā)方法:敏捷開發(fā)方法強調(diào)迭代、快速響應和持續(xù)改進,可以幫助開發(fā)團隊更快速地開發(fā)和交付軟件。
自動化測試和部署:自動化測試和部署可以幫助開發(fā)團隊更快速地檢測和解決問題,并將軟件快速部署到生產(chǎn)環(huán)境中。
使用現(xiàn)代化的開發(fā)工具和技術:使用現(xiàn)代化的開發(fā)工具和技術,如云計算、容器化、微服務等,可以幫助開發(fā)團隊更快速地開發(fā)和部署軟件。
靈活的軟件架構:采用靈活的軟件架構,可以幫助開發(fā)團隊更快速地進行功能擴展和改進。
以上方法是工程、基礎建設和架構設計等方面的最佳實踐,但是即便如此,開發(fā)的工作量也是以人/日計算,而且需要重新部署上線。有沒有一種不需要部署,只需要配置即可實現(xiàn)的設計和方法呢。
2. 預期目標
快速響應滿足客戶需求,快速開發(fā)上線,設計一個系統(tǒng),使頻繁變更的需求,更改上線按小時級計算。一般一個需求,需要設計開發(fā)、測試、發(fā)布上線等流程,整個過程至少需要1-2天,而且頻繁上線,且發(fā)布上線一般要選擇在晚上,等用戶使用低峰期,因此我們希望能達到以下目標:預期實現(xiàn)從需求提出,到發(fā)布上線,按小時計算,可快速完成需求開發(fā)、上線、交付。
3. 技術選型
為了實現(xiàn)預期目標,筆者做了深入的技術調(diào)研,動態(tài)語言可以實現(xiàn)這一目標。動態(tài)語言可以實現(xiàn)熱加載,從而免去了部署的麻煩。熱加載是指在應用程序運行過程中,可以動態(tài)地加載新的代碼或修改已有代碼,而無需停止或重新啟動應用程序。
熱加載還可以帶來如下好處:
- 快速迭代:開發(fā)人員可以在運行時修改代碼,無需停止應用程序,從而快速迭代和測試新功能。
- 減少停機時間:熱加載可以減少停機時間,從而提高應用程序的可用性。
- 簡化部署:熱加載可以免去部署的麻煩,從而簡化部署和維護工作。
總的來說,熱加載可以提高開發(fā)效率、減少停機時間和簡化部署工作。
熱加載主要有如下實現(xiàn)方式:
1)使用JEXL動態(tài)執(zhí)行表達式:
? 優(yōu)點:可以動態(tài)執(zhí)行Java代碼,調(diào)用Java Function(Function需先傳入JexlContext)
◆缺點:只能執(zhí)行一個“表達式”,而不是Function,所以有很多語法局限,不是真正執(zhí)行一個Function
2) 使用Java動態(tài)編譯:
? 優(yōu)點:功能強大,能夠真正實現(xiàn)完整的動態(tài)執(zhí)行功能,能夠動態(tài)調(diào)用全部系統(tǒng)功能和IO操作。
◆ 缺點:雖然功能強大,可以編譯.java文件,但是還是很難在運行時替換框架級的類文件。此外,因為能動態(tài)調(diào)用全部系統(tǒng)功能和IO操作,但與一般代碼環(huán)境沒有隔離,這可能會成為項目中非常嚴重的安全隱患。
3)使用Java ScriptEngine:
? 優(yōu)點:可以執(zhí)行完整的JS方法,并且獲取返回值;在虛擬的Context中執(zhí)行,無法調(diào)用系統(tǒng)操作和IO操作,非常安全;可以有多種優(yōu)化方式,可以預編譯,編譯后可以復用,效率接近原生Java;所有實現(xiàn)ScriptEngine接口的語言都可以使用,并不僅限于JS,如Groovy,Ruby等語言都可以動態(tài)執(zhí)行。
◆ 缺點:無法調(diào)用系統(tǒng)和IO操作 ,也不能使用相關js庫,只能使用js的標準語法。
?在如何快速響應客戶需求,快速變化的技術選型時,我們先后對以上幾種技術進行了需求和技術調(diào)研分析得出如下:
1)JEXL動態(tài)執(zhí)行表達式,功能簡單,支持有限,不滿足日常需求。
2)動態(tài)編碼需要熱部署與熱加載,這個在之前的單機時代還可以,現(xiàn)在是微服務,云服務的時代,大量機器熱部署和熱加載成本高昂且代價巨大。
3)ScriptEngine,可以動態(tài)的執(zhí)行腳本語言,同時無法調(diào)用系統(tǒng)操作和IO操作,非常安全,這個給我們帶來了巨大的便利,我們選擇了 JavaScript 作為可以動態(tài)執(zhí)行的腳本語言,主要還有以下原因:
JavaScript 足夠簡單和強大,可以滿足我們的需求。
JavaScript 作為互聯(lián)網(wǎng)時代的主流語言,為廣大技術人員必備技能,易于使用。
開發(fā)使用環(huán)境簡單,一個文本編輯器就可以寫代碼,一個瀏覽器就可以調(diào)試,非常方便。
以下是一個簡單的 Java ScriptEngine 示例:
在這個示例中,我們使用 ScriptEngineManager 創(chuàng)建了一個 JavaScript 的 ScriptEngine,并執(zhí)行了一段簡單的 JavaScript 代碼,輸出了變量 z 的值。
除了執(zhí)行 JavaScript 代碼,ScriptEngine 還可以將 Java 對象傳遞給 JavaScript 代碼,從而實現(xiàn) Java 和 JavaScript 之間的數(shù)據(jù)交互。以下是一個示例:
例中,我們將 Java 對象 name 和 age 傳遞給了 JavaScript 代碼,并在 JavaScript 中輸出了一個字符串。
從以上示例可以看出,ScriptEngine功能強大,不僅支持簡單的計算,而且可以支持復雜的業(yè)務計算,完全可以滿足我們?nèi)粘5男枨箝_發(fā)。
4. 設計優(yōu)勢
選定ScriptEngine后下一步是如何實現(xiàn)快速響應,實現(xiàn)日常需求。是否能實現(xiàn)片段代碼的可配置化,配置完后可以直接運行,免發(fā)布上線。是否有必要實現(xiàn)代碼的可配置化,可配置化主要有如下優(yōu)勢:
可配置化代碼可以靈活、快速地響應客戶的需求。通過將軟件系統(tǒng)的各個模塊進行拆分,將其變成可配置的組件,然后根據(jù)客戶的需求,選擇合適的組件進行組合,就可以快速地定制出符合客戶需求的軟件系統(tǒng)。
可配置化代碼的優(yōu)點在于它可以大大提高軟件開發(fā)的靈活性和效率。比如,當客戶提出新的需求時,只需要在已有的組件庫中選擇相應的組件進行組合,就可以快速地完成新功能的開發(fā)。這種方式大大縮短了軟件開發(fā)的周期,同時也降低了開發(fā)成本。
可配置化代碼還可以提高軟件系統(tǒng)的可維護性和可擴展性。由于各個模塊都是獨立的可配置組件,因此可以很容易地進行單獨的維護和升級。同時,由于組件是可配置的,因此可以很容易地進行擴展和替換,以適應不同的需求。
總之,可配置化代碼是一種非常靈活,高效的技術手段,可以幫助我們快速響應客戶需求,提高軟件開發(fā)效率和質(zhì)量。
下面,筆者從汽車之家的幾個項目,實踐了代碼可配置化:
對接二手車經(jīng)銷商車源數(shù)據(jù),二手車經(jīng)銷商車源數(shù)據(jù)格式各不相同,要求快速接入,快速上線展示。
導出車源信息到第三方網(wǎng)站展示,做推廣。第三方網(wǎng)站要求的格式也各異,而且導出格式也經(jīng)常變化,如何快速響應變化,滿足客戶需求上線。
5. 系統(tǒng)設計
系統(tǒng)設計要考慮基于變和不變,變化頻度比較大的計算模塊通過JS腳本運行,不變的部分,即整體部分通過Java設計編寫,JS腳本可通過數(shù)據(jù)庫存儲,以方便進行更新。 每次將待運算的數(shù)據(jù)通過接口傳給程序,程序通過調(diào)用JS代碼計算,得出計算結(jié)果,存入數(shù)據(jù)庫,具體設計如下。
圖1 利用ScriptEngine 動態(tài)計算過程
6. 系統(tǒng)設計以及腳本的編寫
6.1腳本設計準則以及適用場景
當需要針對一個場景需求頻繁變化,規(guī)則隨時調(diào)整,上線要求時間短,有明顯的根據(jù)輸入?yún)?shù),返回結(jié)果時,比較適合動態(tài)腳本的引入。
以筆者第一個項目庫存導入為例,其場景如下:
A. 經(jīng)銷商會定期上傳庫存文件,各個經(jīng)銷商的庫存文件格式各不相同。
B. 經(jīng)銷商會不定時調(diào)整自己庫存的格式,比如增加一個字段、減少一個字段、字段格式變化等。
C. 整體汽車參數(shù)基本不變,能覆蓋所有經(jīng)銷商提供庫存文件的格式。
7. 具體場景實施
此場景比較適合動態(tài)腳本解析庫存,以下是項目引用JS代碼片段截圖:
JS腳本保存數(shù)據(jù)庫,可以隨時動態(tài)靈活的新增,更新,避免上線。數(shù)據(jù)庫配置如下:
庫存導出的JS代碼片段:
庫存導出配置示例:
初始化ScriptEngine 引擎代碼如下:
調(diào)用JS代碼解析庫存示例代碼如下:
根據(jù)以上代碼截圖,以及流程圖,可以總結(jié)得出,整體流程如下:
1)建立經(jīng)銷商賬號。
2)根據(jù)經(jīng)銷商庫存文件編寫 JS 解析腳本,保存入數(shù)據(jù)庫。
3)根據(jù)經(jīng)銷商的賬號,找經(jīng)銷商配置的導入Rule (javascript 代碼)。
4)把經(jīng)銷商傳入的庫存文件數(shù)據(jù)傳入 ScriptEngine 執(zhí)行 JS 解析腳本,獲得標準庫存數(shù)據(jù)。
8. 實現(xiàn)效果和收益
1)庫存導入JS動態(tài)腳本上線后,庫存導入需求效率提高400%,由原來的 2人/日, 提高至 0.5人/日。
2)庫存導出JS動態(tài)腳本上線后,庫存導入需求效率提高600%,由原來的 3人/日, 提高至 0.5人/日。
3)在線評分系統(tǒng)JS動態(tài)腳本上線后,庫存導入需求效率提高600%,由原來的 3人/日, 提高至 0.5人/日。
4. 極大的提高了經(jīng)銷商庫存接入,導出效率,和庫存導出效率,給客戶帶來了非常好的體驗。
9. 總結(jié)
以上是我們實踐中根據(jù)業(yè)務的實際需求,經(jīng)過深入的調(diào)研和分析后做出的技術方案和實踐,并取得了很不錯的效果。這樣的場景以后還有很多,本文給快速響應客戶需求,高效完成實際工作提供一種思路和方法。相信隨著技術的發(fā)展也許會有更好的方案和技術,我們不斷探索,不斷追求進步,歡迎有興趣的同學一起探討和學習。
作者簡介
陳培鋒
■ 經(jīng)銷商事業(yè)部-經(jīng)銷商技術部-新產(chǎn)品技術團隊。
■ 2019年加入汽車之家,負責智慧診斷產(chǎn)品研發(fā),熱衷于以客戶價值為本,解決客戶痛點,做給客戶帶來價值產(chǎn)品。