Re[3]: Общие принципы организации GUI для редактирования модели данных
От: maxkar  
Дата: 08.08.13 17:37
Оценка:
Здравствуйте, _hum_, Вы писали:

Давайте уточним, о чем мы говорим. Об "общем случае" или о какой-то конкретной ситуации. Про "общий случай" я расскажу, но ответы, скорее всего, будут совсем не те, которые вы ожидаете.

__>Вопрос же был не в том, как именно выдавать сообщение об ошибочных данных, а в том, как узнать, что процесс ввода завершен, и можно эту проверку начинать.

Какой ввод? Зачем ввод? Все очень зависит от конкретики. В некоторых случаях "можно начинать проверку" на любое редактирование. В некоторых — по смене фокуса. В некоторых — при нажатии на кнопку "сохранить" или начале любого другого действия, не связанного с редактированием (неявный commit данных). Повторю — для различных ситуаций будут различные решения.

__>И да, хоть, как вы говорите, "может быть ситуация, когда нужно валидировать содерижмое нескольких полей вместе", это ничего не меняет, так как фокус ввода всегда находится на каком-то конкретном поле, а значит, именно его данные в данный момент редактируются и ответственны за нарушение целостности — все остальные УЖЕ ВНЕСЕНЫ В МОДЕЛЬ и проблемы с нарушением целостности не представляют (а "подсветить" их при необходимости — плевое дело).


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

Пример "сочетания полей". Заказ билетов в поезде. Нужно указать дату, маршрут, номер поезда, номер вагона, номер места. Допустим, мне на определенную дату места не понравились. Я после этого изменил дату. Оказалось, что в тот день поезд короче или место занято. Вы предлагаете подсвечивать последнее поле ввода или все-таки что-то другое? Заметьте, причиной невалидности стало одно поле, но проблема будет решаться правкой других полей.

И не говорите, что "у вас не так". Сначала расскажите, какая конкретно у вас ситуация и для чего делается UI.

Еще одно замечание. О какой "модели данных" вы говорите? Есть модель UI (которая одним образом обрабатывает валидацию и "невалидная модель" — нормальное состояние). Есть бизнес-модель и модель данных, в которых уже "не допускаются" невалидные данные (невалидные — в рамках сценариев). И модификация бизнес-модели обычно привязана все-таки к какому-нибудь действию (явное сохранение и т.п.).

M>> 2. Выполнять валидацию только по нажатию кнопки и подсвечивать "Невалидные" поля.


__>Какой кнопки? Такое возможно только в случае использования отдельных диалоговых окон редактирования.

Почему? Хотя в основном — да, в окнах редактирования. Но все зависит от приложения. Точнее, от момента начала действия над данными. Вполне может быть кнопка и для сохранения всех внесенных в "таблицу"/список данных. А до этого отдельно подсвечивать невалидные и измененные строки. Или у вас "сохранение" данных автоматически на каждую правку? Это редкий сценарий. Но возможный. В этом случае проще всего обучить оператора и объяснить, что данные сохраняются "сразу после исправления". Кстати, вполне естественно будет в таком случае сохранять любое валидное состояние после редактирования. А может даже и не валидные. Например, оператор начал что-то вводить в текстовое поле и куда-то ушел. В зависимости от задачи можно "потерять" эти изменения, а можно сохранить.

__>А если речь идет о работе с самим исходным представлением данных модели (например, с таблицей), то никаких кнопок попросту нет.

Не важно, какое "исходное представление" для разработки UI! Нужно делать удобный UI. Если "исходное представление" неудобное, значит, нужно его адаптировать в нужную модель в UI. "Таблицы в виде модели предметной области" встречаются не слишком часто. А все остальное нужно подгонять под пользователя, а не под "архитектуру".

M>> 3. Выполнять валидацию по клику и выводить информацию об ошибках в отдельном окне.

__>По какому клику? Вне зоны фокуса редактирования?

По клику, который какое-то действие с данными делает. Или явно сохраняет. Если автосохранение — то при любой смене фокуса.

M>>Данные очень разные и решения нужно подбирать к конкретным вводимым данным и сценариям пользователей. И от самого приложения тоже много зависит. В веб и "толстом клиенте" могут использоваться разные подходы (из-за ограничений архитектуры или используемых библиотек).

__>Это понятно, но неужели надо каждый раз изобретать велосипеды? Вроде ж какие-то концепты на эту тему типа MVC, MVP и проч. разрабатывались. Нет?

Так у всех пользователей свои задачи. Поэтому и взаимодействие пользователя с UI в каждом случае будет свое. Конкретные подходы определяются не "общей архитектурой" а предметной областью. И решения очень чувствительны к массе условий. А какой-нибудь MVC можно использовать. В совершенно общем виде. У вас есть модель UI. Не просто "модель", а именно "модель UI", в которой отражено текущее состояние UI (в том числе — незаконченный ввод и т.п.). Из этого состояния вычисляется валидность. Могут вычисляться прочие статусы (это вот изменившаяся строчка, которая UI уже как-то выделяется). Но это совершенно общие вещи и правильно их использовать в каждом конкретном случае — задача программиста.


__>В явном виде у меня это проблема проявилась при работе с таблицами (данные моей модели представляются в виде таблицы).

Так может это проблемы таблиц? Может, нужно списом с "плашками" определного формата?

__>Если начало редактирования здесь еще явное (пользователь щелкает мышью по ячейке — на месте ячейки вставляется появляется LineEdit, позволяющий осуществлять ввод), то с его завершением полные непонятки. В большинстве случаев неявно пользователю предлагается кликнуть где-нибудь на другой ячейке ("отщелкнуть"), чтобы "подтвердить ввод" тех данных, которые он вводил. Но! Во-первых, это настолько неявно, что многие пользователи просто этого не знают, из-за чего происходят ошибки (например, не "отщелкнул" последнее введенное значение и закрыл программу).


Можно (и нужно) обучить оператора. Нужно выдавать подтверждение о том, что данные могут быть потеряны (если у вас там автосохранение). А лучше сделать так, чтобы при закрытии последнее введенное изменение все равно сохранялось. Может быть, нужна кнопка "сохранить все" (т.е. данные не автосохраняются в постоянное хранилище, а явно, по клику). Это все можно сделать. И если этим заниматься с самого начала, это все будет достаточно просто. Никакой магии нет.

__>Во-вторых, поскольку обычно вид LineEdit отличается от вида ячейки только моргающим курсором, то для пользователя не очевиден момент: он при вводе значения СРАЗУ меняет это значение в модели, или это изменение происходит только после "отщелкивания"?

Ну сделайте явно заметный вид. На HTML я баловался и делал "сильный" фокус. Редактируемая область (примерный аналог вашей строки) выделяется рамкой. Все остальное немного засеривается. Выход делается явным подтверждением.

__>Ну и, в-третьих, нет возможности отмены введенного значения до его подтверждения (типа функции кнопки cancel в диалоговом окне редактирования).

Во-первых, у вас должны работать стандартные шоткаты (Ctrl-Z). Это уже позволяет отменять операции. Во-вторых, у вас там autosave? Вы же сами себя ограничили, что у вас нет явного "сохранения" (и откатываться некуда). Явная кнопка "сохранить" решает много проблем. С подсвечиванием изменений — еще больше. С возможностью отменить/посмотреть изменение в конкретной ячейке — еще больше. Это все нужно делать ручками. Можно для организации сделать и набор контролов, и набор интерфейсов моделей, если задачи частые. Да, нужно ручками работать. Но никаких космических технологий тут нет

__>Из этого я сделал вывод, что такое табличное представление (такой табличный контрол) нацелен именно на синхронное изменение данных в модели:

__> Но как быть, когда хочется использовать табличное представление с асинхронным изменением модели:

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

__>Для таблицы это должно было бы, например, выглядеть так:

__>1) щелчок по ячейке — появление в области ячейки минидиалогового окошка с LineEdit и двумя миникнопками, отвечающими "ОК", "Cancel".
__>2) ввод текста в LineEdit
__>3) нажатие кнопки "ОК"/"Cancel"
__>При попытке щелкнуть на другую ячейку при незавершенном нажатием одной из кнопок"ОК"/"Cancel", редактирование бы запрещалось (как в модальном диалоге).
__>Но почему-то я таких вариантов редактирования таблиц нигде не встречал....
Потому что это издевательство над пользователем. Пользователь же работает не с ячеками. Он с таблицей работает! И "моделью" в этом случае для пользователя является вся таблица, она неделима. То, что у вас там в UI по модели для каждого поля, никого не интересует.


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


Так не является "отдельное поле" моделью с точки зрения пользователя. И "единица редактирования" — это весь ваш экран ввода данных обычно. Именно что не отдельной ячекий. Напишите свои контролы в конце концов. У меня текстовые поля на каждый ввод модель меняют (UI-модель, сохранение — это отдельное действие для всего набора данных). Да, именно любое действие приводит к изменению состояния UI. Как моделировать "пользователь закончил ввод" — это отдельный сложный вопрос. И ответ на него тоже зависит от конкретных сценариев, под которые разрабатывается интерфейс. Общих решений здесь нет. Можно ведь и модальное поле с кнопками "ok/cancel" сделать. Мы где-то на одно текстовое поле делали еще небольшой диалог редактирования (потому что так оказывалось проще).

Общий подход в разработке UI — начать с анализа сценариев пользователей. И уже под это делать архитектурное решение. Общим оно не получится. Слишком требования разные. А вот для определенной области какое-то общее решение может оказаться приемлемым.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.