清晰架構(Clean Architecture)的 Go 微服務: 編碼風格

編碼風格在編程中是一個相對乏味的主題,但是合適的編碼風格對一個有效的程序員是至關重要的。 它有三個組成部分:

  1. 程序結構 ( application layout)

  2. 編碼規則或風格

  3. 命名約定

我已經在清晰架構(Clean Architecture)的 Go 微服務: 程序結構 ¹ 中討論了程序結構,因此本文將介紹後兩點。

編碼規則或風格
  1. 沒有包級別 (package level) 變量。

    包級別變量打破了函數封裝並使函數有了不確定。我在本程序中遵循了這個規則,唯一的例外是在 “容器” 包中,因爲它負責程序級配置,在這裏很難做到。其實即使在 “容器” 包中也可以去除掉包級別變量,但它需要付出很多努力,有些得不償失。但是,由於包級別變量僅限於 “容器” 包中,因此導致的破壞大大減少。

  2. 儘量少使用常量

    常量也是包級別,因爲具有不變性,它們作爲全局變量的危害較小,但它們仍然會破壞函數封裝並需要進行限制。

  3. 依賴於接口而不是具體類型

    當你嘗試最小化外部更改對程序的影響時,無論外來者是函數,包還是應用程序,都要使代碼依賴於接口而不是具體類型。

命名規則

最佳的代碼是自我解釋的,良好的命名起着至關重要的作用。Go 的命名約定與 Java 非常矛盾。嘗試之後,我發現它是有效的,在創建簡潔的代碼同時並沒有降低可讀性。 Go 是一種相對與更底層接近的語言,人們用它來編寫網絡,驅動程序和 docker 容器代碼。在這些環境中,使用簡潔的名稱是合適的。

但是,在編寫業務應用程序時,我們需要創建許多不同的類型或結構來處理相似的業務概念,簡潔的命名便不再適用。例如,爲了處理與 “用戶” 相關概念,我們有 “User”,“UserDataService”,“RegistrationUseCase”,“RegistrationUseCaseIterface” 和“UserDataInterface”,它們都與 “User” 有關,但都完全不同。你確實需要一個相對較長的名字來區分它們。爲了獲得良好的可讀性,我有意違反了 Go 的一些命名約定,我將逐一解釋它們。

我遵循的一條規則是 “變量聲明(name declaration)與其使用之間的距離越大,名稱應該越長”Andrew Gerrand². 我從 Dave Cheney³ 的一篇文章中學到了這一點。基於它,我創建了自己的命名規則:“爲類型(結構,接口)或函數命名使用長名稱使其清晰易讀,爲局部變量命名使用短名稱”,因爲局部變量聲明和使用之間的距離較短。

給類型(types)命名:

當我看到一個名字時,重要的是要了解它是哪種類型,它處於哪個層。例如,“UserDataInterface”,告訴我它是域模型 “User”,它提供數據服務(持久性),並且它是一個接口。

Model:

域模型層,是最容易提供名稱的層。 例如,域模型用戶的 “User”。

Dataservice:

數據持久性服務層。 例如 “UserDataMySql” 作爲用戶持久性服務 MySQL 數據庫的命名; “UserDataCouchdb”作爲 CouchDB 數據庫的用戶持久性服務的命名。 用戶數據服務的不同實現共享相同的前綴“UserData”,並且它們的接口是“UserDataInterface”。

“CourseDataInterface” 是課程數據服務的接口,“CourseDataMySql” 是具體課程數據服務 MSql 數據庫實現的名稱。 所有數據服務共享相同的前綴 “[model]Data”。

Use Case:

用例層。 “RegistrationUseCase”是註冊用例的具體類型,接口是 “RegistrationUseCaseInterface”。 “ListCourseUseCase” 是課程列表用例的具體類型。 所有用例共享相同的後綴“UseCase”

Interface:

在清晰架構(Clean Architecture)中,所有業務邏輯都是基於接口調用的。 在遇到類型時,重要的是要識別類型是接口還是具體實現,因此我在所有接口上添加後綴 “Interface”,例如“UseCaseInterface”。 如果你認爲它太長,你可以用“I”,“If” 或“Intf”等縮略語替換“Interface”。 對我來說,打字不是一個問題,IDE 在大多數時間裏都已經把問題解決了。

Constants:

對於常量,重要的是將它們與變量區分開來,所以我使用全部大寫,如果是多字段常量(multi-words constant),我使用蛇形命名法(Snake Case)而不是駝峯命名法(Camel Case)(我知道它與 Go 命名約定相左)。 例如,“QUERY_USER_BY_NAME” 而不是 “queryUserByName”,這使它易讀性更好。

結論:

編碼風格對於使編程效率至關重要。 良好的命名使代碼自我解釋。 對類型或函數使用長名稱,對局部變量使用短名稱。 將 “interface” 放在接口名稱中是有幫助的。 用蛇形命名法(Snake Case)並且所有字母大寫來命名常量,以便於識別。

源程序:

完整的源程序鏈接 github: https://github.com/jfeng45/servicetmpl

索引:

[1]Go Microservice with Clean Architecture: Application Layout

[2]What’s in a name?

[3]Practical Go: Real world advice for writing maintainable Go programs

不堆砌術語,不羅列架構,不迷信權威,不盲從流行,堅持獨立思考

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://blog.csdn.net/weixin_38748858/article/details/104152116