本頁介紹架構最佳實踐、其重要性,以及我們是否建議你在 Flutter 應用程式中採用這些做法。 你應將這些建議視為參考,而非絕對規則,並根據你應用程式的獨特需求進行調整。

本頁的最佳實踐會標註優先級,這反映了 Flutter 團隊對該建議的推薦程度。

  • 強烈建議: 如果你正在開始建立新應用程式,應始終實作此建議。除非與你現有的架構方式根本衝突,否則也應強烈考慮將現有應用程式重構以實現此做法。
  • 建議: 採用此做法很可能會提升你的應用程式品質。
  • 視情況而定: 在特定情境下,此做法可以改善你的應用程式。

關注點分離

您應該將應用程式分為 UI 層和資料層。在這些層中,應進一步根據職責將邏輯分離到不同的類別。




建議說明

使用明確定義的資料和 UI 層。

強烈建議

關注點分離是最重要的架構原則。 資料層向應用程式的其餘部分公開應用程式資料,並包含應用程式中大多數業務邏輯。 UI 層顯示應用程式資料並監聽來自用戶的用戶事件。 UI 層為 UI 邏輯和小部件包含單獨的類。


在資料層中使用儲存庫模式。

強烈建議

儲存庫模式是一種軟體設計模式,它將資料訪問邏輯與應用程式的其餘部分隔離。 它在應用程式的業務邏輯和底層資料存儲機制(資料庫、API、檔案系統等)之間創建了一個抽象層。 實際上,這意味著要創建儲存庫類和服務類。


在 UI 層中使用 ViewModels 和 Views。(MVVM)

強烈建議

關注點分離是最重要的架構原則。 這種特定的分離使您的代碼不易出錯,因為您的小部件保持「愚蠢」。


使用 ChangeNotifiersListenables 來處理小部件更新。

視情況而定

ChangeNotifier API 是 Flutter SDK 的一部分,是一種方便的方式來讓您的小部件觀察 ViewModels 中的變化。


處理狀態管理有很多選擇,最終決定取決於個人喜好。 了解 [我們的 ChangeNotifier 建議][] 或 [其他流行選擇][]。

不要在小部件中放置邏輯。

強烈建議

邏輯應該封裝在 ViewModel 上的方法中。 視圖中應包含的唯一邏輯是:

  • 根據 ViewModel 中的標誌或可為空字段顯示和隱藏小部件的簡單 if 語句

  • 依賴於小部件計算的動畫邏輯

  • 基於設備資訊(如螢幕大小或方向)的佈局邏輯。

  • 簡單的路由邏輯


使用領域層。

視情況而定

當您的應用程式具有過於複雜的邏輯以至於擠滿了 ViewModels, 或者當您發現自己在 ViewModels 中重複邏輯時,領域層才是必需的。 在非常大的應用程式中,用例是有用的,但在大多數應用程式中,它們會增加不必要的開銷。


在具有複雜邏輯需求的應用程式中使用。


資料處理

謹慎處理資料能讓您的程式碼更易理解、更不易出錯,並防止產生格式錯誤或非預期的資料。





建議說明

使用單向資料流。

強烈建議

資料更新應僅從資料層流向 UI 層。 UI 層的互動會發送到資料層,然後在那裡處理。


使用 Commands 來處理來自用戶互動的事件。

建議

命令可以防止您的應用程式中出現渲染錯誤,並標準化 UI 層如何將事件發送到資料層。 了解有關命令的更多資訊,請參閱 [架構案例研究][]。


使用不可變資料模型。

強烈建議

不可變資料對於確保任何必要的更改僅在適當的位置(通常是資料或領域層)發生至關重要。 由於不可變物件在創建後無法修改,因此必須創建一個新實例以反映更改。 此過程可防止在 UI 層意外更新,並支持清晰的單向資料流。


使用 freezed 或 built_value 來生成不可變資料模型。

建議

您可以使用套件來幫助生成資料模型中的有用功能,例如 freezedbuilt_value. 這些可以生成常見模型方法,例如 JSON ser/des、深度相等檢查和複製方法。 如果您有很多模型,這些代碼生成套件可能會顯著增加應用程式的構建時間。


創建單獨的 API 模型和領域模型。

視情況而定

使用單獨的模型會增加冗長性,但可以防止 ViewModels 和用例中的複雜性。


在大型應用程式中使用。


應用程式結構

良好的程式碼組織不僅有益於應用程式本身的健康,也有益於負責程式碼的團隊。




建議說明

使用依賴注入。

強烈建議

依賴注入可以防止您的應用程式具有全局可訪問的物件,這使得您的程式碼不易出錯。 我們建議您使用 provider 套件來處理依賴注入。


對於導航,使用 go_router

建議

Go_router 是編寫 90% Flutter 應用程式的首選方式。 有一些特定的用例是 go_router 無法解決的, 在這種情況下,您可以直接使用 Flutter Navigator API 或嘗試其他在 pub.dev 上找到的套件。


對類別、檔案和目錄使用標準化命名約定。

建議

我們建議根據它們所代表的架構元件為類別命名。 例如,您可能會有以下類別:

  • HomeViewModel
  • HomeScreen
  • UserRepository
  • ClientApiService

為了清晰起見,我們不建議使用可能與 Flutter SDK 中的物件混淆的名稱。 例如,您應該將共用小部件放在名為 ui/core/ 的目錄中, 而不是放在名為 /widgets 的目錄中。


使用抽象儲存庫類別

強烈建議

儲存庫類別是您應用程式中所有資料的真實來源, 並促進與外部 API 的通信。 創建抽象儲存庫類別允許您創建不同的實現, 可用於不同的應用程式環境,例如「開發」和「測試」。



測試

良好的測試習慣讓您的應用程式更具彈性,也讓新增邏輯和 UI 變得簡單且低風險。

建議說明

分開測試架構元件,並將它們一起測試。

強烈建議

* 為每個服務、儲存庫和 ViewModel 類別編寫單元測試。這些測試應該單獨測試每個方法的邏輯。

  • 為視圖編寫小部件測試。測試路由和依賴注入特別重要。


為測試創建假物件(並編寫利用假物件的程式碼)。

強烈建議

假物件不太關心任何給定方法的內部運作, 更關心輸入和輸出。如果您在編寫應用程式碼時考慮到這一點, 那麼您就被迫編寫具有明確輸入和輸出的模組化、輕量級函數和類別。



推薦資源

#
  • 程式碼與範本
    • Compass app source code - 一個功能完整且健壯的 Flutter 應用程式原始碼,實作了許多本頁建議。
    • very_good_cli - 由 Flutter 專家 Very Good Ventures 製作的 Flutter 應用程式範本。 此範本會產生類似的應用程式結構。
  • 文件
  • 工具
    • Flutter developer tools - DevTools 是一套針對 Dart 與 Flutter 的效能與除錯工具。
    • flutter_lints - 由 Flutter 團隊推薦的 Flutter 應用程式檢查規則套件。 使用此套件可促進團隊間良好的程式撰寫習慣。

意見回饋

#

由於本網站此區塊仍在持續演進中, 我們歡迎你的意見回饋