СОВРЕМЕННЫЕ МЕТОДЫ РАЗРАБОТКИ КЛИЕНТСКИХ WEB-ПРИЛОЖЕНИЙ Гулин Сергей Сергеевич ([email protected]) ЗАО «ИРТех», г. Самара Аннотация В статье раскрыта концептуальная часть реализации современных Web-приложений в соответствии с шаблоном проектирования MVVM. Современные тенденции рынка разработки клиентских приложений направлены в сторону мобильных устройств. Тем не менее разработка клиентских Webприложений не стоит на месте, а активно развивается в направлении усложнения пользовательских интерфейсов, как это уже было несколько лет назад среди клиентских настольных приложений. В настоящий момент применяются различные подходы к преодолению сложности разработки качественных клиентских Web-интерфейсов. К таковым относят шаблоны проектирования слабосвязанного взаимодействия слоя бизнес-логики и отображения, известные как MVC (Model-View-Controller) и MVVM (Model-ViewViewModel) [1]. Основное отличие этого подхода от классического заключается в перераспределении ответственности между клиентом и сервером. Если ранее за отображение всей информации отвечала серверная сторона, то с разработкой Ajax [2] это стало не так. Доля ответственности за отображение наполнения страницы появилась и у клиента. Это изменение поля ответственности привело к долгосрочному переходному процессу, которым Ajax по своей сути и является. Следующие иллюстрации, выполненные в соответствии с нотацией UML 2.0, показывают типовые сценарии взаимодействия клиента и сервера в хронологическом порядке. На рисунке 1 показано «классическое» взаимодействие, которое характеризуется использованием HTTP-глаголов POST (на рисунке не отображен) и GET для получения HTML-страниц целиком. Такое взаимодействие не требует поддержки JavaScript со стороны браузера, отличается высокой стабильностью реализаций среди различных Web-серверов и браузеров. Все браузеры, которые были когдалибо выпущены, поддерживают такое взаимодействие. У этого подхода есть ряд недостатков, которые и привели его к модификации в будущем: 1. высокая нагрузка на сервер в виде генерации HTML-страниц; 2. высокая избыточность передаваемых данных; 3. высокое совокупное время отклика системы на единичную операцию со стороны пользователя. Сервер Браузер GET: / HTML-страница GET: /page2 HTML-страница Рисунок 1. «Классическое» взаимодействие С целью решения выше обозначенных проблем компания Google ввела новую технологию, Ajax. Суть Ajax заключается в частичном обновлении HTML-страницы и передаче HTML-фрагмента от сервера к клиенту. Впоследствии HTML-фрагмент был заменен на XML-код с целью ограничения ответственности передаваемых данных за отображение. Типовой сценарий выполнен на иллюстрации ниже: Сервер Браузер GET: / HTML-страница GET: /contacts/1 HTML-фрагмент Рисунок 2. Передача фрагментов HTML-страниц. Стоит отметить особую роль языка JavaScript в этом качественном изменении, которое отображено на рисунке 2. Именно с его помощью осуществляется обновление части страницы, отправка запроса, обработка ответа и формирование отображения данных при необходимости. Такое новое применение JavaScript обозначило высокие требования к производительности его интерпретаторов: формирование отображения и вставки DOM-элементов является затратной операцией. Тем не менее этот подход решает проблемы нагрузки на сервер по генерации HTML, радикально сокращает избыточность передаваемых данных и в случае высокой производительности вычислительной техники клиента позволяет достичь быстрой реакции пользовательского интерфейса. Первым Webприложением, которое начало использовать подход, описанный выше, считается почтовый клиент Gmail от компании Google [2]. Тем не менее подход передачи фрагментов HTML-страниц или XML-документов с их последующей пост-обработкой в виде генерации представления и вставки в дерево DOM не лишен недостатков. Как часто бывает в индустрии разработки ПО, достигаются цели производительности и начинают преследоваться цели уменьшения стоимости кодирования и поддержки. Можно проверить решение рисунка 2 на предмет хорошего компонентного дизайна и убедиться, что по крайней мере одну ответственность реализуют браузер и Webсервер: генерацию отображения данных. Именно эта ответственность [4] вносит дублирование логики как на стороне клиента, так и на стороне сервера, что с высокой долей вероятности приведет к появлению «спагетти»-кода, поддержка которого не сможет окупиться в будущем. При большом количестве фрагментов реализация механизма на сервере, позволяющего отправлять данные как в составе целой страницы, так и отдельными фрагментами, будет нетривиальной, что повышает риски со стороны сервера. С клиентской стороны риски также становятся высокими из-за нетривиальной реализации механизма эффектов, допускающего изъятие DOM-элемента и вставку на его место нового, являющегося результатом Ajax-запроса. Борьба с эффектом, описанным выше, привела к появлению целого ряда различных практик и способов организации кода, позволяющих управлять сложностью и стоимостью поддержки Web-приложения [4]. К ним можно отнести технологии и библиотеки последнего времени, например, такие как: REST, JSON, CoffeeScript, ASP.NET MVC, ServiceStack, Angular.JS [7], Ruby on Rails и многие другие. Все эти инструменты так или иначе в своей основе используют принцип разделения ответственности, где каждый занимает определенную роль. В свою очередь, шаблоны проектирования слабосвязанного взаимодействия MVC и MVVM являются концептуальной реализацией принципа разделения ответственности, что выводит их на фундаментальный уровень применения [3]. На рисунке 3 изображен объектный обмен данных, характерный для современных Web-приложений, которые будут рассмотрены далее. Его особенностями являются: 1. запрос корня приложения приводит к получению уже заранее скомпилированной, подготовленной статичной Web-части в виде набора, состоящего из HTML-страницы, файлов JavaScript и CSS-стилей; 2. последующий обмен данными выглядит в виде передачи JSON-объектов между браузером клиента и сервером, в качестве транспорта используется REST-интерфейс. Сервер Браузер GET: / HTML-страница (статичная) GET: /contacts/1 JSON-объект Рисунок 3. Объектный обмен данных Приведенный выше пример соответствует современной концепции разработки Webприложений, которая носит название SPA (Single-Page Application). Множество библиотек и продуктов используют ее в своей работе, к таким относятся Sencha, Dojo, Angular.JS, Backbone. Этот подход зарекомендовал себя с лучшей стороны по организации кода приложения, уменьшению издержек на его поддержку и обеспечению высокой гибкости к изменениям приложения, его частей. Тем не менее он не лишен недостатков. Основная претензия пользователей таких приложений к разработчикам заключается в накапливающемся времени отклика: по истечении некоторого промежутка времени работы с приложением интерфейс пользователя все медленнее и медленнее начинает реагировать на действия пользователя. Для ликвидации этой задержки требуется перезапуск страницы с приложением в браузере, что не всегда может быть комфортно для пользователя. Авторы статьи считают, что радикальным решением этой проблемы был бы отказ от реализации всего приложения в виде SPA. Основная мысль заключается в разделении большого приложения на малые секции, которые можно было бы реализовать уже в виде отдельных SPA. Такой подход позволил бы найти компромисс между необходимостью перезагрузки страницы браузера с целью сохранения времени отклика на приемлемом уровне, и в то же время позволил бы гибко сочетать преимущества SPA перед классическим подходом. Важно отметить, что разделение на секции выполняется до непосредственного выполнения приложения. Сохраняются все преимущества применения кеширования статического содержимого и разделения кода логики отображения между клиентом и сервером, которые применяются в SPA. Это решение и его подобные авторы статьи предлагают называть «LSPA» от Large Single-Page Application. На рисунке 4 показана разница реализации приложения по SPA и LSPA: Рисунок 4. Реализации приложения по LSPA и SPA на уровне компонент Как видно из рисунка выше, Web-приложение по LSPA представляет собой композицию из малых частей в виде SPA. Такой подход хорошо сочетается с принципом единой ответственности и принципом высокой связности. Стоит отметить, что на рисунке отмечена специальная корневая секция («/») как равноправная часть всего LSPA. Решение выше позволяет находить компромиссное решение между высокой скоростью отклика отдельных частей приложения и скоростью отклика всего приложения. Также не стоит преуменьшать роль возможности выполнения декомпозиции, что позволяет справляться со сложностью реализации сложных интерфейсов пользователя. Рассмотренный в статье подход позволяет радикально изменить взгляд на сложность разработки больших и «толстых» клиентов на HTML. Авторами представлена концепция LSPA, позволяющая реализовать RIA на JavaScript. Литература 1. Martin Fowler. Patterms of Enterprise Application Architecture. Addison-Wesley Professional, 2002. – 560 с. 2. Дейв Крейн, Эрик Паскарелло, Даррен Джеймс. AJAX в действии: технология – Asynchronous JavaScript and XML = Ajax in Action. — М.: Вильямс, 2006. – С. 640. – ISBN 1-932394-61-3 3. Эванс, Эрик. Предметно-ориентированное проектирование (DDD).: Пер. с англ. – М.: ООО «И.Д. Вильямс», 2011. – 448с.: ил. 4. Мурадов Мурад Доступно о SOLID [Электронный ресурс] – Режим доступа: http://muradovm.blogspot.ru/2012/03/solid.html. 5. Bill Venners Orthogonality and the DRY Principle [Электронный ресурс] – Режим доступа: http://www.artima.com/intv/dry.html.