Название: Большой switch Отправлено: Igors от Декабрь 24, 2014, 09:24 Добрый день
Есть баааальшой switch Код Есть ли что-то лучшее? Спасибо Название: Re: Большой switch Отправлено: Пантер от Декабрь 24, 2014, 09:26 Кот везде одинаковый, за исключением проверяемого поля? Я правильно понял?
Название: Re: Большой switch Отправлено: Пантер от Декабрь 24, 2014, 09:32 С первого приближения, можно часть кода вынести в шаблон.
Код
Название: Re: Большой switch Отправлено: Igors от Декабрь 24, 2014, 10:00 С первого приближения, можно часть кода вынести в шаблон. Именно так я и сделал :) Но1) От switch это все-таки не избавляет (хотя значительно сокращает) 2) Код "не везде одинаковый". Да, в половине случаев из 100 - все одинаково как выше. В других напр UpdateUI не нужно. В других (еще более редких) нужно еще доп действие(я). Можно "продолжать в том же духе", напр Код Но это не очень удобно вызывать Код Как часто бывает, bool нехороший аргумент для вызывающего. Придется рисовать enum'ы. И как-то это все "распухает", дорисовать нужное в switch выглядит проще Да, и радость с темплейт здесь возможна т.к. все члены public (как и есть в этом старом коде). Но ведь "грамотно" все через геттеры/сеттеры Код И как тогда? :) Название: Re: Большой switch Отправлено: Пантер от Декабрь 24, 2014, 10:09 Если ты обернешь мемберов в геттер/сеттер, то можно забабахать через паттерн стратеггия.
Код
Далее делаешь стратегии, заточенные на нужные геттеры/сеттеры и необходимые действия и помещаешь их в фабрику. Твой свитч превращается в запрос у фабрики нужной стратегии и выполнения у нее do. Кода будет больше, зато очень легко можно будет расширять и понятнее кот станет. Название: Re: Большой switch Отправлено: Пантер от Декабрь 24, 2014, 10:12 Даже без геттеров/сеттеров можно, но тогда больше классов получится. Если юзать геттеры/сеттеры, можно создать меньше стратегий, передавая в конструктор std::function и инициализируя их в фабрике с передачей ссылок на нужные методы.
Название: Re: Большой switch Отправлено: sergek от Декабрь 24, 2014, 12:52 Можно switch заменить Mapом.
В MyClass определяете много-много методов с сигнатурой что-то вроде MyClass::copy_тип_проверки(const MyClass & src, int id), ассоциативный массив типа QMap<int, MyClass::*тип_функции> и один метод copyParam с такой-же сигнатурой. В конструкторе один раз заполняете массив, например, massiv[ID_ENABLED] = &MyClass::copy_ENABLED. Все методы, кроме copyParam - закрытые. Метод copyParam находит в массиве нужную функцию и передает ей параметры. В общем и все. Кода меньше не станет, но все можно попрятать в private секцию, и вся реализация - в классе, а не где-то в коде. Название: Re: Большой switch Отправлено: Пантер от Декабрь 24, 2014, 13:03 sergek, а куда засунешь вызовы SaveUndo и UpdateUI?
Название: Re: Большой switch Отправлено: sergek от Декабрь 24, 2014, 13:16 Я могу только посоветовать, куда ;) Сам туда не хочу.
Функции глобальные - какие проблемы? Название: Re: Большой switch Отправлено: Igors от Декабрь 24, 2014, 13:25 Кода меньше не станет, но все можно попрятать в private секцию, и вся реализация - в классе, а не где-то в коде. Я понял, но ф-ция копирования не особо лепится внутри класса, т.к. он должен знать про SaveUndo, UpdateUI и др - а это к нему отношения не имеет.Не то чтобы я прямо-таки несчастен со switch'ом, ничего страшного нет, пополнять/изменять легко. Просто у меня много такого старого кода, вот и прикидываю как бы (может быть) модернизировать. Если ты обернешь мемберов в геттер/сеттер, то можно забабахать через паттерн стратеггия. Ничего не понял :'(. Можно расширить Ваш псевдокод? Придираться не буду :) Да, и если можно - хоть как-то осмысленное имя вместо "do", а то я совсем растерялся. Код
Далее делаешь стратегии, заточенные на нужные геттеры/сеттеры и необходимые действия и помещаешь их в фабрику. Твой свитч превращается в запрос у фабрики нужной стратегии и выполнения у нее do. Кода будет больше, зато очень легко можно будет расширять и понятнее кот станет. Спасибо Название: Re: Большой switch Отправлено: Пантер от Декабрь 24, 2014, 14:14 Совсем псевдокодный псевдокот.
Код
Название: Re: Большой switch Отправлено: _Bers от Декабрь 24, 2014, 21:43 Добрый день Есть баааальшой switch Есть ли что-то лучшее? Альтернатива свитчу - полиморфизм. Известно, что простой свитч (даже если он оч длинный стал с годами) предпочтительнее, чем ооп головного мозга. Не рекомендую рассматривать вам выше приведенные примеры для практического использования. модель ооп должна быть очень простой, или она не имеет смысла. так же, она не должна создавать прецедент падению производительности (использование медленных new и прочее) Название: Re: Большой switch Отправлено: Akon от Декабрь 25, 2014, 03:32 Код: class MyClass Это идея sergek со след. отличиями: 1. весь маппинг производится в компайл-тайм (нет прецедентов падению производительности); 2. маппится не операция над конкретными полями, а смещения полей. Напр. возможно такое: auto sum = dst.*MemberById<ID_COUNT>::Member + src.*MemberById<ID_COUNT>::Member. Использование геттеров/сеттеров принципиальности не вносит - указателю на член будет соответствовать пара указателей на функции-члены. В Qt подобного рода задачи решаются через MetaTypes (напр. QObject::property()/setProperty(), где ключом выступает имя св-ва). OOP головного мозга - это ерунда по сравнению с TMP (template metaprogramming) оного. А вообще самый быстрый вариант - это С-макро... и, зачастую, кто не брезгует, тот впереди :) Название: Re: Большой switch Отправлено: Igors от Декабрь 25, 2014, 09:53 Известно, что простой свитч (даже если он оч длинный стал с годами) предпочтительнее, чем ооп головного мозга. Это старый код писаный др программистом где-то в начале 90-х. Иногда заметно что он переводился с паскаля :) Первое впечатление аховое ("о боже как примитивно!!" и.т.п.), но предложить что-то лучшее совсем непросто, во всяком случае мне это пока не удалось. Ну я особо и не рвусь, просто обдумываю.С паттерном "стратегия" что-то совсем мрачно. Код заметно усложнился для понимания, а достигнуто лишь присваивание члена. Впрочем я никогда не понимал этих "паттернов" Код: template <int Id> struct MemberById; Хорошо, теперь мы можем присваивать члены класса по id. Но пробежаться циклом (вместо switch) все равно не удается, напр Код Хотя даже если бы и можно - все равно недостаточно. Т.к. не все ветки switch одинаковы, (хотя повторов очень иного). А CopyParam да, значение присвоит, но эти доп действия не выполнит Название: Re: Большой switch Отправлено: Bepec от Декабрь 25, 2014, 10:43 switch простейший паттерн множественного ветвления. И как вы не старайтесь у вас в результате получится тот же switch только более сложный по реализации :D
PS на мой взгляд очередная провокация Igors "А давайте сделаем молоток ещё лучше - с пилкой по металлу на другом конце рукояти" :D Название: Re: Большой switch Отправлено: sergek от Декабрь 25, 2014, 12:28 Я понял, но ф-ция копирования не особо лепится внутри класса, т.к. он должен знать про SaveUndo, UpdateUI и др - а это к нему отношения не имеет. Не проблема - вынесите их в отдельный класс(ы) с интерфейсными методами. Будут работать с какими-то глобальными объектами.Свитч - всегда причина задуматься. Название: Re: Большой switch Отправлено: Bepec от Декабрь 25, 2014, 12:42 Я с одним коллегой спорил на протяжении примерно 3 месяцев и ниразу он не смог предложить решения элегантнее и понятнее чем простой свич. Постоянно уходило в сторону шаблонов, фабрик, десятка другого классов с контролями ошибок и прочим. В результате свич на 4 действия превращался в монстра.
Поэтому я скептически отношусь к такого рода спорам. Свич заменить можно, но только в единичных случаях это оправданно. ИМХО Название: Re: Большой switch Отправлено: Igors от Декабрь 25, 2014, 12:46 Я понял, но ф-ция копирования не особо лепится внутри класса, т.к. он должен знать про SaveUndo, UpdateUI и др - а это к нему отношения не имеет. Не проблема - вынесите их в отдельный класс(ы) с интерфейсными методами. Будут работать с какими-то глобальными объектами.switch простейший паттерн множественного ветвления. ... Я искренне наслаждался почти полным отсутствием Ваших постов в течение последней пары месяцев. Увы, все хорошее так быстро кончается :'(Название: Re: Большой switch Отправлено: m_ax от Декабрь 25, 2014, 13:23 Как альтернативу полиморфизму, можно использовать связку boost::variant + соответствующий визитёр visitor
Код
В конструктор визитора можно передавать какие-либо доп. параметры и п.р. Пример с variant нужно воспринимать просто как альтернативу, для "подумать", возможно, подсмотреть какие-то известные решения (иначе всё "мировоззрение" так и останется замкнутым на одном лишь свитче). Название: Re: Большой switch Отправлено: Igors от Декабрь 25, 2014, 14:00 Код
Вообще снабжать каждое поле структуры каким-то template <ID..> мне кажется не таким уж хорошим. Если это ID задается в UI - то пусть UI им и занимается, зачем это тащить в структуру данных? Название: Re: Большой switch Отправлено: Пантер от Декабрь 25, 2014, 14:03 Цитировать и надо мучительно тянуть UpdateUI (типа корову на баню) чтобы вызвать его из того класса Передавай сцыль на метод.Название: Re: Большой switch Отправлено: m_ax от Декабрь 25, 2014, 14:22 Цитировать Вообще снабжать каждое поле структуры каким-то template <ID..> мне кажется не таким уж хорошим. Если это ID задается в UI - то пусть UI им и занимается, зачем это тащить в структуру данных? Я бы покурил тогда ещё вариант с мапом: Код
Кстатии, здесь также никакого полиморфизма нет) Название: Re: Большой switch Отправлено: Igors от Декабрь 25, 2014, 15:01 Код
Название: Re: Большой switch Отправлено: m_ax от Декабрь 25, 2014, 15:15 Цитировать Но напр SaveUndo - совсем не метод Window, да и UpdateUI имеет с пяток вариантов с разными параметрами. И в чём проблема?Цитировать И наконец не вижу где же копируется поле структуры Думал это не требует разъяснения в этом иллюстрирующем примере..Но.. если это так не очевидно: Код
Название: Re: Большой switch Отправлено: Igors от Декабрь 25, 2014, 16:22 Но.. если это так не очевидно: Так присваивать-то надо не всю структуру, а лишь поле (разное для разных id). Пожалуйста прочитайте мой пост #3 в начале темы где я отвечал ПантеруКод
Название: Re: Большой switch Отправлено: m_ax от Декабрь 25, 2014, 16:28 Цитировать Так присваивать-то надо не всю структуру, а лишь поле (разное для разных id). Я понимаю, что не всю, а лишь определённые поля для разных id.. Это же всего лишь пример..Что в конце-концов мешает присваивать определённые поля? В чём проблема то? Название: Re: Большой switch Отправлено: Igors от Декабрь 25, 2014, 16:34 Что в конце-концов мешает присваивать определённые поля? В чём проблема то? Ну хотелось бы обобщить/схлопнуть код. А просто для каждого поля свой метод - ну я так всегда могу сделать, но это ничего не упрощает. Название: Re: Большой switch Отправлено: m_ax от Декабрь 25, 2014, 17:07 Цитировать А просто для каждого поля свой метод - ну я так всегда могу сделать, но это ничего не упрощает. Это разбивает весь этот длинный свитч, и локализует код для каждого действия, что уже плюс..Цитировать Ну хотелось бы обобщить/схлопнуть код. Ну, нуЦитировать Код "не везде одинаковый". Да, в половине случаев из 100 - все одинаково как выше. В других напр UpdateUI не нужно. В других (еще более редких) нужно еще доп действие(я). А завтра окажется, что нужно добавить ещё с десяток доп. действий и условий..И тогда все эти усилия по обобщению/схлопыванию окажутся бесполезными. Название: Re: Большой switch Отправлено: Igors от Декабрь 25, 2014, 17:21 А завтра окажется, что нужно добавить ещё с десяток доп. действий и условий.. Не исключено что и такИ тогда все эти усилия по обобщению/схлопыванию окажутся бесполезными. Это разбивает весь этот длинный свитч, и локализует код для каждого действия, что уже плюс.. Это по меньшей мере спорно. Напр в свитче нередко удобно такКод А вот без свитча может оказаться совсем непросто вынести действия по update в метод Название: Re: Большой switch Отправлено: m_ax от Декабрь 25, 2014, 17:30 Ну и что:
Код
А вообще, если возникают сложности с локализацией свитча, то самое время пересматривать архитектуру, на которую, вероятно (очень вероятно), как всегда забили) Название: Re: Большой switch Отправлено: Old от Декабрь 25, 2014, 17:34 то самое время пересматривать архитектуру Бегите. ;)Название: Re: Большой switch Отправлено: m_ax от Декабрь 25, 2014, 17:37 Бегите. ;) Чувствую, сейчас будут закидывать шапками :) Название: Re: Большой switch Отправлено: Igors от Декабрь 25, 2014, 17:56 Ну и что: Тот update могут устанавливать лишь некоторые ветки - а ф-ции мапы придется иметь параметр. И еще один .. и еще.. Уже упоминал об этом в том же посте #3Код
А вообще, если возникают сложности с локализацией свитча, то самое время пересматривать архитектуру, на которую, вероятно (очень вероятно), как всегда забили) Таких слов "пересматривать архитектуру" лучше не употреблять :) Даются 500K строк которые коряво но работают (что там - хз). и список фич которые надо. очень надо. И баги пофиксить, чтоб не вылетало. И OpenGL присобачить - чтоб времени не было патякать об "архитектуре". Поэтому мои робкие попытки что-то улучшить - уже подвиг :)Название: Re: Большой switch Отправлено: m_ax от Декабрь 25, 2014, 18:13 Цитировать Тот update могут устанавливать лишь некоторые ветки - а ф-ции мапы придется иметь параметр. И еще один .. и еще.. А собрать необходимые параметры в одну структуру (описывающую текущее состояние) и передавать её (или просто возвращать её).. Или не любовь к паттернам (а это тоже считается паттерном) исключает и это решение? Код
Название: Re: Большой switch Отправлено: Igors от Декабрь 25, 2014, 18:59 А собрать необходимые параметры в одну структуру и передавать её (или просто возвращать её).. Или не любовь к паттернам (а это тоже считается паттерном) исключает и это решение? "Давайте заведем структуру и забьем туда параметры на все случаи жизни. И будем эту структуру давать каждому, а он использует нужное ему". Ну как-то это не вяжется с хорошими словами "мировоззрение", "концепт" и др из Вашего лексикона :)Упорное доказательство типа "все равно лучше switch не придумаете!!" совсем не входит в мои планы. Возможно для обобщений мало материала - поэтому я и создал соседний пост. Может не размениваться на один частный случай (копирование параметра), а попробовать обобщить сразу неск больших свитчей? Название: Re: Большой switch Отправлено: sergek от Декабрь 26, 2014, 11:23 Может не размениваться на один частный случай (копирование параметра), а попробовать обобщить сразу неск больших свитчей? Тема, на мой взгляд, полезная. Рассмотреть разные случаи из практики, варианты замены свитча с использованием объектного подхода, шаблонов етц. Хороший может быть материал. |