LINUX.ORG.RU

Что плохого в сигнало-слотах?


0

0

Читаю "QT Профессиональное программирование на C++" Шлее. Там так вкусно рассказывается про сигнало-слоты, что непонятно как вообще все без них обходятся. Однако обходятся. И вроде бы не любят. В связи с этим два вопроса: собственно сабж и как обходятся без сигнало-слотов в других гуях (в том же gtk например)?

★★★★★

Плохо в них то, что они являются костылем для того, что должно было бы делаться средствами языка, но не делается ввиду его убогости.

Кастую гика в тред! Let's flame begin!

pained
()
Ответ на: комментарий от pained

Не готов спорить что в плюсах не реализована передача событий. Не понмаю что плохого в том чтобы реализовать её в рамках отдельно взятой библиотеки? Не stlем единым...

KblCb ★★★★★
() автор топика

>как обходятся без сигнало-слотов в других гуях (в том же gtk например)?

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

dmitry_vk ★★★
()
Ответ на: комментарий от dmitry_vk

>В Gtk+ другая реализация системы событий (на основе сигналов и обработчиков сигналов). Кстати, более правильная, как мне кажется.

То что другая итак понятно. Как она выглядит?

KblCb ★★★★★
() автор топика

Честно говоря так и не осилил что такое сигналы/слоты в Qt(если кто кинет линком на русском языке - буду рад), в Gtk же все довольно просто и понятно. Есть сигнал и есть его обработчик.. В делфи, кстати также..

mono ★★★★★
()
Ответ на: комментарий от mono

>Опять ты за свое?

модель сообщений Tk как была одной из лучших, так ею и остаётся по сей день, хочешь ты того или нет. M$ до подобной системы в своём WFP додумалась всего пару лет назад, ну а всяким Qt/GTK+ остаётся только завидовать

касательно Reactive даже говорить не буду, всё равно не поймёшь же

jtootf ★★★★★
()
Ответ на: комментарий от KblCb

>Как она выглядит?

У каждого класса имеется определенный набор сигналов. Сигнал описывается именем и сигнатурой. На сигнал объекта можно навесить обработчик (а также снимать их, блокировать и разблокировать). Обработчик задается либо указателем на сишную функцию (у которой сигнатура совпадает с сигнатурой сигнала и плюс есть дополнительный параметр void * data), либо замыканием (что позволяет языкам высокого уровня легко и непринужденно вешать обработчики, заданные любым образом).

У каждого класса вседа заданы сигналы для нотификации об изменении свойств.

>модель сообщений Tk как была одной из лучших, так ею и остаётся по сей день .... Qt/GTK+ остаётся только завидовать


Не совсем понятно, чем Tk'шная модель сообщений отличается от Gtk+'шной. Насчет Qt все ясно, там сигнал можно привязать только к методу класса.

В чем такая разница между следующими кусками кода? (для Gtk+ используется мой лисповский биндинг)
Tk:
bind .$buttonName <Button-3> "puts \"$buttonText\""
cl-gtk2:
(connect-signal label "clicked" (lambda (b) (print button-text)))

dmitry_vk ★★★
()
Ответ на: комментарий от dmitry_vk

Гм... Не готов спорить что эта схема чем-то хуже сигналов и слотов. Вижу только одно преимущество: сигнал в qt должен принимать сигналослот, а какому-нибудь перлопитону будет довольно сложно объяснить что это такое. С другой стороны сигналослоты кажутся интуитивно понятнее и читабельнее что ли.

KblCb ★★★★★
() автор топика
Ответ на: комментарий от dmitry_vk

>В чем такая разница между следующими кусками кода?

между этими - никакой. а если вывести, скажем, координаты нажатия?

jtootf ★★★★★
()
Ответ на: комментарий от jtootf

(connect-signal widget "button-press-event"
   (lambda (widget event)
      (format t "x = ~A y = ~A~%" (gdk:event-button-press-x event)
                                  (gdk:event-button-press-y event))))

k_andy ★★★
()
Ответ на: комментарий от KblCb

Ограничением системы сигналов-слотов кроме невозможности использовать в качестве слота функцию не член класса также является невозможность передачи слоту дополнительных параметров. На псевдокоде:

connect(widget, SIGNAL(signal()), target, SLOT(bind(slot(int), x));

т.е. чтобы при генерировании сигнала signal() на объекте widget вызывался слот slot объекта target с аргументом x.

Begemoth ★★★★★
()
Ответ на: комментарий от jtootf

> между этими - никакой. а если вывести, скажем, координаты нажатия?

Если разницы никакой, то чем же модель сигналов Tk лучше модели
сигналов Gtk+ (на самом деле, это не модель сигналов Gtk+,
а модель сигналов Glib)?

То есть от сравнения «моделей сообщений» Tk и Gtk+ плавно перешли
к сравнению конкретных сигналов, т.е. к сравнению библиотеки
виджетов?

В любом случае, вот код, выводящий координаты нажатия кнопки мышки:
(connect-signal widget "button-press-event"
                (lambda (widget event)
                  (when (= 0 (event-button-button event))
                    (format t "~A, ~A" (event-button-x event) (event-button-y y)))))

Интересно посмотреть, как выглядит Tk'шный код.

dmitry_vk ★★★
()
Ответ на: комментарий от Begemoth

>Ну ещё в догонку - слотами являются только специально указанные функции члены класса, а не все.

Ну в этом то вообще нет ничего плохого. Это вроде за ради инкапсуляции. Разве что наследование от QObject не всегда удобно.

KblCb ★★★★★
() автор топика

Абсолютно ничего. Единственная "некрасивость", это то, что connect принимает в качестве параметров строки const char*, описывающие сигнатуры сигнала и слота. Сделано это для большей гибкости и напрягать может лишь эстетствующих гомосексуалистов, т.к. на производительности практически не сказывается.

mannaz
()
Ответ на: комментарий от dmitry_vk

>(connect-signal widget "button-press-event"
                (lambda (widget event)
                  (when (= 0 (event-button-button event))
                    (format t "~A, ~A" (event-button-x event) (event-button-y y)))))

>Интересно посмотреть, как выглядит Tk'шный код.

bind $widget <ButtonPress-1> { puts "%x, %y" }

>То есть от сравнения «моделей сообщений» Tk и Gtk+ плавно перешли
к сравнению конкретных сигналов, т.е. к сравнению библиотеки
виджетов?

сигналы Tk - это сигналы Tk. модель писалась именно для библиотеки
виджетов, и рассматриваю я её именно подобным образом. конкретный
сигнал я привёл в качестве примера, эквивалентный код на Qt или GTK+
(не CL-GTK) будет куда как сложней. разве нет?

собственно, рассматриваемый в данном случае аспект - возможность
использовать неявно передаваемые параметры события плюс отсутствие
необходимости привязывать событие к делегату какого-либо
фиксированного качества (объекту, функции, etc), кроме возможности
этот самый делегат выполнить. впрочем, CL в этом плане значительно
упрощает работу с GTK+, тут не спорю ни разу

jtootf ★★★★★
()
Ответ на: комментарий от mannaz

>напрягать может лишь эстетствующих гомосексуалистов

тоньше надо, тоньше

jtootf ★★★★★
()
Ответ на: комментарий от KblCb

>Ну в этом то вообще нет ничего плохого. Это вроде за ради инкапсуляции. Разве что наследование от QObject не всегда удобно.

на самом деле это всё очень плохо - и не в инкапсуляции дело. это автоматически означает, что использовать в качестве приёмника сигнала готовую сишную или плюсовую библиотеку нельзя. её надо допиливать, наследовать классы от QObject (а если там шаблоны? а сигналы с шаблонами не очень хорошо работают, да), явно объявлять все слоты. либо писать прослойку - Qt'шный фасад, делегирующий вызовы. в общем, code reuse наоборот

jtootf ★★★★★
()
Ответ на: комментарий от jtootf

Я чего-то не понял... Qt при передаче сигналов активно использует в качестве параметров свои классы (QString как минимум и т.д.), а тебя не устраивает, что нельзя привязать к этим сигналам "готовую сишную или плюсовую библиотеку" без проксей и фасадов? Или тебе не нравится, что нельзя пользоваться Qt-шными сигналами/слотами вне контекста Qt? Проблема надуманна от начала и до конца.

mannaz
()
Ответ на: комментарий от mannaz

>Или тебе не нравится, что нельзя пользоваться Qt-шными сигналами/слотами вне контекста Qt?

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

>Qt при передаче сигналов активно использует в качестве параметров свои классы

а это тут при чём?

>Проблема надуманна от начала и до конца

кесарю - кесарево. я не мазохист, предпочитаю простые решения сложным. в Qt - сложно. в GTK+ получше, но всё равно сложно. а ради чего?

jtootf ★★★★★
()
Ответ на: комментарий от k_andy

>В GTK+ на столько просто на сколько позволяет C.

да. что и хорошо, и плохо. впрочем, скорее хорошо - потому как даёт возможность избавляться от недостатков с помощью высокоуровневых байндингов вроде CL-GTK

jtootf ★★★★★
()
Ответ на: комментарий от k_andy

>Если б оно выгрядело не так страшно...

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

и я не виноват, что большинство программистов на Tcl/Tk так любят Motiff. любовь сия загадочна и необъяснима - как, впрочем, и всякая другая любовь, надо полагать :)

jtootf ★★★★★
()
Ответ на: комментарий от jtootf

> потому как даёт возможность избавляться от недостатков с помощью высокоуровневых байндингов вроде CL-GTK
Дык в этом весь смысле. Гткшная модель, перенесенная на высокоуровневый язык - дает код, мало отличающийся по комфортабельности от Тк.

svu ★★★★★
()
Ответ на: комментарий от svu

>Дык в этом весь смысле. Гткшная модель, перенесенная на высокоуровневый язык - дает код, мало отличающийся по комфортабельности от Тк.

это ужасно. в предыдущем треде меня убедили попробовать ридер-макры, здесь почти уже убедили написать что-то на CL-GTK. к чему вы меня склоняете, изверги?

jtootf ★★★★★
()
Ответ на: комментарий от jtootf

> а это тут при чём?

Объясняю:

> ...это автоматически означает, что использовать в качестве приёмника сигнала готовую сишную или плюсовую библиотеку нельзя. её надо допиливать, наследовать классы от QObject... ...либо писать прослойку - Qt'шный фасад, делегирующий вызовы...

Ты не находишь, что это несколько странно - требовать от фреймворка, чтобы его сигналы типа fileReleased(const QString&) без всяких проксей и фасадов свободно коннектились с обработчиками типа removeFile(const string&)? Тип string можешь заменить на тип строк из Xerces, на тип строк из COM/ATL, прости Господи...

Ответь, пожалуйста, на два вопроса: 1. Приходилось ли тебе участвовать в крупных проектах, связанных с разработкой на C++? 2. Если "да", то приходилось ли тебе наблюдать как серьезные библиотеки типа ICU или того же Xerces одновременно без всяких посредников легко и непринужденно интегрировались в код этого проекта?

mannaz
()
Ответ на: комментарий от mannaz

> что это несколько странно - требовать от фреймворка, чтобы его сигналы типа fileReleased(const QString&) без всяких проксей и фасадов свободно коннектились с обработчиками типа removeFile(const string&)?
Ни разу не странно. Это было б естественно, если б кутя не изобретала велосипеды на каждый чих. Впрочем, это общая болезнь многих плюсовых фреймворков. Нет строки, кроме const char* (и двоично совместимых с ней). Если мы не говорим о высокоуровневых языках, к которым плюсы не относятся.

svu ★★★★★
()
Ответ на: комментарий от mannaz

>Ты не находишь, что это несколько странно - требовать от фреймворка

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

положительный пример в свете C++ - boost.signals, libsigc++. отрицательный - Qt

>1. Приходилось ли тебе участвовать в крупных проектах, связанных с разработкой на C++?

да. с использованием Qt в том числе

>приходилось ли тебе наблюдать как серьезные библиотеки...одновременно без всяких посредников легко и непринужденно интегрировались в код этого проекта?

да

jtootf ★★★★★
()
Ответ на: комментарий от svu

>Ну нельзя ж так... Это лор. Тут только и занимаются тем, что советуют дурное.

неправда, я всегда советую только лучшее! :)))

jtootf ★★★★★
()
Ответ на: комментарий от svu

> Ни разу не странно

Очень даже странно

> ...высокоуровневых языках, к которым плюсы не относятся

Это уже вопрос религии

mannaz
()
Ответ на: комментарий от jtootf

Исключение только подтверждает правило;)

svu ★★★★★
()
Ответ на: комментарий от mannaz

Это вопрос определений. Язык, в котором возможен прямой доступ к памяти - не высокоуровневый. Язык, в котором нет определения класса строки на уровне языка - не высокоуровневый.

svu ★★★★★
()
Ответ на: комментарий от jtootf

Тогда приведи конкретный пример проблемы/неудобства с Qt, а заодно пример совместного использования ICU и Xerces (или чего-нибудь подобного, использующего различные классы для представления, например, строк) без посредников.

mannaz
()
Ответ на: комментарий от svu

> Язык, в котором возможен прямой доступ к памяти - не высокоуровневый

Это ОЧЕНЬ вопрос религии

mannaz
()
Ответ на: комментарий от jtootf

Надо рассматривать сигналы Qt только в рамках самого Qt .
T.e. для коммуникации между объектами внутри фрэймворка .
Ведь другие реализации использовать никто не запрещал ,
сигналы Qt прекрасно работают с boost.signals , хотя вторые
не thread safe , но недвано вышла boost.signals2

Кстати если использовать PyQt , то многие ограничения снимаются :-)

kitov ★★★
()
Ответ на: комментарий от mannaz

>Тогда приведи конкретный пример проблемы/неудобства с Qt

не Qt, а реализации событий в Qt. в качестве примера можешь переписать вывод координат щелчка мыши по окошку - там выше были версии на CL-GTK и Tcl/Tk. сравнишь соотношение затрачиваемых усилий и полученного результата

>а заодно пример совместного использования ICU и Xerces (или чего-нибудь подобного, использующего различные классы для представления, например, строк)

ICU я не использовал (и не представляю даже что это такое), xerces использовал так давно, что плохо помню подробности :) однако в качестве хорошо интегрирующегося фреймворка лови ICE:

http://zeroc.com/ice.html

ну и, например, Snack:

http://www.speech.kth.se/snack/

jtootf ★★★★★
()
Ответ на: комментарий от kitov

>Надо рассматривать сигналы Qt только в рамках самого Qt

ну, собственно, в этом и заключается недостаток. сигналы/слоты Qt - это не реализация событий для C++, а реализация событий для Qt. минусы очевидны, а вот плюсы...надо думать. какой-то прок с этого должен быть, но невооружённым глазом он не очень заметен

>недвано вышла boost.signals2

спасибо за новость, надо будет посмотреть

>Кстати если использовать PyQt , то многие ограничения снимаются :-)

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

jtootf ★★★★★
()

Ух ты! Сколько специалистов-то собралось. А кто что скажет про "модель делегирования событий" в Java?

Ian ★★
()
Ответ на: комментарий от Ian

>Ух ты! Сколько специалистов-то собралось

дык пятница же

>А кто что скажет про "модель делегирования событий" в Java?

не видел, не знаю. если расскажешь - можно будет и её покритиковать :)

jtootf ★★★★★
()
Ответ на: комментарий от jtootf

Нужно добавить в класс этого окна метод

[code] void mouseClickEvent (QMouseEvent *event) { QDebug() << event->x() << event->y(); } [/code]

Честно говоря, я не вижу в этом каких-то специфических усилий. Другое дело, что в Qt озвученная задача не имеет никакого отношения к сигналам/слотам - кто-то из нас, похоже, не до конца понимает их реального назначения.

Ладно, ерунда это все на самом деле. Либы посмотрю, спасибо.

mannaz
()
Ответ на: комментарий от mannaz

> [code] void mouseClickEvent (QMouseEvent *event) { QDebug() << event->x() << event->y(); } [/code]
А еще там можно использовать анонимные классы;)

svu ★★★★★
()
Ответ на: комментарий от mannaz

>Нужно добавить в класс этого окна метод

это-то тут при чём? ок, выбери любую другую задачу, более подходящую для использования сигналов и сравнимую по величине с указанной

и в Tk, и в GTK+ эту задачу тоже можно решить ещё двумя-тремя методами, но мы-то обсуждаем сигналы, не?

>кто-то из нас, похоже, не до конца понимает их реального назначения

слушай, достал. у тебя от уровня ЧСВ позвоночник не прогибается? есть что сказать по существу - говори

jtootf ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.