Название: Паттерн наблюдатель Отправлено: Vamireh от Апрель 07, 2016, 09:03 Есть класс по загрузке неких файлов, например. В нем есть сигнал, который информирует о проценте загрузке. В слоте, соответственно, меняется значение QProgressBar. А как бы вы это сделали без Qt только на C++? Только идея интересует. boost:signals, собственный велосипед или еще что-то.
Также интересны ответы в случае, когда файл в структуру грузит функция C в dll, а прогрессбар должен меняться в приложении C#, например. Просто понял, что меня бы подобная задача озадачила бы слегка. Коряво, сделал бы, но интересно как это сделают гуру. Название: Re: Паттерн наблюдатель Отправлено: Igors от Апрель 07, 2016, 09:57 Паттерн наблюдатель здесь явно избыточен. Нормально напр так
Код Ну конечно вызывающий не знает что делают UpdateProgress/Indicator - может рисует окно, может печатает в консоль а может и вообще ничего. А в реализации этих классов уже заниматься конкретикой. Да, и особой выгоды от слот/сигналов здесь не видно Название: Re: Паттерн наблюдатель Отправлено: ViTech от Апрель 07, 2016, 11:36 Есть класс по загрузке неких файлов, например. В нем есть сигнал, который информирует о проценте загрузке. В слоте, соответственно, меняется значение QProgressBar. А как бы вы это сделали без Qt только на C++? Только идея интересует. boost:signals, собственный велосипед или еще что-то. Вроде всё правильно, сами на свой вопрос и ответили :). Считаю, что паттерн применяется по назначению, а его реализацию выбирайте ту, которая лучше всего подходит для вашего проекта. Если уже используется boost, то, возможно, и нет причин отказываться от boost:signals. Есть и другие библиотеки, которые реализуют "сигнал-слот". Если совсем всё глобально, может и свой велосипед написать стоит. Также интересны ответы в случае, когда файл в структуру грузит функция C в dll, а прогрессбар должен меняться в приложении C#, например. Тут уже вопрос сопряжения двух миров. Соответственно и реализация паттерна должна иметь возможность работы в разных средах. Возможно к существующим реализациям нужно добавить какую-нибудь прослойку, ретранслятор, который будет пересылать сигналы из одной среды в другую. Просто понял, что меня бы подобная задача озадачила бы слегка. Коряво, сделал бы, но интересно как это сделают гуру. Если задача озадачивает лишь слегка, значит есть силы самостоятельно её решить :). Название: Re: Паттерн наблюдатель Отправлено: ssoft от Апрель 07, 2016, 11:41 Вариантов решения масса, все зависит от дополнительных требований.
1. Синхронная или асинхронная работа компонентов (например, загрузчика и графического интерфейса). 2. Событийная или распределенная модель обмена данными. 3. Модульность Эти требования определяют выбор паттерна, который целесообразно использовать. Синхронность/асинхронность определяется однопоточностью или многопоточностью программы. Событийность предполагает передачу событий в виде данных или их копии (события/сообщения/данные сигналов) актуальной на момент события. Распределенная модель может подразумевать доступ к распределенным данным, актуальным на момент обращения к ним, а не на момент события. Модульность - следствие личного опыта и требований к легкости дальнейшей модификации и сопровождения ПО. Самый простой и быстрый вариант (с нуля) - синхронная событийная модель, которая в зависимости от необходимой модульности (возможной "вязкости" кода) может быть сведена: - к явным вызовам API одного компонента из другого (подавляющее число реализаций, плохо сопровождаемый код), - к модели наблюдателя (подписка на события, уже лучше), - к модели сигнал-слот boost, Qt (взаимосвязь независимых модулей, еще лучше), - к чему-те еще Все варианты правильные, выбор зависит от разработчика (его опыта) и решаемой задачи. Если задача комплексная (например, загрузка файлов мешает отображению GUI и/или наоборот), то необходимо уже смотреть в сторону асинхронной модели поведения - асинхронный сигнал слот - модель актеров - активные объекты - что-то еще выбор за Вами ... Название: Re: Паттерн наблюдатель Отправлено: Igors от Апрель 07, 2016, 12:43 - к модели сигнал-слот boost, Qt (взаимосвязь независимых модулей, еще лучше), А что тут "еще лучше"? :) Принципиально важна независимость от реализации индикатора, это легко обеспечить. Может еще кто-то может (или должен) ловить испускаемый сигнал? Не видно таких вариантов. Вместо упора на "священную корову" слот/сигнала лучше тщательнее продумать интерфейс (что должен получать индикатор), там не так уж мало данных Название: Re: Паттерн наблюдатель Отправлено: Old от Апрель 07, 2016, 13:10 Принципиально важна независимость от реализации индикатора, это легко обеспечить. Это сейчас ТС хочет просто показать индикатор выполнения, а завтра ему понадобиться эти файлы патчить в процессе загрузки.Сядем и придумаем еще один интерфейс для этого или сразу подумаем и сделаем универсально? Название: Re: Паттерн наблюдатель Отправлено: ssoft от Апрель 08, 2016, 08:25 А что тут "еще лучше"? :) ... Вместо упора на "священную корову" слот/сигнала лучше тщательнее продумать интерфейс (что должен получать индикатор), там не так уж мало данных Как раз сигнал слот не священен ;) Это просто более гибкий механизм взаимодействия, чем паттерн наблюдателя, так как не требует прямых или косвенных взаимосвязей между типами объектов, участвующих во взаимодействии. Если говорить о реализации сигнал-слот взаимодействия в Qt, то наследование от QObject - ооочень неудачное решение), но это всего лишь одна из возможных. Название: Re: Паттерн наблюдатель Отправлено: Racheengel от Апрель 08, 2016, 10:34 Принципиально важна независимость от реализации индикатора, это легко обеспечить. Это сейчас ТС хочет просто показать индикатор выполнения, а завтра ему понадобиться эти файлы патчить в процессе загрузки.Сядем и придумаем еще один интерфейс для этого или сразу подумаем и сделаем универсально? https://en.wikipedia.org/wiki/You_aren't_gonna_need_it Я тоже не вижу, для чего тут нужен обсервер. Подхода Игоря вполне достаточно. Название: Re: Паттерн наблюдатель Отправлено: Old от Апрель 08, 2016, 10:43 Я тоже не вижу, для чего тут нужен обсервер. Подхода Игоря вполне достаточно. А что вы подразумеваете под обсервером?В контексте этого обсуждения "обсервером" может быть просто вызов сигнала. Я только предложил не затачивать его интерфейс только для индикации процесса выполнения, а продумать более универсальное решение. Что сделать совсем не сложно. Название: Re: Паттерн наблюдатель Отправлено: Igors от Апрель 08, 2016, 10:52 Хорошо, пусть нет никаких ограничений на использование Qt и/или буста, используйте что хотите (если в этом счастье). Но вот индикатор нужен "мульти" (этажерка из 2 и более бегунков по вертикали). Это типовая вещь, масса приложений (начиная с самого OC) такие индикаторы делает.
Ваши действия? (кроме поисков "готового решения") Название: Re: Паттерн наблюдатель Отправлено: Old от Апрель 08, 2016, 11:05 Хорошо, пусть нет никаких ограничений на использование Qt и/или буста, используйте что хотите (если в этом счастье). Но вот индикатор нужен "мульти" (этажерка из 2 и более бегунков по вертикали). Это типовая вещь, масса приложений (начиная с самого OC) такие индикаторы делает. Вот об этом я и говорю. Нужно хорошо продумать те события, о которых будет сообщать загрузчик файлов.Ваши действия? (кроме поисков "готового решения") А реализовать диалог с двумя progressbar совсем не сложно. В начале загрузки загрузчик посылает сигнал, где сообщает общий размер всех файлов и их количество. Дальше запускается загрузка файлов. В начале загрузки каждого файла загрузчик посылает сигнал с именем файла, его порядковым номером и размером, а в процессе загрузки периодически посылается сигнал о прогрессе его загрузки. При завершении загрузки каждого файла, посылается сигнал о завершении с передачей его имени и порядкового номера. Этого достаточно для вышеописанной задачи, а также становится доступно выводить прогресс не по размеру, а по целым файлам. Название: Re: Паттерн наблюдатель Отправлено: Igors от Апрель 08, 2016, 12:17 ...загрузчик посылает сигнал, где сообщает .. Типа "главное - сигнал (залог успеха)". А по мне его роль здесь очень скромная - ну разве что "развязаться" из др нитки, т.е. "обертка", не более того. И чего это "двумя" (progressbar)? А для 3 что, "сядем придумаем еще сигналы"? Зачем завязываться на то что второй - суб-процесс первого? Это может быть напр независимое параллельное копирование (или зипирование) файлов/фолдеров, ..загрузчик посылает сигнал с именем файла, ... ..периодически посылается сигнал о прогрессе .. ...посылается сигнал о завершении .. Поэтому вместо беготни с сигналами лучше заняться выделением тех самых "сущностей". Напр я четко вижу сущность "индикатор" (бегунок) которых может быть 2 и более. Но заниматься этим никто не хочет. Вот хапнуть готовый класс, переписать примерчик - то да! А остальное - так себе, "свой велосипед" :) Название: Re: Паттерн наблюдатель Отправлено: Bepec от Апрель 08, 2016, 12:23 Бгг, Igors в своём репертуаре. Давайте вместо передачи 4 байт информации напишем класс индикатора, ползунка, индикатора-ползунка, контейнер общий для них и вариативность постройки диалога вплоть до 256 индикаторных ползунков.
Ну и что, что нужно будет максимум 3-5, зато получится идеально, хотяяя... а вдруг ещё ползунковый цветовой информатор с обратной связью нужен будет :D Название: Re: Паттерн наблюдатель Отправлено: Old от Апрель 08, 2016, 12:34 Типа "главное - сигнал (залог успеха)". Вовсе нет. Сигнал здесь это способ информирования других объектов о изменении состояния текущего. Не более.Как этот "сигнал" будет реализован дело 10 и совершенно не интересное. Это могут быть сигналы Qt или буста, а может сигналы DBus или обычная std::function, а может это будет объект класса Listener... А по мне его роль здесь очень скромная - ну разве что "развязаться" из др нитки, т.е. "обертка", не более того. Точно.И чего это "двумя" (progressbar)? А для 3 что, "сядем придумаем еще сигналы"? Зачем завязываться на то что второй - суб-процесс первого? Это может быть напр независимое параллельное копирование (или зипирование) файлов/фолдеров, А я не на что и не завязывался. Вы захотели два progressbar - с моими сигналами это легко сделать, захочет человек один бар по общему размеру - легко, захочет по количеству файлов - пожалуйста. А может он захочет патчить или проверять загруженные данные совместно с отображение прогресса - ну так сколько угодно.Поэтому вместо беготни с сигналами лучше заняться выделением тех самых "сущностей". Напр я четко вижу сущность "индикатор" (бегунок) которых может быть 2 и более. Но заниматься этим никто не хочет. Вот хапнуть готовый класс, переписать примерчик - то да! А остальное - так себе, "свой велосипед" :) Четко видите сущность индикатор? А мне он сейчас не нужен. Я не хочу показывать прогресс выполнения, а хочу рассчитывать и отображать контрольные суммы загруженных файлов.... В каком месте мне эту "четко видимую сущность" нужно использовать? :)Название: Re: Паттерн наблюдатель Отправлено: Igors от Апрель 08, 2016, 13:52 Вы захотели два progressbar - с моими сигналами это легко сделать, захочет человек один бар по общему размеру - легко, захочет по количеству файлов - пожалуйста. Та неужели? Вот Вы сказали магическое слово "сигнал", и, о чудо, весь ф-ционал волшебным образом появился!! Наверное так работают "Ваши" сигналы, о которых мне ничего не известно :)Название: Re: Паттерн наблюдатель Отправлено: Old от Апрель 08, 2016, 13:59 Та неужели? Вот Вы сказали магическое слово "сигнал", и, о чудо, весь ф-ционал волшебным образом появился!! Наверное так работают "Ваши" сигналы, о которых мне ничего не известно :) Так работают любые "сигналы". Главное хорошо продумать: когда, где и с какими параметрами их вызывать.Название: Re: Паттерн наблюдатель Отправлено: Racheengel от Апрель 08, 2016, 16:02 Я только предложил не затачивать его интерфейс только для индикации процесса выполнения, а продумать более универсальное решение. Что сделать совсем не сложно. Но зачем? И "универсальное" относительно чего? Задача поставлена, по моему, ясно: Цитировать Есть класс по загрузке неких файлов, например. В нем есть сигнал, который информирует о проценте загрузке. то есть единственное, что ожидает получатель - это сигнал вроде Done(int percent), где percent будет меняться от 0 до 100. Если это делать через "обсервер" - то надо регистрировать соответствующий интерфейс для класса, который загружает файлы (чтобы знал, для кого вызывать Done). Если делать через сигнал-слот - то не надо. Достаточно будет emit Done(currentProgress). А кто и как будет реагировать на этот сигнал - дело десятое. Название: Re: Паттерн наблюдатель Отправлено: Old от Апрель 08, 2016, 16:05 Достаточно будет emit Done(currentProgress). А кто и как будет реагировать на этот сигнал - дело десятое. Как вы видите этого не достаточно для запрошенного Igors двухбарного диалога.Название: Re: Паттерн наблюдатель Отправлено: ViTech от Апрель 08, 2016, 18:08 то есть единственное, что ожидает получатель - это сигнал вроде Done(int percent), где percent будет меняться от 0 до 100. Если это делать через "обсервер" - то надо регистрировать соответствующий интерфейс для класса, который загружает файлы (чтобы знал, для кого вызывать Done). Если делать через сигнал-слот - то не надо. Достаточно будет emit Done(currentProgress). А кто и как будет реагировать на этот сигнал - дело десятое. А сигнал-слот на магии работает? ;) И внутри нет никакого аналога "обсервера"? Название: Re: Паттерн наблюдатель Отправлено: Racheengel от Апрель 08, 2016, 23:33 Достаточно будет emit Done(currentProgress). А кто и как будет реагировать на этот сигнал - дело десятое. Как вы видите этого не достаточно для запрошенного Igors двухбарного диалога.Я отвечал исходя из первоначальной задачи ;) Хорошо... расширим сигнал Done до 2 параметров, 1 это общий процент, 2 это процент загрузки текущего файла... Название: Re: Паттерн наблюдатель Отправлено: Racheengel от Апрель 08, 2016, 23:36 Цитата: ViTech link=topic=30002.msg220823#msg220823 А сигнал-слот на магии работает? ;) И внутри нет никакого аналога "обсервера"? В этом ифишка, что внутренняя реализация в этом случае не важна ;) Может там и модель с обсерверами внутри и сидит, но она используется неявно, и юзеру не обязательно про это думать. Название: Re: Паттерн наблюдатель Отправлено: Old от Апрель 09, 2016, 08:04 Хорошо... расширим сигнал Done до 2 параметров, 1 это общий процент, 2 это процент загрузки текущего файла... А какое имя у "текущего файла"?Мы передали загрузчику файлов список имен. Как нам узнать какой файл он сейчас загружет? Название: Re: Паттерн наблюдатель Отправлено: Igors от Апрель 09, 2016, 10:01 А какое имя у "текущего файла"? Загрузчик это прекрасно знает - на то он и загрузчик. А вот индикатор нет, поэтому загрузчик должен ему это передать. Также одной строкой обычно отделаться не удается, выплывает вторая типа "units". Напр прогресс может отображаться в %, Kb, Mb. Плюс число шагов. Мы передали загрузчику файлов список имен. Как нам узнать какой файл он сейчас загружет? По поводу настойчивого (мягко говоря) использования именно сигналов. В примере что я привел удачно обыгрываются деструкторы объявленных классов. Не нужно заботиться о connect. И вообще вызывающий может ничего не знать о Qt. Если же нужно QueuedСonnection, то его удобно реализовать в самих классах индикатора. В этом ифишка, что внутренняя реализация в этом случае не важна ;) Ах как приятно отбрыкнуться от всего, мол, "это несущественные детали реализации" :) Только вот готовой этажерки что-то не видать, и придется ее рисовать самому. Так сказать, заняться "логикой гуя" :)Название: Re: Паттерн наблюдатель Отправлено: Old от Апрель 09, 2016, 10:16 А вот индикатор нет, поэтому загрузчик должен ему это передать. Бинго. А в предложенных вами и Racheengel решениях, я этого что-то не наблюдаю. :)Также одной строкой обычно отделаться не удается, выплывает вторая типа "units". Напр прогресс может отображаться в %, Kb, Mb. Плюс число шагов. А это избыточно. Мы работаем с файлами, поэтому размера в байтах будет достаточно, а зная общий размер и загруженный легко вычислить процент.По поводу настойчивого (мягко говоря) использования именно сигналов. В примере что я привел удачно обыгрываются деструкторы объявленных классов. Не нужно заботиться о connect. И вообще вызывающий может ничего не знать о Qt. Если же нужно QueuedСonnection, то его удобно реализовать в самих классах индикатора. А вы все продолжаете воспринимать "сигналы" как Qt-сигналы? Напрасно, не нужно так зашториваться. :)Название: Re: Паттерн наблюдатель Отправлено: Igors от Апрель 09, 2016, 10:39 А это избыточно. Мы работаем с файлами, поэтому размера в байтах будет достаточно, а зная общий размер и загруженный легко вычислить процент. А для объектов (исчисляемых штуками) уже придется что-то менять? Узковато спланировано, я бы даже сказал - недальновидно :)Бинго. А в предложенных вами и Racheengel решениях, я этого что-то не наблюдаю. :) Так посмотрите первый ответА вы все продолжаете воспринимать "сигналы" как Qt-сигналы? Напрасно, не нужно так зашториваться. :) "Зашориваться", грамотюй :)Название: Re: Паттерн наблюдатель Отправлено: Old от Апрель 09, 2016, 10:44 А для объектов (исчисляемых штуками) уже придется что-то менять? Узковато спланировано, я бы даже сказал - недальновидно :) Перечитайте мой вариант. :)Если пользователю нужно будет отображать прогресс пофайлово, ему достаточно подписаться на сигнал о завершении загрузки каждого файла. Так посмотрите первый ответ Смотрел. И судя по нему, вы не очень представляете, о чем мы говорим. :)У нас уже есть класс FileLoader: Код Нам нужен удобный и универсальный механизм, что бы отслеживать процесс загрузки (для отображения диалога в том числе). А как я буду использовать информацию о прогрессе (отображать бары или выводить в консоль) дело десятое. Поэтому, реализация диалога отображения прогресса в данной теме не интересно никому. :) "Зашориваться", грамотюй :) Ага. Когда по теме сказать нечего, начинаем придираться к словам. Ах этот интернет, он везде одинаковый. :) Название: Re: Паттерн наблюдатель Отправлено: Igors от Апрель 09, 2016, 18:29 Нам нужен удобный и универсальный механизм, что бы отслеживать процесс загрузки (для отображения диалога в том числе). К сожалению - да. Удобно и приятно говорить о "механизме", который (якобы) и является "самым-самым", а рисовать индикаторы - фу как пошло.А как я буду использовать информацию о прогрессе (отображать бары или выводить в консоль) дело десятое. Поэтому, реализация диалога отображения прогресса в данной теме не интересно никому. :) В действительности все точно наоборот. Как только определено "что нужно отображалке" - ни одной проблемы с использованием не вижу. Выбора-то здесь нет, кому нужен индикатор - тот его и создает. Отработал - удаляет. Если индикатору нужна строка(и) - создающий и должен ее обеспечить. То же и со счетчиком прогресса. Это простой и ясный интерфейс, пришивать сюда рукав слот/сигнала ни к чему. Зато хорошо спланировать сам прогресс (в том числе и UI) далеко не просто, и не такая уж рутинная работа как может показаться. Одним классом здесь не обойтись, нужно упр-е каждым индикатором. Добавляемые индикаторы нужно где-то хранить, как ни крути - выплывает еще класс типа Manager, возможно синглтон. Ну и разумеется используемые классы - совсем не UI, до конкретного QDialog там еще далеко. Тут есть о чем поговорить, но ..., согласен, это никому не интересно :) Название: Re: Паттерн наблюдатель Отправлено: Bepec от Апрель 09, 2016, 19:09 Оо синглтон для индикаторов... А можно пояснение - нафига он сдался там?
PS ну просто фантастика на мой взгляд. Название: Re: Паттерн наблюдатель Отправлено: Igors от Апрель 09, 2016, 19:35 Оо синглтон для индикаторов... А можно пояснение - нафига он сдался там? Уже пояснил - хотя бы потому что установки индикаторов надо где-то хранить.PS ну просто фантастика на мой взгляд. Ну вот нужно 2 (или более) индикаторов в 1 окне. Приплыли, попастись на QProgressDialog не удается. Начните делать, и, уверяю, фантастика очень быстро станет реальностью (суровой для Вас :))Название: Re: Паттерн наблюдатель Отправлено: Old от Апрель 09, 2016, 21:20 Тут есть о чем поговорить, но ..., согласен, это никому не интересно :) Так вы тему новую создайте и если кому-то будет интересно обсуждайте. Для чего в чужой теме обсуждать интересные для вас проблемы?Хотя обсуждать там нечего, даже с диалогом с десятью барами. Все сводится к рутиному и скучному гую. А за сингетон, да в таком случае, нужно сразу в разносчика кофе переводить. :) Название: Re: Паттерн наблюдатель Отправлено: Igors от Апрель 10, 2016, 10:41 А за сингетон, да в таком случае, нужно сразу в разносчика кофе переводить. :) Заучив правило (напр "синглтон = плохо"), догматик неуклонно ему следует - таково уж его мЫшление :) Бедный синглтон плох везде и всегда - потому что так заучили.Хорошо, допустим нам не нужны никакие этажерки (то уклонение от темы), QProgressDialog нас прекрасно устраивает. Но вот загрузка разбита на десятки более мелких операций которые выполняются одна за другой, со своим прогрессом каждая. И по-моему вполне разумно сделать глобальный указатель на QProgressDialog (читай - синглтон) чтобы не передавать его в десятки методов/ф-ций. Но "так низзя" (ведь синглтон - это плохо). Так что же нам делать чтобы "было хорошо"? :) Название: Re: Паттерн наблюдатель Отправлено: Old от Апрель 10, 2016, 10:52 Заучив правило (напр "синглтон = плохо"), догматик неуклонно ему следует - таково уж его мЫшление :) Бедный синглтон плох везде и всегда - потому что так заучили. А что это за правило такое: "синглетон = плохо"? Вы опять читали хабр?Хорошо, допустим нам не нужны никакие этажерки (то уклонение от темы), QProgressDialog нас прекрасно устраивает. Но вот загрузка разбита на десятки более мелких операций которые выполняются одна за другой, со своим прогрессом каждая. И по-моему вполне разумно сделать глобальный указатель на QProgressDialog (читай - синглтон) чтобы не передавать его в десятки методов/ф-ций. Но "так низзя" (ведь синглтон - это плохо). Так что же нам делать чтобы "было хорошо"? :) А для чего его передавать в десятки функций? Да еще и сделать его синглетоном, что бы не передавать на него ссылки? Это уже какое-то дно.Синглетон - это объект, который может существовать ТОЛЬКО в одном экземпляре. Это не в коем случае, не удобная точка доступа к объекту. А диалогов прогресса может быть много. А решается это все несколькими сигналами, которые методы объекта исполнителя будут посылать и объектом диалога, который их будет обрабатывать. Послал объект исполнитель сигнал started, в котором передал общее количество операций, диалог настроил общий бар. Послал объект исполнитель сигнал startedStage с длительностью конкретного этапа, диалог создал бар для этапа, пришел сигнал finishedStage - удалил бар для законченного этапа. Вы не свои сообщения читаете, пытаетесь их понять? Я это уже описывал выше. Название: Re: Паттерн наблюдатель Отправлено: Bepec от Апрель 10, 2016, 11:27 Igors - гениально. У вас в вашей программе будет.
1 исходные данные в системе обработки. 1 копия данных в синглтоне. 1 копия данных в каждом индикаторе/прогрессбаре. Вопрос - где лишнее? :D Название: Re: Паттерн наблюдатель Отправлено: Racheengel от Апрель 10, 2016, 13:15 Хорошо... расширим сигнал Done до 2 параметров, 1 это общий процент, 2 это процент загрузки текущего файла... А какое имя у "текущего файла"?Мы передали загрузчику файлов список имен. Как нам узнать какой файл он сейчас загружет? Изначальное ТЗ такого требования не содержало. Но если хотите велик на все случаи жизни, то ради бога. .. Эмитируем из загрузчика onProgress (this). Гуй по получению указателя на класс загрузки обращается к нему через публичный интерфейс и получает все необходимые данные. Только в обоих случаях придется все время что то где то дописывать, либо параметры сигнала расширять, либо интерфейс загрузчика. Где мы выигрываем? Название: Re: Паттерн наблюдатель Отправлено: Racheengel от Апрель 10, 2016, 13:19 И да, я тоже не понимаю смысл синглтона...
Пусть всем занимается логика конкретного гуя, загрузчику должно быть фиолетово, что да как там отображается. Название: Re: Паттерн наблюдатель Отправлено: Old от Апрель 10, 2016, 13:23 И да, я тоже не понимаю смысл синглтона... Потому что у Igors идея обратная, дать всем возможность управлять объектом ProgressDialog.Пусть всем занимается логика конкретного гуя, загрузчику должно быть фиолетово, что да как там отображается. Название: Re: Паттерн наблюдатель Отправлено: Old от Апрель 10, 2016, 13:35 Эмитируем из загрузчика onProgress (this). И после каждого такого сигнала, на стороне получателя, пытаемся понять, а что же там у загрузчика изменилось (он загрузил еще один кусок файла или начал загрузку другого файла, а может он закончил загрузку файла). :)И все это только что бы иметь один сигнал вместо 4-5, четко сообщающих что происходит? :) Название: Re: Паттерн наблюдатель Отправлено: Igors от Апрель 10, 2016, 18:52 А решается это все несколькими сигналами, которые методы объекта исполнителя будут посылать и объектом диалога, который их будет обрабатывать. Вот напр, следуя Вашим советам, мы написалиПослал объект исполнитель сигнал started, в котором передал общее количество операций, диалог настроил общий бар. Послал объект исполнитель сигнал startedStage с длительностью конкретного этапа, диалог создал бар для этапа, пришел сигнал finishedStage - удалил бар для законченного этапа. Код И типа "все хорошо", никаких зависимостей (якобы) нет, знай посылай сигналы - и дело в шляпе. Так это в теории :) Ничего хорошего здесь нет. Индикаторы могут создаваться очень многими классами, которым QObject нужен как собаке пятая нога, а то и просто ф-циями. Придется делать какой-то левый QObject (тем же синглтоном?) или "смешиваться" с boost::signal (число энтузиастов сокращается). Но то еще цветочки. Бросается в глаза уязвимость посылки - по имени файла (а как еще?). "Кому" это шлется? Сугубо частный случай: заведем сигнал для счетчика файлов и другой для текущего файла, - ну общность и расширяемость такого решения нулевые. Заметим также что finishedStage придется кропотливо отслеживать или навешивать какой-то "scoped". А зависимости никуда не делись - только теперь они не объявлены ясно в интерфейсе, а раскиданы там и сям по слотам и сигналам. Что же хорошего? Да ничего, слепое следование паттерну который считается "хорошим" :) И вообще, неплохо бы знать "предмет", или хотя бы иметь о нем понятие. ...диалог настроил общий бар. Ага, щас, побежал создавать/удалять/настраивать. Операции с длительностью меньше заданной (напр 0.5 сек) вообще не должны показываться, и удалять из UI надо c задержкой чтобы заново всякий раз не вставлять т.е. не мельтешить с диалогом. А значит исполнитель должен хранить список активных и по Update уже рулить всеми. ...диалог создал бар для этапа, ...удалил бар для законченного этапа. Название: Re: Паттерн наблюдатель Отправлено: Bepec от Апрель 10, 2016, 19:13 Igors во всей красе...
No comments. Название: Re: Паттерн наблюдатель Отправлено: Old от Апрель 10, 2016, 19:17 И типа "все хорошо", никаких зависимостей (якобы) нет, знай посылай сигналы - и дело в шляпе. Так это в теории :) Ничего хорошего здесь нет. Индикаторы могут создаваться очень многими классами, которым QObject нужен как собаке пятая нога, а то и просто ф-циями. Придется делать какой-то левый QObject (тем же синглтоном?) или "смешиваться" с boost::signal (число энтузиастов сокращается). Где что раскидано? Какие зависимости? :)Но то еще цветочки. Бросается в глаза уязвимость посылки - по имени файла (а как еще?). "Кому" это шлется? Сугубо частный случай: заведем сигнал для счетчика файлов и другой для текущего файла, - ну общность и расширяемость такого решения нулевые. Заметим также что finishedStage придется кропотливо отслеживать или навешивать какой-то "scoped". А зависимости никуда не делись - только теперь они не объявлены ясно в интерфейсе, а раскиданы там и сям по слотам и сигналам. Вы сейчас выдали кучу голословных проблем, которые есть в вашем восприятии. Кодом доказывайте, кодом. Где там раскиданы зависимости. :) Так же не понятно для чего в очередной раз притянуты сигналы Qt и буста. Не хотите не используйте. :) Что же хорошего? Да ничего, слепое следование паттерну который считается "хорошим" :) Какому паттерну? Вы мне хоть скажите, каким патерном я здесь пользуюсь. :)И вообще, неплохо бы знать "предмет", или хотя бы иметь о нем понятие. Я то знаю, не понятно вы тут что делаете? :)Ага, щас, побежал создавать/удалять/настраивать. Операции с длительностью меньше заданной (напр 0.5 сек) вообще не должны показываться, и удалять из UI надо c задержкой чтобы заново всякий раз не вставлять т.е. не мельтешить с диалогом. Так кто вам мешает сделать все так как вы описали. Правда не очень понятно откуда взялись эти "странные требования". :)А значит исполнитель должен хранить список активных и по Update уже рулить всеми. Для чего ему этот идиотизм. Исполнитель должен хорошо работу свою работать, а не думать как там ему диалоги обновлять, тем более никакого ГУЯ может не быть вообще. Опять все притащили в класс MainWindow.Название: Re: Паттерн наблюдатель Отправлено: m_ax от Апрель 10, 2016, 23:08 Перечитав 3 страницы я так и не понял, какой основной тезис у товарища igors.. В чём, собственно преимущества С-подхода по сравнению с патерном обсёрвера? Не, ну реально, может я, как всегда не допонимаю, но причём здесь конкретнгые реализации диалогов и т.д.. Речь о архитектуре, как поставил вопрос ТС. Какой механизм наиболее гибок и независим для данной ситуации. Т.е. у нас есть некая сущьность, которая выполняет свою работу - всё. Мы не хотим 100500 раз вмешиваться в её код) Как по мне, то основная проблема здесь в выделдении минимально необходимого интерфейса этого файллоудера с внешним миром.) В чём проблема?)
Название: Re: Паттерн наблюдатель Отправлено: Old от Апрель 10, 2016, 23:19 Как по мне, то основная проблема здесь в выделдении минимально необходимого интерфейса этого файллоудера с внешним миром.) В чём проблема?) Какой fileloader, он уходит на второй план, а на первый у нас выходит диалог прогресса. :)Для него мы искаверкаем ядро, "познакомим" с ним всех, кого только можно и научим fileloader его правильно вызывать, даже если диалог прогресса в большинстве случаев нафик никому будет не нужен. В общем, у нас новый MainWindow с именем ProgressDialog. :) Очередной пробой дна после Переходничка. ;D Название: Re: Паттерн наблюдатель Отправлено: m_ax от Апрель 10, 2016, 23:36 Как по мне, то основная проблема здесь в выделдении минимально необходимого интерфейса этого файллоудера с внешним миром.) В чём проблема?) Какой fileloader, он уходит на второй план, а на первый у нас выходит диалог прогресса. :)Для него мы искаверкаем ядро, "познакомим" с ним всех, кого только можно и научим fileloader его правильно вызывать, даже если диалог прогресса в большинстве случаев нафик никому будет не нужен. В общем, у нас новый MainWindow с именем ProgressDialog. :) Очередной пробой дна после Переходничка. ;D Вот вот, какое то гипертрофированое раздувание из мухи слона) И я так и не понял, почему, конкрено, патерн обсёрвер плох в данной ситуации? Название: Re: Паттерн наблюдатель Отправлено: Old от Апрель 10, 2016, 23:42 Вот вот, какое то гипертрофированое раздувание из мухи слона) И я так и не понял, почему, конкрено, патерн обсёрвер плох в данной ситуации? Да ничем он не плох.Дело в том, что в первом ответе было заявлено, что наблюдатель здесь избыточен, а теперь приходится выдумывать проблемы, что бы это хоть как-то оправдать. :) Название: Re: Паттерн наблюдатель Отправлено: m_ax от Апрель 11, 2016, 00:17 Цитировать Дело в том, что в первом ответе было заявлено, что наблюдатель здесь избыточен, а теперь приходится выдумывать проблемы, что бы это хоть как-то оправдать. Ну всё как обычно, да :)Название: Re: Паттерн наблюдатель Отправлено: Racheengel от Апрель 11, 2016, 02:12 Эмитируем из загрузчика onProgress (this). И после каждого такого сигнала, на стороне получателя, пытаемся понять, а что же там у загрузчика изменилось (он загрузил еще один кусок файла или начал загрузку другого файла, а может он закончил загрузку файла). :)И все это только что бы иметь один сигнал вместо 4-5, четко сообщающих что происходит? :) Зачем что либо диалогу понимать вообще? Он получил сигнал, вытащил по this то, что он хочет показать - имя текущего файла, кол.во загруженных байт, ну еще там кол.во файлов и т.д., отрисовал все это и ждет себе дальше следующего сигнала. Таким образом и загрузчик минимально модифицируется, и логика гуя находится в гуе. Разве что интерфейс чтения прогресса распухет со временем, но это уже задача программиста выделить в интерфейс все только необходимое. Название: Re: Паттерн наблюдатель Отправлено: Old от Апрель 11, 2016, 07:54 Зачем что либо диалогу понимать вообще? Ну тут кто как больше привык. :)Он получил сигнал, вытащил по this то, что он хочет показать - имя текущего файла, кол.во загруженных байт, ну еще там кол.во файлов и т.д., отрисовал все это и ждет себе дальше следующего сигнала. Я предпочитаю несколько разных сигналов, несущих в себе информацию о произошедшем событии, со всеми необходимыми данными. IMHO, с несколькими разными сигналами проще обрабатывать происходящее. Например, мы хотим после загрузки каждого файла, посчитать его контрольную сумму и отобразить ее в диалоге прогресса. Тогда по сигналу загрузчик finishedFile, мы можем легко запустить процесс расчета контрольной суммы. И несколько сигналов с параметрами упрощают взаимодействие между объектами загрузчика и диалога, если они живут в разных потоках. Послали сигнал и забыли. А с указателем, нужно проверить, что загрузчик еще жив и все публичные методы, придется защищать средствами синхронизации. Название: Re: Паттерн наблюдатель Отправлено: Racheengel от Апрель 11, 2016, 08:39 Ну, если нужна реакция на конкретное событие, а не общий прогресс, то сигналы самое оно, согласен.
Хотя мы немного от темы отошли, вроде был вопрос, как сделать без сигналов. Но это такое уже. От фреймворка зависеть будет имхо. Название: Re: Паттерн наблюдатель Отправлено: Old от Апрель 11, 2016, 08:50 Ну, если нужна реакция на конкретное событие, а не общий прогресс, то сигналы самое оно, согласен. На самом деле это легко можно сделать на чистом C++, но это будет чуть многословней, чем через сигналы.Хотя мы немного от темы отошли, вроде был вопрос, как сделать без сигналов. Но это такое уже. От фреймворка зависеть будет имхо. Сигналы как раз для упрощения таких вещей и придумывались. :) Название: Re: Паттерн наблюдатель Отправлено: Igors от Апрель 11, 2016, 09:45 ..отрисовал все это и ждет себе дальше следующего сигнала. Еще один "быстрый" :) Не должно UI дергаться на каждый чих, эдак все время уйдет в индикатор (как нередко бывает). См мой предыдущий постОн получил сигнал, вытащил по this то, что он хочет показать - имя текущего файла, кол.во загруженных байт, ну еще там кол.во файлов и т.д., Какой this, откуда Вы его возьмете (для подачи индикатору) в каждой конкретной ситуации которых десятки? ПримерКод Все наоборот, интерфейс должен предоставлять индикатор Код
Название: Re: Паттерн наблюдатель Отправлено: Old от Апрель 11, 2016, 09:58 Есть программы где нет GUI, от слова совсем. А один и тот же код загрузчика мы должны уметь использовать как в программах с GUI, там и без него.
Зачем мне в рабочем коде какие-то индикаторы, которые ничего умного для рабочего процесса не делают? Название: Re: Паттерн наблюдатель Отправлено: Igors от Апрель 11, 2016, 10:10 Есть программы где нет GUI, от слова совсем. А один и тот же код загрузчика мы должны уметь использовать как в программах с GUI, там и без него. На это и нацелено. Надеюсь понятно что UserIndicator - отнюдь не диалог.Зачем мне в рабочем коде какие-то индикаторы, которые ничего умного для рабочего процесса не делают? Ну это вряд ли, хотя бы без cancel обычно не прожить.Вот вот, какое то гипертрофированое раздувание из мухи слона) И я так и не понял, почему, конкрено, патерн обсёрвер плох в данной ситуации? Покажите как это будет выглядеть для примера ReadVertices выше Название: Re: Паттерн наблюдатель Отправлено: Old от Апрель 11, 2016, 10:23 Ну это вряд ли, хотя бы без cancel обычно не прожить. А cancel легко делается с сигналами.Покажите как это будет выглядеть для примера ReadVertices выше Код
Код
Название: Re: Паттерн наблюдатель Отправлено: ssoft от Апрель 11, 2016, 11:57 Не могу понять предмет спора. Чей подход лучше? По мне, так нет никакой разницы, каждый опирается на свои требования к коду и конкретизацию задачи.
Передали this - получили гибкость, скорость, вязкость кода и проблемы при асинхронной работе (необходимость синхронизации). Реализовали через signal-slot - получили модульность, больше кода, небольшую приторможенность (в GUI совсем незаметную), возможное копирование данных, неудобство взаимосвязи между объектами разных иерархических уровней. Взяли за основу, например, конечные автоматы - получили другие достоинства и недостатки. Можно реализовать и через периодический опрос загрузчика по таймеру со своим геморроем. Любой из вариантов верный, если решает задачу в рамках заданных требований. Если требование - решить задачу за 5 минут при том со всеми фенечками, то загрузчик вообще будет частью диалога и вся реализация будет в одном файле. Если нужна асинхронная загрузка от GUI, то, например, использование this уже будет не удобно и будет ваяться concurrent, signal-slot, model-controller-view их суперпозиция или еще что-то. Нет единственно верного подхода, и в любой работе всегда действует правило треугольника время - качество - ресурсы, всего должно быть достаточно, а идеальный случай недостижим. Название: Re: Паттерн наблюдатель Отправлено: Old от Апрель 11, 2016, 12:14 Не могу понять предмет спора. Топик как раз создан чтобы обсудить возможные варианты решения и найти их сильные и слабые стороны. Их и обсуждаем. :)Название: Re: Паттерн наблюдатель Отправлено: ssoft от Апрель 11, 2016, 13:12 Если не изменяет память, изначально вопрос состоял как-то так
... А как бы вы это сделали без Qt только на C++? Только идея интересует. boost:signals, собственный велосипед или еще что-то ... Почему тогда обсуждаем Qt signal-slot, его возможности и преимущества? Название: Re: Паттерн наблюдатель Отправлено: Old от Апрель 11, 2016, 13:26 Почему тогда обсуждаем Qt signal-slot, его возможности и преимущества? Нет. Qt-сигналы здесь не обсуждаются, я уже не раз это подчеркивал.Под "сигналом" подразумевается информирование одним объектом другого о изменении своего состояния. Какой механизм будет выбран для этого не так важно, важно о каких событиях стоит сообщать и какие данные с этими событиями передавать. Название: Re: Паттерн наблюдатель Отправлено: Racheengel от Апрель 11, 2016, 13:59 Еще один "быстрый" :) Не должно UI дергаться на каждый чих, эдак все время уйдет в индикатор (как нередко бывает). И не будет. Индикатор сам должен решать, как часто ему апдейтиться. Например, каждый десятый сигнал, или 2 раза в секунду - это с загрузчиком никак не связано. Какой this, откуда Вы его возьмете (для подачи индикатору) в каждой конкретной ситуации которых десятки? this - это поинтер на загрузчик. Он же предоставляет интерфейс для опроса своего текущего состояния. Все наоборот, интерфейс должен предоставлять индикатор Это с какого перепуга? Загрузчику вообще все равно, есть индикатор или нет. Его задача - загружать. Основное правило: индикатор не может существовать без загрузчика -> следовательно, индикатор - это подчиненный. А значит, он и должен получать инфу от загрузчика, а не загрузчик должен знать о (возможно несуществующем) индикаторе. Название: Re: Паттерн наблюдатель Отправлено: Old от Апрель 11, 2016, 14:01 Это с какого перепуга? Загрузчику вообще все равно, есть индикатор или нет. Его задача - загружать. Думаю скоро Igors замутит голосование по этому вопросу. :)Название: Re: Паттерн наблюдатель Отправлено: Igors от Апрель 11, 2016, 14:15 Код
И, что интересно, никакого выгодного ф-ционала этим не достигается. Скорее наоборот - хоть тот же m_canсel, куда легче было спросить его у интерфейса индикатора в любой момент. Сигналы сделаны в предположении на один индикатор. Хорошо, пусть даже один (для показа) - но ведь следующий не обязан начинаться только по окончании предыдущего, т.е. возможен стек. Чтобы это изменить - потребуются еще сигналы. Получилось что-то типа дешифратора, вместо 4 бит - 16 проводов :) А finished вообще не наблюдаю, как и отработку исключения. Из этого вовсе не следует что "слот/сигнал = плохо", просто здесь он неуместен. Напр когда Qt испускает что-то типа itemChanged, то испускающий не имеет понятия кто и что будет с ним делать. Действительно, тогда лучше испустить, и пусть кому надо разбирается. А здесь-то все определено и известно, поэтому гораздо выгоднее и проще иметь интерфейс с которым можно полноценно общаться. Не могу понять предмет спора. Чей подход лучше? По мне, так нет никакой разницы, каждый опирается ... Вероятно такой "диалектический" подход основан на предположении что.. ну ведь это жалкий (смехотворный и.т.п) индикатор прогресса, ну какие здесь могут быть проблемы/тонкости? Да как угодно можно сделать! Во всяком случае я думал примерно так (пока не дошло др дела/реализации :))Название: Re: Паттерн наблюдатель Отправлено: Old от Апрель 11, 2016, 14:23 Вот, вместо скромной ф-ции мы уже соорудили целый класс :) Конечно, мы же здесь на C++ пишем, а это объектно-ориентированный язык (обратите внимание на выделенное слово). :)А ведь использующих индикатор много десятков - и что, все их переводить в такие классы? Ну это просто нереально, да и выглядит совсем уж глупо :). Кстати QObject наверное нужен если есть сигналы. Это выглядит глупо только для вас. А QObject не нужен, мы это уже два или три раза выше прошли. Вы уже забыли? :)И, что интересно, никакого выгодного ф-ционала этим не достигается. Достигается. :)Скорее наоборот - хоть тот же m_canсel, куда легче было спросить его у интерфейса индикатора в любой момент. Нет, это глупо, что-то спрашивать в асинхронной системе.Сигналы сделаны в предположении на один индикатор. Хорошо, пусть даже один (для показа) - но ведь следующий не обязан начинаться только по окончании предыдущего, т.е. возможен стек. Сигналов старт может прийти несколько, если работа выполняется в несколько потоков и никаких новых сигналов, кроме описанных мной ранее для FileLoader не понадобиться.А finished вообще не наблюдаю, как и отработку исключения. А сможете сами догадаться, куда вставить emit finished? :)Из этого вовсе не следует что "слот/сигнал = плохо", просто здесь он неуместен. Из этого ничего не следует, потому что ни одной проблемы вы привести так и не смогли. :)Во всяком случае я думал примерно так (пока не дошло др дела/реализации :)) Так у вас получилось или вы еще реализуете? ;DНазвание: Re: Паттерн наблюдатель Отправлено: Igors от Апрель 11, 2016, 14:29 И не будет. Индикатор сам должен решать, как часто ему апдейтиться. Например, каждый десятый сигнал, или 2 раза в секунду - это с загрузчиком никак не связано. И я того же мнения - но тогда не надо утверждать "получил сигнал - отрисовал"Все наоборот, интерфейс должен предоставлять индикатор Это с какого перепуга? Загрузчику вообще все равно, есть индикатор или нет. Его задача - загружать.Основное правило: индикатор не может существовать без загрузчика -> следовательно, индикатор - это подчиненный. А значит, он и должен получать инфу от загрузчика, а не загрузчик должен знать о (возможно несуществующем) индикаторе. Название: Re: Паттерн наблюдатель Отправлено: Igors от Апрель 11, 2016, 14:39 Нет, это глупо, что-то спрашивать в асинхронной системе. Как ни странно, флажок отмены не требует никаких средств синхронизации, достаточно его отдавать простым геттером. Так иногда бывает :)Название: Re: Паттерн наблюдатель Отправлено: Old от Апрель 11, 2016, 14:41 Как ни странно, флажок отмены не требует никаких средств синхронизации, достаточно его отдавать простым геттером. Так иногда бывает :) Ну и что? :)Название: Re: Паттерн наблюдатель Отправлено: Bepec от Апрель 11, 2016, 16:33 Спор глухого с умным. Результат примерно тот же в этой теме :D
offtop: я предрекаю что тема загнётся через день :D Название: Re: Паттерн наблюдатель Отправлено: Racheengel от Апрель 11, 2016, 16:46 Да, загрузчик керует, вот он и пишет данные в интерфейс предоставляемый индикатором. Откуда загрузчику знать, что где-то существует какой-то индикатор? Это проблема индикатора - получить данные от загрузчика. Умеет загрузчик слать сигналы - вешаемся на сигналы. Умеет загрузчик только DoUpdate(this) - следим за его интерфейсом. Думайте о загрузчике, как о "черном ящике", тогда все станет на места. Название: Re: Паттерн наблюдатель Отправлено: Igors от Апрель 11, 2016, 17:43 Откуда загрузчику знать, что где-то существует какой-то индикатор? Попробуйте изобразить это для примера ReadVertices выше. Ну хоть "схематично" (я без понятия как реализовать Ваше предложение) Это проблема индикатора - получить данные от загрузчика. Думайте о загрузчике, как о "черном ящике", тогда все станет на места. Зато с раздачей рекомендаций все отлично :)Название: Re: Паттерн наблюдатель Отправлено: Vamireh от Апрель 13, 2016, 14:06 Я что-то уже запутался. Если не рассматривать асинхронность, то все к callback'ам сводится, получается?
А вот подход с опросом по таймеру из GUI встречал неоднократно у коллег. Название: Re: Паттерн наблюдатель Отправлено: Igors от Апрель 15, 2016, 11:32 Я что-то уже запутался. Если не рассматривать асинхронность, то все к callback'ам сводится, получается? По таймеру это другой ф-ционал/подход. Здесь индикатор знает подробности выполняемой операции (обычно в др нитке), положительная сторона - операции ничего самой делать не нужно. Отрицательная - плохо с общностью, нужно приспосабливать индикатор к каждой операции.А вот подход с опросом по таймеру из GUI встречал неоднократно у коллег. Название: Re: Паттерн наблюдатель Отправлено: _Bers от Апрель 21, 2016, 00:27 Есть класс по загрузке неких файлов, например. В нем есть сигнал, который информирует о проценте загрузке. В слоте, соответственно, меняется значение QProgressBar. А как бы вы это сделали без Qt только на C++? Только идея интересует. boost:signals, собственный велосипед или еще что-то. Также интересны ответы в случае, когда файл в структуру грузит функция C в dll, а прогрессбар должен меняться в приложении C#, например. Просто понял, что меня бы подобная задача озадачила бы слегка. Коряво, сделал бы, но интересно как это сделают гуру. как то так: http://rextester.com/CEHV62401 Код: //g++ 4.9.3 output: Цитировать Hello, world! loading ... 0% loading ... 10% loading ... 20% loading ... 30% loading ... 40% loading ... 50% loading ... 60% loading ... 70% loading ... 80% loading ... 90% loading abort! |