На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! информация о разделе
user posted imageДанный раздел предназначается для обсуждения вопросов использования баз данных, за исключением составления запросов на SQL. Для этого выделен специальный раздел. Убедительная просьба - соблюдать "Правила форума" и не пренебрегать "Правильным оформлением своих тем". Прежде, чем создавать тему, имеет смысл заглянуть в раздел "Базы данных: FAQ", возможно там уже есть ответ.

Модераторы: Chow, Bas, MIF
  
> UI многопользовательской системы
    Добрейшего времени суток, уважаемые!

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

    Краткое описание проблемы

    Есть некоторая многопользовательская система, где пользователи могут редактировать данные, зачастую - могут пытаться работать с одними и теми же сущностями одновременно. Вопрос: а как удобнее?

    Реализации, которые доселе обсуждались

    1) Рекомендация Akina. Суть: пользователь независино от другого обрабатывает данные, помещая промежуточные данные во временные структуры БД. После желания пользователя занести все измененное в БД - программа открывает транзакцию и единым блоком переносит данные в основные таблицы БД. Если данные несогласованны, транзакция откатывается и пользователю предоставляется возможность данные скорректировать и повторить коммит.

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

    И в первом, и во втором варианте есть свои преимущества и недостатки. Буду опираться далее на свою, ранее решенную, задачу.

    По варианту Akin'ы реализовать повторное редактирование в случае невозможности согласования - просто не представляю как. Например, открывается 15 вложенных диалогов (а у меня на вложенность ограничений нет по ТЗ), на 2-м диалоге второй пользователь во время редактирования первым пользователем - запись удалил. В результате 13 "диалогов с данными первого пользователя" невалидны, ибо привязаны к уже несуществующей записи. Согласование невозможно. Пользователи такого не одобрят.

    По моему варианту нечто подобное возможно в случае нестабильной связи с серваком БД. Но тут мне проще перекинуть ответственность на сисадмина, нежели попытаться так же выстроить повторный каскадный "захват" сущностей бд и каскадное открытие транзакций. Ну и второй момент, против которого пользователи не особенно трепыхались, но все же ... это блокировки данных для редактирования для всех, кроме первого пользователя.

    Надумался третий подход

    Упоминания о нем тож есть в обсуждениях, в другой теме (так же упоминал Akina). В моем (том - втором) варианте это частично используется - для обновления таблиц в реальном времени. В принципе, очень даже удобно.

    Вот и возник вопрос (типа третий вариант): а что если вообще уйти от транзакций и блокировок? Актуализировать обновление полей (не записей!) в реальном масштабе времени в UI, типа pure push-UI? Иными словами, как только пользователь изменил поле - средствами БД идет уведомление всем подключенным пользователям. Если в данный момент они открыли диалог, где это поле присутствует - у них автоматом меняются измененные данные другим пользователем. Ну и некое уведомление о произошедшем (например над полем мелким шрифтом надпись "данные изменены пользователем Иванов").

    Пока сложность в случае если пользователь, который изменил данные диалога решил нажать Отмену. Хотя, навскидку, сложность не большая - просто храним в UI кто же последний изменил поле. В случае отмены - "возвращаем" предпоследнее значение и рассылаем всем "кто текущий автор этого предпоследнего значения".

    Вообщем, пока просто ищу способ упростить взаимодействие пользователей. На первый взгляд - последний вариант достаточно удобен и гладок в плане UI.
    Что скажете, push-методика имеет право на жысть?

    ЗЫ: На 100% от блокировок не уйти, вернее можно, но не комильфо. Пример: я бы заблокировал удаление редактируемой записи. Вариант автоматического схлопывания диалога(ов) у всех пользователей с уведомлениями, если один из них удалил эту запись - ИМХО, как-то совсем кощунственно :lol:
      С планшета, посему пока коротко.

      Редактируемые сущности - это всегда дерево?
      Если второй юзер намрен грохнуть сущность второго уровня, надо ли заставлять его полчаса ждать пока первый юзер поправит сущность десятого уровня? Всё одно она сдохнет, что правленая, что нет.
      Чем третий подход отличен от первого, кроме того, что сведения о корректировке поступают сразу, а не при попытке сохранения?
        Цитата Akina @
        Редактируемые сущности - это всегда дерево?

        Нет, это произвольный (почти) неограниченный граф. По связям "Семья" из любой Карточки Клиента (КК) можно открыть (добавить, удалить, редактировать) любую другую КК из этой семьи. В данный момент повторное открытие одних и тех же - запрещено логикой (блокировкой). Но!!! ... по свзям "Групповое Обслуживание" (Карточка Обслуживания = КО) можно в принципе зацепить на редактирование 100% всех карточек из БД (как КК, так и КО), и это возможно и заложено в UI, лишь бы на компе пользователя хватило памяти. Хотя, по факту, такую глубину открытия диалогов делают не часто. Максимум 10-15, дальше обычно логика правок не уходит. В гипотетической ситуации, когда формируется группа обслуживания из 15 клиентов, и все новые, и все с семьями по 2-3 человека, возможно до 40-50 диалогов. Я предлагал пользователям строить работу иначе, сперва ввод и сохранение КК, а потом уже формирование КО. Это немного больше по количеству действий, но "прозрачнее", ИМХО. Но, увы, юзера добрались до описанной выше методики (вернее разобрались), делают в обратной последовательности - сперва создают Карточку Обслуживания (групповую), прямо в ней создают новые Карточки Клиентов, там же, объединяют их в семьи, и сохраняют. Говорят, что им так частенько гораздо удобнее. Короче за уши не оттянешь :)

        Цитата Akina @
        Если второй юзер намрен грохнуть сущность второго уровня, надо ли заставлять его полчаса ждать пока первый юзер поправит сущность десятого уровня?

        Пока это так. Но если делать без блокировки по варианту 1 и 3, то девять уровней выше потеряем, то ли из-за невозможности согласования, то ли из-за "схлопывания" девяти вышестоящих диалогов. Поэтому считаю это единственный момент, где блокировка оправдана.

        Цитата Akina @
        Чем третий подход отличен от первого, кроме того, что сведения о корректировке поступают сразу, а не при попытке сохранения?

        Отсутствием необходимости арбитража "чьи данные более актуальны". В третьем варианте это решается просто, без необходимости введения временных штампов модификации данных, нужных для этого арбитража, ибо - все в рилтайме.
          Цитата JoeUser @
          юзера добрались до описанной выше методики (вернее разобрались), делают в обратной последовательности - сперва создают Карточку Обслуживания (групповую), прямо в ней создают новые Карточки Клиентов, там же, объединяют их в семьи, и сохраняют.

          На этом пути (как, впрочем, и на альтернативном) я слабо представляю себе конфликт с другим оператором системы. Это же ж надо не только внести правки в карточку, но и вообще догадаться, что в системе появилась эта самая новая карточка, которую можно править.

          Цитата JoeUser @
          это произвольный (почти) неограниченный граф. По связям "Семья" из любой Карточки Клиента (КК) можно открыть (добавить, удалить, редактировать) любую другую КК из этой семьи. В данный момент повторное открытие одних и тех же - запрещено логикой (блокировкой). Но!!! ... по свзям "Групповое Обслуживание" (Карточка Обслуживания = КО) можно в принципе зацепить на редактирование 100% всех карточек из БД (как КК, так и КО), и это возможно и заложено в UI, лишь бы на компе пользователя хватило памяти. Хотя, по факту, такую глубину открытия диалогов делают не часто. Максимум 10-15, дальше обычно логика правок не уходит. В гипотетической ситуации, когда формируется группа обслуживания из 15 клиентов, и все новые, и все с семьями по 2-3 человека, возможно до 40-50 диалогов.

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

          Цитата JoeUser @
          Отсутствием необходимости арбитража "чьи данные более актуальны".

          Ой, да ладно! никуда он не делся. Просто арбитром стал ты, безапелляционно заявив, что прав всегда тот, кто первым изменил атрибут. И пофиг, как это согласуется с другими данными.

          Добавлено
          JoeUser
          На самомо деле я всё пытаюсь представить себе реакцию того самого конечного пользователя на обнаружение факта изменения "его" данных кем-то.

          И если по варианту 1 ему при попытке сохранения (т.е. тогда, когда он теоретически готов к такой ситуации) объявляют, что есть траблы, которые надо разрулить, и выдают в общем хоть какой-то консолидированный перечень этих неувязок, то по варианту 3 он это сообщение получает в случайный момент работы со случайным документом. Прикинь, счастьице - выкопать из груды окно, где произошли изменения, понять, как они увязаны со всем остальным, и тут же внести все необходимые коррективы, да при этом ещё не пролюбить мысль о том, что ты делал в момент оповещения, и в каком именно из полусотни окон - это при том, что рядом сидит и смотрит на тебя клиент, который и без того считает тебя тормознутым идиотом...
            Цитата Akina @
            но и вообще догадаться, что в системе появилась эта самая новая карточка, которую можно править.

            Ну так, используя push, пользователь видит уже динамическое содержание таблицы в реальном масштабе времени.

            Цитата Akina @
            Интересно, вот теоретически по описанной схеме у операторов просто обязаны образовываться дедлоки... чё они в таких случаях делают?

            Теоретически "да". Но с ростом количества записей в базе - вероятность дедлоков снижается, ибо правки данных в большинстве случаев проводятся на инфе вновь прибывших клиентов. А за это отвечает "первичка" (ну типа ресепшен), там всего два сотрудника. В рамка UI моей программы реализован интерфейс типа ICQ, на тех же NOTIFY. Могут разрулить самостоятельно. А ... хотя нет, диалоги-то модальные. Надо будет подумать.

            Цитата Akina @
            Ой, да ладно! никуда он не делся. Просто арбитром стал ты, безапелляционно заявив, что прав всегда тот, кто первым изменил атрибут. И пофиг, как это согласуется с другими данными.

            Это в моей нынешней реализации. А в случае варианта 3 - прав тот, кто осознанно меняет чужую правку. Мне кажется - это более логично. В конечном счете, зачем мне изобретать арбитраж, если я могу перенести это на энд юзера. Его предметная область, вот пусть разбирается.

            Цитата Akina @
            И если по варианту 1 ему при попытке сохранения (т.е. тогда, когда он теоретически готов к такой ситуации) объявляют, что есть траблы, которые надо разрулить, и выдают в общем хоть какой-то консолидированный перечень этих неувязок, то по варианту 3 он это сообщение получает в случайный момент работы со случайным документом. Прикинь, счастьице - выкопать из груды окно, где произошли изменения, понять, как они увязаны со всем остальным, и тут же внести все необходимые коррективы, да при этом ещё не пролюбить мысль о том, что ты делал в момент оповещения, и в каком именно из полусотни окон - это при том, что рядом сидит и смотрит на тебя клиент, который и без того считает тебя тормознутым идиотом...

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

            user posted image

            Вот смотри, пусть таких диалогов открыто 15. Сотрудник начал сохранять. На предпоследнем диалоге (в случае варианта 3) можно вкладки, где были изменения, раскрасить красным цветом, label полей - красным, измененные поля - розовым. Ну так, для примера, дахоть фиолетовым. Над измененными полями всунуть надпись шрифтом 7pt о последнем изменении и слева кнопочку принять. Для осознания, что в момент редактирования какой-то карточки выше, кто-то поправил данные в ниже стоящей карточке - "сигналов" ну просто предостаточно. Осталось только "принять" (что вас это устраивает), ну или вернуть на старое значение.

            ... а сослуживцу посредством системы оповещения прислать "КГ/АМ" :lol:

            Заметь - никаких извращений в плане анализа "правомерна-неправомерна правка". Хм ... я даже сам себя убедил! :lool:
              Цитата JoeUser @
              используя push, пользователь видит уже динамическое содержание таблицы в реальном масштабе времени.

              Вот ты правда думаешь, что затраханный манагер видит, что в двадцатом окне из сорока открытых нарисовалось что-то новое? А если тебе придёт в голову всплывать ему окно, в котором произошли изменения, то убивать тебя будут с особой жестокостью...

              Цитата JoeUser @
              пусть таких диалогов открыто 15. Сотрудник начал сохранять.
              ...
              Осталось только "принять" (что вас это устраивает), ну или вернуть на старое значение.

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

              Цитата JoeUser @
              прав тот, кто осознанно меняет чужую правку.

              Это не обсуждается. Тем более что подробное протоколирование и волшебный пендаль виновному, ежели чего не то, никто не отменял...
              Блин, но как же часто чужие правки меняют НЕосознанно! вернее, бессознательно... с последующим "Да я ничего не делал!"...
                Цитата Akina @
                Это не обсуждается. Тем более что подробное протоколирование и волшебный пендаль виновному, ежели чего не то, никто не отменял...
                Блин, но как же часто чужие правки меняют НЕосознанно! вернее, бессознательно... с последующим "Да я ничего не делал!"...


                На каждую правку у меня ведется журнал правок - и от доступен в режиме чтения всем сотрудникам. Тут уж хрен отвертисся. Как говорилось в классике "Позвольте! У меня все ходы записаны!"(С) :lol: И ежемесячно делается сброс в архив и чистка. Я себя обезопасил в плане "я не знаю, оно само".

                Цитата Akina @
                Вот ты правда думаешь, что затраханный манагер видит, что в двадцатом окне из сорока открытых нарисовалось что-то новое?


                Так ему это по барабану. Ну тока если была одна строчка, а станет две (типа добавилась) - заметит. Если же ему что-то действительно нужно - все уже привычным образом лезут в строковый фильтр - 2-4 критерия, и из 3000 тыщ записей в таблице остается 3, выбирай не хочу. Фильтр работает со всеми полями записей, как с текстом, в том числе - и с собираемыми "на лету". Тут вопрос - не вопрос.

                Цитата Akina @
                Угу. Вот теперь представь, что правка должна быть принята, но это требует внесения корректировок на предыдущих, уже закрытых, формах.

                Если она правомерная и законная, значит в данный момент автор этой правки - правит сам в тех "закрытых диалогах". Но в логике моей программы такого нет. Единственный момент, какой я вижу, невозможности чистого push - удаления. Ну я уже об этом писал.

                Хотя это разруливается и сейчас норм - веду журнал текущей работы в отдельной таблице. Если кто че открыл на изменение - там создается запись PID сотрудника, имя таблицы и номер записи. Пока это есть - логика программы удалить не даст. Если сотрудник "отвалился" от БД, не беда. Каждое действие выполняется в два этапа:

                1) Пробую удалить - не могу, запись есть
                2) А если почистить невалидные PID'ы - тогда норм
                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                0 пользователей:


                Рейтинг@Mail.ru
                [ Script execution time: 0,0358 ]   [ 16 queries used ]   [ Generated: 26.04.24, 18:09 GMT ]