這是 Jerry 2021 年的第 72 篇文章,也是汪子熙公眾號總共第 349 篇原創文章。
基於 ABAP 技術棧的 SAP 產品,客戶可以通過安裝 Enhancement Package(增強包)的方式,為當前使用的應用導入新的功能。
Enhancement Package(增強包),顧名思義,包含了應用程序增強功能的集合。客戶可以根據企業實際的業務流程,有選擇性的啟用增強包里的部分新功能。每個新增的功能,都對應着一個 Business Function.只有在系統中激活 Business Function 后,其對應的新功能,包含前台頁面,后台業務程序,以及 SPRO 實施活動才會生效。

借助增強包,客戶能夠在不升級 Netweaver 版本的情況下,使用到 SAP 產品的新功能。Business Function 則對增強包中的新功能,提供了更細粒度的管理靈活性,客戶能夠根據自己的實際需要,有選擇性地啟用部分新功能。
ABAP Business Function 對增強包新功能的控制,最終通過其包含的 Business Switch 即業務開關實現。該開關和我們實際生活中的開關概念一致,具有 On 和 Off 兩種狀態。業務開關能夠控制 ABAP 前后台代碼實現的行為,以及后台配置表中的記錄。

下面通過實際的例子來說明。
SAP CRM 通過中間件可以從 SAP ERP 下載物料主數據。SAP ERP 作為這個數據交換場景的源系統,可以繼續對物料主數據某些字段做修改,這些修改會自動同步到 CRM,這稱為 Delta Download.
但是,某些字段的修改,在 SAP CRM 的默認實現里是無法接收到的。比如 SAP ERP 起初維護了英文和中文版本的物料描述文本,這兩個版本的描述信息成功同步到 SAP CRM 之后,客戶再在 ERP 刪除中文版本的描述文本,則這個刪除動作,無法同步到 SAP CRM.
因此 Jerry 之前工作過的 SAP CRM 開發團隊,在 SAP CRM EHP3 里開發了一個新功能,用於支持上述描述的場景。
下圖展示了事物碼 SFW5 里包裹該新功能的 Business Function,ID 為 CRM_PROD_REQ_LOAD_SUBTRACTION.
當前處於未激活狀態。

雙擊則能進入該 Business Function 明細頁面,找到關聯的業務開關 CRM_PROD_SETTYPE_RL_SUBTRACT.

在 ABAP 代碼里,我們使用工具類,判斷該開關的狀態。如果狀態為關閉,直接返回,不執行包含新功能的后續代碼。

總之,SAP ABAP Enhancement Package 里新增添的應用業務邏輯,總是包裹在一段以檢查業務開關狀態作為條件評估的 IF 代碼塊里,偽代碼如下:
IF 對應的業務開關處於開啟狀態.
執行增強包的新功能.
ENDIF.
除了代碼邏輯外,前台 UI 頁面某些元素的顯示與否,也能通過業務開關動態控制。比如下圖這個 SAP CRM 產品搜索頁面的 Simple Search 按鈕,就被一個 ID 為 CRM_MD_PRD_SEARCH 的業務開關控制。僅當該開關開啟時,才會執行到下圖第 6 行開始的代碼,將按鈕繪制到頁面上。

簡而言之,當 SAP Enhancement Package 安裝到系統之后,增強包內的代碼,數據庫表和其他 ABAP 資源均已存儲到系統內。除非顯式開啟新功能對應的業務開關,否則新功能不會生效。
SAP 電商雲
在 SAP 電商雲 Spartacus UI 中也可以采取所謂的 Feature Level 概念,給用戶提供有選擇性地啟用部分新功能的靈活度。
SAP 電商雲 Spartacus UI 本身是一個高度模塊化的 Storefront 開發框架和開發庫,電商網站運行涉及到的功能塊,按照業務層面划分並實現在不同的功能模塊(Feature Modules)里,這些功能模塊的列表下圖所示:

客戶實施 Spartacus 時,可以根據自己的實際業務,有選擇性地安裝功能模塊。
下圖是一個例子,我安裝 Spartacus 時,選擇了 Store Finder 和 Tracking 相關的幾個功能模塊,而未選擇 Product Configurator, Qualtrics 和 SmartEdit 這三個功能模塊:

最后客戶決定啟用的所有功能模塊,通過藍色高亮信息顯示在安裝控制台:

基於選擇的這些功能模塊,構建出的 JavaScript Bundles 文件如下圖所示:

未啟用的功能模塊,不會參加構建,當然更不會出現在最終 Spartacus Storefront 的運行時環境里。這個機制有助於減小構建出的 JavaScript Storefront Bundles 文件尺寸,提高運行時加載資源的速度。
至此不難看出,SAP 電商雲 Spartacus UI 功能模塊這一選擇性安裝的機制,同本文前半部分介紹的 SAP ABAP 增強包全部安裝,部分啟用的機制有所區別。
當然,SAP 電商雲 Spartacus UI 也存在類似 SAP ABAP 增強包的表現行為,即客戶已經將新功能的實現代碼安裝到了本地,只是通過某種開關的控制,暫時不啟用。Feature Level 就扮演了這個開關的角色。
由於歷史原因,像修改電商頁面全局 Directionality 這種特性,並沒有封裝到某個功能模塊里,而是通過 Feature Level 控制。
世界上某些國家和地區,比如使用阿拉伯語和希伯來語的客戶,習慣以從右到左的方式瀏覽網頁。為了滿足 SAP 產品標准之一即 Internationalization(國際化,簡稱 i18n), SAP 電商雲 Spartacus UI 也對這部分客戶的瀏覽習慣提供了支持。
下圖是默認的使用從左到右的方式渲染的 SAP 電商雲主頁,SAP Logo 在屏幕上方最左邊,購物車圖標在屏幕上方最右邊:

在產品明細頁面里,產品圖片在左邊,添加到購物車的按鈕在右邊:

下面是一個測試,我們使用下列配置,告訴 SAP 電商雲 Spartacus UI,當客戶使用的語言為 zh 即中文時,讓電商頁面按照從右到左(Right to Left, RTL) 的方式渲染:

在 RTL 顯示模式下,SAP Logo 和購物車的位置調換了順序,整個屏幕成了 LTR 模式下顯示頁面的一個鏡像。


按照 Spartacus 官網文檔,從 2.1 版本開始提供對 Directionality 的支持。

在 Spartacus 初始化鈎子函數 APP_INITIALIZER 里,存在一段包裹在 IF 語句中的代碼,邏輯和之前介紹 ABAP 業務開關時提到的偽代碼很像。
這段代碼的語義是,如果當前 Spartacus Feature Level 大於等於 2.1,則執行 Directionality 相關的邏輯處理。

因此,如果出於某種原因,需要在 2.1 之后的版本中,暫時停用 Directionality, 除了修改對應的語言配置外,最快捷的做法就是,將當前 Spartacus 應用的 Feature Level,降至 2.1 之前的版本,比如 2.0:

如此一來,雖然我在第 116 行的設置里,讓 Spartacus 在客戶使用中文登錄時,以 RTL 模式顯示,但是第 110 行的 Feature Level 設置具有更高的優先級。
這個例子里,因為當前 Feature Level 並沒有達到啟用 Directionality 所需的最低要求,所以最后我使用中文登錄時,Spartacus 仍然采用默認的 LTR 模式顯示:

SAP 電商雲 Spartacus UI 的 Feature Level 除了能控制應用程序的執行邏輯外,也能像前文介紹的 ABAP 業務開關一樣,動態控制 UI 元素的顯示與否,而且使用方式更加簡潔易懂。
看個具體的例子。下圖是 SAP 電商雲 Spartacus UI 購物車界面,點擊紅色的 Proceed To Checkout 按鈕可以跳轉到結帳頁面。

點擊 Proceed To Checkout 按鈕之后,我們會向 SAP Commerce Cloud 后台發起一個 Cart Validation 的 API 調用,對當前購物車的內容進行校驗。我們最初的實現,並未將該按鈕禁用,因此如果用戶短時間內迅速點擊該按鈕,每點擊一次都會觸發一次 API 調用:

於是,在版本 4.2 里,我們用自開發的按鈕控件,Progress Button, 替換了之前版本里使用的普通 Button.
兩種按鈕在沒有被用戶點擊之前,外觀沒有任何區別,然而點擊之后,Progress Button 會出現一個旋轉的動畫效果,讓客戶無法重復點擊。
這種 Progress Button 被點擊之后,外觀如下:

兩種按鈕在最終渲染出的 HTML 頁面里源代碼差異比較如下:

在購物車頁面里,我們使用自定義指令 cxFeatureLevel,實現了兩種按鈕的條件顯示邏輯:如果 Feature Level 小於 4.2,顯示普通 Button;否則顯示 Progress Button:

自定義指令 cxFeatureLevel 的實現原理為,當指令傳入的 Feature Level 同當前應用配置的 Feature Level 相匹配時,調用 Angular ViewContainerRef 動態創建視圖的方法 createEmbeddedView,將施加了該指令的 DOM 元素繪制出來。

總結
ABAP 業務開關和 SAP 電商雲 Spartacus UI 的 Feature Level,二者實現原理各不相同,但都能夠給客戶提供一定的自由度,讓其靈活控制某些業務功能的啟用和關閉。
Jerry 的 SAP 電商雲 Spartacus UI 開發合集
更多Jerry的原創文章,盡在:"汪子熙":

