雖然 JavaScript 沒有完整物件導向程式設計的實作例如抽象 (abstract)、介面 (interface),但我們仍可以把在其它程式語言用到的物件導向的習慣帶到 JavaScript 模組化設計,以幫助我們在設計套件時,把各個模組的功能、職則、檔案架構劃分的更清楚。
SOLID 是物件導向程式設計的五大原則,也是設計的精神。
最白話的方式來說明:
一個套件作品在想法剛萌芽後,一定會有很多點子,而且初一十五不一樣,以致於核心的程式碼會不斷地修改。在這一段時期過後,作品開始很多人使用了,開放封閉原則就變得十分重要。
一旦打破這個原則,軟體版本就要以大版號發佈,提醒使用者有核心程式碼的大幅改動,讓使用者決定要用新版本還是改動小的舊版本。
只要遵守「開放封閉原則」,對擴展開放,用子類別進行擴充;對修改封閉,別動到父類別的程式碼。另外在覆寫 (override) 父類別的方法 (method) 時,輸入和輸出的條件都是一致的,就能符合里氏替換原則。
簡單來說,Class B 繼承了 Class A,所有呼叫 Class A 的程式碼,改使用 Class B 也能正常使用,不會有預期外的結果,例如應拋出異常、產生錯誤,或該回傳小於 100 的數字,但給了 120,諸如此類非預期的結果。
雖然 JavaScript 沒有介面及抽象,但概念上,只要有使用到依賴的套件,依然可以使用這個原則,應用在模組化設計中。
舉例:
這個 API 模組中的函式,都依賴 jQuery 套件,有一天,團隊開會後決定完全拋棄 jQuery,改用 Axios 套件。相同的程式功能,換成 Axios 套件的寫法如下。
如果只有幾段函式內容要改,那還好,萬一有幾十個檔案要改,改它的風險可就太大了喔。
在使用依賴套件時,在各個需要實作它的地方不直接使用它,而是使用一個中介函式。
以這個例子來說,改用 apiGet
這個自行創建的函式,而依賴套件的實作寫在它裡面。
base-api.js 檔案內容:
就算有 100 個 API 函式都用 jQuery 取資料,改成依賴中介函式之後,要改換 Axios 套件,也只要更換中介函式的內容即可,例如第 2 行至 11 行,可刪除,改寫成 Axios 套件的實作方法。
JavaScript 模組化的優點,把常常使用到、重覆的程式碼整理為可以引入的模組,不但可以讓程式碼看起來更清爽,有意義的模組命名,也可以增加我們在日後維護的效率。更顯著的例子,當有新的專案開啟,以前寫過的模組,能夠使用的就直接使用。
在這次鐵人賽的示範作品中,筆者詳細地將初期介紹 CSS 和 Slider 基本範例中的程式碼,把混雜的邏輯,依功能切分。
圖 a: 檔案目錄架構
雖然檔案多很多,但相對地每一個檔案的行數都很少,便於維護。
在切分的時候,至少朝向單一職責原則,以及開放封閉原則這兩個原則去努力,我想就是很不錯的模組化設計了。
文中範例可在 GitHub Page 閱讀。
原始碼可在 2022 鐵人賽專用 GitHub Repo 下載。
本次鐵人賽的 Sliderm 套件初版在,demo/sliderm-alpha,不會進行修改,後續的功能開發可以瀏覽 Sliderm.js 官方網站。