Прогрессивное расширение — не зная броду, не суйся в воду

Кристиан Хельман (Christian Heilman) | 4 августа 2010 года

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

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

Интернет — для всех

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

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

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

Ограничение диапазона при разработке

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

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

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

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

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

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

Что такое прогрессивное расширение?

Прогрессивное расширение — это методика и концепция ИТ-разработки. В самой общей форме она распадается на несколько этапов, которые следует продумать:

  • Убедитесь, что текущая среда поддерживает определенную технологию
  • Если поддержка существует, примените эту технологию для улучшения продукта

В этом подходе нет ничего сверхъестественного, и множество людей, разглагольствующих о прогрессивном расширении, которое якобы сдерживает наши творческие возможности, не понимают предмета. Речь не идет о поддержке Internet Explorer 6 или устаревших версий JavaScript, что означает двойную поддержку — речь о том, чтобы не создавать решения, которые, очевидно, станут нефункциональными.

Поддержка нового оборудования

Это становится все более важным с учетом изменяющейся среды, в которой мы развертываем свои продукты: Интернет используется не только на настольных компьютерах, но все больше и больше на мобильных устройствах, многие из которых снабжены сенсорными интерфейсами, а не мышью. Если решения основаны на эффектах наведения курсора и используют крошечные элементы, расположенные слишком близко друг к другу, их использование может стать ужасным разочарованием для пользователей таких устройств, как Google Nexus, iPhone или iPad. Вместо построения систем, учитывающих оба сценария, разработчики начинают создавать одно приложение по 5 раз для различных сред. Это кошмар для поддержки, и, хотя и позволяет обслуживать некоторые специальные системы, но также означает, что вы потратите в пять раз больше времени на разработку решения. Программное обеспечение достаточно «разумно», чтобы позволить не разрабатывать одно и то же решение несколько раз — если использовать его разумно.

Прогрессивное расширение — это разделение задач

Вместо того, чтобы начинать с вопроса о представлении и поведении продукта, ответьте на несколько простых вопросов:

  • Откуда поступают данные?
  • Какую основную задачу необходимо выполнить пользователям?
  • Как это можно упростить?
  • Что наиболее вероятно изменится в будущем?
  • Что может пойти не так и как избежать наиболее очевидных сбоев?

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

Несколько примеров

Давайте рассмотрим несколько примеров метода прогрессивного расширения.

Цены на жилье в Великобритании

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

Если JavaScript недоступен или используется браузер, который его не поддерживает, вместо автозаполнения и ползунка используются раскрывающиеся меню.

При выборе временного интервала отображается интерактивная гистограмма с данными и предложениями жилья в определенной области:

Система этой гистограммы не вполне очевидна, и возможно вы не сразу поймете, что это такое. Если отключить CSS (или просмотреть ее с помощью телефона Blackberry), станет видно, что это чистое CSS-решение:

Итак, вы видите, что решение изменяется в соответствии с поддержкой устройства, а это и есть прогрессивное расширение. Способ, которым я этого добился — полное отделение данных от интерфейса. Первое, что я сделал — написал скрипт PHP, который извлекает данные и преобразует их в HTML на основе различных параметров.

Если щелкнуть эту ссылку на демонстрацию, можно увидеть, как это выглядит:

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

Это дало мне несколько возможностей, которых бы не было, если бы я начал с JavaScript:

  • Я опубликовал Решение и API гистограммы CSS как дополнительный фрагмент программы (исходный код гистограммы CSS находится здесь) и таким образом поделился своим кодом и сделал рекламу веб-сайта среди разработчиков.
  • Я поддерживаю любую среду, так как раскрывающиеся списки заменяются автозаполнением и ползунком, только если браузер поддерживает их (оба эти решения на самом деле были скопированы из примеров для YUI автозаполнения и YUI ползунка и просто слегка изменены).
  • Я мог опубликовать запускающий систему API как открытый API или сделать его частью YQL, чтобы иметь кэшированную веб-службу
  • У меня еще осталось время, чтобы добавить немного дизайна (хотя это не моя сильная сторона), и я все равно уложился в 24-часовой срок

Так как создание приложения с помощью метода прогрессивного расширения не заняло много времени, я также успел преобразовать его в приложение для домашней страницы Yahoo, изменив всего несколько строк кода:

Примечание: представьте, сейчас решение не работает на сенсорном интерфейсе (по крайней мере, на моем Nexus). Скоро я это исправлю, когда получу для тестирования другое устройство. Хорошая новость заключается в том, что исправление будет не сложнее, чем определение устройства, после чего нужно будет НЕ применять JavaScript. Если бы я написал решение без прогрессивного расширения, мне бы пришлось полностью переделывать его.

Другим примером возможностей этого метода является следующий небольшой инструмент.

Сборщик Flickr

В настоящее время я создаю множество презентаций и мне нравится использовать в них изображения, так же как и в записях блога, чтобы слегка оживить их. Вместо того, чтобы покупать эти изображения, я использую Flickr для поиска картинок, выпущенных под лицензией творческих сообществ (Creative Commons), что позволяет мне использовать их.

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

Вы можете получить исходный код сборщика Flickr на GitHub

Как видно из этого кода, сборщик Flickr позволяет выполнять поиск по определенным условиям и получать фотографии из Flickr. Можно щелкнуть любой эскиз и просмотреть сведения о фотографии, а также получить HTML-код, готовый для копирования и вставки. Если браузер позволяет (т. е. поддерживает JavaScript), можно также перетаскивать эскизы в контейнер коллекции внизу экрана или удалять их, перетаскивая в мусорную корзину в правом нижнем углу. Когда нужная коллекция собрана, можно нажать кнопку и получить HTML-код для всех изображений.

Без JavaScript работают только функции поиска и отображения, а фрагмент приложения, отвечающий за сборку, теряется. Однако, если отключить JavaScript (или открыть приложение на Blackberry), будет видно, что на самом деле эти функции не потеряны, а вообще не фигурируют в приложении:

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

Сборщик Flickr — это простой интерфейс для сбора фотографий из Flickr и копирования HTML-кода для вставки в веб-сайты. Щелкните любую фотографию, чтобы просмотреть сведения о ней. Под фотографией находится HTML-код для копирования и вставки. Фотографии можно перетаскивать в коллекцию под эскизами и удалять оттуда, перетаскивая в корзину. После завершения выбора нажмите кнопку «Просмотреть весь код», чтобы получить HTML-код для всех фотографий в коллекции.

Если JavaScript недоступен, отображается следующий текст:

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

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

Практические выводы о прогрессивном расширении:

Прежде всего я надеюсь, что эти объяснения и выводы из примеров показали, что у применения прогрессивного расширения существует множество преимуществ:

  • Вы создаете архитектуру решений, а не просто разрабатываете и строите их — вы предусматриваете несколько уровней функциональности (данные, отображение, внешняя передача через API), каждый из которых может существовать сам по себе и может быть при необходимости заменен — вместо создания единой монолитной системы, которую гораздо труднее поддерживать.
  • При создании архитектуры решения вы делите его на части, которые можно разработать быстрее, и можете с уверенностью планировать время на разработку. Если вы создаете одну большую систему от проекта до решения, ваши временные оценки всегда будут ошибочными.
  • Поскольку вы тестируете приложения во время разработки, создаете практичные, рабочие решения и расширяете их последовательно, вы всегда будете поставлять рабочие программы. Если вы превысили бюджет или временные рамки, у вас все же есть какое-то рабочее решение, которое можно улучшить позднее.
  • Поскольку вы создаете решение, которое ясно разделяет внутреннюю и интерфейсную части приложения, в будущем можно изменять каждую из них в отдельности, не затрагивая другую часть.
  • Так как задачи разделены, вы можете работать параллельно — все, что нужно согласовать между внутренней и интерфейсной частями — это данные, поступающие обратно из API, и способ доступа к ним.
  • Поддержка также упрощается — вы знаете наверняка, что все данные поступают из внутренней части через API, а значит вы знаете, где выполнять отладку при проблемах с отображением, которые не связаны с частью HTML/CSS.
  • Время на тестирование значительно уменьшается — так как среда, которая не поддерживает определенную технологию, не затрагивается этой технологией и в ней не существует ошибок, которые нужно исправлять.

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