跳到主內容

架構案例研究

透過一個實現 MVVM 架構模式的 Flutter 應用進行詳細剖析。

本指南中的程式碼示例來自 Compass 示例應用,該應用旨在幫助使用者構建和預訂旅行行程。這是一個功能完備的示例應用,擁有豐富的功能、路由和螢幕。該應用與 HTTP 伺服器通訊,具備開發和生產環境,包含品牌特定的樣式,並擁有較高的測試覆蓋率。透過這些方式,它模擬了一個真實的、功能豐富的 Flutter 應用。

A screenshot of the splash screen of the compass app.
A screenshot of the home screen of the compass app.
A screenshot of the search form screen of the compass app.
A screenshot of the booking screen of the compass app.

Compass 應用的架構最接近 Flutter 應用架構指南中所述的 MVVM 架構模式。本架構案例研究透過剖析 Compass 應用的“首頁”功能,演示瞭如何實現這些指南。如果你不熟悉 MVVM,建議先閱讀這些指南。

Compass 應用的首頁顯示了使用者賬戶資訊和已儲存的旅行列表。在此螢幕上,你可以登出、開啟詳細的旅行頁面、刪除已儲存的旅行,以及導航到核心應用流程的第一頁,從而允許使用者構建新的行程。

在本案例研究中,你將學習以下內容:

本案例研究按順序閱讀編寫。任何頁面都可能引用前面的頁面。

本案例研究中的程式碼示例包含了理解架構所需的所有細節,但它們不是完整的、可執行的程式碼片段。如果你更喜歡跟隨完整的應用學習,可以在 GitHub 上找到它。

包結構

#

組織良好的程式碼更便於多位工程師協作,減少程式碼衝突,也更容易讓新加入的工程師理解和上手。良好的程式碼組織既得益於定義明確的架構,也能促進架構的完善。

組織程式碼有兩種流行方式:

  1. 按功能劃分 - 將每個功能所需的類歸為一組。例如,你可能有一個 auth 目錄,其中包含 auth_viewmodel.dartlogin_usecase.dartlogout_usecase.dartlogin_screen.dartlogout_button.dart 等檔案。
  2. 按型別劃分 - 將每種“型別”的架構元件歸為一組。例如,你可能擁有 repositoriesmodelsservicesviewmodels 等目錄。

本指南推薦的架構結合了這兩種方式。資料層物件(倉庫和服務)不繫結到單個功能,而 UI 層物件(檢視和檢視模型)則繫結到特定功能。以下是 Compass 應用中程式碼的組織方式。

  • lib/
    • ui/
      • core/
        • ui/
          • <shared_widgets>
        • themes/
      • <feature_name>/
        • view_models/
          • <view_model_class>.dart
        • widgets/
          • <feature_name>_screen.dart
          • <other_widgets>
    • domain/
      • models/
        • <model_name>.dart
    • data/
      • repositories/
        • <repository_class>.dart
      • services/
        • <service_class>.dart
      • model/
        • <api_model_class>.dart
    • config/
    • utils/
    • routing/
    • main_staging.dart
    • main_development.dart
    • main.dart
  • test/// 包含單元測試和元件測試。
    • data/
    • domain/
    • ui/
    • utils/
  • testing/// 包含其他類執行測試所需的模擬物件 (mocks)。
    • fakes/
    • models/

大部分應用程式碼位於 datadomainui 資料夾中。Data 資料夾按型別組織程式碼,因為倉庫和服務可以在不同的功能之間被多個檢視模型共享。Ui 資料夾按功能組織程式碼,因為每個功能恰好有一個檢視和一個檢視模型。

此資料夾結構的其他顯著特點:

  • UI 資料夾還包含一個名為“core”的子目錄。Core 包含由多個檢視共享的元件和主題邏輯,例如帶有品牌樣式的按鈕。
  • Domain 資料夾包含應用資料型別,因為它們被資料層和 UI 層共同使用。
  • 該應用包含三個“main”檔案,分別作為開發、預釋出(staging)和生產環境的應用入口點。
  • lib 同級目錄下有兩個與測試相關的目錄:test/ 包含測試程式碼,其結構與 lib/ 對應。testing/ 是一個子包,包含可用於其他包測試程式碼的模擬物件和其他測試工具。testing/ 資料夾可以描述為你不釋出的那部分應用內容,也就是被測試的內容。

Compass 應用中還有一些與架構無關的附加程式碼。如需檢視完整的包結構,請在 GitHub 上檢視

其他架構選項

#

本案例研究中的示例演示了一個應用如何遵循我們推薦的架構規則,但實際上還有許多其他編寫應用的方式。此應用的 UI 嚴重依賴於檢視模型和 ChangeNotifier,但它完全可以用流(streams)或使用其他庫(如 riverpodflutter_blocsignals)來編寫。此應用各層之間的通訊全權透過方法呼叫處理,包括輪詢新資料。它也可以改用流來將資料從倉庫暴露給檢視模型,同時依然遵循本指南所涵蓋的規則。

即使你完全遵循本指南且不引入額外的庫,你仍然需要做出抉擇:是否需要領域層(domain layer)?如果需要,如何管理資料訪問?答案很大程度上取決於團隊的具體需求,因此沒有唯一的標準答案。無論你如何回答這些問題,本指南中的原則都將幫助你編寫可擴充套件的 Flutter 應用。

如果仔細觀察,其實所有架構本質上都是 MVVM,不是嗎?

反饋

#

隨著網站該部分的完善,我們歡迎你的反饋