Название: Инкапсуляция флажков Отправлено: Igors от Февраль 21, 2018, 07:59 Добрый день
Задача выглядит очень "хрестоматийной". Есть класс (Container) элементы которого (Element) имеют флажок selected. Нередко требуется узнать а есть ли в контейнере элементы с этим флажком = true (взведенным). Др словами выбрал ли юзер чего-нибудь. Пробегать всякий раз по всему контейнеру... Не, ну оно конечно просто и надежно, но уж очень коряво, да и тормоза возможны. Я пошел по очевидному пути: сделал член флажок private и объявил Container friend'ом. Ну и нарисовал (псевдокод) Код И вроде все "по уму" - флажок надежно засисен! Однако вскоре я получил немало хлопот. У котейнера масса методов удаления, вставки и (самое противное) перетасовки эл-тов. И на всех них забота об этом гребаном флажке повисает неприятным грузом. Может я что-то не так "трактую" и/или есть лучший способ? Спасибо Название: Re: Инкапсуляция флажков Отправлено: ssoft от Февраль 21, 2018, 10:16 Это такие накладные расходы).
Если хочется иметь счетчик/кеш каких либо свойств, например флажка selected, то придется все вручную отслеживать. При этом нужно учитывать как изменения свойств самих элементов, так и изменение состава элементов в контейнере. Вариант 1. Перебирать все элементы и кешировать значение. Это можно делать периодически или в момент запроса. Вариант 2. Менять свойства элементов только через методы контейнера. Вариант 3. Организовывать обратную связь между элементами и контейнером. Ассоциация, как в примере, сигнал-слот, паттерн Observer и т.п. Название: Re: Инкапсуляция флажков Отправлено: qate от Февраль 21, 2018, 12:52 если работает быстро, то лучше пробежаться по всем
Название: Re: Инкапсуляция флажков Отправлено: Racheengel от Февраль 21, 2018, 23:46 На хрестоматийный вопрос - хрестоматийный ответ)
Сделать еще один флажок для контейнера - bool m_isChanged. Флажок ставим в тру внутри методов вставки-удаления-перетасовки-выделения. Функцию "пробегания" по выбранным элементам делаем так: int getSelectedCount() { if (m_isChanged) { m_isChanged = false; m_count = // тут пробегаемся, а шо делать, и считаем выделенное... } return m_count; } Название: Re: Инкапсуляция флажков Отправлено: Igors от Февраль 22, 2018, 10:06 На хрестоматийный вопрос - хрестоматийный ответ) Да, "lazy" вполне хрестоматийно, доп флажок часто называют типа m_dirty. Но ничего особо хорошего не видно. Добавили еще член данных. Связались с mutable (метод getSelectedCount наверняка потребуется константным). И.. чего добились? Да особо ничего - все равно "нужно быть (предельно) внимательным", установка dirty по-прежнему "на ручняке", компилятор никак не поможет. Ну разве что dirty = true легче воткнуть первой строкой во всех методах - не густо. Я сделал метод CalcSelectedAll и вызываю его если возможны неясности - тоже не блеск.Сделать еще один флажок для контейнера - bool m_isChanged. Флажок ставим в тру внутри методов вставки-удаления-перетасовки-выделения. Функцию "пробегания" по выбранным элементам делаем так: если работает быстро, то лучше пробежаться по всем А так тонем в подробностях "если". Да, если эл-тов всего 10 - не проблема. Но сотни тоже возможны. И какова частота вызова HasSelected()? Выяснить это непросто даже в среднем проекте.Вариант 1. Перебирать все элементы и кешировать значение. Это можно делать периодически или в момент запроса. Насколько я понял, 1 - что предложил Racheengel, 2 - стартовый пост, 3 - не понял (ох уж этот обстервер - так я его ни разу и не применил :)). Вариант 2. Менять свойства элементов только через методы контейнера. Вариант 3. Организовывать обратную связь между элементами и контейнером. Ассоциация, как в примере, сигнал-слот, паттерн Observer и т.п. Собсно после нескольких сеансов отладки все работает вполне прилично. Попробуем присмотреться где обычно недосмотры. Ну конечно удаление эл-та "извне" я сразу учел Код Но вот банальное clear() - прощелкал. Также есть неск ситуаций "take", т.е. извлекаем, потом возможно вставляем, но может и нет, удаляем. Приходится и take/insert перекрывать. В общем довольно много обычных методов контейнера (что пишутся интуитивно) оказываются под ударом. Название: Re: Инкапсуляция флажков Отправлено: qate от Февраль 22, 2018, 12:35 Да, если эл-тов всего 10 - не проблема. Но сотни тоже возможны. И какова частота вызова HasSelected()? Выяснить это непросто даже в среднем проекте. сотни разве проблема ? и почему сложно выяснить частоту - неясно назначение контейнера ? вон в субд пробегают по таблице в поисках и все ок Название: Re: Инкапсуляция флажков Отправлено: m_ax от Февраль 22, 2018, 21:43 Я бы посмотрел на концепт/паттерн так называемого trackable, который используется в boost::signals.. Т.е. по сути заменить флажёк на отдельный класс, который регестрируется менеджером флажков, и который сам сбрасывает своё состояние при удалении, перемещении и т.д.. и сообщает САМ своему менеджеру при своём изменении..
Но я сейчас подозреваю, что отморозил страшную скверну - знания, принятые на вооружения в boost'е :) Название: Re: Инкапсуляция флажков Отправлено: Igors от Февраль 23, 2018, 13:59 сотни разве проблема ? Вы чувствуете что разговор как-то "уходит в сторону" от программирования? :) и почему сложно выяснить частоту - неясно назначение контейнера ? вон в субд пробегают по таблице в поисках и все ок Цитировать А может все-таки можно не делать? И вообще, если у юзверя тормоза - пусть покупает железо помощнее (скоро докатимся и до этого) Т.е. кто-то (дядя? начальник?) должен взять на себя ответственность и заявить (или утвердить) что brute force здесь приемлема. Так вот, насколько я знаю проект - это не так.Я бы посмотрел на концепт/паттерн так называемого trackable, который используется в boost::signals.. Т.е. по сути заменить флажёк на отдельный класс, который регестрируется менеджером флажков, и который сам сбрасывает своё состояние при удалении, перемещении и т.д.. и сообщает САМ своему менеджеру при своём изменении.. Ну организовывать сигналы/оповещения для флажка/счетчика - слишком жирно будет. И почему "сброс состояния"? (установка dirty). Это для случаев когда операция трудоемка (напр пересчет айтемов в лайауте) и приходится делать ее "по запросу" (а не на всякое изменение). Изменить счетчик флажков такой операцией не является. Кстати, а что за паттерн, навскидку гугл ничего о нем не выдает.Но я сейчас подозреваю, что отморозил страшную скверну - знания, принятые на вооружения в boost'е :) Сейчас контейнер сделан так (псевдокод) Код При этом внешние попытки нарушить корректность счетчика флажков легко пресекаются. Но конечно ф-ционал льется в класс контейнер (нормальное желание работать с классом его методами). Поэтому внутри Container'а вызов mElements.clear(), erase() и.т.п. носит массовый характер, уследить тяжело. Вот если бы как-то запретить вызов этих методов, тем самым заставить вызывать другие (что учитывают флажок). Но пока не вижу как это удобно сделать Название: Re: Инкапсуляция флажков Отправлено: m_ax от Февраль 23, 2018, 18:56 Цитировать Ну организовывать сигналы/оповещения для флажка/счетчика - слишком жирно будет. Я не говорю о сигналах в их привычном понимании.. Идея в том, чтобы переложить контроль над текущим состоянием флажка не на методы Вашего Container, а на функционал самого флажка (он, конечно, теперь должен быть классом, с деструктором, в котором при его уничтожении выставляется соответствующая информация - я самовыпилился и т.д. и другими методами). И + дружественный классу флажка менеджер, который будет регестрировать объекты флажков, если они создаются и кладутся в Container. Элемент контэйнера удалился, у флажка сработал деструктор, который сообщил менеджеру о том, что всё - меня нет) У меня, к сожалению, сейчас нет возможности привести минимальный код, и, наверное не получится это сделать до след. воскресенья.. Но, надеюсь, идея более-менее ясна) Цитировать Кстати, а что за паттерн, навскидку гугл ничего о нем не выдает. И не найдёте) Это класс такой в boost::signals) У меня здесь, на этом форуме, в теме про доморощенную реализацию механизма сигнал-слот какие то слова на эту тему есть..) Где то)Название: Re: Инкапсуляция флажков Отправлено: Igors от Февраль 24, 2018, 13:39 Я не говорю о сигналах в их привычном понимании.. Чтобы самовыпиливаться нужно создать у эл-та поле m_owner, это достаточно обязывающее решение/зависимость. Напр "take" - эл-т извлечен из контейнера (на не удален). С менеджером тоже как-то мутно, неясно на основании чего он будет что-то решать/делать Идея в том, чтобы переложить контроль над текущим состоянием флажка не на методы Вашего Container, а на функционал самого флажка (он, конечно, теперь должен быть классом, с деструктором, в котором при его уничтожении выставляется соответствующая информация - я самовыпилился и т.д. и другими методами). И + дружественный классу флажка менеджер, который будет регестрировать объекты флажков, если они создаются и кладутся в Container. Элемент контэйнера удалился, у флажка сработал деструктор, который сообщил менеджеру о том, что всё - меня нет) Название: Re: Инкапсуляция флажков Отправлено: Авварон от Февраль 24, 2018, 13:53 При этом внешние попытки нарушить корректность счетчика флажков легко пресекаются. Но конечно ф-ционал льется в класс контейнер (нормальное желание работать с классом его методами). Поэтому внутри Container'а вызов mElements.clear(), erase() и.т.п. носит массовый характер, уследить тяжело. Вот если бы как-то запретить вызов этих методов, тем самым заставить вызывать другие (что учитывают флажок). Но пока не вижу как это удобно сделать Что мешает завернуть вектор в "контейнер2" только с функционалом счетчика флажков? Название: Re: Инкапсуляция флажков Отправлено: Igors от Февраль 24, 2018, 14:47 Что мешает завернуть вектор в "контейнер2" только с функционалом счетчика флажков? Ждал этого ответа (на мой взгляд самое разумное). Правда тогда неясно кто должен быть friend'ом эл-та?Название: Re: Инкапсуляция флажков Отправлено: Авварон от Февраль 24, 2018, 21:29 Что мешает завернуть вектор в "контейнер2" только с функционалом счетчика флажков? Ждал этого ответа (на мой взгляд самое разумное). Правда тогда неясно кто должен быть friend'ом эл-та?а надо?) Название: Re: Инкапсуляция флажков Отправлено: ViTech от Февраль 25, 2018, 13:52 сотни разве проблема ? Вы чувствуете что разговор как-то "уходит в сторону" от программирования? :) и почему сложно выяснить частоту - неясно назначение контейнера ? вон в субд пробегают по таблице в поисках и все ок Разговор как раз в сторону программирования и двигался, уходя от кодирования. Ждал этого ответа (на мой взгляд самое разумное). Правда тогда неясно кто должен быть friend'ом эл-та? а надо?) Я бы ещё задумался над тем, нужно ли самому элементу вообще знать, что его кто-то где-то "выбрал" :). Название: Re: Инкапсуляция флажков Отправлено: qate от Февраль 26, 2018, 08:44 Вы чувствуете что разговор как-то "уходит в сторону" от программирования? :) это я почувствовал еще в первом сообщении ) минимально рабочий пример, с указанием места тормозов и примеров использования - вот технически грамотная постановка вопроса а так может это флажки редко используются или их мало - смыла не видно, а работы разной много уследить, проверить, не допустить ошибки |