日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

架构模块化设计

發(fā)布時間:2025/3/19 18 豆豆
生活随笔 收集整理的這篇文章主要介紹了 架构模块化设计 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

本文轉載自開源GoFrame框架的官網,作者關于架構設計的思考,值得閱讀。
原文鏈接:GoFrame模塊化設計

本章節(jié)我們先講一講在軟件設計中,模塊化的一些設計和復用原則,然后再介紹GoFrame框架的模塊化設計,以便于大家更好地了解GoFrame框架模塊化設計的思想。

一、什么是模塊

模塊也稱作組件,是軟件系統(tǒng)中可復用的功能邏輯封裝單位。在不同的軟件架構層次,模塊的概念會有些不太一樣。在開發(fā)框架層面,模塊是某一類功能邏輯的最小封裝單位。在Golang代碼層面中,我們也可以將package稱作模塊。

二、模塊化的目標

軟件進行模塊化設計的目的,是為了使得軟件功能邏輯盡可能的解耦和復用,終極目標也是為了保證軟件開發(fā)維護的效率和質量。

三、模塊復用原則

REP 復用/發(fā)布等同原則

復用/發(fā)布等同原則(Release/Reuse Equivalency Principle):軟件復用的最小粒度應等同于其發(fā)布的最小粒度。直白地說,就是要復用一段代碼就把它抽成模塊。

CCP 共同閉包原則

共同閉包原則(Common Closure Principle):為了相同目的而同時修改的類,應該放在同一個模塊中。CCP 原則是 SRP 原則在模塊層面的描述。

對大部分應用程序而言,可維護性的重要性遠遠大于可復用性,由同一個原因引起的代碼修改,最好在同一個模塊中,如果分散在多個模塊中,那么開發(fā)、提交、部署的成本都會上升。

CRP 共同復用原則

共同復用原則(Common Reuse Principle):不要強迫一個模塊依賴它不需要的東西。CRP 原則是 ISP 原則在模塊層面的描述。

相信你一定有這種經歷,集成了模塊A,但模塊A依賴了模塊B、C。即使模塊B、C 你完全用不到,也不得不集成進來。這是因為你只用到了模塊A的部分能力,模塊A中額外的能力帶來了額外的依賴。如果遵循共同復用原則,你需要把A拆分,只保留你要用的部分。

復用原則競爭關系

REP、CCP、CRP 三個原則之間存在彼此競爭的關系,REP 和 CCP 是黏合性原則,它們會讓模塊變得更大,而 CRP 原則是排除性原則,它會讓模塊變小。遵守REP、CCP 而忽略 CRP ,就會依賴了太多沒有用到的模塊和類,而這些模塊或類的變動會導致你自己的模塊進行太多不必要的發(fā)布;遵守 REP 、CRP 而忽略 CCP,因為模塊拆分的太細了,一個需求變更可能要改n個模塊,帶來的成本也是巨大的。


圖. 模塊復用原則競爭關系張力圖

優(yōu)秀的架構師應該能在上述三角形張力區(qū)域中定位一個最適合目前研發(fā)團隊狀態(tài)的位置,例如在項目早期,CCP比REP更重要,隨著項目的發(fā)展,這個最合適的位置也要不停調整。

四、框架模塊設計

經過前面關于模塊設計原則和復用原則的介紹,我們應該對模塊開發(fā)和管理這塊的原則有了大概的了解,那么我們接著介紹框架的模塊化設計就比較容易理解了。

單倉庫包設計

根據REP原則我們了解到,一個可復用的模塊是支持獨立版本管理的,單倉庫包設計也正是如此。Golang中很多這樣的單倉庫包,一個包就是一個獨立的模塊。單倉庫包根據CRP原則可以再進一步的細化解耦拆分。我們來舉個例子,在開發(fā)復雜的業(yè)務項目場景下,常見的包依賴情況,類似于這樣的:

module business go 1.16 require (business.com/golang/strings v1.0.0business.com/golang/config v1.15.0business.com/golang/container v1.1.0business.com/golang/encoding v1.2.0business.com/golang/files v1.2.1business.com/golang/cache v1.7.3business.com/framework/utils v1.30.1github.com/pkg/errors v0.9.0github.com/goorm/orm v1.2.1github.com/goredis/redis v1.7.4github.com/gokafka/kafka v0.1.0github.com/gometrics/metrics v0.3.5github.com/gotracing/tracing v0.8.2github.com/gohttp/http v1.18.1github.com/google/grpc v1.16.1github.com/smith/env v1.0.2github.com/htbj/command v1.1.1github.com/kmlevel1/pool v1.1.4github.com/anolog/logging v1.16.2github.com/bgses123/session v1.5.1github.com/gomytmp/template v1.3.4github.com/govalidation/validate v1.19.2github.com/yetme1/goi18n v0.10.0github.com/convman/convert v1.20.0github.com/google/uuid v1.1.2// ... )

示例中的模塊依賴,都是一些通用模塊,大部分業(yè)務項目都會涉及到。模塊地址是便于演示而寫的隨意地址,并不一定真實存在。

使用Golang開發(fā)過復雜一點的業(yè)務項目的小伙伴們,對于這樣的場景大家一定不會陌生。一個正常的軟件企業(yè),往往至少有數百個這樣的項目,真實的模塊依賴關系比這里的例子更加復雜。在Golang項目開發(fā)中,對于模塊依賴的維護性挑戰(zhàn)是比較大的,我們往往會遇到一些痛點,主要的幾點:

  • 實現相同功能邏輯的模塊較多,選擇成本增加
  • 項目依賴的模塊過多,項目整體的穩(wěn)定性會受到影響
  • 項目依賴的模塊過多,項目無從下手是否應當升級這些模塊版本
  • 模塊分散設計,不成體系,難以統(tǒng)一。具體請參考章節(jié):統(tǒng)一框架設計

拿作者本廠舉例更好說明。我們的自研模塊有數十個,這些模塊已經被頻繁使用遍布到數百個業(yè)務項目中。有一次,我們提交了對幾個模塊的bug fix,其中有兩個還是比較重要的bug,緊接著,我們要求所有業(yè)務項目全部升級一下對應模塊的版本號,并且這些版本號也得小心別寫錯了。當然,這肯定也不是唯一的一次,隨后相同的場景各位同學可以自行腦補一下。

我們也可以選擇,不去主動推進所有業(yè)務項目升級模塊,只要項目還沒有觸發(fā)這些bug,那么就等著業(yè)務項目踩到了坑再由項目組自行去升級。領導一聽這種解決方案……各位同學再自行腦補一下和諧的場景。

其實這種問題主要的原因,還是來源于模塊的不穩(wěn)定,模塊也是需要不停迭代改進的。項目使用到這些模塊,那么就與這些模塊建立了耦合關系,耦合模塊的變化,必然會影響到依賴的相關項目。越底層的基礎模塊,頂層模塊則對其依賴的越多,影響面也就越大。那是不是只要模塊穩(wěn)定了,就不會存在這樣的問題了呢?風險依舊是存在的。Golang標準庫大家覺得算穩(wěn)定吧,但是它也是在不斷的迭代改進過程中,也是不斷有bug出現,只是大家幸運沒踩上去而已,風險相對較低。

好的軟件設計,并不是一成不變,而是能夠做到快速響應變化,根據變化快速改進完善。模塊的設計和管理,亦是如此。尋求能夠快速改進模塊邏輯、有效維護模塊依賴的方案,比編寫更加穩(wěn)定的功能模塊,更加高效和務實。

模塊聚合設計

GoFrame的模塊化管理思想更偏重于CCP原則,看重可維護性比可復用性更多。由于GoFrame是基于開發(fā)框架層面的出發(fā)點考慮,因此整體框架的設計不是單點設計的,而是自頂向下設計的。前面有提到,越底層的基礎模塊,頂層模塊則對其依賴的越多,影響面也就越大。因此,框架將一些通用性的核心模塊進行統(tǒng)一維護,這樣做的目的是使得這些模塊共同形成閉包,保證基礎模塊的穩(wěn)定性,并通過統(tǒng)一的版本管理,提高開發(fā)效率和可維護性,降低接入和維護成本。

站在GoFrame框架模塊化設計的角度,前面例子中的依賴情況應當變成以下的樣子:

module business go 1.16 require (github.com/gogf/gf v1.16.0github.com/goorm/orm v1.15.1 github.com/goredis/redis v1.7.4github.com/gokafka/kafka v0.1.0github.com/google/grpc v1.16.1// ... )

GoFrame只維護一些通用性的核心模塊,其他非通用核心模塊或者穩(wěn)定性較高的模塊,依舊建議使用單倉庫包的形式進行依賴引入,正如REP和CRP模塊復用原則倡導的那樣。在這種設計模式下:

  • 框架核心維護較全面的通用基礎模塊,降低基礎模塊選擇成本
  • 我們只需要維護一個統(tǒng)一的框架版本,而不是數十個模塊版本
  • 我們只需要了解一個框架的內容變化,而不是數十個模塊的內容變化
  • 升級的時候只需要升級一個框架版本,而不是數十個模塊版本的升級
  • 減輕開發(fā)人員的心智負擔,提高模塊可維護性,更容易保證各業(yè)務項目的模塊版本一致性

五、常見問題解答

1、雖然每一個模塊都按照低耦合設計,模塊可以選擇性引入,但在使用時也得全量下載完整框架代碼

文件層面的源文件下載與模塊之間的邏輯耦合沒有直接關系。需要注意的是,編譯型語言和解釋型語言的模塊管理邏輯不太一樣。

  • 編譯型語言:(以靜態(tài)編譯為例)往往以main包為入口,編譯器會自動分析源碼并將所有邏輯依賴模塊中對應的資源進行編譯處理,最終生成為靜態(tài)二進制文件進行發(fā)布,自身源文件以及依賴模塊(邏輯依賴)的源文件只在編譯階段使用,源碼文件并不會直接用于發(fā)布,如:C/C++、Golang、Rust等。
  • 解釋型語言:往往會將自身源文件(或中間碼)以及依賴模塊的源文件(或中間碼)全部進行打包發(fā)布,例如:PHP、Java、NodeJS、Python等。這個時候,依賴模塊的源碼大小對于項目發(fā)布來說影響會比較大。并且,打包時候的模塊依賴處理并不會檢查”邏輯依賴”,只要依賴配置文件中存在指定模塊,那么該模塊都會被共同打包發(fā)布。假如模塊中有10萬個函數,即使其中只有一個函數被使用到,該模塊所有函數將被共同打包發(fā)布。因為解釋型語言在代碼發(fā)布前并沒有”編譯-匯編-鏈接”等階段,只能在運行時對源碼及模塊依賴做完整解析處理。特別是PHP/Java轉Go的同學,這一塊的思維需要轉變適應。

2、框架中任一模塊的版本變更都會引起框架版本的發(fā)布,框架的發(fā)布頻次是否會變高

最主要的一點,框架的模塊設計也會充分考慮穩(wěn)定性因素,僅會將一些通用性的核心模塊按照CCP進行管理,并不會包含特定業(yè)務的邏輯封裝,因為涉及到特定業(yè)務的功能邏輯實現將會為框架模塊帶來更多的不穩(wěn)定變化。

在保證一定的穩(wěn)定性前提下,模塊的版本發(fā)布按照框架統(tǒng)一的迭代開發(fā)計劃進行,除了必要的hot fix之外,版本發(fā)布設置有固定的時間窗口,以保證框架核心的穩(wěn)定性。因此,框架通過模塊聚合的方式進行版本管理,不僅沒有增加框架的版本發(fā)布頻次,反而降低了框架的版本發(fā)布頻次,使得框架中的模塊版本更加穩(wěn)定。

3、框架聚合并維護通用性的核心模塊,通用性的核心模塊定義是什么

首先,它們是基礎模塊,往往位于模塊依賴鏈的最底層,這部分的模塊變化對項目穩(wěn)定性影響最大。

其次,絕大部分項目(二八定律來講為80%以上)都會依賴的通用性基礎模塊,可以稱作核心模塊。

最后,這部分模塊不包含具體業(yè)務的封裝實現。例如:微信公眾號/小程序、CMS/CRM、區(qū)塊鏈等相關模塊都是具體業(yè)務實現封裝。

關于模塊通用性的評估無法完全準確,框架為保證核心精簡會盡可能持保守態(tài)度,并且會根據實際情況在未來的迭代中逐步做調整。

以下為可供參考的模塊分層:

模塊分層參考

  • 業(yè)務實現模塊:特定業(yè)務項目邏輯實現,這里包含業(yè)務項目進一步的代碼分層。

  • 通用業(yè)務模塊:可復用的業(yè)務邏輯封裝,例如微信公眾號/小程序、CMS/CRM、區(qū)塊鏈等相關業(yè)務邏輯封裝模塊。

  • 通用基礎模塊:標準庫不提供或者基于標準庫封裝擴展的基礎模塊,例如:配置、校驗、緩存、ORM、I18N等等。

  • 標準基礎模塊:Golang標準庫。

4、框架中包含的模塊多,我覺得每個模塊的性能往往就不會高

哈哈。

總結

以上是生活随笔為你收集整理的架构模块化设计的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。