Задумался об идеологически правильной обработке ошибок (исключительных ситуаций) в приложениях для обычных пользователей.
Конечный итог ошибки может быть таким:
1. Подсветить поле с неверно введенными данными. Самый мягкий случай, когда ошибка ввода данных. Нужно сделать без перехода и диалогов.
2. Отобразить пользователю диалог модальный, когда ошибка важная и требует чтобы пользователь увидел.
4. Отобразить всплывающее окошко. Когда ошибка не важна, скрывать будет не верно (хотя бы для целей отладки и светлого будущего программы), но и она особо погоды не строит.
5. Перевести пользователя в оффлайн-режим. К примеру, если нет подключения, но программа может работать в оффлайн.
6. Заставить пользователя пройти повторную авторизацию (переадресовать на форму входа). Если данные аутентификации отозваны, устарели и пр. Сюда же относим прочие переадресации на формы для обязательного ввода данных (а может быть и не обязательные).
7. Просто записать данные в лог/удаленный лог.
8. Ничего не делать — проигнорить, но оборвать текущую операцию.
9. Возможно — удалить текущую базу данных ввиду ее повреждения (если база не критична) или отобразить форму невозможности продолжения работы ввиду повреждения базы.
10. Попытаться устранить проблему автоматически — как-то устаревший формат файла — провести приведение к новому формату.
Итого — дофига разных вариантов какие типы реакций могут быть.
Фактически нужно помнить что каждая КАЖДАЯ операция может либо завершиться успешно — либо с ошибкой. Причем нужно правильно отреагировать — выбрать какой из 10 вариантов применить.
Есть типовые проблемы, которые могут возникнуть в любом приложении — но очень редко и маловероятно. К примеру, что если я выйду из RSDN, но форму с сообщением не закрою. Потом войду под другим аккаунтом и отправлю сообщение. Под каким пользователем оно опубликуется — под новым или под старым? А ведь я отвечал на сообщение старого пользователя, там от его имени все. Отож. Вывод:
Каждая операция должна проверять под каким пользователем она была начала и если пользователь в процессе операции изменился — то оборвать работу (или даже откатить изменения).
Благо что все эти проблемы возникают не так часто, можно об этом не думать, иначе архитектура усложняется на порядок.
Здравствуйте, Shmj, Вы писали:
S>Задумался об идеологически правильной обработке ошибок (исключительных ситуаций) в приложениях для обычных пользователей.
...
Здравствуйте, Shmj, Вы писали:
S>Задумался об идеологически правильной обработке ошибок (исключительных ситуаций) в приложениях для обычных пользователей
У Вас ошибка: п. 3 пропал.
Вообще, большая часть того, что Вы описали, это не исключительные ситуации, а вполне обычный flow, о котором должен думать ещë аналитик на этапе постановки задачи.
S>Благо что все эти проблемы возникают не так часто, можно об этом не думать, иначе архитектура усложняется на порядок.
Архитектура усложняется не от частоты ошибок, а от того, какие гарантии бизнес-операций мы хотим получить.
Здравствуйте, Shmj, Вы писали:
S>Конечный итог ошибки может быть таким:
Завтра мода на GUI поменяется, и список твой будет звучать по-другому.
В конечном итоге, сообщение об ошибке, как бы оно не выглядело, должно нести следующую информацию:
1. Чего, собственно, хотят от пользователя? Попробовать еще раз? Исправить ошибки ввода? Подёргать провод? Перезагрузиться? Позвать старщего? Позвонить в техподдержку? Отнести компутер в ремонт?
2. Что случилось с его запросом? Он вообще не исполнен? Он исполнен наполовину? Деньги ушли, но пылесос не приедет?
3. Если есть негативные последствия, как их исправить?
4. Насколько всё это серьезно? Само рассосётся?
Ну, и кроме того, должна сохраняться подробная информация для профессионального разбора полётов.
S>Конечный итог ошибки может быть таким:
S>1. Подсветить поле с неверно введенными данными. Самый мягкий случай, когда ошибка ввода данных. Нужно сделать без перехода и диалогов.
валидация
S>2. Отобразить пользователю диалог модальный, когда ошибка важная и требует чтобы пользователь увидел.
ошибка
пункт 3 где? тоже вот, пожалуйста, ошибочка закралась ))
S>4. Отобразить всплывающее окошко. Когда ошибка не важна, скрывать будет не верно (хотя бы для целей отладки и светлого будущего программы), но и она особо погоды не строит.
уведомление (тост)
S>5. Перевести пользователя в оффлайн-режим. К примеру, если нет подключения, но программа может работать в оффлайн.
это вообще из другой тематики. В большинстве случаев этого не надо либо достаточно сделать через пункты 2 или 4
S>6. Заставить пользователя пройти повторную авторизацию (переадресовать на форму входа). Если данные аутентификации отозваны, устарели и пр. Сюда же относим прочие переадресации на формы для обязательного ввода данных (а может быть и не обязательные).
редирект
S>7. Просто записать данные в лог/удаленный лог.
логгирование
S>8. Ничего не делать — проигнорить, но оборвать текущую операцию.
+пункт 2 или 4
S>9. Возможно — удалить текущую базу данных ввиду ее повреждения (если база не критична) или отобразить форму невозможности продолжения работы ввиду повреждения базы.
ОМГ что???
S>10. Попытаться устранить проблему автоматически — как-то устаревший формат файла — провести приведение к новому формату.
бизнес-логика
S>Итого — дофига разных вариантов какие типы реакций могут быть.
S>Фактически нужно помнить что каждая КАЖДАЯ операция может либо завершиться успешно — либо с ошибкой. Причем нужно правильно отреагировать — выбрать какой из 10 вариантов применить.
Итого: 1 пункт про ошибку + 1 про уведомляшку. Остальное про всякое разное стандартное полезное: логгирование, валидация и бизнес-логика
Здравствуйте, DiPaolo, Вы писали:
S>>1. Подсветить поле с неверно введенными данными. Самый мягкий случай, когда ошибка ввода данных. Нужно сделать без перехода и диалогов. DP>валидация
Ну да, обработка ошибки пользователя по месту. Можно и модальный диалог "Вы ввели неверный email" [ОК].
S>>2. Отобразить пользователю диалог модальный, когда ошибка важная и требует чтобы пользователь увидел. DP>ошибка
DP>пункт 3 где? тоже вот, пожалуйста, ошибочка закралась ))
S>>4. Отобразить всплывающее окошко. Когда ошибка не важна, скрывать будет не верно (хотя бы для целей отладки и светлого будущего программы), но и она особо погоды не строит. DP>уведомление (тост)
Красное уведомление — чтобы было понятно что есть проблема и возможно требуется решение. К примеру — временное уведомление — фоновая операция не удалась, сервер не доступен.
S>>5. Перевести пользователя в оффлайн-режим. К примеру, если нет подключения, но программа может работать в оффлайн. DP>это вообще из другой тематики. В большинстве случаев этого не надо либо достаточно сделать через пункты 2 или 4
Почему из другой? К примеру, у тебя есть некая фоновая операция по обновлению данных. Если обновление не удалось — можно отобразить пользователю — не удалось, нет подключения. Но постоянно терзать его этими сообщениями — уже не комильфо — нужно бы просто отобразить плашку — "оффлайн-режим".
S>>6. Заставить пользователя пройти повторную авторизацию (переадресовать на форму входа). Если данные аутентификации отозваны, устарели и пр. Сюда же относим прочие переадресации на формы для обязательного ввода данных (а может быть и не обязательные). DP>редирект
Так редирект то — как реакция на ошибку протухших данных доступа. Это реакция на исключительную ситуацию, т.к. в стандартном случае данные сами собой не протухают. А так сервер вернул ошибку — мы должны как-то отработать.
S>>7. Просто записать данные в лог/удаленный лог. DP>логгирование
Перехватил исключение — и залогировал в фоновом сервисе, т.к. клиент не видит формы никакой, это происходит без клиента. Нельзя никому ничего отобразить.
S>>8. Ничего не делать — проигнорить, но оборвать текущую операцию. DP>+пункт 2 или 4
Тут смотрите как важно. Если изменился пользователь а некая операция продолжила выполняться и завершилась после смены пользователя — то это не ошибка, это штатное поведение. Но при этом нельзя применять результаты данной операции — нужно сгенерить исключение. Но! Пользователю и даже в лог вносить это исключение смысла нет, т.к. ситуация штатная и доп. решения не треубет.
S>>9. Возможно — удалить текущую базу данных ввиду ее повреждения (если база не критична) или отобразить форму невозможности продолжения работы ввиду повреждения базы. DP>ОМГ что???
Да, а что. Если база повреждена — что делать? Если это локальная копия-кеш серверной — удалить и запросить данные заново. А если же база важна — то отобразить как есть, пусть пользователь нанимает специалиста по восстановлению баз данных — ему виднее, может сектор какой на диске полетел.
S>>10. Попытаться устранить проблему автоматически — как-то устаревший формат файла — провести приведение к новому формату. DP>бизнес-логика
Ну оно все бизнес-логика, по сути. То что окошко красное — это не выводит из разряда бизнес-логики.
DP>Итого: 1 пункт про ошибку + 1 про уведомляшку. Остальное про всякое разное стандартное полезное: логгирование, валидация и бизнес-логика
Даже первый пункт — это бизнес-логика. Это все бизнес-логика, но бизнес-логика по обработке исключений.
Здравствуйте, Pzz, Вы писали:
Pzz>Завтра мода на GUI поменяется, и список твой будет звучать по-другому.
Нет, это не зависит от GUI никаким образом. Более того — часть пунктов не применима к GUI — а только к фоновым сервисам.
Pzz>В конечном итоге, сообщение об ошибке, как бы оно не выглядело, должно нести следующую информацию: Pzz>1. Чего, собственно, хотят от пользователя? Попробовать еще раз? Исправить ошибки ввода? Подёргать провод? Перезагрузиться? Позвать старщего? Позвонить в техподдержку? Отнести компутер в ремонт?
Очень важен вариант обработки ошибки вот какой, копирую:
Если изменился пользователь а некая операция продолжила выполняться и завершилась после смены пользователя — то это не ошибка, это штатное поведение. Но при этом нельзя применять результаты данной операции — нужно сгенерить исключение. Но! Пользователю и даже в лог вносить это исключение смысла нет, т.к. ситуация штатная и доп. решения не треубет.
Т.е. важно уметь оборвать операцию в процессе, но при этом не тревожить пользователя лишними оповещениями, т.к. это штатная ситуация.
Pzz>2. Что случилось с его запросом? Он вообще не исполнен? Он исполнен наполовину? Деньги ушли, но пылесос не приедет?
Тут не только что случилось. Допустим нет интернета. И что? Программа пытается сделать некую фоновую задачу — не получилось. Сообщать пользователю? Ведь он может проверить WiFi-роутер свой или оплатить задолженность по интернету провайдеру. Не сообщим — плохо. Но при этом дублировать сообщение о том что интернета нет каждые 3 секунды, доставать пользователя — так же плохо.
Читайте внимательно пункты — там не от балды а опыт 20 лет разработки.
Pzz>3. Если есть негативные последствия, как их исправить?
Если мы знаем как исправить — то можно исправить и без того, чтобы беспокоить пользователя.
Пробуйте практические примеры подобрать.
Pzz>4. Насколько всё это серьезно? Само рассосётся?
Нет сети, сервер не доступен — это, возможно, рассосется. Поврежден файл данных — уже усё. Не так много вариантов.
Pzz>Ну, и кроме того, должна сохраняться подробная информация для профессионального разбора полётов.
А вот это уже можно не отображать пользователю а отправлять разработчику в удаленный лог.
Здравствуйте, Shmj, Вы писали:
S>Очень важен вариант обработки ошибки вот какой, копирую:
S>
S>Если изменился пользователь а некая операция продолжила выполняться и завершилась после смены пользователя — то это не ошибка, это штатное поведение. Но при этом нельзя применять результаты данной операции — нужно сгенерить исключение. Но! Пользователю и даже в лог вносить это исключение смысла нет, т.к. ситуация штатная и доп. решения не треубет.
S>Т.е. важно уметь оборвать операцию в процессе, но при этом не тревожить пользователя лишними оповещениями, т.к. это штатная ситуация.
Это не "очень важен", это какое-то наркомание. Ложка огурцы банка майонез.
1. Что такое "изменился пользователь"? Во время операции ему (в другом потоке) изменили список ролей/привилегий? Или просто он отключился от "соединения"?
2. Что значит "применять результаты"? Операция — это, как правило, атомарное действие, у которого может быть результат (который просто возвращается, как результат вычисления выражения 2*3), а может быть эффект (который влияет на состояние, как результат выполнения стейтмента x = 2*3). Может быть и то и другое. В итоге, "не применять результаты" — это какой-то оксюморон: результат и так никуда не "применяют". А "не применять эффект" нужно детализировать: то ли разрешать частичное выполнение, то ли нет.
Вот, к примеру, MS SQL Server поддерживает heartbeet даже во время выполнения длинного запроса, который не предусматривает коммуникации с клиентом в процессе.
Ну, там insert into mytable(v) (select sum(values) from VeryLongTableWithoutAppropriateIndices lt where lt.tag % 17 = 3) — результат "1 row(s) updated" приедет только в самом-самом конце.
Но если я в процессе исполнения запроса отключусь (штатно там или аварийно), то сервер это заметит и выполнит rollback transaction.
3. Зачем генерировать исключение, которое вы не собираетесь ни вносить в лог, ни показывать кому-то?
В общем, вам надо аккуратно факторизовать задачу на составляюшие. И тогда решение станет очевидным.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
S>1. Что такое "изменился пользователь"? Во время операции ему (в другом потоке) изменили список ролей/привилегий? Или просто он отключился от "соединения"?
Это актуально не для того типа приложений, которое вы представили.
В моем случае программа десктопная (или мобильная), вход осуществлен под одним пользователем всегда. Одна база открывается в при открытии программы. При этом пользователь может выйти и зайти под другим никнеймом, в то время как некие операции продолжат выпоняться и запишут результат своей работы (после запроса к серверу) — уже на имя нового пользователя.
Варианты решений?
S>2. Что значит "применять результаты"? Операция — это, как правило, атомарное действие, у которого может быть результат (который просто возвращается, как результат вычисления выражения 2*3), а может быть эффект (который влияет на состояние, как результат выполнения стейтмента x = 2*3). Может быть и то и другое. В итоге, "не применять результаты" — это какой-то оксюморон: результат и так никуда не "применяют". А "не применять эффект" нужно детализировать: то ли разрешать частичное выполнение, то ли нет.
1. Сделал запрос к серверу — получил данные от сервера. Раз.
2. Внес новые данные от сервера в таблицу.
Какая тут может быть атомарность?
S>Вот, к примеру, MS SQL Server поддерживает heartbeet даже во время выполнения длинного запроса, который не предусматривает коммуникации с клиентом в процессе.
Это другая ситуация.
S>3. Зачем генерировать исключение, которое вы не собираетесь ни вносить в лог, ни показывать кому-то?
TG>Вообще, большая часть того, что Вы описали, это не исключительные ситуации, а вполне обычный flow, о котором должен думать ещë аналитик на этапе постановки задачи.
Хорошие у тебя аналитики. У меня обычно на доске нарисуют несколько квадратов со стрелочками и норм.
Жизнь не обязана доставлять удовольствие. Достаточно отсутствия страданий.
Здравствуйте, s_aa, Вы писали:
>>Но в универах так практически никто этого не делает...
D>>Исправил
_>И в реальном бизнесе так сплошь и рядом. Надо быстро и ещё вчера.А когда развернется все, нас тут скорее всего уже не будет.
И поэтому мы сейчас занимаемся стабилизацией так написаных, но важных и глючных фич. И проектируем обработку обшибок вместо тех, которых "уже здесь нет".
Здравствуйте, Shmj, Вы писали:
S>Это актуально не для того типа приложений, которое вы представили.
Это актуально для всех типов приложений. S>В моем случае программа десктопная (или мобильная), вход осуществлен под одним пользователем всегда. Одна база открывается в при открытии программы. При этом пользователь может выйти и зайти под другим никнеймом, в то время как некие операции продолжат выпоняться и запишут результат своей работы (после запроса к серверу) — уже на имя нового пользователя.
Вот это и есть дизайн в стиле безумного шляпника, который создаёт вам проблемы.
S>Варианты решений?
Не делать безумное чаепитие. S>1. Сделал запрос к серверу — получил данные от сервера. Раз. S>2. Внес новые данные от сервера в таблицу.
Пока что вы описали ровно вариант "получить результат запроса". Если пользователь отключился — всё, результат ему не нужен. Зачем вы берётесь записывать этот результат в какие-то таблицы? Пользователь явно выразил своё намерение завершить сессию. Нужно ли извещать сервер о том, что результат не нужен — дело вкуса.
S>Какая тут может быть атомарность?
Очень простая. Но детали сильно зависят от того, что именно делает приложение. С учётом окружающих рассуждений, велики шансы на то, что вы вместо одного из двух типовых паттернов изобрели ещё какое-то безумие.
Поэтому советы по реализации давать трудно.
Остаётся только повториться: вы делаете какую-то дичь, именно поэтому никакие типовые решения вам не подходят. Ни в какой области. Ни в области персистенса, ни в области асинхронного программирования, ни в области обработки ошибок.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
S>Вот это и есть дизайн в стиле безумного шляпника, который создаёт вам проблемы.
Говорите конкретно что не так.
S>Пока что вы описали ровно вариант "получить результат запроса". Если пользователь отключился — всё, результат ему не нужен.
Он вышел, но программу не закрыл — старые операции продолжают работать. Механизма отмены нет.
S>Зачем вы берётесь записывать этот результат в какие-то таблицы? Пользователь явно выразил своё намерение завершить сессию. Нужно ли извещать сервер о том, что результат не нужен — дело вкуса.
Весь вопрос в том — как делать отмену. Будете ли вы встраивать в каждый сетевой запрос возможность отмены?
S>>Какая тут может быть атомарность? S>Очень простая. Но детали сильно зависят от того, что именно делает приложение. С учётом окружающих рассуждений, велики шансы на то, что вы вместо одного из двух типовых паттернов изобрели ещё какое-то безумие.
Атомарность может быть при записи в базу. А когда внешний вызов — атомарности быть не может, разве что внешний сервис это предусмотрел — но сразу проблема двух генералов, которая неразрешима в принципе.
S>Поэтому советы по реализации давать трудно. S>Остаётся только повториться: вы делаете какую-то дичь, именно поэтому никакие типовые решения вам не подходят. Ни в какой области. Ни в области персистенса, ни в области асинхронного программирования, ни в области обработки ошибок.
Так напишите как вы решите задачу:
1. Пользователь сделал запрос к серверу от имени Вася.
2. Пока идет запрос — пользователь Вася вышел и зашел под пользователем Петя. Программу не останавливали.
3. Пришел ответ запрос, но теперь текущий пользователь — Петя.
4. ?
Здравствуйте, Shmj, Вы писали:
S>Говорите конкретно что не так.
Я вам конкретно сказал, что не так. S>Он вышел, но программу не закрыл — старые операции продолжают работать. Механизма отмены нет.
Зачем они "продолжают работать", когда пользователь уже вышел?
S>Весь вопрос в том — как делать отмену. Будете ли вы встраивать в каждый сетевой запрос возможность отмены?
Я же вам вроде бы объяснял, что делать с отменой.
1. Не делать её вообще. Нет никакой разницы, вышел пользователь, или отключился, или у него на клиенте пропало питание. Действие на стороне сервера дорабатывает до конца.
2. Делать отмену на основе транзакционности. См. пример с MS SQL Server.
S>Атомарность может быть при записи в базу. А когда внешний вызов — атомарности быть не может, разве что внешний сервис это предусмотрел — но сразу проблема двух генералов, которая неразрешима в принципе.
Поэтому придумали REST.
S>Так напишите как вы решите задачу:
S>1. Пользователь сделал запрос к серверу от имени Вася. S>2. Пока идет запрос — пользователь Вася вышел и зашел под пользователем Петя. Программу не останавливали. S>3. Пришел ответ запрос, но теперь текущий пользователь — Петя. S>4. ?
Нет такой задачи. Вы её себе нафантазировали, и теперь огребаете.
Упростим ваш сложный сценарий%
1. Пользователь сделал запрос к серверу от имени Вася.
2. Пока идёт запрос — пользователь Вася вышел
Или так:
1. Пользователь сделал запрос к серверу от имени Вася.
2. Пока идёт запрос — пользователь Вася остановил программу
Или так:
1. Пользователь сделал запрос к серверу от имени Вася.
2. Пока идёт запрос — операционная система на клиентской машине аварийно завершила программу
Или так:
1. Пользователь сделал запрос к серверу от имени Вася.
2. Пока идёт запрос — клиентская машина аварийно завершилась (села батарея, отключилась сеть, и т.п.)
Внезапно оказывается, что если научиться обрабатывать одну из этих ситуаций, то автоматически получится ответ на все эти ситуации, и, заодно, на все более сложные сценарии вроде придуманного вами выше.
И способ — очень простой:
1. Пишем в локальную базу "мы собираемся сделать к серверу вот такой запрос" (атомарно)
2. Делаем запрос
3. Получив ответ на запрос, пишем в базу "на запрос получен вот такой ответ" (атомарно).
0. При старте системы, поднимаем из локальной базы список всех запросов, которые прошли через п.1 и не прошли через п.3. Повторяем для всех их них п.2 и 3.
Всё понятно?
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
S>>Весь вопрос в том — как делать отмену. Будете ли вы встраивать в каждый сетевой запрос возможность отмены? S>Я же вам вроде бы объяснял, что делать с отменой. S>1. Не делать её вообще. Нет никакой разницы, вышел пользователь, или отключился, или у него на клиенте пропало питание. Действие на стороне сервера дорабатывает до конца. S>2. Делать отмену на основе транзакционности. См. пример с MS SQL Server.
Так речь о действии на стороне клиента — у клиента своя база.
S>>Атомарность может быть при записи в базу. А когда внешний вызов — атомарности быть не может, разве что внешний сервис это предусмотрел — но сразу проблема двух генералов, которая неразрешима в принципе. S>Поэтому придумали REST.
И как он решит задачу, которая не разрешима даже в теории?
S>Внезапно оказывается, что если научиться обрабатывать одну из этих ситуаций, то автоматически получится ответ на все эти ситуации, и, заодно, на все более сложные сценарии вроде придуманного вами выше. S>И способ — очень простой: S>1. Пишем в локальную базу "мы собираемся сделать к серверу вот такой запрос" (атомарно) S>2. Делаем запрос S>3. Получив ответ на запрос, пишем в базу "на запрос получен вот такой ответ" (атомарно).
S>0. При старте системы, поднимаем из локальной базы список всех запросов, которые прошли через п.1 и не прошли через п.3. Повторяем для всех их них п.2 и 3.
1. Тебе нужно проверить что текущая открытая база (а это десктопное или моб. приложение) — та же самая, того же пользователя. Что если пользователь другой?
2. Результат запроса нужно не только сохранить в базе, но и применить на форме. Пользователь нажал на кнопку — делаем запрос к серверу, обновляем таблицу, отображаем на форме. Если пользователь изменился (но форма все так же доступна через IoC глобально) — то что?
Здравствуйте, Shmj, Вы писали:
S>И как он решит задачу, которая не разрешима даже в теории?
Очень просто — вероятностным образом.
S>>0. При старте системы, поднимаем из локальной базы список всех запросов, которые прошли через п.1 и не прошли через п.3. Повторяем для всех их них п.2 и 3. S>1. Тебе нужно проверить что текущая открытая база (а это десктопное или моб. приложение) — та же самая, того же пользователя. Что если пользователь другой?
У каждого пользователя — своя база. Например. Или нет — зависит от архитектуры.
Например, если бы мы велосипедили клиента к RSDN, то вполне можно было бы использовать ровно одну базу. Потому что состояние локальной реплики никак не зависит от того, под каким пользователем выполняется репликация.
Ну, разве что админские форумы видны только админам; удалять ли их во время репликации под "обычным" аккаунтом — дело вкуса заказчика.
А если бы мы велосипедили, к примеру, почтовый клиент, то для каждого аккаунта создавали бы отдельную базу. Возможность совместного показа писем из нескольких баз была бы решением продакт менеджера (например, в мобильном Outlook она есть, в десктопном — нету).
S>2. Результат запроса нужно не только сохранить в базе, но и применить на форме.
Какой ещё форме? Пользователь вышел из приложения, всё, никаких форм нету.
S>Пользователь нажал на кнопку — делаем запрос к серверу, обновляем таблицу, отображаем на форме. Если пользователь изменился (но форма все так же доступна через IoC глобально) — то что?
То увольняем того, кто так спроектировал. Раз уж он не поддаётся обучению. Либо форма была открыта в контексте пользователя, и при логауте она обязана закрыться. Либо форма открыта в "глобальном" контексте, и тогда её всё равно, кто там пользователь.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.