亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

嵌入golang是否違反了德米特法則?

嵌入golang是否違反了德米特法則?

Go
慕絲7291255 2021-11-15 20:35:09
這就是Effective GO關于嵌入在 golang 中所說的話當我們嵌入一個類型時,該類型的方法成為外部類型的方法,但是當它們被調用時,方法的接收者是內部類型,而不是外部類型我有一個代碼片段,其中Struct User定義如下type User struct {    Name     string    Password string    *sql.Tx}然后我打電話給u.Query("some query here")等等。我專門做了這個,這樣我就可以避免這樣的電話u.Transaction.Query("query"),這顯然違反了迪米特法則?,F在,在閱讀了文檔和有效的 go 之后,我也懷疑第一種方法的優點。我是否違反了得墨忒耳定律?如果是,我該如何避免?
查看完整描述

1 回答

?
慕容708150

TA貢獻1831條經驗 獲得超4個贊

嵌入概念在某種程度上違反了迪米特法則,因為如果類型本身被導出,它不會隱藏類型被嵌入的事實。請注意,嵌入未導出的類型不會違反 LoD(您不能引用未導出的字段和方法)。


但這并不強制您以同樣違反 LoD 的方式引用提升的字段或方法。嵌入本身只是一種技術,因此您可以將通用的共享代碼“外包”給其他類型;或者從另一個角度來看,在創建新類型時使用其他類型。您引用嵌入類型的提升字段或方法的方式可能違反法律。


正如您所說,如果您將其稱為u.Tx.Query(),則明顯違反了迪米特法則:您正在使用User嵌入的實現細節*sql.Tx。


但如果你這樣稱呼它:u.Query()那沒問題。這種形式不會暴露或利用*sql.Tx嵌入的事實。如果實現發生變化,此表單將繼續工作并且*sql.Tx不再嵌入(例如,它被更改為“常規”字段或完全刪除,并User.Query()添加了一個方法)。


如果您不想允許訪問導出的嵌入類型的字段值,請將其設為未導出的常規字段并添加一個User.Query()可以委托給該字段的“顯式”方法,例如:


type User struct {

    Name     string

    Password string

    tx       *sql.Tx // regular field, not embedded; and not exported

}


func (u *User) Query(query string, args ...interface{}) (*sql.Rows, error) {

    return u.tx.Query(query, args...)

}

補充說明:


在示例中,如果u.Query()使用了 ,則使用 this 的客戶端在 的內部User發生更改時不會受到影響(無論是u.Query()表示提升的方法還是表示 的方法User,即:)User.Query()。


如果sql.Tx更改,是的,u.Query()可能不再有效。但sql.Tx不太可能發生不相容。如果您是更改包的開發人員,并且進行了不兼容的更改,則您有責任更改依賴于您的不兼容更改的其他代碼。這樣做(正確更新u.Query())調用的客戶端u.Query()不會受到影響,客戶端仍然不需要知道引擎蓋下的某些更改。


這正是 LoD 所保證的:如果您使用u.Query()而不是u.Tx.Query(),如果在User內部發生更改,則客戶端調用u.Query()不需要知道或擔心這一點。LoD 不是壞事。你不應該放棄它。你可以選擇你遵循的原則,但你也應該思考而不是不惜一切代價一直遵循所選原則所規定的一切。


還有一件事需要澄清:LoD 不涉及 API 不兼容的更改。它提供的是,如果遵循,實體的內部更改不會對使用實體“公共”面的其他實體產生影響。如果sql.Tx以一種Tx.Query()將不再可用的劇烈方式更改,則 LoD 不會“涵蓋”。


查看完整回答
反對 回復 2021-11-15
  • 1 回答
  • 0 關注
  • 187 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號