跳至主要內容

常見的架構概念

在本節中,您會找到經過考驗且真實的原則,這些原則指導了應用程式開發領域中較大的架構決策,以及它們如何具體地融入 Flutter 的資訊。這是一個對建議架構和最佳實踐相關的詞彙和概念的溫和介紹,以便可以在本指南中更詳細地探索它們。

關注點分離

#

關注點分離是應用程式開發中的核心原則,它透過將應用程式的功能劃分為不同的、獨立的單元來促進模組化和可維護性。從高層次來看,這意味著將您的 UI 邏輯與業務邏輯分開。這通常被描述為分層架構。在每個層中,您應該進一步按特性或功能分隔您的應用程式。例如,您應用程式的驗證邏輯應該與搜尋邏輯位於不同的類別中。

在 Flutter 中,這也適用於 UI 層中的 Widget。您應該編寫可重複使用、精簡的 Widget,它們包含盡可能少的邏輯。

分層式架構

#

Flutter 應用程式應該以的方式編寫。分層式架構是一種軟體設計模式,它將應用程式組織成不同的層,每個層都有特定的角色和職責。通常,根據複雜性,應用程式分為 2 到 3 層。

The three common layers of app architecture, the UI layer, logic layer, and data layer.
  • UI 層 - 向使用者顯示由業務邏輯層公開的資料,並處理使用者互動。這通常也稱為「展示層」。
  • 邏輯層 - 實現核心業務邏輯,並促進資料層和 UI 層之間的互動。通常稱為「領域層」。邏輯層是可選的,只有在您的應用程式在客戶端發生複雜的業務邏輯時才需要實作。許多應用程式只關心向使用者展示資料並允許使用者更改該資料(俗稱 CRUD 應用程式)。這些應用程式可能不需要此可選層。
  • 資料層 - 管理與資料來源(例如資料庫或平台外掛程式)的互動。向業務邏輯層公開資料和方法。

這些被稱為「層」,因為每一層只能與其直接下方或上方的層進行通訊。UI 層不應該知道資料層的存在,反之亦然。

單一事實來源

#

您應用程式中的每個資料類型都應該有一個單一事實來源 (SSOT)。事實來源負責表示本地或遠端狀態。如果可以在應用程式中修改資料,則 SSOT 類別應該是唯一可以這樣做的類別。

這可以大幅減少應用程式中的錯誤數量,並且可以簡化程式碼,因為您將只有一份相同資料的副本。

一般來說,應用程式中任何給定類型資料的事實來源都保存在一個名為 Repository 的類別中,它是資料層的一部分。您的應用程式中每種類型的資料通常都有一個 Repository 類別。

此原則可以應用於應用程式中的各層和元件,以及個別類別中。例如,Dart 類別可以使用 getter 來從 SSOT 欄位衍生值(而不是有多個需要獨立更新的欄位),或使用 record 列表來對相關值進行分組(而不是索引可能不同步的平行列表)。

單向數據流

#

單向資料流 (UDF) 指的是一種設計模式,它有助於將狀態與顯示該狀態的 UI 解耦。簡而言之,狀態從資料層透過邏輯層流到 UI 層中的 Widget。來自使用者互動的事件以相反的方向流動,從展示層流回邏輯層,然後流到資料層。

The three common layers of app architecture, the UI layer, logic layer, and data layer, and the flow of state from the data layer to the UI layer.

在 UDF 中,從使用者互動到重新渲染 UI 的更新迴圈如下所示

  1. [UI 層] 由於使用者互動而發生事件,例如點擊按鈕。Widget 的事件處理程式回呼會叫用邏輯層中類別公開的方法。
  2. [邏輯層] 邏輯類別呼叫 Repository 公開的方法,這些方法知道如何更改資料。
  3. [資料層] Repository 更新資料(如果需要),然後將新資料提供給邏輯類別。
  4. [邏輯層] 邏輯類別儲存其新狀態,並將其傳送到 UI。
  5. [UI 層] UI 顯示 View Model 的新狀態。

新資料也可以從資料層開始。例如,Repository 可以輪詢 HTTP 伺服器以取得新資料。在這種情況下,資料流僅完成旅程的後半部分。最重要的觀點是資料變更始終發生在SSOT 中,也就是資料層。這使您的程式碼更容易理解、不易出錯,並防止建立格式錯誤或意外的資料。

UI 是 (不可變) 狀態的函數

#

Flutter 是宣告式的,這表示它會建立其 UI 以反映您應用程式的目前狀態。當狀態變更時,您的應用程式應該觸發對依賴該狀態的 UI 進行重建。在 Flutter 中,您經常會聽到這被描述為「UI 是狀態的函數」。

UI is a function of state.

您的資料驅動您的 UI 至關重要,反之亦然。資料應該是不可變且持久的,而且視圖應該包含盡可能少的邏輯。這可以最大限度地減少在關閉應用程式時遺失資料的可能性,並使您的應用程式更易於測試且更能抵抗錯誤。

可擴展性

#

每個架構部分都應該有一個定義完善的輸入和輸出列表。例如,邏輯層中的 View Model 應該只接受資料來源(例如 Repository)作為輸入,並且只公開為視圖格式化的命令和資料。

以這種方式使用乾淨的介面可讓您交換類別的具體實作,而無需變更使用該介面的任何程式碼。

可測試性

#

使軟體可擴展的原則也使軟體更易於測試。例如,您可以透過模擬 Repository 來測試 View Model 的獨立邏輯。View Model 測試不需要您模擬應用程式的其他部分,而且您可以將 UI 邏輯與 Flutter Widget 本身分開進行測試。

您的應用程式也將更具彈性。新增新邏輯和新 UI 將是直接且低風險的。例如,新增新的 View Model 不會破壞資料層或業務邏輯層中的任何邏輯。

下一節說明您應用程式架構中任何給定元件的輸入和輸出的概念。

意見回饋

#

由於本網站的這一部分正在發展中,我們歡迎您的意見回饋