Блог → О построении пользовательского интерфейса. Часть 1

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

Часть интерфейса определяется аппаратными средствами, часть - особенностями операционной системы и т.д., и каждый из этих уровней вносит свои ограничения в построение интерфейса. Но самая важная его часть, конечно, определяется тем, что делает проблемная программа, но здесь нас больше будет интересовать не ЧТО именно она делает, а КАК организовано её взаимодействие с пользователем.

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

Однако использование стандартных средств создания интерфейса накладывает ограничения не только на способ общения программы с пользователем, что в общем-то полезно, но и на структуру самой программы, а тем самым осложняет построение программ, весьма простых при традиционных подходах.

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

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

Способы организации интерфейса

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

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



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

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

Состояния и события

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

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

Что такое состояние? Грубо говоря, состояние - это набор уникальных реакций на события. Состояния различаются в том случае, когда хотя бы на одно событие они реагируют по-разному. Состояние имеет следующие характеристики и атрибуты:
- тип, различаются только меню и остальные состояния;
- главное окно, это окно, в котором осуществляется работа в данном состоянии, с точки зрения пользователя;
- списки кодов событий, определяющих это состояние. Списков таких два: один включает события, при которых заведомо не происходит смены состояния и, следовательно, не требуется его регенерация, а другой - события, при которых может (но не обязательно) произойти смена состояния;
- функции инициализации состояния, его регенерации, временного и окончательного выхода из него. Эти функции автоматически вызываются пакетом при изменении текущего со стояния;
- указания на строку короткой подсказки и имя страницы в файле помощи для работы контекстной помощи.

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