<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                今天,我們來聊一聊 Flutter 應用的工程架構這個話題。 在軟件開發中,我們不僅要在代碼實現中遵守常見的設計模式,更需要在架構設計中遵從基本的設計原則。而在這其中,DRY(即 Don’t Repeat Yourself)原則可以算是最重要的一個。 通俗來講,DRY 原則就是“不要重復”。這是一個很樸素的概念,因為即使是最初級的開發者,在寫了一段時間代碼后,也會不自覺地把一些常用的重復代碼抽取出來,放到公用的函數、類或是獨立的組件庫中,從而實現代碼復用。 在軟件開發中,我們通常從架構設計中就要考慮如何去管理重復性(即代碼復用),即如何將功能進行分治,將大問題分解為多個較為獨立的小問題。而在這其中,組件化和平臺化就是客戶端開發中最流行的分治手段。 所以今天,我們就一起來學習一下這兩類分治復用方案的中心思想,這樣我們在設計 Flutter 應用的架構時也就能做到有章可循了。 ## 組件化 組件化又叫模塊化,即基于可重用的目的,將一個大型軟件系統(App)按照關注點分離的方式,拆分成多個獨立的組件或模塊。每個獨立的組件都是一個單獨的系統,可以單獨維護、升級甚至直接替換,也可以依賴于別的獨立組件,只要組件提供的功能不發生變化,就不會影響其他組件和軟件系統的整體功能。 :-: ![](https://img.kancloud.cn/4f/49/4f49b09f5bc9fd33db010d9286ae2e82_1022x402.png) 圖 1 組件化示意圖 可以看到,組件化的中心思想是將獨立的功能進行拆分,而在拆分粒度上,組件化的約束則較為松散。一個獨立的組件可以是一個軟件包(Package)、頁面、UI 控件,甚至可能是封裝了一些函數的模塊。 **組件的粒度可大可小,那我們如何才能做好組件的封裝重用呢?哪些代碼應該被放到一個組件中?**這里有一些基本原則,包括單一性原則、抽象化原則、穩定性原則和自完備性原則。 接下來,我們先看看這些原則具體是什么意思。 **單一性原則指的是**,每個組件僅提供一個功能。分而治之是組件化的中心思想,每個組件都有自己固定的職責和清晰的邊界,專注地做一件事兒,這樣這個組件才能良性發展。 一個反例是 Common 或 Util 組件,這類組件往往是因為在開發中出現了定義不明確、歸屬邊界不清晰的代碼:“哎呀,這段代碼放哪兒好像都不合適,那就放 Common(Util)吧”。久而久之,這類組件就變成了無人問津的垃圾堆。所以,再遇到不知道該放哪兒的代碼時,就需要重新思考組件的設計和職責了。 **抽象化原則**指的是,組件提供的功能抽象應該盡量穩定,具有高復用度。而穩定的直觀表現就是對外暴露的接口很少發生變化,要做到這一點,需要我們提升對功能的抽象總結能力,在組件封裝時做好功能抽象和接口設計,將所有可能發生變化的因子都在組件內部做好適配,不要暴露給它的調用方。 **穩定性原則**指的是,不要讓穩定的組件依賴不穩定的組件。比如組件 1 依賴了組件 5,如果組件 1 很穩定,但是組件 5 經常變化,那么組件 1 也就會變得不穩定了,需要經常適配。如果組件 5 里確實有組件 1 不可或缺的代碼,我們可以考慮把這段代碼拆出來單獨做成一個新的組件 X,或是直接在組件 1 中拷貝一份依賴的代碼。 **自完備性**,即組件需要盡可能地做到自給自足,盡量減少對其他底層組件的依賴,達到代碼可復用的目的。比如,組件 1 只是依賴某個大組件 5 中的某個方法,這時更好的處理方法是,剝離掉組件 1 對組件 5 的依賴,直接把這個方法拷貝到組件 1 中。這樣一來組件 1 就能夠更好地應對后續的外部變更了。 在理解了組件化的基本原則之后,**我們再來看看組件化的具體實施步驟**,即剝離基礎功能、抽象業務模塊和最小化服務能力。 首先,我們需要剝離應用中與業務無關的基礎功能,比如網絡請求、組件中間件、第三方庫封裝、UI 組件等,將它們封裝為獨立的基礎庫;然后,我們在項目里用 pub 進行管理。如果是第三方庫,考慮到后續的維護適配成本,我們最好再封裝一層,使項目不直接依賴外部代碼,方便后續更新或替換。 基礎功能已經封裝成了定義更清晰的組件,接下來我們就可以按照業務維度,比如首頁、詳情頁、搜索頁等,去拆分獨立的模塊了。拆分的粒度可以先粗后細,只要能將大體劃分清晰的業務組件進行拆分,后續就可以通過分布迭代、局部微調,最終實現整個業務項目的組件化。 在業務組件和基礎組件都完成拆分封裝后,應用的組件化架構就基本成型了,最后就可以按照剛才我們說的 4 個原則,去修正各個組件向下的依賴,以及最小化對外暴露的能力了。 ## 平臺化 從組件的定義可以看到,組件是個松散的廣義概念,其規模取決于我們封裝的功能維度大小,而各個組件之間的關系也僅靠依賴去維持。如果組件之間的依賴關系比較復雜,就會在一定程度上造成功能耦合現象。 如下所示的組件示意圖中,組件 2 和組件 3 同時被多個業務組件和基礎功能組件直接引用,甚至組件 2 和組件 5、組件 3 和組件 4 之間還存在著循環依賴的情況。一旦這些組件的內部實現和外部接口發生變化,整個 App 就會陷入不穩定的狀態,即所謂牽一發而動全身。 :-: ![](https://img.kancloud.cn/4b/d6/4bd68bca82792a0e12561d072372c573_1022x562.png) 圖 2 循環依賴現象 平臺化是組件化的升級,即在組件化的基礎上,對它們提供的功能進行分類,統一分層劃分,增加依賴治理的概念。為了對這些功能單元在概念上進行更為統一的分類,我們按照四象限分析法,把應用程序的組件按照業務和 UI 分解為 4 個維度,來分析組件可以分為哪幾類。 :-: ![](https://img.kancloud.cn/b6/5d/b65d4d3e320763be9794a31fb6658978_836x712.png) 圖 3 組件劃分原則 可以看出,經過業務與 UI 的分解之后,這些組件可以分為 4 類: 1. 具備 UI 屬性的獨立業務模塊; 2. 不具備 UI 屬性的基礎業務功能; 3. 不具備業務屬性的 UI 控件 4. 不具備業務屬性的基礎功能 按照自身定義,這 4 類組件其實隱含著分層依賴的關系。比如,處于業務模塊中的首頁,依賴位于基礎業務模塊中的賬號功能;再比如,位于 UI 控件模塊中的輪播卡片,依賴位于基礎功能模塊中的存儲管理等功能。我們將它們按照依賴的先后順序從上到下進行劃分,就是一個完整的 App 了。 :-: ![](https://img.kancloud.cn/95/45/954527aafaaab090b5bb5a044725d49c_992x502.png) 圖 4 組件化分層 可以看到,平臺化與組件化最大的差異在于增加了分層的概念,每一層的功能均基于同層和下層的功能之上,這使得各個組件之間既保持了獨立性,同時也具有一定的彈性,在不越界的情況下按照功能劃分各司其職。 **與組件化更關注組件的獨立性相比,平臺化更關注的是組件之間關系的合理性,而這也是在設計平臺化架構時需要重點考慮的單向依賴原則。** 所謂單向依賴原則,指的是組件依賴的順序應該按照應用架構的層數從上到下依賴,不要出現下層模塊依賴上層模塊這樣循環依賴的現象。這樣可以最大限度地避免復雜的耦合,減少組件化時的困難。如果我們每個組件都只是單向依賴其他組件,各個組件之間的關系都是清晰的,代碼解耦也就會變得非常輕松了。 平臺化強調依賴的順序性,除了不允許出現下層組件依賴上層組件的情況,跨層組件和同層組件之間的依賴關系也應當嚴格控制,因為這樣的依賴關系往往會帶來架構設計上的混亂。 **如果下層組件確實需要調用上層組件的代碼怎么辦?** 這時,我們可以采用增加中間層的方式,比如 Event Bus、Provider 或 Router,以中間層轉發的形式實現信息同步。比如,位于第 4 層的網絡引擎中,會針對特定的錯誤碼跳轉到位于第 1 層的統一錯誤頁,這時我們就可以利用 Router 提供的命名路由跳轉,在不感知錯誤頁的實現情況下來完成。又比如,位于第 2 層的賬號組件中,會在用戶登入登出時主動刷新位于第 1 層的首頁和我的頁面,這時我們就可以利用 Event Bus 來觸發賬號切換事件,在不需要獲取頁面實例的情況下通知它們更新界面。關于這部分內容,你可以參考第[20](https://time.geekbang.org/column/article/116382)和[21](https://time.geekbang.org/column/article/118421)篇文章中的相關內容,這里就不再贅述了。 **平臺化架構是目前應用最廣的軟件架構設計,其核心在于如何將離散的組件依照單向依賴的原則進行分層。**而關于具體的分層邏輯,除了我們上面介紹的業務和 UI 四象限法則之外,你也可以使用其他的劃分策略,只要整體結構層次清晰明確,不存在難以確定歸屬的組件就可以了。 比如,Flutter 就采用 Embedder(操作系統適配層)、Engine(渲染引擎及 Dart VM 層)和 Framework(UI SDK 層)整體三層的劃分。可以看到,Flutter 框架每一層的組件定義都有著明確的邊界,其向上提供的功能和向下依賴的能力也非常明確。 :-: ![](https://img.kancloud.cn/eb/15/eb1550dd9df00fd5b37e181628b782dd_1920x1001.png) 圖 5 Flutter 框架架構 備注:此圖引自[Flutter System Overview](https://flutter.dev/docs/resources/technical-overview) ## 總結 好了,今天的分享就到這里,我們總結一下主要內容吧。 組件化和平臺化都是軟件開發中流行的分治手段,能夠將 App 內的功能拆分成多個獨立的組件或模塊。 其中,組件化更關注如何保持組件的獨立性,只要拆分的功能獨立即可,約束較為松散,在中大型 App 中容易造成一定程度的功能耦合現象。而平臺化則更強調組件之間關系的合理性,增加了分層的概念,使得組件之間既有邊界,也有一定的彈性。只要滿足單向依賴原則,各個組件之間的關系都是清晰的。 分治是一種與技術無關的架構思想,有利于降低工程的復雜性,從而提高 App 的可擴展和可維護性。今天這篇文章,我重點與你分享的是組件化與平臺化這兩種架構設計的思路,并沒有講解它們的具體實現。而關于組件化與平臺化的實現細節,網絡上已經有很多文章了,你可以在網上自行搜索了解。如果你還有關于組件化和平臺化的其他問題,那就在評論區中給我留言吧。 其實,你也可以琢磨出,今天這篇文章的目的是帶你領會 App 架構設計的核心思想。因為,理解思想之后剩下的就是去實踐了,當你需要設計 App 架構時再回憶起這些內容,或是翻出這篇文章一定會事半功倍。 ## 思考題 最后,我給你留一道思考題吧。 在 App 架構設計中,你會采用何種方式去管理涉及資源類的依賴呢?
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看