Когда использовать сигналы и слоты, а когда нет - PullRequest
23 голосов
/ 24 февраля 2010

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

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

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

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

Ответы [ 5 ]

12 голосов
/ 24 февраля 2010

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

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

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

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

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

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

12 голосов
/ 24 февраля 2010

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

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

10 голосов
/ 24 февраля 2010

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

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

5 голосов
/ 24 февраля 2010

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

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

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

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

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

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

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

3 голосов
/ 24 февраля 2010

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

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

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

...