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

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

Страниц: 1 [2] 3   Вниз
  Печать  
Автор Тема: Sets of Objects  (Прочитано 19663 раз)
spectre71
Гость
« Ответ #15 : Сентябрь 10, 2009, 21:18 »

1) Пользователь удаляет объект. Нужно пробежаться по всем set'ам и удалить указатель на удаляемый объект из каждого set'а. Как Вы знаете, я не фанат ООП, но это уж слишком даже для меня. Это как же получается, ВСЕ объекты должны знать о существовании set'ов?
2) Пользователь передумал и "возвращает объект взад" вызывая undo. Как поддержать откат? Какие данные заносить в стек undo? Давайте сохраним для undo все set'ы в которые объект входил? Не жирно ли?
Igors, BRE! Это не относится к данной теме!
Igors, если желаешь обсудить эти вопросы, создавай отдельную тему. Не надо мешать все в одну кучу.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #16 : Сентябрь 10, 2009, 21:30 »

Это никак не связано с записью/чтением(сериализацией) системы объектов в поток(например, запись в файл и восстановление из файла; или создание копии)!
Это совсем другая задача, вернее задачи.
Мы сказали/утверждаем: set знает объект как указатель, в файле записан "индекс" объекта. Так мы решаем I/O. Понятно, но из этого же вытекают проблемы о которых я писал в предыдущем посте.

Возвращает объект из набора - удалили указатель на объект из набора.
Не понял как это связано с undo

Ладно, вот еще парочка проблем:

3) При чтении самих объектов не каждый из них может быть прочитан. Например, объект ссылается на файл а его на диске уже нет. Но если мы не добавим такой объект в ObjPool - "индексы" для set'ов улетят.

4) Пользователь хочет загрузить файл данных не удаляя текущие объекты. То есть просто "append". С "индексами" нужно что-то делать.

И.т.д, и.т.п. Конечно, все проблемы можно решить (я же и занимался их решением Улыбающийся) но я прекрасно понимаю что это "латки".  Схема "указатель/индекс" больная/дефективная, ее нужно менять "в прынцыпе" а не латать.
Записан
spectre71
Гость
« Ответ #17 : Сентябрь 10, 2009, 21:42 »

Это никак не связано с записью/чтением(сериализацией) системы объектов в поток(например, запись в файл и восстановление из файла; или создание копии)!
Это совсем другая задача, вернее задачи.
Мы сказали/утверждаем: set знает объект как указатель, в файле записан "индекс" объекта. Так мы решаем I/O. Понятно, но из этого же вытекают проблемы о которых я писал в предыдущем посте.
Да с какой стати они отсюда вытекают? Совершенно не связанные задачи!
Есть система объектов, сохраняем в поток, восстанавливаем из потока(как было или как хотим).
И всякие операции удаления, перемещения объектов в рамках системы(до ее сохранения или после чтения) никак с этим не связаны!
Записал систему в файл как есть. Делай с тем что в памяти что хочешь.
Создал  систему (прочитал из файла). Делай с тем что в памяти что хочешь.
Записан
BRE
Гость
« Ответ #18 : Сентябрь 10, 2009, 21:49 »

Не понял как это связано с undo
Пользователь дал команду добавить объект в набор, в стек undo записали команду удалить объект из набора. Или я не понял вопрос.

3) При чтении самих объектов не каждый из них может быть прочитан. Например, объект ссылается на файл а его на диске уже нет. Но если мы не добавим такой объект в ObjPool - "индексы" для set'ов улетят.
Варианты:
1. Создать объект с флагом, что объект не валиден. После чтения удалить все не валидные объекты, они автоматически удаляться из всех наборов.
2. При чтении объектов сохранять индексы не валидных и не включать их в наборы.

4) Пользователь хочет загрузить файл данных не удаляя текущие объекты. То есть просто "append". С "индексами" нужно что-то делать.
Как правильно ты написал ниже, и это решается, если захотеть.  Подмигивающий
Если вначале продумать весь необходимый функционал, а потом приступить к реализации, думаю многих костылей можно будет избежать.

И.т.д, и.т.п. Конечно, все проблемы можно решить (я же и занимался их решением Улыбающийся) но я прекрасно понимаю что это "латки".  Схема "указатель/индекс" больная/дефективная, ее нужно менять "в прынцыпе" а не латать.

Igors, BRE! Это не относится к данной теме!
Igors, если желаешь обсудить эти вопросы, создавай отдельную тему. Не надо мешать все в одну кучу.
Spectre, согласен, но уже начали обсуждать здесь. Может модераторы смогут разделить.
Записан
spectre71
Гость
« Ответ #19 : Сентябрь 10, 2009, 21:49 »

3) При чтении самих объектов не каждый из них может быть прочитан. Например, объект ссылается на файл а его на диске уже нет. Но если мы не добавим такой объект в ObjPool - "индексы" для set'ов улетят.
Это никак не связано с сериализацией объекта имеющего поле "имя файла".
С таким же успехом, у тебя есть в памяти объект ссылающийся на файл, в какой-то момент файл был удален, ну и что, все точно также.
С другой стороны, никто тебе не запрещает во время чтения полей объекта из потока, проводить при необходимости нужные проверки.
Записан
spectre71
Гость
« Ответ #20 : Сентябрь 10, 2009, 21:57 »

4) Пользователь хочет загрузить файл данных не удаляя текущие объекты. То есть просто "append". С "индексами" нужно что-то делать.
Загружается(сохраняется) целостная система объектов из потока.
Проблемы объединения(и возможности объединения) ее с другими системами, это уже другай задача и решается она для конкретных случаев.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #21 : Сентябрь 10, 2009, 22:14 »

1. Создать объект с флагом, что объект не валиден. После чтения удалить все не валидные объекты, они автоматически удаляться из всех наборов.
А если этот объект parent для других объектов и они рассчитывают на валидный parent? Ступив на "скользкий путь", мы должны по нему идти и идти. Почему мы создаем флаг "не валид"? Из идейных соображений? Вовсе нет, давайте признаемся - надо закрыть очередную дыру Улыбающийся

Spectre, согласен, но уже начали обсуждать здесь. Может модераторы смогут разделить.[/quote]
Не могу с Вами согласиться. Если мы сказали - связки должны работать "по указателю", то мы себе и создали букет проблем которые потом будем решать и решать.

Использование "просто указателя" для серъезных данных (вне UI) плохо!

О боже, как кощунственно это звучит  Улыбающийся
Записан
BRE
Гость
« Ответ #22 : Сентябрь 10, 2009, 22:38 »

А если этот объект parent для других объектов и они рассчитывают на валидный parent? Ступив на "скользкий путь", мы должны по нему идти и идти. Почему мы создаем флаг "не валид"? Из идейных соображений? Вовсе нет, давайте признаемся - надо закрыть очередную дыру Улыбающийся
Какие дыры?
Можно много придумывать, но проще огласить спецификации, что бы мы не гадали что это за объекты и какие у них могут быть свойства.
Что касается:
Цитировать
3) При чтении самих объектов не каждый из них может быть прочитан. Например, объект ссылается на файл а его на диске уже нет. Но если мы не добавим такой объект в ObjPool - "индексы" для set'ов улетят.
Если файла нет на диске и объект имеет подчиненные объекты, создаем объект, отмечая что данные в нем не валидны (файл с данным стерт). Место данных из файла выводим, например, иконку с фигой. Если же для объекта важен файл на диске и его нет, то мы обязаны прервать загрузку данных и вывести диагностическое сообщение.

Указатели используются как уникальный ключ, можно добавить еще один уровень косвенности и использовать не указатели, а какие нибудь идентификаторы. Но пока я не вижу причин для этого, но и полностью задачу я не знаю.
Записан
spectre71
Гость
« Ответ #23 : Сентябрь 10, 2009, 22:47 »

1. Создать объект с флагом, что объект не валиден. После чтения удалить все не валидные объекты, они автоматически удаляться из всех наборов.
А если этот объект parent для других объектов и они рассчитывают на валидный parent? Ступив на "скользкий путь", мы должны по нему идти и идти. Почему мы создаем флаг "не валид"? Из идейных соображений? Вовсе нет, давайте признаемся - надо закрыть очередную дыру Улыбающийся

Цитировать
Spectre, согласен, но уже начали обсуждать здесь. Может модераторы смогут разделить.
Не могу с Вами согласиться. Если мы сказали - связки должны работать "по указателю", то мы себе и создали букет проблем которые потом будем решать и решать.

Использование "просто указателя" для серъезных данных (вне UI) плохо!

О боже, как кощунственно это звучит  Улыбающийся
1) Связь объектов между собой и динамика их отношений:
  - parent <-> children
  - object <-> ref
  - owner <-> children
Это твоя проблема которая зависит от условий твоей задачи и твоих ресурсов итд..., о которой здесь никто пока не знает.

2) Абстарктные высказывания типа "давайте признаемся - надо закрыть очередную дыру" или "то мы себе и создали букет проблем которые потом будем решать и решать", это от бессилия, лени или злости, и никакого отношения к делу не имеют. Так что давай последовательно и конкретно.

3)
Использование "просто указателя" для серъезных данных (вне UI) плохо!
О боже, как кощунственно это звучит  Улыбающийся
А это вообще откуда вылезло. Шокированный
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #24 : Сентябрь 11, 2009, 15:22 »

1) Связь объектов между собой и динамика их отношений:
  - parent <-> children
  - object <-> ref
  - owner <-> children
Это твоя проблема которая зависит от условий твоей задачи и твоих ресурсов итд..., о которой здесь никто пока не знает.
Проблема безусловно моя, с этим не поспоришь Улыбающийся Но она так же и общая, поскольку BRE, Вы и я - все мы используем один и тот же подход/метод для связок между объектами (различия в реализации).

Так что давай последовательно и конкретно.
Я описал 4 совершенно конкретных проблемы которых мне пришлось решать. Могу добавить еще (не вопрос Улыбающийся). Или можем обсудить более детально любую из уже сказанных - выбирайте какую. Но во всех случаях Вы утверждаете что (поправьте меня если не так):

- это конкретные проблемы конкретной задачи, которые надо решать в рабочем порядке. 

Я с этим НЕ согласен и утверждаю: эти проблемы общие и вызваны принципиальными ошибками в проектировании связей между объектами. То что мы все используем ("указатель на используемый объект") разваливается  в первую очередь там где указатель исчезает: I/O и Undo. Но и без этого не сладко: все время приходится искать по всем данным "кто ссылается на меня". Потом делать то же для "каждого сославшегося". Это хотя и возможно (так оно сейчас и есть  Улыбающийся) но жрет время и производит уродливый код (в огромных количествах)

Переформулирую вопросы (все данные описаны в этой теме, если что упустил - спрашивайте, добавлю)
Как мне сделать общий механизм чтобы:

- Undo восстанавливало не только объекты но и связки между ними?
- Загружать (безболезненно и без акробатики с индексами) не только объекты но и связки между ними?
- сообщать ссылающемуся о том что ссылка изменилась (по-умному, а не напрямую)?

Интересует (предлагаю обсудить) общий механизм который поможет во всем этом. Если же Вы считаете что это проблемы частные/локальные - просто не отвечайте.
Записан
spectre71
Гость
« Ответ #25 : Сентябрь 11, 2009, 16:14 »

1) У меня куча разных объектов и разных базовых списков с ними, а также ссылок и списков со ссылками на эти объекты. И никаких проблем с невалидностью ссылок на объект после удаления его где-то(например в базовом списке) не возникает. Я просто не допускаю таких ситуаций! Удалил объект - удалил(или обнулил) ссылки на него, а как правило лучше наоборот сначала разбираемся со ссылками, а затем уже удаляем объект.
2) Не спорю, что в некоторых случаях это не удобно, но как правило такие случае возникают из-за плохого проектирования. В исключительных случаях можно пользоваться всякими "умными указателями" и им подобным вещам. Нужно ли это и какая модель того-же "умного указателя" или какого-нибудь "мультиссылочного супер-саморастворяемого Улыбающийся объекта" необходима зависит от твоей задачи.
Записан
spectre71
Гость
« Ответ #26 : Сентябрь 11, 2009, 16:42 »

Теперь по поводу undo/redo. Опять же все зависит от конкретной задачи! Сделать абстрактную систему объектов с операциями дабавления/удаления/перемещения/изменения + undo/redo безсмысленно!
- для текста это один механизм,
- для списка к примеру можно перемещать элементы в другой список для простого их восстановления потом в основном
- для сложной системы, также можно куда-то перемещать элементы и запоминать связи, а можно периодически(например на определенные операции) снимать копии системы целиком(для чего хорошо подходит сериализация)

- Undo восстанавливало не только объекты но и связки между ними?
Можешь снимать копии(через сериализацию или другими методами).

- Загружать (безболезненно и без акробатики с индексами) не только объекты но и связки между ними?
Сериализация.

- сообщать ссылающемуся о том что ссылка изменилась (по-умному, а не напрямую)?
Всякие "умные указатели" и "глупые объекты" Улыбающийся и еже им подобная дребедень используемая как правило при плохом проектировании.
А на напрямую и не обязательно:
- можно например оповещать элементы системы (хотя бы через те же сигналы/слоты) об изменеии состояний связанных(или
взаимодействующих) с ними элементов.
- можно создавать отношения типа родитель-потомок
« Последнее редактирование: Сентябрь 11, 2009, 16:46 от Spectre » Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #27 : Сентябрь 11, 2009, 17:14 »

Я своего мнения не навязываю. Если у Вас в проекте таких злосчастных проблем нет - то и слава богу. Просто у меня они есть и уже достали конкретно  Показает язык
Теперь по поводу undo/redo. Опять же все зависит от конкретной задачи! Сделать абстрактную систему объектов с операциями дабавления/удаления/перемещения/изменения + undo/redo безсмысленно!
Я и не претендую чтобы "чудесная система/механизм" за меня undo делал. А хочу просто писать undo разумно.  

- для текста это один механизм,
- для списка к примеру можно перемещать элементы в другой список для простого их восстановления потом в основном
- для сложной системы, также можно куда-то перемещать элементы и запоминать связи, а можно периодически(например на определенные операции) снимать копии системы целиком(для чего хорошо подходит сериализация)
Для меня всякое копирование исключено. Объекты должны быть реально удалены и указатели на них будут невалидны. Снимать копии системы мне тоже не подходит (боюсь диска не хватит). Давайте на том же простом примере:

Есть 3 объекта QString. Пользователь удалил 2-ю. Естественно, перед удалением мы записали ее в стек undo. Все хорошо, но эта строка входила в set(ы). Значит и указатели на нее в set'ах должны быть удалены. Как сказать undo что надо восстановить связки?
Записан
BRE
Гость
« Ответ #28 : Сентябрь 11, 2009, 17:25 »

Есть 3 объекта QString. Пользователь удалил 2-ю. Естественно, перед удалением мы записали ее в стек undo. Все хорошо, но эта строка входила в set(ы). Значит и указатели на нее в set'ах должны быть удалены. Как сказать undo что надо восстановить связки?
Для выполнения это операции нужно выполнить два действия:
* Если в наборе есть указатель на этот объект - убрать указатель из сета;
* Удалить объект.

Для выполнения undo также нужны два действия:
* Создать объект
* Добавить указатель на него в сет.

Какие проблемы?  Улыбающийся
Записан
spectre71
Гость
« Ответ #29 : Сентябрь 11, 2009, 18:08 »

Для меня всякое копирование исключено. Объекты должны быть реально удалены и указатели на них будут невалидны. Снимать копии системы мне тоже не подходит (боюсь диска не хватит). Давайте на том же простом примере:
- Естественно снимать копии можно только относительно небольших систем.
- Можно снимать копии отдельных частей системы, и при undo восстанавливать связи части с остальной системой.
Естественно что применение данного подхода разумно не во всех случаях.

Есть 3 объекта QString. Пользователь удалил 2-ю. Естественно, перед удалением мы записали ее в стек undo. Все хорошо, но эта строка входила в set(ы). Значит и указатели на нее в set'ах должны быть удалены. Как сказать undo что надо восстановить связки?
Опять абстрактная задача. Ну хорошо, приведу один абстрактный пример решения.

1) Базовый объект(аналогично QObject) назовем IObject в отличии от QObject может привязываться ко многим родителям, соответственно имеет как список детей, так и список родителей.
2) Аналогично QObject, при удалении IObject, в деструкторе, удаляет себя из списка всех родителей вызовом метода "removeFromAllParents", это метод публичный и может быть вызван без деструкции объекта(отвязка от родителей)
3) Родитель, в зависимости от его типа, может так-же вызвать removeFromAllParents ребенка и после уничтожить его, или просто вызвать метод ребенка removeFromParent(this)
4) Можно для IObject иметь только одного Главного родителя(котрый разрушает) и список Дополнительных родителей(которые просто связаны) с ним.

Дальше развивать не буду. Подобные схемы взаимодействия объектов решают твою проблему удаления из sets при удалении из главного set. Или другую задачу, разрушение объекта при удалении из всех sets(или последнего который его содержал). Еще решаются проблемы аналогичные оповещению всех(или части) родителей об изменении состояния объекта

====
Теперь по поводу примера.
Сделай классы IMainSet, и ISet. С Каждым добавляемым IObject связан флаг актуальности (int), если он 0, то IObject актуален(содержится в set), если нет, то IObject отброшен. флаг типа int для отслеживания уровней отброшенности.
IMainSet имеет метод destroyObjects(int level=0), разрушает все IObject с флагом >= level. Метод removeObject не удаляет объект, а меняет его флаг актуальности.
IMainSet - для главного предка, ISet - второстепенных.
Используя систему оповещения IObject всех своих родителей об изменении, легко автоматически сменить актуальность объекта во всех sets одновременно.
Это просто набросок, захочешь сделаешь как надо.
Дальше развивать не буду, устал. Грустный

« Последнее редактирование: Сентябрь 11, 2009, 18:12 от Spectre » Записан
Страниц: 1 [2] 3   Вверх
  Печать  
 
Перейти в:  


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