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

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

Страниц: 1 [2] 3   Вниз
  Печать  
Автор Тема: Большой switch  (Прочитано 14331 раз)
sergek
Гипер активный житель
*****
Offline Offline

Сообщений: 872


Мы должны приносить пользу людям.


Просмотр профиля
« Ответ #15 : Декабрь 25, 2014, 12:28 »

Я понял, но ф-ция копирования не особо лепится внутри класса, т.к. он должен знать про SaveUndo, UpdateUI и др - а это к нему отношения не имеет.
Не проблема - вынесите их в отдельный класс(ы) с интерфейсными методами. Будут работать с какими-то глобальными объектами.
Свитч - всегда причина задуматься.
Записан

Qt 5.13.0 Qt Creator 5.0.1
Win10, Ubuntu 20.04
Bepec
Гость
« Ответ #16 : Декабрь 25, 2014, 12:42 »

Я с одним коллегой спорил на протяжении примерно 3 месяцев и ниразу он не смог предложить решения элегантнее и понятнее чем простой свич. Постоянно уходило в сторону шаблонов, фабрик, десятка другого классов с контролями ошибок и прочим. В результате свич на 4 действия превращался в монстра.
Поэтому я скептически отношусь к такого рода спорам.

Свич заменить можно, но только в единичных случаях это оправданно. ИМХО
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #17 : Декабрь 25, 2014, 12:46 »

Я понял, но ф-ция копирования не особо лепится внутри класса, т.к. он должен знать про SaveUndo, UpdateUI и др - а это к нему отношения не имеет.
Не проблема - вынесите их в отдельный класс(ы) с интерфейсными методами. Будут работать с какими-то глобальными объектами.
Не очень представляю как это. Можно (псевдо) код? Спасибо

switch простейший паттерн множественного ветвления. ...
Я искренне наслаждался почти полным отсутствием Ваших постов в течение последней пары месяцев. Увы, все хорошее так быстро кончается   Плачущий
Записан
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2094



Просмотр профиля
« Ответ #18 : Декабрь 25, 2014, 13:23 »

Как альтернативу полиморфизму, можно использовать связку boost::variant  + соответствующий визитёр visitor

Код
C++ (Qt)
struct ID_ENABLED{};
struct ID_COUNT{};
...
 
class switch_visitor : public boost::static_visitor<>
{
public:
   void operator()(ID_ENABLED) const
   {
       // бла-бла-бла
   }
 
   void operator()(ID_COUNT) const
   {
       // бла-бла-бла
   }
 
   // и т.д.
};
 
 
boost::variant<ID_ENABLED, ID_COUNT> id = ID_COUNT();
 
 
boost::apply_visitor(switch_visitor(), id);
 

В конструктор визитора можно передавать какие-либо доп. параметры и п.р.
Пример с variant нужно воспринимать просто как альтернативу, для "подумать", возможно, подсмотреть какие-то известные решения (иначе всё "мировоззрение" так и останется замкнутым на одном лишь свитче).
Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #19 : Декабрь 25, 2014, 14:00 »

Код
C++ (Qt)
struct ID_ENABLED{};
struct ID_COUNT{};
...
 
class switch_visitor : public boost::static_visitor<>
{
public:
   void operator()(ID_ENABLED) const
   {
       // бла-бла-бла
   }
 
   void operator()(ID_COUNT) const
   {
       // бла-бла-бла
   }
 
   // и т.д.
};
 
 
boost::variant<ID_ENABLED, ID_COUNT> id = ID_COUNT();
 
 
boost::apply_visitor(switch_visitor(), id);
 
Конечно всех деталей я не понял, но что меня смущает - классов/типов уже немало, а вот откуда возьмется нужный ф-ционал - хз. Напр UpdateUI удобно иметь методом окна, а в др методе (того же окна) сидит большой switch. Все норм. Но вот мы хотим "классами" - и надо мучительно тянуть UpdateUI  (типа корову на баню) чтобы вызвать его из того класса.

Вообще снабжать каждое поле структуры каким-то template <ID..> мне кажется не таким уж хорошим. Если это ID задается в UI - то пусть UI им и занимается, зачем это тащить в структуру данных?
Записан
Пантер
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 5876


Жаждущий знаний


Просмотр профиля WWW
« Ответ #20 : Декабрь 25, 2014, 14:03 »

Цитировать
и надо мучительно тянуть UpdateUI  (типа корову на баню) чтобы вызвать его из того класса
Передавай сцыль на метод.
Записан

1. Qt - Qt Development Frameworks; QT - QuickTime
2. Не используйте в исходниках символы кириллицы!!!
3. Пользуйтесь тегом code при оформлении сообщений.
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2094



Просмотр профиля
« Ответ #21 : Декабрь 25, 2014, 14:22 »

Цитировать
Вообще снабжать каждое поле структуры каким-то template <ID..> мне кажется не таким уж хорошим. Если это ID задается в UI - то пусть UI им и занимается, зачем это тащить в структуру данных?

Я бы покурил тогда ещё вариант с мапом:

Код
C++ (Qt)
class Window
{
public:
   enum id_type { ID_ENABLED, ID_COUNT};
 
   Window()
   {
       _map[ID_ENABLED] = &Window::action_enabled;
       _map[ID_COUNT] = &Window::action_count;
   }
 
   void updateUI() { std::cout << "UbdateUI" << std::endl; }
 
   void some_method(id_type id) { _map[id](this); } // <-- Это вместо длинного свитча
 
private:
   void action_enabled()
   {
       std::cout << "ID_ENABLED" << std::endl;
       updateUI();
   }
 
   void action_count()
   {
       std::cout << "ID_COUNT" << std::endl;
   }
 
   std::map<id_type, std::function<void(Window*)>> _map;
};
 
 
int main()
{
   Window wnd;
 
   wnd.some_method(Window::ID_COUNT);
   wnd.some_method(Window::ID_ENABLED);
 
   return 0;
}
 

Кстатии, здесь также никакого полиморфизма нет)
« Последнее редактирование: Декабрь 25, 2014, 14:46 от m_ax » Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #22 : Декабрь 25, 2014, 15:01 »

Код
C++ (Qt)
   _map[ID_ENABLED] = &Window::action_enabled;
   _map[ID_COUNT] = &Window::action_count;
 
   std::map<id_type, std::function<void(Window*)>> _map;
 
Ах какой Вы быстрый  (на заглушках Улыбающийся) Но напр SaveUndo - совсем не метод Window, да и UpdateUI имеет с пяток вариантов с разными параметрами. И наконец не вижу где же копируется поле структуры
Записан
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2094



Просмотр профиля
« Ответ #23 : Декабрь 25, 2014, 15:15 »

Цитировать
Но напр SaveUndo - совсем не метод Window, да и UpdateUI имеет с пяток вариантов с разными параметрами.
И в чём проблема?

Цитировать
И наконец не вижу где же копируется поле структуры
Думал это не требует разъяснения в этом иллюстрирующем примере..

Но.. если это так не очевидно:
Код
C++ (Qt)
typedef int MyClass;
 
class Window
{
public:
   enum id_type { ID_ENABLED, ID_COUNT};
 
   Window()
   {
       _map[ID_ENABLED] = &Window::action_enabled;
       _map[ID_COUNT] = &Window::action_count;
   }
 
   void updateUI() { std::cout << "UbdateUI" << std::endl; }
 
   void some_method(MyClass & dst, const MyClass & src, id_type id) { _map[id](this, dst, src); } // <-- Вариант свитча с копированием структуры
 
private:
   void action_enabled(MyClass & dst, const MyClass & src)
   {
       std::cout << "ID_ENABLED" << std::endl;
       dst = src;
       updateUI();
   }
 
   void action_count(MyClass & dst, const MyClass & src)
   {
       std::cout << "ID_COUNT" << std::endl;
       dst = src;
   }
 
   std::map<id_type, std::function<void(Window*, MyClass&, const MyClass&)>> _map;
};
 
 
Window wnd;
 
   MyClass src = 1;
   MyClass dst = 2;
 
   wnd.some_method(dst, src, Window::ID_COUNT);
   wnd.some_method(dst, src, Window::ID_ENABLED);
 

  
Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #24 : Декабрь 25, 2014, 16:22 »

Но.. если это так не очевидно:
Код
C++ (Qt)
Вариант свитча с копированием структуры
 
private:
   void action_enabled(MyClass & dst, const MyClass & src)
   {
       std::cout << "ID_ENABLED" << std::endl;
       dst = src;
       updateUI();
   }
 
Так присваивать-то надо не всю структуру, а лишь поле (разное для разных id). Пожалуйста прочитайте мой пост #3 в начале темы где я отвечал Пантеру
Записан
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2094



Просмотр профиля
« Ответ #25 : Декабрь 25, 2014, 16:28 »

Цитировать
Так присваивать-то надо не всю структуру, а лишь поле (разное для разных id).
Я понимаю, что не всю, а лишь определённые поля для разных id.. Это же всего лишь пример..

Что в конце-концов мешает присваивать определённые поля?   В чём проблема то?
Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #26 : Декабрь 25, 2014, 16:34 »

Что в конце-концов мешает присваивать определённые поля?   В чём проблема то?
Ну хотелось бы обобщить/схлопнуть код. А просто для каждого поля свой метод - ну я так всегда могу сделать, но это ничего не упрощает. 
Записан
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2094



Просмотр профиля
« Ответ #27 : Декабрь 25, 2014, 17:07 »

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

Цитировать
Ну хотелось бы обобщить/схлопнуть код.
Ну, ну
Цитировать
Код "не везде одинаковый". Да, в половине случаев из 100 - все одинаково как выше. В других напр UpdateUI не нужно. В других (еще более редких) нужно еще доп действие(я).
А завтра окажется, что нужно добавить ещё с десяток доп. действий и условий..
И тогда все эти усилия по обобщению/схлопыванию окажутся бесполезными.     
Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #28 : Декабрь 25, 2014, 17:21 »

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

Это разбивает весь этот длинный свитч, и локализует код для каждого действия, что уже плюс..
Это по меньшей мере спорно. Напр в свитче нередко удобно так
Код
C++ (Qt)
bool update = false;
switch (id) {
case ID_ENABLE:
 ...
 update = true;
 break;
 ....
 ....
 update = true;
}
 
if (update) {
...
}
А вот без свитча может оказаться совсем непросто вынести действия по update в метод
Записан
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2094



Просмотр профиля
« Ответ #29 : Декабрь 25, 2014, 17:30 »

Ну и что:
Код
C++ (Qt)
bool update = false;
_map[id](this, update);
 
if (update) { ... }
 

А вообще, если возникают сложности с локализацией свитча, то самое время пересматривать архитектуру, на которую, вероятно (очень вероятно),  как всегда забили)   
Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
Страниц: 1 [2] 3   Вверх
  Печать  
 
Перейти в:  


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