Go中struct巢狀與物件導向以及上下文

banq發表於2024-02-16


我一直傾向於儘量避免Go struct結構體嵌入,因為我發現這樣做會增加閱讀難度,因為這個 "上帝結構體god struct "恰好實現了大量獨立的介面,並被傳遞到很多地方。不過我還是想聽聽其他人的意見。

您對結構嵌入(尤其是實現trait介面時)有什麼看法?


Reddit網友討論:

每次我這樣做我都會後悔。我發現它們非常難以閱讀。

====================================

上次我設計一些嚴重依賴結構嵌入的東西時,我迷失了幾周,最終把它全部撕掉了。
我認為這是一個教訓。當我建造它的時候,我對整個骯髒的行業產生了一種令人毛骨悚然的厭惡。

====================================

結構嵌入的一個很好的用例是限制對資料的訪問並實現職責分離。如果特定程式碼需要對較大資料的子集進行操作,有時使用結構嵌入會更容易完成。一個例子是處理配置:

type AWSConfig {
  Region string `env:<font>"AWS_REGION"`
  S3Bucket string `env:
"S3_BUCKET"`
}

type DbConfig {
  Username string `env:
"DB_NAME"`
  Host string `env:
"DB_HOST"`
}

type Config {
  AWSConfig
  DbConfig
}

// ...<i>

cfg := readConfig()
// Reads everything<i>
m1 := NewModule1(cfg.AWSConfig)
// Only concerned with AWS<i>
m2 := NewModule2(cfg.DbConfig)  
// Only concerned with DB<i>

====================================

我認為如果您的結構代表一個真正的業務實體並且它具有組成部分,那麼它就有意義。我覺得它有點麻煩,但我並不反對它有時很好地代表一些真實事物的想法。

====================================

介面一直存在,結構幾乎從不存在

====================================

據我所知,我們在應用程式中只有兩個地方使用了結構嵌入:

  • 具有通用資料集的模型(也就是說,您希望擁有一個包含 int ID、created_at 和 Updated_at 等內容的基本模型)。應該小心謹慎,但看起來效果還不錯。在這種情況下可能更願意明確,但它也從未引起重大問題,所以......
  • 在我們的企業專案中擴充套件我們的 FOSS 專案的資料庫 god 結構和 God 介面。問題是我們首先有上帝物件,但是當你堅持使用它時,嵌入介面和結構來建立滿足呼叫的超集,它就很重要了。非常噁心,僅用作臨時解決方法

====================================

除了實現介面,我不知道還有其他原因。

有一個用例我有時會用到,但用起來還是覺得噁心。那就是:聯合型別union types。

我製作了一個空結構體,其中的方法什麼也不做,只是有一個唯一的名字。然後,我用這個方法建立一個介面,任何嵌入這個空結構的東西都可以實現這個介面。因此,該介面型別就是嵌入該結構的所有東西的聯合。

我使用聯合型別的主要目的是異構樹。節點 A 可以有 B 或 C 作為子節點,B 可以有 A 作為子節點,等等。

====================================
banq注:

  • 結構struct + 介面trait = DDD聚合 =>Being in Context(上下文)
  • Data + interactive =>Being in Context (DCI
  • 資料 + 單一職責 = 物件  =>Being in Context(上下文) 
  • 資料結構 + 演算法 = 應用 =>Being in Context(上下文) 
  • MVC:M模型資料 + V檢視動作事件 = C控制器 =>Being in Context(上下文) 
  • DDD聚合 = 上帝結構體god struct (沒有考慮上下文、場景的聚合都會變成上帝物件

相關文章