本文探討如何提升 Genero 系統的可組合性,以及如何將龐大的單體式應用程式拆分為更小、更易管理的組成部分。所謂「可組合性」,指的是你的系統與其他系統之間的整合能力

背景

過去,Genero 系統通常以獨立的單體架構運作。然而現代需求要求這些系統能與其他應用程式介接、部署在雲端分散式環境,或允許以第三方解決方案替換其中部分功能。

核心定義

  • 應用程式/程式(Application/Program):單一個含有 MAIN 的 Genero 程式。
  • 系統(System):實作某項業務功能的所有 Genero 程式打包在一起。
  • 模組(Module):系統中包含多個程式的子集合。

程式碼規範

文章強調,程式碼規範是建構可組合系統的核心基礎,其意義遠超過單純的撰寫慣例——它能確保系統長期持續成功運作與可靠性。

以明暗主題切換為例:要支援此功能,規範必須禁止硬編碼顏色值。正確做法是使用呈現樣式(Presentation Styles):

ERROR error_text ATTRIBUTES(STYLE="error")

而非:

ATTRIBUTES(RED)

規範的目的在於確保「解決方案的各個部分」能在定義好的介面上可靠地運作。

程式碼審查

自動化與人工審查都是維持規範遵循度的必要手段。自動化審查能即時發現違規;人工審查則能捕捉難以自動化偵測的問題。

Genero Studio 提供 Code Quality 工具以協助規範執行。審查時應特別留意模組介面的部分。

現代化程式碼方式

系統必須採用現代技術——例如 RESTful Web Services 與 JSON——才能與現代應用程式保持互通性。文章指出:「如果世界上其他系統都使用 RESTful Web Services、JSON……你也應該做好使用它們的準備。」

IMPORT FGL 與 PACKAGE

相較於傳統的 fgllink 方式,結構化的 import 機制帶來以下好處:

  • 在檔案開頭清楚可見相依關係
  • 編譯器可驗證函式參數
  • 改善編輯器的自動補全功能
  • 更易於管理建置規則

建議:「你應該評估從建置流程中移除 fgllink 使用所需的工作量。」

避免循環相依

循環相依會導致結構不清晰,應予以避免。循環關係意味著所有相依檔案必須一起使用,降低了模組化程度。例外處理程式碼應自給自足,不應引用函式庫。

全域變數

指引方向仍是消除 GLOBALS,改用 IMPORT FGL 與 PUBLIC 變數,依照移轉指南逐步完成。

相依關係圖

Genero Studio 的 Dependency Diagram(相依關係圖)可視化呈現原始碼檔案之間的關係。初期圖表可能相當複雜,但在模組結構正確建立後,透過篩選與摺疊應能逐漸簡化。

當程式碼組織良好時,相依箭頭應向上流動,基底在上方,端點在下方。

命名慣例

使用 2 至 3 個字母的短碼在檔名中標識模組或用途,方便快速識別有效的引用來源。例如,一個 ERP 系統可能使用:lib(函式庫)、sys(系統)、gl(總帳)、dl(應收帳款)、st(庫存)、so(銷售訂單)、hr(人力資源)。

按業務功能拆分

模組將相關程式集中管理。程式碼規範強制執行邊界——「gl」的資料庫資料表只能由「gl」的原始碼存取,「gl」的表單只能從「gl」的檔案開啟。

對於模組間的溝通,文章建議採用 Web Services 而非直接引用:

錯誤做法(直接存取資料表):

SELECT dl_current_balance FROM dl_balance

正確做法(透過 Web Service 介面):

so_dl_interface.get_current_balance()

這樣就能替換特定模組的實作,而不需要修改呼叫端的程式碼。

按程式碼功能拆分

進一步的分離包括:

  • ui:使用者介面(User Interface)
  • br:業務規則(Business Rules)
  • ct:控制器(Controller)
  • ws:Web Service
  • db:資料庫(Database)
  • rp:報表(Report)

關鍵規則:「OPEN WINDOWINPUTERRORDISPLAY 等使用者介面語法,只能出現在檔名包含 _ui_ 的 4gl 檔案中。」

此分離能確保安全地對外公開 Web Service。業務邏輯不得包含 UI 程式碼。

有問題的程式碼範例:

#! ?_br_?.4gl
FUNCTION validate_number(number) RETURNS (ok)
   IF number < 0 THEN
      ERROR "Number must not be negative"  -- 錯誤:br 檔案中含有 ui 程式碼

正確做法:

#! ?_br_?.4gl
FUNCTION validate_number(number) RETURNS (ok, error_text)
   IF number < 0 THEN
      RETURN FALSE, "Number must not be negative"  -- 正確

如此一來,業務邏輯便可在 GUI 與 Web Service 情境下重複使用。

資料庫與報表的獨立性

將資料庫與報表程式碼分離到獨立檔案,能更輕鬆地因應資料庫切換(包含 NoSQL)或報表工具更換。

Web Services

文章鼓勵優先探索高階的 RESTful Web Services 框架,而非 SOAP 或低階做法。

建議的三個練習,展示循序漸進的過程:

  1. 將一個簡單函式公開為 Web Service,並用 curl 或 Postman 呼叫它。
  2. 在 Genero 中呼叫第三方 Web Service。
  3. 建立兩個程式,一個公開功能,另一個加以呼叫。

錯誤處理注意事項:呼叫 Web Service 需要比直接函式呼叫更完整的錯誤處理,程式碼必須考慮服務無法使用或發生失敗的情況。

效能影響:由於網路額外負擔以及參數的封裝與解封,Web Service 呼叫比直接呼叫慢。在迴圈中的效能損耗會被放大。

最佳化方式:將重複呼叫合併為單次 Web Service 請求。例如,與其逐一查詢每位客戶的餘額,不如傳入客戶代碼陣列、一次回傳餘額陣列,減少網路來回次數。

使用者介面的可組合性

當應用程式來自多家廠商時,一致的使用者體驗至關重要。Genero Browser Customization 能透過顏色、圖示及 Date Picker 等元件的自訂,讓介面風格與第三方應用程式保持一致。

總結

作者指出,部分開發者從 1990 年代起就已落實這些規範。許多組織已部分具備這些元素,但缺乏明確定義的介面。

建議:使用 Dependency Diagram 審視你的程式碼庫。組織良好的程式碼「一旦正確,看起來就是對的。」

原文:https://4js.com/ask-reuben/ig-206/  ·  有任何 Genero 技術問題或翻譯疑問,歡迎來信 support@t100.app