Если бы microsoft не была такой ленивой...
Как-то в предыдущих статьях я уже упоминал о прекрасной (и полезной!) возможности операционной системе линукс, суть которой заключается в том, что можно окну любого приложения придать статус "Поверх всех". Казалось бы мелочь, но в реальной жизни очень удобно. И очень жаль, что в Windows такой возможности нет. Даже подумываю утилитку написать, которая будет это реализовывать.
Сегодня возникла еще одна идея, реализовав которую, microsoft смогла бы заработать нехилую благодарность, как от пользователей, так и от программистов. Особенно от программистов.
Дело в том, что рано или поздно перед разработчиками прикладных программ встает проблема проверки этого самого правописания в вводимом пользователями тексте. Вот и я тоже наступил на эти грабли.
Искать сторонние компоненты, проверяющие синтаксис по своим словарям я не стал, т.к. подобные библиотеки-модули как правило платные и разработаны где-нить на западе. Да и сами алгоритмы проверки, которые отлично справляются с английским языком, при переходе на великий-могучий обычно начинают откровенно глючить и косячить. На то он великий и могучий. В нем одних только приставок и суффиксов столько, что ни один буржуйский рядом не стоял. Потому западные алгоритмы терпят такое же фиаско, как французы под Полтавой.
Отечественные наработки не сильно лучше. Причина, видимо, в том, что они в основе своей содержат все те же западные поделки, которые наши умельцы слегка "адаптировали" под русский. В результате получаем тот же косяк, только вид "с боку".
Наилучшим решением в данной ситуации является использование механизма из уже упомянутого microsoft Office. Как ни странно, но офисный алгоритм от майкрософта справляется с русским гораздо лучше всяких сторонних изобретений. Даже странно как-то. Но факт.
Ну что ж, офис, так офис! Тем более, что большинство разработчиков именно его модули и использует.
Начинаю копать. Первым делом естественно MSDN. Попытка найти нужное решение "в лоб" терпит крах (как обычно), потому начинаю думать головой.
Теоретически к офису обратиться можно через технологию COM (Component Object Model), значит роем MSDN на тему привязки COM-объектов к C#-коду. И тут же получаем готовый пример именно проверки правописания в свобственной программе, используя механизм из microsoft Word. Вот это удача!
Правда без косяков не обошлось. Пример, описанный во всех деталях в MSDN, у меня просто не откомпилировался. :)
Пришлось снова подумать головой, и снова покопаться в доках, и даже переустановить Office. Наконец мое рвение получило по заслугам - "оно" наконец заработало. Но радости, как и следовало ожидать, не принесло. Как это обычно делает мелко-мягкая контора, пример оказался хоть и рабочим (правда с натяжками), но совершенно неприменимым в практической жизни.
Замеченные в первые минуты неудобства:
- Проверка осуществляется только над всем текстом целиком и состоит в вызове стандартного окна замены неверно написанных слов. Следствие – очень ограниченная функциональность.
- При каждой проверке запускается сам Word (хоть и в фоне в невидимом окне) и по окончании проверки убивается. Следствие – тормоза.
- После окончания проверки и перед тем как окно Ворда будет убито, оно странным образом появляется на экране, хотя при создании ему ясно указали быть невидимым. Следствие – моргание полноэкранного окна ворда поверх вашей программы при каждой проверке орфографии.
- Для связи с вордом используется промежуточная сборка (в умных книжках ее зовут RCW – Runtime COM Wrapper или "COM-оболочка времени выполнения" - на мой взгляд весьма жудкое название). Т.е. связь с вордом устанавливается еще в момент запуска программы (ранне связывание) и, если на машине клиента вдруг ворда не кажется или окажется, но другой версии, то ваша программа покажет пользователю большую фигу в виде фолта. А пользователи фиг очень не любят. Следствие – катастрофическая зависимость от наличия определенной версии ворда в системе.
- Сама RCW представляет собой не что иное как DLL-файл, который придется таскать вместе с программой (без него тоже получите фолт, причем уже вне зависимости от наличия ворда на машине клиента). Размер у этой библиотеки ни много, ни мало, а целых пол-мегабайта. И это лишь для передачи вызовов из NET в COM и обратно. Стоит задуматься.
Короче, предлагаемый майкрософтом вариант меня полностью не устроил. Мне бы хотелось, чтоб выполнялись следующие условия:
- Была возможность определять правильность отдельных слов, без окон замены и т.д. Программе нужно лишь определить, правильно написано это слово или неправильно. Весь остальной механизм с заменами и словарями – дело техники.
- Для работы программа использовала бы только одну копию ворда, т.е. при старте программы он загружается, при завершении программы – выгружается
- Никаких внешних признаков присутствия ворда – окошек, мограний и т.д.
- Нормальная обработка отсутствия ворда в системе. Т.е. даже если офис не установлен, программа должна корректно работать (естественно уже без проверки орфографии).
- Отсутствие потребности в каких бы то ни было дополнительных сборках-библиотеках. Тем более таких диких размеров.
Согласитесь, требования весьма скромные. Значит и реализация должна быть достаточно простой. А вот собственно и она:
/*********************************/
/* Simple Spell Checker */
/* Copyright (C) FIT-Media, 2008 */
/* http://fit-media.com */
/*********************************/
using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
public class SpellChecker : IDisposable
{
System.Type TWord = null; object com_app = null;
private static SpellChecker Checker = new SpellChecker();
private SpellChecker()
{
try {
TWord = Type.GetTypeFromProgID("Word.Application");
com_app = Activator.CreateInstance(TWord);
}
catch { com_app = null;}
}
public static SpellChecker GetChecker() { return Checker; }
public void Dispose()
{
if (com_app != null) {
object[] arg = { null, null, null };
TWord.InvokeMember("Quit", BindingFlags.InvokeMethod,
null, com_app, arg);
com_app = null;
}
}
public bool CheckWord(string word)
{
object[] arg = { word };
return (bool)TWord.InvokeMember("CheckSpelling",
BindingFlags.InvokeMethod, null, com_app, arg);
}
}
Пример настолько прост, что в пояснениях не нуждается. Он реализует лишь минимальный базовый уровень - проверку единственного слова. Весь остальной функционал допишите сами (кому нужно) - там уже ничего сложного нет.
Единственное, на что стоит обратить внимание, это необходимость вызова метода SpellChecker.Dispose() при завершении работы вашей программы. Иначе запущенная копия ворда останется в памяти (привет нормальным пацанам из microsoft и их гениальному сборщику мусора) и будет болтаться там до перезапуска системы.
А-а-а, сейчас глянул на начало статьи и понял, что начал об одном, а потом как-то незаметно пришел совсем к другому. :)
Если вы не против, то я все же вернусь к рассказу о моей идее и лени мелко-мягких.
Суть идеи сводится к "глобализации" системы проверки правописания, которая уже встроена в microsoft Office. Прикол в том, что практически 100% программ используют для ввода текста элементы управления, встроенные в операционную систему.
Так вот, достаточно встроить механизм проверки орфографии в саму ОС и подключить его к двум основным средствам ввода текста (в терминах NET Framework это TextBox и RichTextBox), как абсолютно все программы, без какого бы то ни было вмешательства разработчиков, приобретут возможность отображения неверно написанных слов. А перед счастливыми программистами больше никогда не встанет задача реализации в своих программах этой самой "проверки грамотности ввода".
Кстати, при таком подходе словари тоже окажутся глобальными, т.е. добавили вы в словарь слово в ворде и его уже опознают все остальные программы. Здорово? Конечно!
Вот только дети дяди Билла толи сильно ленивые, толи очень жадные (что скорее всего) и ни за что не хотят дать нам всем такую замечательную возможность. :(
Как создать хороший интерфейс пользователя?
Нужен ли нам специальный метод разработки пользовательского интерфейса?
Каждый день разработчики программного обеспечения создают интерфейс своих программ без применения каких-либо специальных методов. Нужен ли нам вообще метод разработки пользовательского интерфейса? Я думаю нужен, и вот почему:
- Пользователи думают, что интерфейс - это и есть программа.
- Чтобы пользователи работали более продуктивно, программа должна быть простой в использовании.
- Достижения технологии значительно увеличили количество решений, которые необходимо принимать во время разработки интерфейса
- Общеплатформенные стандарты пользовательского интерфейса решают только 15% вопросов разработки в типичном проекте.
- Большинство программных проектов ограничены во времени.
- Пользователи становятся все более привередливыми.
- Хороший интерфейс может стать преимуществом против конкурентов, плохой - послужить причиной неудачи всего проекта.
Разработчики программ могут последовать простому прагматическому методу, кратко описанному в этой статье. Более подробно этот метод описан в моей книге "GUI Design for Dummies".
Выяснение целей и ограничений проекта
Начните процесс создания интерфейса с определения целей проекта а также внутренних и внешние обстоятельств, которые вы должны принять во внимание. Убедитесь, что клиенты или руководители проекта согласны с вашим анализом ситуации, и все остальные участники проекта по крайней мере проинформированы.
Рекомендую вам уделить одинаковое внимание следующим пунктам:
- Пользователи: их опыт работы с компьютером, мотивы, размер/важность групп пользователей, образцы (типовые ситуации) использования
- Задачи: что послужило причиной создания проекта, этапы создания проекта, какие результаты должны быть получены, какая информация необходима и когда
- Технология разработки и платформа, на которой будут работать пользователи
- Среда, в которой будет создаваться и использоваться проект (физическая, рыночная, организационная и культурная)
Используйте эту информацию для определения и расстановки приоритетов. Вот пара простых примеров:
- Когда группа пользователей постоянно меняет свой состав и предполагаемый образец использования используется нечасто, акцентируйте внимание на простоте понимания интерфейса
- Когда одна и та же задача повторяется многократно, и группа пользователей довольно большая, самой важной целью должна быть эффективность использования.
Если вы пропускаете шаг выяснения целей в своем процессе разработки, вы рискуете получить:
- Неожиданное или неконтролируемое повторение процесса разработки, когда некоторые важные факторы становится известны вам слишком поздно в процессе разработки. "Что? У пользователей будут экраны с разрешением 800х600? Окна нашей программы просто не поместятся на экране!"
- Много дискуссий без значительного прогресса
- Вы не оправдаете ожиданий спонсоров вашего проекта (людей у которых есть причины забоится о доходе)
Начальная фаза разработки: концептуальный дизайн
В этой фазе разработки вы должны решить какой интерфейс лучше всего будет подходить для достижения ваших целей - текстовый, графический или мультимедиа. Затем выберите наиболее подходящую структуру взаимодействия. Например, для графического интерфейса пользователя выбор следующий:
- Множественные окна
- MDI (много-документный интерфейс)
- Множественные фреймы
- Неструктурированное взаимодействие: экраны с гиперссылками
Различные структуры взаимодействия обеспечивают разные степени гибкости для пользователей. Обычно, чем гибче структура, тем больше она требует от пользователя обучения, понимания, и времени на работу с окнами (открыть, закрыть, разместить и т.д.). Основывайте ваш выбор на той собранной вами информации о пользователях и ситуациях, в которых они работают, а не просто делайте вашу программу похожей на среду разработки. В конце концов, среда разработки была разработана для вас, а не для пользователей.
Затем создайте концептуальную модель программы. Под концептуальной моделью я имею в виду чертеж, схему, которая показывает главные элементы, процессы и связи в программе с точки зрения пользователя. Вам нужно другое определение концептуальной модели? Как насчет такого: "абсолютный минимум, который пользователь может понять о программе, и тем не менее успешно пользоваться ею". Ваш дизайн - ваши окна, меню и текст - должен передать это понимание пользователю. Вот почему вы должны разработать детальную концептуальную модель. Если у вас есть только нечеткая модель того, что вы пытаетесь сказать пользователю, он в конце концов останется с еще более нечеткой идеей того что делает ваша программа и как она работает.
Для выполнения начальной фазы разработки погрузитесь целиком в задачи пользователей и создайте бумажный прототип навигационной модели. Навигационная модель показывает, как вы планируете распределять функции или задачи между окнами вашей программы. Навигационная модель определяет как пользователям смогут перемещаться как между различными задачами так и внутри отдельной задачи. Например, можно ли будет оставить частично завершенную задачу и начать другую.
Для того чтобы создать хороший интерфейс, на каждой стадии разработки необходима обратная связь от пользователей. Чтобы оценить концептуальную модель программы, вы можете просто показать ее схему пользователям и попросить объяснить ее вам. Если у них возникнут трудности, значит вы еще не достигли точки зрения пользователя в понимании проблемы.
Если вы пропустите раннюю фазу разработки, ваш интерфейс может страдать от следующих проблем:
- Несоответствие группам пользователей
- Сложность в обучении
- Неадекватная степень гибкости
- Нецелостное или непредсказуемое использование разных типов окон
Разработка на основе задач пользователя
Итак, ваши окна пока не имеют содержания. Вы знаете для чего нужно каждое, но для того чтобы наполнить их элементами управления, вам необходимо четкое понимание задач пользователя. Когда вы проводите интервью, задавайте открытые вопросы, чтобы пользователь мог дать вам ответ на основе своих действий. "Пожалуйста покажите мне какие типы документов вы храните на своем компьютере" - гораздо лучший вопрос чем "Используете ли вы текстовый редактор для заметок?".
Для создания дизайна, представьте в деталях, как бы пользователь выполнил данную задачу от начала до конца. Отметьте те места, в которых ваша программа может помочь ему в его работе. Затем сконструируйте окна, основываясь на своих заметках. И снова, проверьте результаты, проведя простые тесты с окнами или их набросками.
Например, прорабатывая задачи для программы планирования расписаний я обнаружила, что учителя обычно создают планы уроков для нескольких предметов даже если они еще не знают в какой день и в какое время будут проходить занятия. Исходная программа, которую я оценивала, имела ориентированный на расписание подход, встроенный в базу данных, так что учителя могли планировать уроки только назначив их дату и время.
Если вы не будете использовать этот подход, вы рискуете создать программу, в которой пользователи будут перемещаться от одного окна к другому для того, чтобы выполнить свою задачу. Процесс разработки, основанный на задачах пользователей особенно важен, когда ваша программа предназначена для того, чтобы помогать пользователям работать быстрее и эффективнее.
Визуальный дизайн: использование компонентов
На этом этапе вы должны правильно использовать компоненты визуального дизайна чтобы показать пользователю для чего нужно каждое окно, и как им пользоваться.
Хорошо выполненный дизайн выглядит чистым, простым и аккуратным. Его можно понять одним взглядом. Пользователь должен сразу распознавать какие данные можно редактировать, какие нет; по каким объектам можно щелкать мышью и какие объекты можно перетаскивать.
Чтобы выполнить этот этап, вы должны понимать, как пользователь воспринимает различные элементы управления. Существует понятие "предоставленная возможность" (affordance), хотя сам термин выглядит довольно неуклюже. "Предоставленные возможности" это визуальные характеристики объектов, которые сигнализируют о том, что с ними можно сделать. Например гребни на крышке банки с овощами говорят мне о том, что крышка отвинчивается, а не открывается открывашкой. Поля ввода, например, приглашают пользователя ввести любое текстовое или числовое значение. Если же набор вводимых величин ограничен, то лучше использовать выпадающий список.
Вы также должны понимать принципы визуальных сообщений. Размер, цвет, яркость, местоположение, форма и текстура - все это средства, которые используются для того чтобы сгруппировать элементы вместе по важности или по похожести. Если у вас есть возможность воспользоваться услугами профессионального визуального дизайнера, не пренебрегайте ею.
Если вы пропустите эту стадию, вы рискуете получить программу, которая выглядит непрофессионально и непривлекательно. Если вы будете пренебрегать визуальным дизайном, ваша программа будет посылать хаотические сигналы, что приведет к увеличению ошибок, путанице и раздражению пользователя.
И снова, если вы хотите знать, какие сигналы вы подаете, не спрашивайте "Что я сказал?". Вместо этого спросите свою аудиторию, как они восприняли это.
Проверка на пользователях
Половина процесса разработки - это анализ и создание; вторая половина - получение обратной связи, и применение полученной информации.
Если вы хотите быть уверенным что ваша программа понравится пользователям, собирайте мнения потенциальных пользователей во время процесса разработки. Тестирование на пользователях даст вам наиболее верную информацию. Так же как и в визуальном дизайне существуют люди, чья профессиональная работа - проводить тестирование на пользователях. Если вы сможете привлечь специалиста по usability или human factors - это замечательно. Если нет, учитесь проводить тесты самостоятельно.
Тестирование на пользователях это не обсуждение дизайна с пользователями. В тестировании вы предлагаете пользователю выполнить определенное задание на некоторой версии вашей программы (рисунок одного окна, бумажный прототип, или рабочая система). Затем вы должны молча наблюдать за тем, что происходит. Вы можете даже снять весь процесс на видео или просто делать заметки.
Тестируя бумажные прототипы на нескольких разных пользователях, вы можете выявить множество серьезных usability-проблем еще до того, как приступите к кодированию. Тестируя готовую программу до ее официального выпуска вы можете найти и подчистить небольшие проблемы, которые могут стать причиной раздражения пользователя.
Запомните - все системы тестируются на пользователях. Вопрос только в том, хотите ли вы, чтобы это случилось когда вы еще можете исправить найденные проблемы. Думайте о тестировании как о способе получить новую информацию. Наблюдение пользователей в процессе тестирования вашей программы это самый лучший и самый дешевый способ образования.
Автор: Laura Arlov
Грамотный интерфейс: поля ввода
Очень часто в программах данные вводятся в формах, содержащих множество полей: поле фамилии, имени, адреса, номера паспорта, размера обуви... Проблема состоит в том, что внешне эти поля очень похожи друг на друга и рано или поздно оператор (из-за усталости, по неопытности или по какой другой причине) вобьет фамилию в поле номера паспорта или адрес в поле отчества.
Отследить программно такого рода ошибки бывает довольно сложно: попробуйте написать модуль который бы смог отличить имя человека от названия населенного пункта или номер телефона от номера паспорта. Частично решить эту проблему позволяют контролы, принимающие ввод по маске (MaskEdit или MaskEditBox), но, честно говоря, им не хватает гибкости. Да и оператору с ними работать не очень удобно ибо капризны они.
Гораздо лучше изначально создать такие условия ввода данных, чтобы подобные ошибки просто не возникали.
Рассмотрим варианты.
Решений тут несколько. Наиболее популярное на данный момент - разбить форму с десятком полей ввода на несколько форм, по два-три поля в каждом. Такое решение можно часто встретить при регистрации на всяких интернет-сайтах. Для интернета это оказывается удобным, но в оффлайновых программах, где вводимых данных гораздо больше, возникает масса проблем:
- необходимо предусмотреть в каждой следующей форме отображение введенных данных из предыдущих форм, чтобы пользователь мог видеть, что он уже ввел ранее;
- для изменения ранее введенных данных (например неверно введенной фамилии) необходимо сделать в формах навигацию "вперед - назад";
- проблема "раздутия проекта" из-за создания множества по-сути бесполезных форм;
- достаточно сложно управлять таким интерфейсом, используя только клавиатуру - время от времени пользователю все же придется хватать в руки мышь, а это не есть хорошо;
- и т.д. и т.п.
Программировать такой интерфейс - сплошная морока, да и пользователи от него не в восторге. Значит будем искать другое решение.
Нам нужно, чтобы интерфейс каким-то образом подсказывал пользователю, что именно от него (пользователя) требуется в данный момент. И очень желательно, чтобы эти подсказки не отвлекали и в тоже время были достаточно заметными, чтоб пользователь не смог их проигнорировать.
Всплывающие подсказки (ToolTips) тут не годятся, т.к. после нескольких часов работы они начинают дико раздражать. Кроме того, чтоб понять что именно нужно программе, подсказку нужно прочесть - а это приводит к рассеиванию внимания. Сообщения в статус-строке (StatusBar) вещь вобщем-то не плохая, но не привлекают должного внимания, поэтому они могут использоваться лишь как вспомогательное средство. Я предлагаю другой вариант.
Раскрасим поля ввода.
На мой взгляд для решения вышеописанной проблемы необходимо разукрасить фон полей ввода. Но не стоит делать их яркими как новогодняя елка, а нужно просто слегка изменить цвет, чтобы каждое поле приобрело свой уникальный легкий цветовой оттенок. Поработав пару часов с таким интерфейсом, человек уже на уровне подсознания будет знать, что в розовое поле нужно вводить фамилию, а в голубое - адрес.
Наше сознание устроено таким образом, что даже малейшее несоответствие вызывает у нас в мозгу стоп-сигналы, заставляющие нас остановиться и проверить все ли верно мы делаем. Обратите внимание как просто мы находим нужную кнопку на пульте от телевизора (ориентируясь не на рисунок-пиктограмму, а только на цвет) и как сложно бывает воспользоваться пультом от другого телевизора, в котором кнопки расположены по-другому и имеют другую раскраску.
Окрашивание полей имеет и еще один плюс - если разработчики в будущем поменяют расположение полей, но при этом сохранят их цветовое соответствие (фамилия - розовый, адрес - голубой), то пользователям будет намного легче приспособиться новому виду, т.к. для поиска нужного поля они будут ориентироваться по цвету, а не читать все подряд надписи на форме.
Раскрасим формы
В продолжение идеи предлагаю раскрашивать и формы, в зависимости от выполняемых действий. Суть состоит в том, что для ввода новой записи в базу и для редактирования уже введенной записи как правило используется одна и та же форма. Так вот, если во время редактирования придать фону формы какой-нибудь оттенок (например сделать ее слегка красноватой), то пользователь, занимающийся только вводом новых данных, сразу же заметит это изменение цвета и не введет по ошибке новые данные поверх старых.
Ну и чтоб поставить жирную точку в вопросе путаницы при вводе и редактировании данных опишу еще одно простое, но очень полезное улучшение интерфейса.
Раскрасим текст.
Когда на форме расположено множество полей, то из-за усталости глаз, не очень хорошего зрения, слишком высокого разрешения монитора и многих других проблем возникает ситуация, когда пользователь не может сразу отпределить позицию коретки ввода - моргающая полоска может быть не заметна. Обычно в таких случаях пользователь хватает мышь и "тычет" ей в нужное поле.
Помочь пользователям в этом случае можно раскрасив текст в текущем поле ввода. Программируется такое поведение сверх-просто: как только фокус ввода передается какому-то контролу, значение его свойства "цвет текста" (ForeColor, TextColor) меняется на "красный" (Color.Red), а при потере фокуса контролом цвет текста восстанавливается на стандартный (SystemColors.WindowText). Это простое дополнение даст возможность пользователю всегда точно знать, где именно находится коретка ввода и что именно нужно сейчас вводить.