天天看點

Go實戰🧧系統(三) - 架構設計1 代碼架構的意義2 代碼架構的操作3 代碼架構的設計4 Go 語言規範5 🧧系統 - 代碼結構6 🧧系統 - 包結構7 包設計規範8 Go的包管理參考

1 代碼架構的意義

Go實戰🧧系統(三) - 架構設計1 代碼架構的意義2 代碼架構的操作3 代碼架構的設計4 Go 語言規範5 🧧系統 - 代碼結構6 🧧系統 - 包結構7 包設計規範8 Go的包管理參考

代碼架構就是詳細設計中的核心内容!

1.1 代碼架構承上啟下,決定軟體品質

◆ 承上

說明業務邏輯和業務領域模型

◆ 本身

保證代碼有更好的可讀性和可維護性、可擴充性

◆ 啟下

承載代碼運作的硬體部署架構

2 代碼架構的操作

2.1 業務邏輯表達

向上溝通,提供互動入口

2.2 自身業務邏輯及技術實作

向下溝通,儲存運作狀态

3 代碼架構的設計

先看一下DDD和分層架構的相關知識。

3.1 DDD

DDD(Domain Driven Design,領域驅動設計)作為一種軟體開發方法,它可以幫助我們設計高品質的軟體模型。在正确實作的情況下,我們通過DDD完成的設計恰恰就是軟體的工作方式。

UL(Ubiquitous Language,通用語言)是團隊共享的語言,是DDD中最具威力的特性之一。不管你在團隊中的角色如何,隻要你是團隊的一員,你都将使用UL。由于UL的重要性,是以需要讓每個概念在各自的上下文中是清晰無歧義的,于是DDD在戰略設計上提出了模式BC(Bounded Context,限界上下文)。UL和BC同時構成了DDD的兩大支柱,并且它們是相輔相成的,即UL都有其确定的上下文含義,而BC中的每個概念都有唯一的含義。

一個業務領域劃分成若幹個BC,它們之間通過Context Map進行內建。BC是一個顯式的邊界,領域模型便存在于這個邊界之内。領域模型是關于某個特定業務領域的軟體模型。通常,領域模型通過對象模型來實作,這些對象同時包含了資料和行為,并且表達了準确的業務含義。

從廣義上來講,領域即是一個組織所做的事情以及其中所包含的一切,表示整個業務系統。

由于“領域模型”包含了“領域”這個詞,我們可能會認為應該為整個業務系統建立一個單一的、内聚的和全功能式的模型。然而,這并不是我們使用DDD的目标。正好相反,領域模型存在于BC内。

在微服務架構實踐中,人們大量地使用了DDD中的概念和技術:

微服務中應該首先建立UL,然後再讨論領域模型。

一個微服務最大不要超過一個BC,否則微服務内會存在有歧義的領域概念。

一個微服務最小不要小于一個聚合,否則會引入分布式事務的複雜度。

微服務的劃分過程類似于BC的劃分過程,每個微服務都有一個領域模型。

微服務間的內建可以通過Context Map來完成,比如ACL(Anticorruption Layer,防腐層)。

微服務間最好采用Domain Event(領域事件)來進行互動,使得微服務可以保持松耦合。

.

下面介紹最為流行的分層代碼架構

3.1 分層架構簡介

分層架構的一個重要原則是每層隻能與位于其下方的層發生耦合。

分層架構可以簡單分為兩種

  • 嚴格分層架構

    某層隻能與位于其直接下方的層發生耦合

  • 松散分層架構

    松散分層架構中,則允許某層與它的任意下方層發生耦合。

分層架構的好處是顯而易見的。首先,由于層間松散的耦合關系,使得我們可以專注于本層的設計,而不必關心其他層的設計,也不必擔心自己的設計會影響其它層,對提高軟體品質大有裨益。其次,分層架構使得程式結構清晰,更新和維護都變得十分容易,更改某層的具體實作代碼,隻要本層的接口保持穩定,其他層可以不必修改。即使本層的接口發生變化,也隻影響相鄰的上層,修改工作量小且錯誤可以控制,不會帶來意外的風險。

要保持程式分層架構的優點,就必須堅持層間的松散耦合關系。設計程式時,應先劃分出可能的層次,以及此層次提供的接口和需要的接口。設計某層時,應盡量保持層間的隔離,僅使用下層提供的接口。

3.2 分層架構的優點

單一職責

高内聚低耦合

提高複用性

開發人員可以隻關注整個結構中的某一層。

可以很容易的用新的實作來替換原有層次的實作。

可以降低層與層之間的依賴。

有利于标準化。

利于各層邏輯的複用。

3.3 分層架構的缺陷

“金無足赤,人無完人”,分層架構也不可避免具有一些缺陷:

降低了系統的性能。這是顯然的,因為增加了中間層,不過可以通過緩存機制來改善。

可能會導緻級聯的修改。這種修改尤其展現在自上而下的方向,不過可以通過依賴倒置來改善。

在每個BC中為了凸顯領域模型,DDD中提出了分層架構模式

最基本的為三層架構

3.4 三層架構

表現層

業務邏輯層

資料持久層

但是職責定義并不明确,耦合度高

是以我們項目使用四層邏輯分層架構

3.5 邏輯分層架構

Go實戰🧧系統(三) - 架構設計1 代碼架構的意義2 代碼架構的操作3 代碼架構的設計4 Go 語言規範5 🧧系統 - 代碼結構6 🧧系統 - 包結構7 包設計規範8 Go的包管理參考
  • User Interface - 使用者接口

    人機互動,為使用者界面層(或表示層),負責向使用者顯示資訊和解釋使用者指令。這裡指的使用者可以是另一個計算機系統,不一定是使用使用者界面的人。

  • Application - 應用層

    定義軟體要完成的任務,并且指揮表達領域概念的對象來解決問題。這一層所負責的工作對業務來說意義重大,也是與其它系統的應用層進行互動的必要管道。應用層要盡量簡單,不包含業務規則或者知識,而隻為下一層中的領域對象協調任務,配置設定工作,使它們互相協作。它沒有反映業務情況的狀态,但是卻可以具有另外一種狀态,為使用者或程式顯示某個任務的進度。

  • Domain - 領域層(或模型層)

    表達業務概念,業務狀态資訊以及業務規則。盡管儲存業務狀态的技術細節是由基礎設施層實作的,但是反映業務情況的狀态是由本層控制并且使用的。領域層是業務軟體的核心,領域模型位于這一層。

  • Infrastructure - 基礎實施層

    向其他層提供通用的技術能力:為應用層傳遞消息,為領域層提供持久化機制,為使用者界面層繪制螢幕元件,等等。基礎設施層還能夠通過架構架構來支援四個層次間的互動模式。

傳統的四層架構都是限定型松散分層架構,即Infrastructure層的任意上層都可以通路該層(“L”型),而其它層遵守嚴格分層架構

在四層架構模式的實踐中,對于分層的本地化定義主要為:

  • User Interface層主要是Restful消息處理,配置檔案解析,等等。
  • Application層主要是多程序管理及排程,多線程管理及排程,多協程排程和狀态機管理,等等。
  • Domain層主要是領域模型的實作,包括領域對象的确立,這些對象的生命周期管理及關系,領域服務的定義,領域事件的釋出,等等。
  • Infrastructure層主要是業務平台,程式設計架構,第三方庫的封裝,基礎算法,等等。
嚴格意義上來說,User Interface指的是使用者界面,Restful消息和配置檔案解析等處理應該放在Application層,User Interface層沒有的話就空缺。但User Interface也可以了解為使用者接口,是以将Restful消息和配置檔案解析等處理放在User Interface層也行。

3.6 實體分層

  • 魔改四層的六層架構
    Go實戰🧧系統(三) - 架構設計1 代碼架構的意義2 代碼架構的操作3 代碼架構的設計4 Go 語言規範5 🧧系統 - 代碼結構6 🧧系統 - 包結構7 包設計規範8 Go的包管理參考

◆ 使用者接口

◆ 應用服務層接口:

◆ 核心層

  • 應用服務實作層
  • 領域層
  • 資料通路層

◆ 基礎設施層

  • 架構設計圖
    Go實戰🧧系統(三) - 架構設計1 代碼架構的意義2 代碼架構的操作3 代碼架構的設計4 Go 語言規範5 🧧系統 - 代碼結構6 🧧系統 - 包結構7 包設計規範8 Go的包管理參考

4 Go 語言規範

4.1 包名

◆ 完整包名組成:引入路徑+包名

◆ 源代碼中的包名稱

  • 可以和檔案夾名稱不一緻,建議盡量一緻
  • 同一檔案夾中所有源檔案中的包名必須一緻

    ◆ 代碼引用時使用包名,而非檔案夾名稱

◆ 源代碼導入的是檔案夾路徑名稱

  • 非包名
  • 非檔案名

4.2 源代碼檔案名

◆ 檔案名稱隻是約定描述性的,并無任何程式設計含義

5 🧧系統 - 代碼結構

Go實戰🧧系統(三) - 架構設計1 代碼架構的意義2 代碼架構的操作3 代碼架構的設計4 Go 語言規範5 🧧系統 - 代碼結構6 🧧系統 - 包結構7 包設計規範8 Go的包管理參考
Go實戰🧧系統(三) - 架構設計1 代碼架構的意義2 代碼架構的操作3 代碼架構的設計4 Go 語言規範5 🧧系統 - 代碼結構6 🧧系統 - 包結構7 包設計規範8 Go的包管理參考

6 🧧系統 - 包結構

Go實戰🧧系統(三) - 架構設計1 代碼架構的意義2 代碼架構的操作3 代碼架構的設計4 Go 語言規範5 🧧系統 - 代碼結構6 🧧系統 - 包結構7 包設計規範8 Go的包管理參考

7 包設計規範

7.1 apis包 - 使用者接口層

◆ 檔案名稱可以描述其業務含義的單詞

◆ 定義外部互動邏輯和互動形式: UI、RESTful接口

◆ 不涉及任何業務,随時可以替換為其他形式的互動方式

◆ services構造和初始化

7.2 services包 - 應用層接口

◆ 檔案名稱使用可以描述其業務含義

◆ 需要對外暴露

  • DTO、 service interface
  • 枚舉、常數等

7.3 core包 - 應用層/領域層/資料通路層

◆ 檔案名稱使用可以描述

業務含義 +分層名稱

◆ Service實作

Domain、Dao、 PO

8 Go的包管理

8.1 曆史

go get => vendor => go modules

◆ go get無版本概念

◆ vendor曲線救國,但仍未版本化

◆ go1.11 modules開啟版本依賴新大門

詳細過程推薦閱讀
Go 包管理的前世今生

8.2 Go modules

通過GO 1.11 MODULE環境變量來開啟或者關閉,預設是auto

◆ off/on/auto

關閉,開啟,自動識别

◆ 使用module後,GOPATH失去了部分意義

◆ 要用module ,第一步将項目從GOPATH中移出去

8.3 go.mod 檔案

go.mod檔案來管理依賴,定義子產品依賴

◆ go.mod檔案放在項目根目錄

◆ go.mod檔案面向行,由指令+參數組成

◆ 注釋使用//

8.3.1 go.mod 主要指令

◆ module:定義目前子產品和包路徑

◆ require: 定義依賴的子產品和版本

◆ exclude: 排除特定子產品和版本的使用

◆ replace:子產品源的替換

8.3.2 go.mod 指令

go.mod檔案用go mod指令來建立和維護

◆ 指令格式

go mod <指令> [可選參數]           

◆ 8個子指令

  • init ,tidy,vendor,verify
  • download,edit,graph ,why

8.3.3 實戰示範

8.3.3.1 使用go mod init 建立和初始化go.mod檔案

go mod init javaedge.com/GoDemo           
Go實戰🧧系統(三) - 架構設計1 代碼架構的意義2 代碼架構的操作3 代碼架構的設計4 Go 語言規範5 🧧系統 - 代碼結構6 🧧系統 - 包結構7 包設計規範8 Go的包管理參考
  • 生成檔案
    Go實戰🧧系統(三) - 架構設計1 代碼架構的意義2 代碼架構的操作3 代碼架構的設計4 Go 語言規範5 🧧系統 - 代碼結構6 🧧系統 - 包結構7 包設計規範8 Go的包管理參考

8.3.3.2 go get引入依賴

Go實戰🧧系統(三) - 架構設計1 代碼架構的意義2 代碼架構的操作3 代碼架構的設計4 Go 語言規範5 🧧系統 - 代碼結構6 🧧系統 - 包結構7 包設計規範8 Go的包管理參考

8.3.3.3 tidy子指令更新子產品依賴

對于已存在項目進行module化,即可使用該指令

會自動添加依賴的包,使用go build更新依賴

參考

DDD分層架構的三種模式

更多内容請關注 JavaEdge 公号

繼續閱讀