当没有来自 GUI 的输入时,在 Qt 中使用信号和槽是一个好习惯吗?

Lui*_*405 4 c++ qt

我已经获得了 C++ 方面的经验,但我是 Qt 方面的新手。我得到了一个真正的项目,由不再在这家公司工作的人开发。我不知道这是否是一个好的做法,我提前为可能不太合适的术语表示歉意:我注意到这个项目实际上充满了我认为不必要的信号/槽对。更准确地说:规定应用程序逻辑的类相互看到,公开一些公共方法来触发所需的过程就足够了,但是,尽管如此,这几乎总是使用信号和槽来实现(我在这里再说一遍) :即使没有来自 GUI 的输入)。鉴于我是 Qt 的新手,这样做是一个很好的做法吗?谢谢。

编辑:我报告的情况不包含来自计时器、线程或其他任何东西的信号。这家伙使用了信号和槽对,就像它是从类(例如 A 类到 B 类)的直接方法调用的替代

V.K*_*.K. 5

过度使用使用信号和槽是一种非常糟糕且不幸的是非常常见的做法。它隐藏了依赖关系,使代码难以调试,并且从长远来看基本上无法维护。不幸的是,许多程序员认为这是一个很好的做法,因为他们实现了“解耦”,这对他们来说似乎是一个圣杯。这是无稽之谈。

我并不是说你根本不应该使用信号和槽。我只是说你不应该过度使用它们。信号和槽是实现的完美工具观察者设计模式的完美工具,以实现“反应式”系统,其中对象对更改其状态的其他对象做出反应。只有这样才是信号和槽的正确使用。几乎所有其他对信号和槽的使用都是错误的。我见过的最极端的情况是通过信号槽连接实现 getter 函数。信号发送对变量的引用,槽用一个值填充它,然后返回到发射器。这太疯狂了!

您如何知道您的信号和槽正确实现了观察者模式?这些是我长期使用 Qt 的经验得出的经验法则:

  1. 信号的本质是发射器通过发送一些信号来公开宣布其状态已发生某种变化(信号始终是公共的 - 除非您使用私有类虚拟参数)。
  2. 发射器不关心谁是观察者或者是否存在任何观察者,即发射器不能以任何方式依赖于观察者。
  3. 建立或管理连接绝不是发射器的责任 - 永远不要这样做!连接/断开是观察者的责任(然后它通常连接到私有插槽)或某个知道发射器和观察者两者存在的父对象的责任(在这种情况下,共同的父对象将发射器的信号连接到观察者)公共插槽)。

您会在 GUI 层中看到大量信号槽连接是正常的,这是完全可以的(注意:GUI 层包括视图模型!)。这是因为 GUI 通常是一个反应式系统,其中对象对其他对象或底层的某些变化做出反应。但是您可能会在业务逻辑层中看到更少的信号槽连接(顺便说一句,在许多项目中,业务逻辑是在不使用 Qt 的情况下进行编码的)。

关于命名:我遇到了一种有趣的代码味道。当观察者的公共(!)槽被称为onSomethingHappened()- 时,强调前缀on。这几乎总是不良设计和滥用信号和槽的迹象。通常这个槽应该a)设为私有,并且连接应该由观察者建立,或者b)应该重命名为doSomething()或c)应该重命名并且应该作为正常方法调用,而不是使用信号和槽。

并说明为什么过度使用信号和槽难以维护。从长远来看,有许多潜在的问题可能会破坏您的代码:

  1. 信号和槽的依赖关系通常隐藏在代码中看似不相关的遥远部分。当发射器实际上依赖于观察器时,这与信号槽滥用有关,但在查看发射器的代码时并不清楚。如果您的类依赖于其他一些类/模块,则这种依赖关系应该是明确且清晰可见的。
  2. 当信号和槽通过代码以编程方式连接然后断开时,您通常会陷入忘记断开连接而现在有多个连接的状态。拥有多个连接经常被忽视,因为它通常不会造成任何损害,它只会使代码稍微变慢,即更改的文本会更新多次而不是只更新一次 - 除非您有一千倍的连接,否则没有人会发现这个问题。这些乘法连接有点类似于内存泄漏。小内存泄漏通常不会被注意到,这与多个连接类似。
  3. 您经常会依赖于建立连接的顺序。当这些依赖于顺序的连接在代码的遥远部分建立时,你就会遇到大麻烦,这段代码迟早会崩溃。

要检查我是否没有多个连接或者连接/断开连接是否成功,我正在使用这些我的帮助实用程序https://github.com/vladimir-kraus/qtutils/blob/main/qtutils/safeconnect.h

PS:在上面的文本中,我使用术语“发射器”(发射信号)和“观察者”(观察发射器并接收信号)。有时人们使用“发送者”和“接收者”来代替。我的目的是强调这样一个事实:发射器发出信号时实际上并不知道是否有人接收到它。“发送者”一词给人的印象是您将信号发送给某人,但这正是信号槽过度使用和不良设计的原因。因此,在我看来,使用“发送者”只会导致混乱。通过使用“观察者”,我想强调信号和槽是实现观察者设计模式的工具。

PPS:信号和槽也是 Qt 中线程之间异步通信的完美工具。这个用例可能是我上面描述的原则的极少数例外之一。