1 回答

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 不會“涵蓋”。
- 1 回答
- 0 關注
- 187 瀏覽
添加回答
舉報