在開發過程中,業務需求可能各不相同且經常變化,因此創建一個靈活、可擴展和可維護的架構非常重要。同樣關鍵的是,團隊成員和客戶等每個人都要清楚地了解項目。為了避免大量文件、頻繁開會和不斷改進,我們採用了下面的架構方法。本文章將探討流行架構的優勢,並幫助您選擇最佳解決方案來滿足您的獨特需求。
很多人認為下面列出的架構只是 "文件夾結構",這只是一種說法。事實上,如果深入研究,它們有幾個重要方面:
- 模塊合作:應用程序中不同模塊 / 組件之間的高效通信和互動(使用基於組件的架構、可重複使用的代碼)。
- 改進項目導航:以易於導航和維護的方式構建項目(清晰的文件夾層次結構、命名約定、關注點分離)。
- 業務邏輯與用戶界面組件分離:將業務邏輯(數據獲取、狀態管理)與用戶界面組件分離,以提高可維護性和可重用性(例如,使用 Redux、Context API 等服務或存儲)。
- DRY: Don’t repeat yourself 不要重複
- DAC: Divide and conquer 分而治之
請看下圖 -- 我們的重點是右下角的區域,這裡是這些原則最有效的結合點:
理想結果(示例)
我們希望藉助架構來實現這些方面。現在,讓我們對每一種架構進行詳細分析,並根據具體情況選擇最適合的架構。
經典架構(無架構)- Classic architecture (without architecture)#
經典架構是許多人已經在使用的一種方法。我們通常專注於基本概念,將項目劃分為 “頁面”、“組件”、“助手” 等。然而,問題在於隨著應用程序的增長,結構開始瓦解,找到正確的組件或其業務邏輯變得更加困難。讓我們舉例說明:
組件過度使用(示例)
在這個例子中,我們有 3 個頁面,顯然沒有被過度使用。但是,它們可能包含下面顯示的所有組件。如果我們觀察一下這些組件,就會發現真正的 "混亂"🤯:每個組件都會主動使用其他組件,從而在它們之間產生依賴關係。這使得它們難以擴展和重用。
下面是另一個使用 Redux 狀態管理器的示例:
分散的應用程序邏輯 - Redux 狀態管理器(示例)
在我們的設置中,每個組件都由指定的 "還原器" 管理,該還原器負責處理其特定的邏輯。然而,有些組件邏輯被錯誤地放在了不正確的還原器中。出現這種情況的原因可能是開發人員沒有注意到現有的文件,或者由於當時需要的邏輯數量有限而沒有考慮創建一個新文件。因此,一些組件的邏輯現在分散在整個項目中,使其不夠清晰,也更難維護。
下圖展示了一個缺失的架構:
破壞性解耦示意圖(示例)
這種方法(或者更正確地說,缺乏架構)往往會造成難以跟蹤依賴關係的混亂環境,從而導致混亂,難以為項目提供支持。不過,這種方法在一些特殊情況下可能還是有用的,例如:
- 小型團隊(1-2 名開發人員)
- MVP 項目
- 不是長期支助項目
- 學習項目或模板
模塊化結構 - Modular architecture#
模塊化架構是一種將應用程序劃分為若干層( pages 、 modules 、 components 、 UI 等)的方法,在這些層中,已經有獨立的模塊,它們有自己的邏輯和責任範圍。
模塊化架構 -- 層結構(示例)
在這個例子中,可以看到應用層的排列方向是一致的: pages → modules → components → ui (如果從另一側看,則相反)。這意味著層數越高(例如 pages ),可以使用的下層層數就越少 -- 組件不能使用模塊,但可以使用用戶界面層的所有內容,而模塊可以使用組件,但不能使用頁面。而頁面已經只能使用模塊了。
模塊化架構 -- 模塊和公共應用程序接口(示例)
如前所述,每個模塊都有自己的職責範圍。同樣重要的是,每個模塊都應該有自己的公共 API( index.ts 文件),它封裝了模塊的所有內部邏輯,只提供外部需要的部分。(這與 OOP 原理非常相似:當一個類有很多私有方法時,這些方法不能從外部訪問,但可以在類本身內部使用)說到 pages 文件,其實很簡單:理想情況下,它應該只是模塊和組件的封裝,應用程序的所有業務邏輯都應該放在模塊和組件的層面上。
(⚠️) 重要:一個模塊不應使用另一個模塊,一個組件不應包含複雜的邏輯。如果仍然需要邏輯,則應盡可能簡單和易於維護,否則 -- 它就是一個模塊!
請看下圖:
近似理想圖(示例)
但是我們仍然有 components/ 和 ui/ 這樣的全局目錄,它們可能會被過度使用。在某些情況下,邏輯可能會增長,不再總是很清楚什麼是組件,什麼是模塊。此外,我們還經常發現,隨著應用程序的增長,開發人員開始在其他模塊中使用模塊,這就破壞了該架構的原則,並造成不必要的依賴。儘管如此,我們的架構提供了以下功能:
- 單線程
- 在不同層級重複使用組件的能力
- 近乎完美的層次感
- 封裝
功能分片設計(FSD)架構 - Feature Sliced Design#
概述 - https://feature-sliced.design/
功能切片設計(FSD)架構 -- 與模塊化架構有很多相似之處,但也避免了我們上面討論過的情況。這種方法是按功能區域(特性)而不是按層來構建項目。這種組織方式有助於避免全局目錄增長(如模塊化架構中的 components 、 UI ),並在組件、模塊和層之間提供了明確的職責分工。
FSD - 圖層示例
架構的構建方式是,頂層 pages 整合並組織所有子模塊和組件的工作,而每一層則提供更詳細、更具體的功能和元素。是的,我們在這裡遵循同樣的規則 -- 層級越高(例如 pages ),可以使用的下層層級就越少:
- 頁面 - 頂層包含應用程序中顯示的 pages 。
- 進程 - 在此架構中已被棄用,因此我們可以跳過它。
- 功能 / 小工具 - pages 下面是主要的 features 塊,這些塊構建了頁面的核心功能,使其具有可管理性和獨立性。
- 實體(Entities)-- 功能模塊下面的 entities 是由 "共享" 層中可用的較簡單用戶界面組件編譯而成的。
- 共享 - 底層包含通用的用戶界面組件,可用於應用程序的不同部分。
(⚠️) 重要:與模塊化架構一樣,各層之間不要過度使用。
概述(片 / 段)- https://feature-sliced.design/
FSD 体系結構以模塊化元素為特色,稱為 "片" 和 "段"。"切片" 指的是每一層中的模塊,每個模塊代表一個不同的業務實體。同時,"段" 包含各種結構組件,如 api/
、 components/
、 config/
、 constants/
等,將架構組織成更清晰、更易於管理的部分。
最後,我們達到了目標結果:
理想 - 圖表(示例)
將這種方法集成到項目中既不容易也不快速。它至少需要最低限度的架構知識,而且你必須牢記這可能需要時間。但是,掌握 FSD 的使用方法可以:
- 結構清晰
- 層次分明
- 靈活組件
- 獨立模塊
- 平衡重用性
順便說一句,這種架構提倡在文件命名中使用 "kebab case"👀。
product-description.vue
/shopping-cart.tsx
/get-base-url.ts
/ 等等。
使用 "模塊化架構" 的實例:
使用 "FSD 架構" 的實例:
結論#
在本文中,我們探討了經典架構、模塊化架構和 FSD 架構之間的區別,並討論了它們的用途。