Ярмухаметов Ф.Ф.1, Кейно П.П.2
1 ФГБОУ ВПО «Московский авиационный институт (национальный исследовательский университет)», г. Москва, студент кафедры «Системное моделирование и инженерная графика»,
science @ blockset. ru
2 ФГБОУ ВПО «Московский авиационный институт (национальный исследовательский университет)», г. Москва, преподаватель кафедры «Системное моделирование и инженерная
графика»
ПРАКТИКА ИСПОЛЬЗОВАНИЯ ВЕБ-ШАБЛОНИЗАТОРОВ В ПРОГРАММНОМ КОМПЛЕКСЕ ИНТЕРПРЕТАТОРА НА ПРИМЕРЕ CTPP2
КЛЮЧЕВЫЕ СЛОВА
Веб-разработка, веб-приложение, шаблонизатор, программирование, MVC, CTPP2, C++, JSON, BlockSet, BML.
АННОТАЦИЯ
В статье обсуждаются принципы построения шаблонизаторов на основе концепции MVC. Рассматриваются особенности реализации шаблонизатора CTPP2 на языке C++. Сопоставляются показатели производительности с другими шаблонизаторами.
Разработка и внедрение современных веб-проектов является комплексной трудоёмкой задачей, решаемой целым коллективом веб-разработчиков: программистами, верстальщиками, дизайнерами. Для того, чтобы предоставить каждому участнику проекта комфортную среду для выполнения своей подзадачи, необходимо разделить структуру веб-страницы и генерируемые на ней данные. Такую возможность предоставляют шаблонизаторы.
Шаблонизатор - это программное обеспечение, оперирующее некоторым каркасом (шаблоном) сайта с использованием переменных, простых логических конструкций и встроенных функций шаблонизатора. Все перечисленные конструкции работают с данными, которые соединяются с шаблоном. В конечном итоге на выходе генерируется готовая страница в формате HTML или любом другом. Благодаря этой особенности, работа верстальщиков, дизайнеров и программистов над одним проектом может быть разграничена.
Большинство современных шаблонизаторов основаны на принципе MVC (Model-viewcontroller) (рис. 1) [1,2,3]. Этот принцип требует жесткого разделения структуры шаблонизатора на «Модель», «Контроллер» и «Представление». «Модель» - это абстрактный набор данных, который будет использоваться в шаблоне. При помощи компоненты «Контроллер» указывается список используемых моделей, а «Представление» используется только для вставки в шаблон конкретных данных, подготовленных «Контроллером» и «Моделью». Подобное жесткое разделение приводит к необходимости постоянной коммуникации между частями шаблонизатора, что в свою очередь приводит к замедлению работы сервера.
ПРЕДСТАВЛЕНИЕ
1. Действие
Д. Обновление представления
КОНТРОЛЛЕР
2. Модификация
3. Оповещение об изменениях
МОДЕЛЬ
Рис. 1. Схема парадигмы MVC Практическая реализация концепции М^ сложнее, чем её теоретическое описание и
может иметь множество особенностей реализации и применения связанных с требованиями языка программирования. Общий вид М^ может быть изменён с целью повышения скорости обработки данных. Одним из возможных вариантов является объединение компоненты «Представление» с «Контроллером». Таким образом, будет уменьшена зависимость от необходимости постоянной коммуникации между частями шаблонизатора, но остается преимущество разделения верстки страницы и обрабатываемых данных. Идея реализации шаблонизатора бесспорно удобна в языках программирования без жесткого указания типов данных.
Подобный метод реализует шаблонизатор СТРР2. Архитектура шаблонизатора состоит из четырех подсистем: компилятора шаблонов, виртуальной машины, системы кэширования шаблонов и библиотеки функций.
Компилятор шаблонов преобразует код шаблона в код виртуальной машины и сразу, «на лету» выполняет простые операции, такие как вставка других шаблонов и подстановка значений переменных. Виртуальная машина генерирует конечную страницу, используя байт-код. Если в байт-коде нет обращений к функциям шаблонизатора, то генерация происходит сразу. В противном случае, сначала вызываются необходимые функции из библиотеки.
Система кэширования шаблонов позволяет ускорить работу как виртуальной машины в частности, так и всего шаблонизатора в целом. Библиотека функций используется виртуальной машиной для обработки сложных шаблонов. Она также была спроектирована таким образом, что позволяет без особых затруднений добавлять новые функции в шаблонизатор.
Функции API шаблонизатора
Вчгутуэпьнаи машина
Результат
Каш
Бд ит-код
Шаблон
Кэш
Рис. 2. Архитектура шаблонизатора CTPP2
В реализации CTPP2 в роли «Модели» выступает компилятор, в роли «Контроллера» -виртуальная машина, а роль «Представления» разделена между ними. Компилятор обрабатывает примитивные данные, а виртуальная машина изменяет их, используя различные функции.
Существуют реализации CTPP2 на PHP, PERL и C++. Различия в них заключаются исключительно в требованиях используемого языка программирования. Самое заметное различие заключается в представлении данных. Для передачи данных в шаблонизатор используется универсальный тип, называемый CDT (Common Data Type), к которому, теоретически, возможно привести данные любого типа. В PHP и PERL, благодаря отсутствию жесткой типизации данных, использование CDT не вызывает никаких проблем, но не в C++. Из-за строгого контроля типов данных в C++, в реализации CTPP2 данные могут быть представлены как значение без имени (string), переменная (HASH_VAL) и массив (ARRAY_VAL). В результате перегрузка оператора присваивания была реализована только для встроенных типов и элементов типа CDT.
Например, класс CDT хранит только строковое (или любой другой встроенный тип, а так же типа CDT) значение без имени переменной: CTPP::CDT data = "Данные"; CTPP::CDT value = data;
В другом примере, класс CDT хранит переменную "name" в виде HASH_VAL со значением строкового типа (здесь: строка «Шаблонизатор CTPP2»). Кроме того, значение может быть и любого другого встроенного в язык C++ типа, а также экземпляром класса CDT. Так, во второй строке происходит переопределение новым значением из переменной "data" неопределённого типа, что является вполне допустимым, если "data" является экземпляром класса CDT. CTPP::CDT var["name"] = "Шаблонизатор CTPP2"; var["name"] = data;
Так же есть реализация функции Push_Back() для заполнения массивов, причем элементом массива может быть переменная типа CDT: CTPP::CDT mas; for(int i = 0; i<10; i++){
mas.Push_Back(i);
}
mas.Push_B ach (data);
Переменная mas заполняется элементами массива, но в представлении шаблонизатора не имеет имени, по которому к ней можно обратиться. Для того чтобы иметь возможность обратиться к массиву по имени необходимо присвоить его переменной типа CDT: CTPP::CDT name_mas; name_mas["array"] = mas;
В результате передача сложных структур данных в шаблонизатор становится нетривиальной задачей. Необходимо определять является ли данная переменная массивом, и, если да, то возникает необходимость создавать дополнительный элемент типа CDT с последующим его заполнением, а если те, в свою очередь, являются элементами массива, то возникает необходимость в еще одной переменной типа CDT и т.д.
Пример [4]: {
"Articles" [ {
"Name" : "Scientific_Article", "Author" : "Dr. Smith",
"Comments" [
{
"Author" : "Dr. Johns",
"Comment" : "Very good article" },
{
"Author" : "Adams, Ph.D.",
"Comment" : "Boo..." }
]
},
{
"Name" : "New_Scientific_Article", "Author" : "Vikulin, ma",
"Comments" [ Author"
Comment" : "It's very useful.
{
"Author" : "Ivanov, B.F.A.",
} ]
} ] }
Простым решением данной проблемы является генерация ^ОЫ-строки, подобной представленной выше, или файла с необходимыми данными, а затем передача его в функцию
шаблонизатора, которая, в свою очередь, произведет синтаксический анализ JSON-а и, при его корректности, CDT будет заполнен. Данный вариант достаточно прост, но несет в себе дополнительные накладные расходы, ведь возникает необходимость в лишнем шаге на составление JSON-а, да и анализ его достаточно дорогая операция в плане ресурсов.
Другой вариант заключается в построении структуры данных, позволяющей легко определить глубину вложенности данных, а затем, используя рекурсивно вызываемую функцию, заполнить CDT путём применения стандартных функций шаблонизатора. При условии выбора оптимальной структуры данных второй способ заметно эффективней и по памяти, и по использованию процессорного времени во время работы, и при заполнении структуры данных нет возможности допустить синтаксическую ошибку, в отличие от возможных проблем при составлении JSON-строки.
В ходе работы с шаблонизатором CTPP2 в реализации на C++ для решения данной проблемы с передачей данных было принято решение использовать второй метод, а именно согласно поступившим данным составлять вектор структуры, в которой хранится глубина текущего элемента, имя элемента и его значение [5]. struct data {
int deep; std::string name; std::string value;
}
Затем была написана рекурсивно вызываемая функция, в которую передается вектор структуры, представленной выше. Данная функция поэлементно просматривает вектор и заполняет CDT. Если значение (value) текущего элемента вектора является пустой строкой, а значение глубины (deep) текущего элемента вектора меньше значения глубины следующего элемента вектора, то данный элемент является массивом. В этом случае функция рекурсивно вызывает себя для его заполнения, иначе элемент является простой переменной и сразу добавляется в CDT. После добавления в CDT элемент вектора удаляется, освобождая память, чего не происходит при работе с JSON-ом.
Шаблонизатор CTPP2 является одним из самых эффективных средств управления шаблонами, несмотря на сложности с добавлением данных в реализации на C++. Доказательством тому служат данные тестов производительности CTPP2 вместе с аналогами. Этот тест опубликован на сайте библиотеки [6]: Template Toolkit = 2.878 (25.2) HTML::Template = 2.682 (23.1) HTML::Template::Pro = 0.596 (5.1) HTML::CTPP2 = 0.116 (1)
Шаблонизаторы играют ключевую роль при реализации парадигмы MVC на современных веб-проектах, в особенности на больших высоконагруженных системах интернет-сервисов, где данная парадигма является краеугольным камнем эффективной разработки. Эти системы особенно требовательны к скорости выполнения математических операций, поэтому любое внедрение дополнительных компонентов может негативно сказаться на производительности. Статистика, приведённая выше, показывает, что шаблонизатор CTPP2 является эффективным решением, рекомендуемым для применения не только в легковесных проектах, но и на высоконагруженных системах.
Литература
1. Джесс Чедвик и др. ASP.NET MVC 4: разработка реальных веб-приложений с помощью ASP.NET MVC = Programming ASP.NET MVC 4: Developing Real-World Web Applications with ASP.NET MVC. — М.: «Вильямс», 2013. — 432 с.
2. Pitt. C. Experts Voice - Pro PHP MVC. - Apress,inc, 2012. - 500.
3. Симонова О.Н., Лясин Д.Н. Шаблон проектирования MVC как эффективное средство построения архитектуры программной системы // Современные наукоёмкие технологии. 2014. №5-2. С. 96-97.
4. Smith B. Beginning JSON - Apress,inc, 2015. - 324.
5. Кейно П.П., Силуянов А.В. Автоматизированная разработка динамических Веб-узлов средствами декларативного языка программирования. / / Прикладная информатика.-2014.-6(54).-70-78.
6. Шетухин А. Документация // Шаблонизатор CTPP. URL: http://ctpp.havoc.ru/doc.