Проектирование взаимодействия с пользователем
При проектировании внешних сопряжений программной системы разработчик интересуется тремя областями, имеющими отношение к надежности программного обеспечения:
– минимизацией ошибок пользователя;
– обнаружением ошибок пользователя, когда они все же возникают;
– минимизацией сложности.
Ошибки пользователя увеличивают вероятность перехода системы в непредвиденное состояние. Минимизация ошибок пользователя не уменьшает числа ошибок в программном обеспечении, но увеличивает его надежность за счет уменьшения вероятности обнаружения оставшихся ошибок. Основные правила минимизации ошибок пользователя в диалоговых системах:
1. Согласовывайте способ взаимодействия с подготовкой и уровнем пользователя, а также с ограничениями, в условиях которых пользователь работает. Например, можно ожидать, что взаимодействие с пользователем банковской системы должно существенно различаться в зависимости от того, является ли пользователь клиентом банка или опытным кассиром.
2. Проектируйте таким образом, чтобы сообщения, вводимые пользователем, были как можно короче, но не настолько, чтобы исчезла их осмысленность. При этом учитывайте частоту работы с системой для среднего пользователя (часто или изредка), а также возможность стрессовой ситуации для пользователя в момент его работы с системой.
3. Обеспечивайте концептуальную целостность для разных типов вводимых и выводимых сообщений. Например, все сообщения должны иметь одинаковые форматы, стиль, сокращения.
4. Обеспечивайте развитые средства помощи.
5. Старайтесь, чтобы система «не рассердила» пользователя, поскольку это может привести к некоторым неожиданным ситуациям на входе. Избегайте оскорбительных сообщений системы, общайтесь с пользователем на его языке, а не на жаргоне программистов.
6. Всегда на каждое входное сообщение выдавайте какое-нибудь уведомление (кроме тех случаев, когда реакция системы сама является уведомлением). Без этого пользователь может засомневаться, правильно ли сообщение было введено, и попытается повторить ввод, вследствие чего может возникнуть ошибочная ситуация.
Помимо минимизации ошибок пользователя система должна также надлежащим образом обращаться с ошибками, если они все-таки возникают – а возникать они будут независимо от того, насколько хорошо были спроектированы правила взаимодействия. Например, операторы Московской системы диспетчеризации такси в свободное время развлекались тем, что пытались вывести систему из строя, подавая заведомо неправильные сообщения.
Основные правила обнаружения ошибок пользователя:
1. Спроектируйте систему так, чтобы она принимала любые данные. Если введенная информация не является тем, что системы считает допустимым, она должна информировать пользователя.
2. Если пользователь вводит сложное сообщение, особенно если для этого нужно несколько обращений к системе, позвольте ему проверить это сообщение, прежде чем оно начнет обрабатываться.
3. Проектируйте систему так, чтобы ошибки пользователя обнаруживались немедленно. Если пользователь вводит вероятность ошибки на символ, не прописанную в лабораторной работе, лучше сразу указать ему на это обстоятельство, чем выполнить расчеты, ошибочность которых обнаружится только при оформлении отчета.
4. Там, где особенно важна аккуратность, обеспечьте избыточность входных данных: например, самопроверяемые счета в банковских системах.
Непосредственное отношение к надежности имеет еще одна задача – минимизация сложности внешнего проекта с целью уменьшения внутренней сложности будущей системы и минимизации ошибок пользователей. Распространено представление, что «гуманизированный» внешний проект должен быть сложным. Это представление ошибочно.
Вопрос, который всегда возникает при внешнем проектировании диалоговой системы, – подсказывать ли пользователю, в какой части входного сообщения содержится ошибка. Предположим, что студент задал вероятность ошибки на символ, равную 10–4, при кратности исправляемой ошибки 2.
Система обнаруживает ошибку: указанная вероятность ошибки на символ не предполагает работы с кодами, исправляющими двукратную ошибку. Следует ли системе сообщать студенту, что он ошибся при введении вероятности ошибки на символ и просить его исправить именно эту величину? Но студент мог ошибиться не здесь, а при вводе кратности исправляемой ошибки. Возникает ситуация, заводящая пользователя в тупик. Вывод – неправильные запросы надо вводить заново целиком. Проще всего записывать их в буфере и предоставлять пользователю для исправления текст через буфер.
Вторая проблема, связанная со сложностью системы, – представление пользователю слишком большого числа дополнительных возможностей и вариантов. В операционной системе OS/360 имелся процесс настройки, называемый «генерация системы», позволяющий перекраивать систему при ее настройке. Это привело к тому, что почти каждая установка OS/360 способствовала появлению очередной уникальной операционной системы, и неудивительно, что возникли проблемы с ее сопровождением.
До широкого распространения Delphi и С++ для научных и инженерных вычислений использовался язык ПЛ/1. Он содержал такой широкий набор синтаксических конструкций и встроенных функций, что, вероятно, не существует ни одного компилятора, поддерживающего все возможности этого языка. Простое перечисление всех вариантов вызова компилятора занимало две страницы руководства для пользователей. В результате неопытный пользователь долго и мучительно пытался сообразить, как же откомпилировать его маленькую простейшую учебную программу. Вообще говоря, обилие дополнительных возможностей неблагоприятно сказывается на работе пользователя, подталкивая его к выбору по принципу «скорее всего, так» и приводя к последствиям неправильного выбора. Разработчик должен тщательно рассмотреть каждую предоставляемую возможность, сопоставляя ее полезность и степень усложнения ПО. Когда имеются сомнения, безопаснее отказаться от рассматриваемого варианта. Множество доступных мелких возможностей не повысит конкурентоспособности продукта, а скорее всего, негативно повлияет на потенциального покупателя, показывая, что разработчик не имеет ясного представления о том, как именно его система будет использоваться.
Таким образом, для обеспечения надежности при разработке взаимодействия с пользователем необходимо обеспечить его единообразие и простоту, ожидать на входе всего, немедленно обнаруживать как можно больше ошибок и не пытаться их исправлять, а предоставить этот тонкий вопрос на рассмотрение пользователю.
Подготовка внешних спецификаций
Внешнее проектирование может быть представлено в виде двух этапов: предварительного и детального внешнего проектирования. В случае если спецификации организованы иерархически, этим двум этапам соответствуют просто контрольные точки в процессе нисходящего проектирования системы. Первый шаг в разработке внешних спецификаций – обрисовать основные компоненты (или то, что находится на верхнем уровне), второй шаг – обрисовать компоненты, третий – внешние функции (функции пользователя) и, наконец, детали всех функций пользователя.
Предварительное внешнее проектирование включает три первых шага. Система проектируется до такого уровня, когда уже выделены все функции пользователя, но их точные синтаксис, семантика и выходные результаты остаются еще не определенными. Этим преследуются две цели: во-первых, внутри продолжительного процесса внешнего проектирования устанавливается контрольная точка для руководства; во-вторых, становится возможной проверка правильности промежуточного уровня проекта и сопоставление его с поставленными целями.
Правильно составленные внешние спецификации – объемный документ. Чтобы справиться с таким большим документом, лучше всего применить иерархическую организацию. С успехом применяется метод, который состоит в том, чтобы разбить спецификации на основные компоненты, затем просто компоненты и, наконец, функции. Допустим, одна из основных компонент – управляющий библиотекой. В рамках этой основной компоненты примером компоненты может быть администратор секретности. В рамках этой компоненты примером функции будет запрос СООБЩИТЬ О НАРУШЕНИЯХ СЕКРЕТНОСТИ.
Детальный внешний проект каждой функции пользователя должен освещать следующие вопросы:
1. Описание входных данных. Точное описание синтаксиса (например, формат, допустимые значения, области изменения) и семантики всех данных, вводимых пользователем. Этими данными могут быть и команда, и ответ на подсказку, и введенная пластиковая карта, и аналоговый сигнал.
2. Описание выходных данных. Точное описание всех результатов функции (например, реакция терминала, сообщения об ошибках, отчеты, управляющие сигналы). Должна быть описана функциональная связь входных данных с выходными; это значит, что читатель спецификаций должен быть в состоянии представить себе выходные данные, порождаемые каждым конкретным вариантом входных. Для каждой функции должны быть указаны также результаты для всех (по возможности) неправильных входных данных.
3. Преобразования системы. Многие внешние функции не только порождают выходные данные, но изменяют также состояние системы. Здесь должны быть описаны все такие преобразования системы, но при этом следует помнить, что речь идет о внешних спецификациях, поэтому преобразования должны быть описаны с точки зрения пользователя. Например, тестовая система имеет команду «выполнить тестирование», которая используется студентом, чтобы начать написать тест. Эта функция имеет два выходных результата: результат, который выводится на терминал студента, и результат, который выводится на терминал преподавателя. Она вызывает также преобразование системы: изменяется база данных результатов тестирования.
4. Характеристики надежности. Описание воздействия всех возможных отказов функций на саму систему, файлы и пользователя. Практика показывает, что включение этого раздела оказывает небольшое, но положительное влияние на надежность. Хотя разработчики внутренней структуры системы никогда сознательно не допустят, чтобы ошибка, например в запросе пользователя, вызвала общий отказ системы, этот раздел служит постоянным напоминанием об этом.
5. Эффективность. Описание всех требований, которые предъявляются к эффективности функции, таких как затрачиваемое время и используемая память. Эффективность редко удается указать в абсолютных терминах, поскольку она зависит от конфигурации аппаратуры, скорости линий связи, эффективности всех остальных параллельно выполняемых программ, числа активных пользователей терминалов и т.д. Чтобы справиться с этой проблемой, в спецификациях можно описать несколько стандартных конфигураций и уровней нагрузки, а затем указать эффективность отдельных функций по отношению к ним.
6. Замечания по программированию. Внешние спецификации должны описывать продукт с точки зрения пользователя и избегать ограничений на внутреннее устройство системы. Однако иногда бывает необходимо подсказать или сообщить какие-то идеи относительно внутреннего проектирования функции. Практиковать это следует как можно реже, но, если это необходимо, соответствующую информацию следует сообщать в этом разделе.