Когда использовать сигналы и слоты, а когда нет

Мы используем Qt, который предлагает сигналы и слоты, которые я считаю очень удобными. Однако, с большой силой приходит большая ответственность, и я думаю, что это очень легко злоупотреблять этой функцией.

Есть ли какие-либо передовые методы использования сигнала-слота? Таким образом, мне сложно найти некоторые общие рекомендации. Некоторые вопросы (у меня есть четкие мнения, но не все члены моей команды согласны):

  • Можно ли использовать сигналы для сообщения об ошибках?
  • Можно ли предположить, что сигнал будет обработан?
  • Можно ли использовать сигналы для инициирования действий? Например. signal displayInfoScreen() должен обрабатываться слотом, отображающим информационный экран.

Любые другие мнения о том, когда сигналы должны/не должны использоваться, очень приветствуются!

5 ответов

Можно ли использовать сигналы для отчета ошибки?

Да, например, см. QFtp, где выполненный сигнал имеет статус. Он не несет фактическую ошибку, просто информацию о том, что произошла ошибка.

Можно ли предположить, что сигнал будет обрабатываться?

Нет. Отправитель никогда не может предположить, что, однако, ваше конкретное приложение может зависеть от него. Например, QAction, представляющий File-New, нужно обрабатывать для работы приложения, но объект QAction не волнует.

Сигналы могут использоваться для инициирования действия? Например. сигнал displayInfoScreen() должен обрабатываться слот, который отображает информационный экран.

Опять же, да, например, объект QAction. Но если вы хотите иметь возможность повторно использовать компоненты, вы должны быть осторожны, чтобы гарантировать, что фактический класс не зависит от него.


Сигналы и слоты мощные, потому что отделяют объекты. Вы не можете предположить, что сигнал имеет слот, как было сказано ранее.

Основной недостаток дизайна на основе сигнала/слота заключается в том, что вы можете очень легко избавиться от логики, которую вы реализовали, поскольку одно действие объекта может инициировать другие действия любого другого объекта, который подключен к выдается сигнал. Гораздо легче иметь нежелательные побочные эффекты, рекурсивные вызовы и т.д.


Можно ли предположить, что сигнал будет обработан?

Нет, нет. Сигналы являются огнем и забывают о вещах. Кто подключается к сигналу и что он делает, не должен быть проблемой эмитентов.


Можно ли использовать сигналы для сообщения об ошибках?

Да, но я обычно делал бы эту ситуацию зависимой. Если ошибка может возникать асинхронно, тогда сигнал, указывающий на это, определенно является правильным. Если ошибка возникает только тогда, когда клиентский код вызывает одну определенную функцию, тогда ошибка должна быть в ответе от этой функции, а не как сигнал. Однако между ними существует множество различных ситуаций, которые могут выполняться в каждом конкретном случае.

Кроме того, механизмы сигнальных слотов могут облегчить межпоточную связь (что вполне можно рассматривать как асинхронный случай), и я буду использовать их для этой цели (ошибка или нет).

Можно ли предположить, что сигнал будет обработан?

Сигналы (философски) предназначены для обозначения того, что что-то произошло. Как указывали другие, никогда не рекомендуется предполагать, что сигнал будет согласован с слотом или даже с одним другим слотом.

Можно ли использовать сигналы для инициирования действий? Например. сигнал displayInfoScreen() должен обрабатываться слотом, который отображает информационный экран.

Сигналы могут использоваться для инициирования действий, но, вероятно, не так, как вы думаете. Сигнал указывает на то, что произошло foo. Если код, контролирующий ваш класс, решает, что, когда происходит foo, необходимо показать диалог, затем сигнал был использован для инициирования этого действия. Однако, как правило, не ответственность класса, излучающего сигнал, чтобы обеспечить надлежащее действие, поскольку оно не несет ответственности за выполнение этого действия. (Если это так, то оно должно быть частью одного и того же класса, и никакой сигнал не понадобится.)


Сигналы/слоты (также называемые событиями) - хороший способ удаления связи между объектами.

Например, вместо того, чтобы иметь представления, которые понимают, как работает модель, и когда модель изменяется, они "слушают" модель. Модель отвечает за то, что она изменится, что изменится.

Проблема с событиями - это когда вы разрабатываете свои события с требованиями клиента. Например, вы не должны иметь сигнал displayInfoScreen, потому что он предполагает что-то об объектах, использующих этот сигнал. Вместо этого он должен быть infoChanged, а InfoScreenDisplayer прослушивает эти сигналы, чтобы отобразить его на экране. Если вам нужно, вы можете добавить позже InfoTweeterPoster, которые публикуют информацию о Tweeter всякий раз, когда они меняются.

licensed under cc by-sa 3.0 with attribution.