我已經獲得了 C 的經驗,但我是 Qt 的新手。我得到了一個真正的專案,由一個不再為這家公司作業的人開發。我不知道這是否是一個好的做法,我提前為可能不合適的術語道歉:我注意到這個專案實際上充滿了我認為不必要的信號/插槽對。更準確地說:規定應用程式邏輯的類相互看到,公開一些公共方法來觸發所需的程序就足夠了,但是,這幾乎總是使用信號和插槽來實作(我在這里再說一遍:即使沒有來自 GUI 的輸入)。鑒于我是 Qt 的新手,這樣做是一個好習慣嗎?謝謝。
編輯:我報告的案例不包括來自計時器、執行緒或其他的信號。這家伙使用了信號和槽對,就像它是從類直接呼叫方法的替代品,比如說,A 到 B 類
uj5u.com熱心網友回復:
當然,這取決于,但大多數情況下是的,這是一種正確的做法,因為它使物件保持解耦。兩個相互看到的類并不意味著如果它們不處于主從關系或不遵循邏輯層次結構,它們就可以相互使用。大多數情況下,由于呼叫的鰭狀肢效應,您將以不可逆的方式耦合所有內容。證據可能是您想要修復“公開方法”,這可能會破壞類的封裝和契約,這可能導致不依賴于使用 Qt 的錯誤設計選擇。
由于我們沒有看到實際的代碼,因此他也可能在濫用信號,但根據您的解釋,我會選擇第一個選項。
uj5u.com熱心網友回復:
過度使用信號和插槽是一種非常糟糕且非常普遍的做法。它隱藏了依賴關系,使代碼難以除錯,并且從長遠來看基本上無法維護。不幸的是,許多程式員認為這是一個很好的做法,因為他們實作了“解耦”,這對他們來說似乎是一個圣杯。這是胡說八道。
我并不是說您根本不應該使用信號和插槽。我只是說你不應該過度使用它們。信號和槽是實作觀察者設計模式的完美工具,以擁有一個“反應式”系統,其中物件對改變其狀態的其他物件做出反應。只有這樣才能正確使用信號和槽。幾乎所有其他信號和槽的使用都是錯誤的。我見過的最極端的情況是使用信號槽連接實作 getter 函式。信號發送一個對變數的參考,槽用一個值填充它,然后它回傳到發射器。這簡直是??瘋了!
你怎么知道你的信號和槽正確地實作了觀察者模式?這些是我長期使用 Qt 的經驗得出的經驗法則:
- 信號的本質是發射器通過發送一些其狀態已發生某種變化的信號來公開宣布(信號始終是公開的 - 除非您使用私有類虛擬引數)。
- 發射器不關心誰是觀察者或是否有任何觀察者,即發射器不能以任何方式依賴于觀察者。
- 建立或管理連接絕不是發射器的責任——永遠不要這樣做!連接/斷開是觀察者的責任(然后它通常連接到一個私有插槽)或某個知道發射器和觀察者存在的父物件(在這種情況下,共同的父物件將發射器的信號連接到觀察者)公共插槽)。
你會在 GUI 層看到很多信號槽連接是正常的,這完全沒問題(注意:GUI 層包括視圖模型!)。這是因為 GUI 通常是一個反應系統,其中物件對其他物件或對底層中的某些更改做出反應。但是您可能會在業務邏輯層中看到更少的信號槽連接(順便說一句。在許多專案中,業務邏輯是在不使用 Qt 的情況下撰寫的)。
關于命名:我遇到了一種有趣的代碼異味。當觀察者的公共(!)槽被稱為like onSomethingHappened()- 強調前綴on。這幾乎總是不良設計和濫用信號和插槽的跡象。通常這個槽應該是 a) 私有的并且連接應該由觀察者建立或者 b) 應該重命名為doSomething()或者 c) 應該重命名并且應該作為正常方法呼叫而不是使用信號和槽。
并說明為什么過度使用信號和插槽很難維護。從長遠來看,有許多潛在的問題可能會破壞您的代碼:
- 與信號和槽的依賴關系通常隱藏在遙遠的看似無關的代碼部分中。這與發射器實際上依賴于觀察者時的信號槽濫用有關,但在查看發射器的代碼時并不清楚。如果您的類依賴于其他一些類/模塊,那么這種依賴關系應該是明確且清晰可見的。
- 當信號和插槽通過代碼以編程方式連接然后斷開連接時,您通常會處于忘記斷開連接的狀態并且現在有多個連接。擁有多個連接經常被忽視,因為它通常不會造成任何傷害,它只會使代碼變慢一些,即更改的文本會更新多次而不是僅更新一次 - 除非您有千倍的連接,否則沒有人會發現這個問題。這些乘法連接有點類似于記憶體泄漏。小的記憶體泄漏通常不會被注意到,這類似于多個連接。
- 您經常依賴于建立連接的順序。而當這些依賴于順序的連接在遙遠的代碼部分建立起來時,你就遇到了大麻煩,這段代碼遲早會崩潰。
要檢查我是否沒有多個連接或連接/斷開連接是否成功,我正在使用這些我的幫助工具https://github.com/vladimir-kraus/qtutils/blob/main/qtutils/safeconnect.h
PS:在上面的文字中,我使用了術語“發射器”(發射信號)和“觀察者”(觀察發射器并接收信號)。有時人們使用“發送者”和“接收者”來代替。我的意圖是強調發射器在不知道是否有人收到信號的情況下發出信號這一事實。“發送者”一詞給人的印象是您將信號發送給某人,但這正是信號槽過度使用和設計不良的原因。所以使用“發件人”只會導致混亂,IMO。通過使用“觀察者”,我想強調信號和插槽是實作觀察者設計模式的工具。
PPS:信號和插槽也是 Qt 中執行緒之間異步通信的完美工具。這個用例可能是我上面描述的原則的極少數例外之一。
uj5u.com熱心網友回復:
信號和槽機制是 Qt 的核心特性。
一般來說,信號和槽是首選/使用的,因為:
- 它們允許通過排隊連接進行異步執行。
- 它們是松耦合的。
- 它們允許將 n 個信號連接到一個插槽,一個信號連接到 n 個插槽,并將信號連接到另一個信號。
在您的專案中,如果使用了信號槽機制來實作上述目的,那么它很可能是正確的用法。
GUI 輸入處理并不是唯一使用信號槽機制的地方。
除非我們知道您專案的用例,否則很難評論信號槽機制是否被誤用/過度使用。
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/409781.html
標籤:
上一篇:類似系統的QT普通命令執行
下一篇:使用回圈和前綴更新表中的所有行
