Два лица вашего сайта

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

Когда в пользовательском интерфейсе, предназначенном для использования человеком, слишком явно просвечивает программный, это сбивает с толку. В то же время, если информация не структурирована должным образом, она становится непригодной для “машинной” обработки - следовательно и системные требования игнорировать нельзя.

Люди и машины обрабатывают информацию по-разному. Мы должны установить баланс между удовлетворением потребностей и тех, и других.

Закон Постела

В 1980 году программист Джон Постел опубликовал первую спецификацию для протокола управления передачей данных (Transmission Control Protocol), который по сей день остается главным средством передачи данных в Интернете. В своей спецификации Джон сформулировал принцип устойчивости:

Будь требователен к тому, что отсылаешь, и либерален к тому, что принимаешь.

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

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

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

  1. Позволяет пользователю вводить данные в разных формах, выделяет потребностям и предпочтениям человека более высокий приоритет, чем требованиям машины;
  2. Проводит интерпретацию данных предоставленных пользователем, в соответствии с требованиями компьютерных систем;
  3. Определяет какие вводимые данные являются приемлемыми в конкретной ситуации;
  4. Обеспечивает обратную связь с пользователем в понятной для него форме, особенно когда введённые данные не поддаются обработке.

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

Числа

Человек не видит особой разницы между «один», «1» и «1.00». Однако, для компьютера они очень сильно отличаются. В большинстве языков программирования они относятся к разным типам данных с уникальными характеристиками. Попытка произвести математические расчеты с неподходящим для этого типом данных приведет к непредсказуемым результатам. Таким образом, если для работы приложения нужно, чтобы пользователь ввел число, его разработчики должны позаботиться о том, чтобы формат вводимой информации соответствовал требованиям системы. Пользователи обычно не обращают внимание на такие нюансы, но разработчика они подстерегают на каждом шагу.

Покупая что-нибудь по телефону, вы никогда не услышите от оператора просьбу назвать номер вашей кредитки, используя только цифры, без пробелов или чёрточек. Его не введут в смятение паузы или заминки в вашей речи. Он без труда различает цифры на слух. Однако подсказки о том, как пользователю следует вводить данные, чтобы они соответствовали требованиям компьютера, встречаются в веб-формах сплошь и рядом. А не лучше ли бы было, если компьютер мог бы понимать такие данные, которые пользователь без труда введёт?

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

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

Поле ввода запрашивающее числовые данные

В HTML 5 введены новые атрибуты для элемента input, среди них type для number и атрибут pattern, с помощью которых разработчик может указать необходимый формат вводимой информации. К сожалению, поддержка этих атрибутов браузерами пока неполная и нестабильная. Однако, то же самое можно воплотить и с помощью JavaScript. Например:

Код первой строки блокирует введение данных, которые не являются цифрами или точкой в десятичном числе. Вторая строка выводит уведомление.

Этот простой пример можно значительно усложнить и следовательно улучшить, но такие приемы всё равно вынуждают пользователя подчиняться правилам, которые устанавливает компьютер. В качестве альтернативы, можно предоставить пользователю возможность вводить данные в том формате, который он считает нужным, и затем, используя те же регулярные выражения 1, перевести их в десятичные значения на сервере. Согласно директиве №3, приложение проведет проверку на работоспособность и выдаст ошибку, если данные предоставленные пользователем являются невразумительными или выходят за рамки понимания системы.

Либеральное человеческое лицо будет считать такую ситуацию исключением: если мы хорошо спроектировали интерфейс и подписали поля, то большинство людей будут вводить именно то, что нужно. Но то, что именно они вводят («10$ или 10.00») будет отличаться. Большинство таких вводных данных легко поддаются машинной обработке и позволяют получить нужные данные в десятичном формате как на стороне клиента, так и на стороне сервера, но осторожное лицо машины проверит это, прежде чем что то делать. Если это важное действие, например пользователь вводит сумму денег, которую хочет пожертвовать, система должна обеспечить явный отклик и попросить подтверждения перед осуществлением дальнейших действий, даже если данные в пределах допустимого. В противном случае грубая конвертация текстового значения в числовое может привести к неожиданным и потенциально нежелательным для пользователя последствиям:

Слишком грубая конвертация текстового значения в числовое может привести к неожиданным последствиям

Даты

С точки зрения компьютера, дата и время - всего лишь особенный вид числовых данных. В системах на базе UNIX, например, время часто обозначается количеством секунд прошедших с 1 января 1970 года.

Для человека, однако, контекст играет большую роль в понимании даты. Когда Аня спрашивает: “Встретимся в четверг?”, Иван может спокойно предположить, что она имеет ввиду следующий четверг и у него нет необходимости это уточнять. Разработчикам интерфейсов стоит сделать всё возможное, чтобы максимально приблизиться к человеческому методу интерпретации дат в зависимости от контекста.

Это можно сделать, если вспомнить типичные методы запроса даты у пользователя:

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

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

Хочу отметить, что устанавливая слишком жесткие требования к формату, в котором вводится дата, мы сводим на нет преимущество текстового ввода - если Иван должен определиться с точной датой в числовом формате и ввести ее в определенном виде, ему все же может потребоваться календарь. Или, например, приложение запрашивает дату рождения Ани в формате мм/дд/гггг, и выдает ошибку когда она вводит 1/1/1970, пропуская ноль в месяце и дате, что вызывает недоумение. Ведь человеку оба варианта написания даты кажутся одинаково понятными.

Приложение, построенное с учетом принципа стабильности, принимает от пользователя любые данные, если они напоминают дату, опять-таки, запрашивая подтверждение того, что система их интерпретировала правильно. Уведомление об ошибке выводится только в том случае, если интерпретация данных прошла неудачно или же они выходят за рамки понимания системы. Существует несколько программных библиотек, которые помогают компьютерам переводить человеческие описания дат, вроде “завтра”, “в следующую пятницу” или “Апрель, 11” в структурированные эквиваленты, поддерживаемые машинами. Хотя многие из библиотек достаточно сложные, все же у них есть ограничения. Поэтому, используя их, стоит предоставить пользователю примеры форматов правильного введения данных, даже если система принимает и другие варианты.

Адреса

Наверное из всех типов данных, поля для ввода адреса намного больше зависят от строения базы данных, чем от заботы об удобстве пользователей. Взгляните на этот распространенный шаблон:

Стандартные набор полей для ввода адреса

Такой набор полей подходит для большинства адресов в США, но далеко не для всех адресов других стран мира. И даже в США, для некоторых официальных адресов, такой набор полей не будет достаточным.

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

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

Рассмотрим следующий адрес:

Avenue Appia 20

1211 Genève 27

Аня

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

"address_components" : [
  {
     "long_name" : "20",
     "short_name" : "20",
     "types" : [ "street_number" ]
  },
  {
     "long_name" : "Avenue Appia",
     "short_name" : "Avenue Appia",
     "types" : [ "route" ]
  },
  {
     "long_name" : "Geneva",
     "short_name" : "Geneva",
     "types" : [ "locality", "political" ]
  },
  {
     "long_name" : "Genève",
     "short_name" : "Genève",
     "types" : [ "administrative_area_level_2", "political" ]
  },
  {
     "long_name" : "Geneva",
     "short_name" : "GE",
     "types" : [ "administrative_area_level_1", "political" ]
  },
  {
     "long_name" : "Switzerland",
     "short_name" : "CH",
     "types" : [ "country", "political" ]
  },
  {
     "long_name" : "1202",
     "short_name" : "1202",
     "types" : [ "postal_code" ]
  }
]

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

Исключение или правило?

Преобразование человеческого языка в структурированные данные - не всегда проходит успешно. Согласно директиве №4, устойчивая система должна быть способна определить пограничный случай и изящно справиться с ним, не напрягая пользователя, и в то же время минимизируя возможность повторения такой ситуации. Как в поговорке: нельзя ставить телегу впереди лошади. Так и в плане взаимодействия системы с пользователем: если возможно создание интерфейса, который будет работать без сбоев в 95% случаев, сократит время, затрачиваемое на выполнение задач, и будет полностью соответствовать ожиданиям пользователя, тогда наверняка результат стоит усилий потраченных на создание дополнительного цикла обратной связи для обработки остальных пяти процентов.

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

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

Для большинства разработчиков, по понятным причинам, целостность системы является приоритетной задачей. Чем лучше продумана структура введения данных пользователем, тем надежнее она ведет себя при дальнейшей обработке. Мы стремимся к созданию надежных систем, и потому рьяно защищаем потребности машины. Когда введенные данные не проходят валидацию, мы виним в этом пользователя, считая что он допустил ошибку: ввел неправильные данные в тщательно спроектированное нами приложение.

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

Неизменное влияние закона Постела на Интернет, в течение трёх десятилетий, доказывает его значимость. Пусть же всё программное обеспечение созданное нами и впечатление пользователей от работы с ним, соответствует высоким стандартам этого закона.


Примечания

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