Russian Qt Forum
Ноябрь 22, 2024, 17:57 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: 1 2 3 [4] 5   Вниз
  Печать  
Автор Тема: Паттерн наблюдатель  (Прочитано 38006 раз)
Racheengel
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2679


Я работал с дискетам 5.25 :(


Просмотр профиля
« Ответ #45 : Апрель 11, 2016, 02:12 »

Эмитируем из загрузчика onProgress (this).
И после каждого такого сигнала, на стороне получателя, пытаемся понять, а что же там у загрузчика изменилось (он загрузил еще один кусок файла или начал загрузку другого файла, а может он закончил загрузку файла). Улыбающийся
И все это только что бы иметь один сигнал вместо 4-5, четко сообщающих что происходит? Улыбающийся

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

What is the 11 in the C++11? It’s the number of feet they glued to C++ trying to obtain a better octopus.

COVID не волк, в лес не уйдёт
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #46 : Апрель 11, 2016, 07:54 »

Зачем что либо диалогу понимать вообще?
Он получил сигнал, вытащил по this то, что он хочет показать - имя текущего файла, кол.во загруженных байт, ну еще там кол.во файлов и т.д., отрисовал все это и ждет себе дальше следующего сигнала.
Ну тут кто как больше привык. Улыбающийся
Я предпочитаю несколько разных сигналов, несущих в себе информацию о произошедшем событии, со всеми необходимыми данными. IMHO, с несколькими разными сигналами проще обрабатывать происходящее. Например, мы хотим после загрузки каждого файла, посчитать его контрольную сумму и отобразить ее в диалоге прогресса. Тогда по сигналу загрузчик finishedFile, мы можем легко запустить процесс расчета контрольной суммы.

И несколько сигналов с параметрами упрощают взаимодействие между объектами загрузчика и диалога, если они живут в разных потоках. Послали сигнал и забыли. А с указателем, нужно проверить, что загрузчик еще жив и все публичные методы, придется защищать средствами синхронизации.
« Последнее редактирование: Апрель 11, 2016, 07:57 от Old » Записан
Racheengel
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2679


Я работал с дискетам 5.25 :(


Просмотр профиля
« Ответ #47 : Апрель 11, 2016, 08:39 »

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

What is the 11 in the C++11? It’s the number of feet they glued to C++ trying to obtain a better octopus.

COVID не волк, в лес не уйдёт
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #48 : Апрель 11, 2016, 08:50 »

Ну, если нужна реакция на конкретное событие, а не общий прогресс, то сигналы самое оно, согласен.
Хотя мы немного от темы отошли, вроде был вопрос, как сделать без сигналов.
Но это такое уже. От фреймворка зависеть будет имхо.
На самом деле это легко можно сделать на чистом C++, но это будет чуть многословней, чем через сигналы.
Сигналы как раз для упрощения таких вещей и придумывались. Улыбающийся
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #49 : Апрель 11, 2016, 09:45 »

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

Он получил сигнал, вытащил по this то, что он хочет показать - имя текущего файла, кол.во загруженных байт, ну еще там кол.во файлов и т.д.,
Какой this, откуда Вы его возьмете (для подачи индикатору) в каждой конкретной ситуации которых десятки? Пример
Код
C++ (Qt)
std::vector<Vertex>  ReadVertices( Model * model )
{
std::vector<Vertex> dst;  
size_t count = model->numVertices();
emit someSignal(???);   // (стартуем) что здесь?
for (size_t i = 0; i < count; ++i) {
 DoReadVer(i, dst);
 emit someSignal_2(???);   // (апдейтим) что здесь? И где cancel ?
}
emit someSignal_3(???);   // (завершаем) а если ушли по exception из DoReadVer ?
return dst;
}
 
Все наоборот, интерфейс должен предоставлять индикатор
Код
C++ (Qt)
std::vector<Vertex>  ReadVertices( Model * model )
{
std::vector<Vertex> dst;  
size_t count = model->numVertices();
UserIndicator indicator("Reading Vertices", "Step", 0, count);
for (size_t i = 0; i < count; ++i) {
 DoReadVer(i, dst]);
 indicator.Update(1);
 if (indicator.IsCancel()) break;
}
// ~UserIndicator  
return dst;
}
 
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #50 : Апрель 11, 2016, 09:58 »

Есть программы где нет GUI, от слова совсем. А один и тот же код загрузчика мы должны уметь использовать как в программах с GUI, там и без него.
Зачем мне в рабочем коде какие-то индикаторы, которые ничего умного для рабочего процесса не делают?
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #51 : Апрель 11, 2016, 10:10 »

Есть программы где нет GUI, от слова совсем. А один и тот же код загрузчика мы должны уметь использовать как в программах с GUI, там и без него.
На это и нацелено. Надеюсь понятно что UserIndicator - отнюдь не диалог.

Зачем мне в рабочем коде какие-то индикаторы, которые ничего умного для рабочего процесса не делают?
Ну это вряд ли, хотя бы без cancel обычно не прожить.

Вот вот, какое то гипертрофированое раздувание из мухи слона) И я так и не понял, почему, конкрено, патерн обсёрвер плох в данной ситуации? 
Покажите как это будет выглядеть для примера ReadVertices выше
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #52 : Апрель 11, 2016, 10:23 »

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

Покажите как это будет выглядеть для примера ReadVertices выше

Код
C++ (Qt)
class VertexLoader
{
public:
   VertexLoader() : m_canceled( false ) {}
 
   void load( Model *model )
   {
       size_t count = model->numVertices();
       emit started( count );
       for( size_t i = 0; i < count; ++i )
       {
           DoReadVer( i, m_data );
           emit update( i );
           if( m_canceled ) break;
       }
   }
 
signals:
   void started( size_t cnt );
   void update( size_t cur );
   void finished();
 
public slots:
   void cancel()
   {
       m_canceled = true;
   }
 
private:
   std::vector<Vertex> m_data;
   bool m_canceled;
};
 

Код
C++ (Qt)
VertexLoader ldr;
ProgressDialog dlg;
 
connect( &ldr, SIGNAL(started(size_t)), &dlg, SLOT(started(size_t)) );
connect( &ldr, SIGNAL(update(size_t)), &dlg, SLOT(update(size_t)) );
connect( &ldr, SIGNAL(finished()), &dlg, SLOT(finished()) );
 
connect( &dlg, SIGNAL(pressCancel()), &ldr, SLOT(cancel()) );
 
Записан
ssoft
Программист
*****
Offline Offline

Сообщений: 584


Просмотр профиля
« Ответ #53 : Апрель 11, 2016, 11:57 »

Не могу понять предмет спора. Чей подход лучше? По мне, так нет никакой разницы, каждый опирается на свои требования к коду и конкретизацию задачи.
Передали this - получили гибкость, скорость, вязкость кода и проблемы при асинхронной работе (необходимость синхронизации).
Реализовали через signal-slot - получили модульность, больше кода, небольшую приторможенность (в GUI совсем незаметную), возможное копирование данных, неудобство взаимосвязи между объектами разных иерархических уровней.
Взяли за основу, например, конечные автоматы - получили другие достоинства и недостатки.
Можно реализовать и через периодический опрос загрузчика по таймеру со своим геморроем.

Любой из вариантов верный, если решает задачу в рамках заданных требований.

Если требование - решить задачу за 5 минут при том со всеми фенечками, то загрузчик вообще будет частью диалога и вся реализация будет в одном файле. Если нужна асинхронная загрузка от GUI, то, например, использование this уже будет не удобно и будет ваяться concurrent, signal-slot, model-controller-view их суперпозиция или еще что-то. Нет единственно верного подхода, и в любой работе всегда действует правило треугольника время - качество - ресурсы, всего должно быть достаточно, а идеальный случай недостижим.
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #54 : Апрель 11, 2016, 12:14 »

Не могу понять предмет спора.
Топик как раз создан чтобы обсудить возможные варианты решения и найти их сильные и слабые стороны. Их и обсуждаем. Улыбающийся
Записан
ssoft
Программист
*****
Offline Offline

Сообщений: 584


Просмотр профиля
« Ответ #55 : Апрель 11, 2016, 13:12 »

Если не изменяет память, изначально вопрос состоял как-то так

... А как бы вы это сделали без Qt только на C++? Только идея интересует. boost:signals, собственный велосипед или еще что-то ...

Почему тогда обсуждаем Qt signal-slot, его возможности и преимущества?
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #56 : Апрель 11, 2016, 13:26 »

Почему тогда обсуждаем Qt signal-slot, его возможности и преимущества?
Нет. Qt-сигналы здесь не обсуждаются, я уже не раз это подчеркивал.
Под "сигналом" подразумевается информирование одним объектом другого о изменении своего состояния. Какой механизм будет выбран для этого не так важно, важно о каких событиях стоит сообщать и какие данные с этими событиями передавать.
Записан
Racheengel
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2679


Я работал с дискетам 5.25 :(


Просмотр профиля
« Ответ #57 : Апрель 11, 2016, 13:59 »

Еще один "быстрый" Улыбающийся Не должно UI дергаться на каждый чих, эдак все время уйдет в индикатор (как нередко бывает).

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

this - это поинтер на загрузчик. Он же предоставляет интерфейс для опроса своего текущего состояния.

Все наоборот, интерфейс должен предоставлять индикатор

Это с какого перепуга? Загрузчику вообще все равно, есть индикатор или нет. Его задача - загружать.
Основное правило: индикатор не может существовать без загрузчика -> следовательно, индикатор - это подчиненный. А значит, он и должен получать инфу от загрузчика, а не загрузчик должен знать о (возможно несуществующем) индикаторе.
Записан

What is the 11 in the C++11? It’s the number of feet they glued to C++ trying to obtain a better octopus.

COVID не волк, в лес не уйдёт
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #58 : Апрель 11, 2016, 14:01 »

Это с какого перепуга? Загрузчику вообще все равно, есть индикатор или нет. Его задача - загружать.
Думаю скоро Igors замутит голосование по этому вопросу. Улыбающийся
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #59 : Апрель 11, 2016, 14:15 »

Код
C++ (Qt)
class VertexLoader
{
public:
   VertexLoader() : m_canceled( false ) {}
...
 
Вот, вместо скромной ф-ции мы уже соорудили целый класс Улыбающийся  А ведь использующих индикатор много десятков - и что, все их переводить в такие классы? Ну это просто нереально, да и выглядит совсем уж глупо  Улыбающийся. Кстати QObject наверное нужен если есть сигналы.

И, что интересно, никакого выгодного ф-ционала этим не достигается. Скорее наоборот - хоть тот же m_canсel, куда легче было спросить его у интерфейса индикатора в любой момент. Сигналы сделаны в предположении на один индикатор. Хорошо, пусть даже один (для показа) - но ведь следующий не обязан начинаться только по окончании предыдущего, т.е. возможен стек. Чтобы это изменить - потребуются еще сигналы. Получилось что-то типа дешифратора, вместо 4 бит - 16 проводов  Улыбающийся А finished вообще не наблюдаю, как и отработку исключения.

Из этого вовсе не следует что "слот/сигнал = плохо", просто здесь он неуместен. Напр когда Qt испускает что-то типа itemChanged, то испускающий не имеет понятия кто и что будет с ним делать. Действительно, тогда лучше испустить, и пусть кому надо разбирается. А здесь-то все определено и известно, поэтому гораздо выгоднее и проще иметь интерфейс с которым можно полноценно общаться.

Не могу понять предмет спора. Чей подход лучше? По мне, так нет никакой разницы, каждый опирается ...
Вероятно такой "диалектический" подход основан на предположении что.. ну ведь это жалкий (смехотворный и.т.п) индикатор прогресса, ну какие здесь могут быть проблемы/тонкости? Да как угодно можно сделать! Во всяком случае я думал примерно так (пока не дошло др дела/реализации  Улыбающийся)
Записан
Страниц: 1 2 3 [4] 5   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.501 секунд. Запросов: 23.