Содержание к диссертации
Введение
ГЛАВА 1. Технологии облачных приложений 18
1.1 Основные понятия и характеристики облачных приложений. 18
1.2 История развития облачных технологий (Amazon AWS и Microsoft Azure) 29
1.3 Основные компоненты и сервисы облачных платформ Amazon AWS и Microsoft Azure 31
1.4 Google App Engine 44
1.5 Red Hat OpenShift 44
1.6 Выводы по главе 46
ГЛАВА 2. Аспектно-ориентированные технологии 47
2.1 Аспектно-ориентированное программирование для платформы Java с AspectJ 52
2.2 Бесшовное аспектно-ориентированное программирование веб-сервисов в FuseJ 57
2.3 Применение контейнера управления зависимостями Microsoft Unity для АОП на платформе .NET 60
2.4 Статическое применение аспектов в PostSharp на платформе .NET 65
2.5 Aspect.NET 69
2.6 Выводы по главе 76
ГЛАВА 3. Применение и адаптация aspect.net для разработки облачных веб приложений в microsoft azure 78
3.1 Принципы реализации облачных веб-приложений на платформе Microsoft Azure с помощью Aspect.NET 78
3.2 Реализация совместимости Aspect.NET с Microsoft Visual Studio 2015 81
3.3 Замещение аспектом целевого класса для перехвата событий 85
3.4 Внедрение в конфигурационный файл веб-приложения настроек аспектов 87
3.5 Выводы по главе 92
ГЛАВА 4. Реализация библиотеки аспектов для облачных веб-приложений
4.1 Перенаправление диагностической информации в Azure Diagnostics Storage 94
4.2 Определение в аспекте стратегии реакции на исключения 96
4.3 Кэширование в аспекте результатов операций, сессии и ответа сервера 98
4.4 Аспект для аутентификации на базе форм 102
4.5 Выводы по главе 104
ГЛАВА 5. Аспектно-ориентированный рефакторинг облачных веб приложений 106
5.1 Применимость АОП-рефакторинга для веб-приложений на платформе Microsoft Azure 106
5.2 Локализация в аспекте объектов службы. 108
5.3 Перенос вызовов объектов службы в аспектный производный класс 110
5.4 Привязка действий аспекта к вызовам методов базового класса 111
5.5 Выделение управляющих службой элементов в .ascx компонент аспекта 112
5.6 Управление аспектом через “пустые” private свойства в целевом коде 113
5.7 Демонстрация АОП-рефакторинга в приложениях N2CMS и Orchard 116
5.8 Выводы по главе 118
ГЛАВА 6. Бесшовное расширение облачных веб-приложений с помощью microsoft enterprise library integration pack 121
6.1 Применимость Microsoft EL для реализации сквозной функциональности 121
6.2 Logging Application Block 122
6.3 Autoscaling Application Block 124
6.4 Transient Fault Handling Application Block 125
6.5 Выводы по главе 128
Заключение 129
Список литературы
- История развития облачных технологий (Amazon AWS и Microsoft Azure)
- Применение контейнера управления зависимостями Microsoft Unity для АОП на платформе .NET
- Замещение аспектом целевого класса для перехвата событий
- Кэширование в аспекте результатов операций, сессии и ответа сервера
Введение к работе
Актуальность темы исследования. В работе рассматриваются два перспективных направления в области развития информационных технологий: облачные вычисления на платформе Microsoft Azure и аспектно-ориентированное программирование (АОП). Перспективность облачных приложений не вызывает сомнений: в настоящее время почти любая крупная компания предлагает свои облачные продукты от хранения личных файлов (Dropbox) и до офисных процессоров (Microsoft Office 360), от программной библиотеки распознавания образов (ABBYY Cloud OCR SDK) и до целых сред разработки (Microsoft Visual Studio Online).
В свою очередь, АОП применяется для выделения “сквозной функциональности” (распределенной по многим уровням объектно-ориентированной иерархии классов целевой системы) в один модуль — аспект. После такой операции улучшаются метрики качества исходного кода целевой системы, облегчается тестирование как аспекта, так и бизнес-логики.
Актуальность темы исследования обусловлена необходимостью повышения качества, производительности и облегчения сопровождения облачных веб-приложений. При этом актуальной является задача идентификации сквозной функциональности (авторизация, кэширование, протоколирование и пр.), которая встречается во многих веб-приложениях, а затем ее реализации: отделение от бизнес-логики в отдельные аспекты, пригодные для повторного использования. Таким образом, веб-приложение будет сфокусировано на выполнении задач предметной области, в то время как ряд нефункциональных требований переносится в сторонний проект — библиотеку аспектов. С учетом того, что для облачных веб-приложений уже существует библиотека Microsoft Enterprise Library Integration Pack, компоненты которой облегчают реализацию сквозной функциональности, также актуальной является реализация библиотеки аспектов с их помощью.
Степень разработанности темы исследования. Для аспектно-ориентированной разработки программ применяется множество инструментов, самыми популярными из которых являются AspectJ и PostSharp (по данным Google Trends). Однако анализ предметной области, проведенный в процессе написания работы, показал, что при изменении поведения программы с помощью современных АОП-инструментов для платформы Microsoft.NET отсутствует бесшовная интеграция аспектов и целевого исходного кода системы. Термин “бесшовная интеграция” можно раскрыть следующим образом: это такое расширение функциональности целевого кода, при котором не требуется вносить изменения в целевой проект, включая его код, файлы настроек и свойства проекта.
В качестве примера инструмента АОП, обеспечивающего бесшовное применение аспектов, в работе описывается и анализируется система As-pect.NET (среда аспектно-ориентированной разработки программ
для платформы Microsoft.NET), разработанная в лаборатории Java-технологии математико-механического факультета СПбГУ под научным руководством профессора В. О. Сафонова.
Впервые вопросы применения Aspect.NET к разработке веб-приложений исследовал в 2010 г. Нгуен В.Д., аспирант кафедры информатики математико-механического факультета СПбГУ. Результатом его работы стала библиотека с универсальными аспектами для безопасности, криптографии и расширения пользовательского Web-интерфейса приложений на базе ASP.NET. Проведенные им оценки производительности результирующей сборки после применения Aspect.NET показали, что накладные расходы на вызовы действий аспектов минимальны и соразмерны со вставкой их в исходный код вручную.
Объектом исследования являются инфраструктура, программные компоненты и сервисы платформы облачных вычислений Microsoft Azure, а также модели, методы и алгоритмы применения аспектов на базе инструмента Aspect.NET.
Предметом исследования является возможность улучшения качества исходного кода облачных веб-приложений с помощью АОП-рефакторинга. Кроме того, исследуется процесс разработки, реализации и применения универсальных аспектов, предназначенных для бесшовного расширения облачных веб-приложений, в том числе с использованием стороннего фреймворка Microsoft Enterprise Library Integration Pack.
Целью данной работы является повышение с помощью АОП качества и производительности, а также улучшение сопровождаемости облачных веб-приложений на платформе Microsoft Azure.
Достижение поставленной цели осуществляется решением следующих задач.
-
Разработать и реализовать библиотеку аспектов, расширяющую облачные веб-приложения следующими видами сквозной функциональности: перенаправление протоколирования в хранилище отладочной информации Microsoft Azure, кэширование информации, получаемой из SQL Azure, обработка исключений.
-
Предложить методику, позволяющую перехватывать обратные вызовы методов от инфраструктуры Microsoft Azure, не затрагивая при этом целевой код.
-
Найти способ публикации в облаке АОП-программ, разработанных с помощью Aspect.NET, а также обеспечить возможность их отладки в Microsoft Visual Studio.
-
Разработать метод бесшовного расширения функциональности облачных веб-приложений с помощью библиотеки Microsoft Enterprise Library и Aspect.NET.
5. Разработать методику аспектно-ориентированного рефакторинга для улучшения метрик исходного кода веб-приложения с помощью системы Aspect.NET.
Цель и задачи диссертации соответствуют области исследований паспорта специальности 05.13.11 «Математическое и программное обеспечение вычислительных машин, комплексов и компьютерных сетей» – пункту 1 (модели, методы и алгоритмы проектирования и анализа программ и программных систем, их эквивалентных преобразований, верификации и тестирования), пункту 2 (языки программирования и системы программирования, семантика программ), пункту 3 (модели, методы, алгоритмы, языки и программные инструменты для организации взаимодействия программ и программных систем) и пункту 9 (модели, методы, алгоритмы и программная инфраструктура для организации глобально распределенной обработки данных).
Методология и методы исследования. В исследовании комбинировались два вида методологии. Первый, типичный для диссертационного исследования: обобщение, анализ и синтез теоретического и практического материала и второй, специфичный для темы исследования и задач практического программирования облачных веб-приложений на платформе Microsoft Azure:
-
сквозная функциональность из библиотеки Microsoft Enterprise Library (которая реализует в виде функциональных блоков практические методы решения наиболее актуальных задач в разработке программного обеспечения);
-
методы низкоуровневого программирования MSIL-сборок для расширения возможностей Aspect.NET;
-
метод программирования интерпретатора cmd.exe для описания событий пред- и пост-компиляции Microsoft Visual Studio;
-
методики аспектно-ориентированного программирования и рефакторинга.
Степень достоверности. Достоверность и обоснованность результатов подтверждается дополняющими друг друга, согласующимися экспериментальными данными, полученными автором при применении разработанных методик для целевых программных продуктов.
Обоснованность полученных результатов обеспечивается
-
корректным применением теории объектно-ориентированного и аспектно-ориентированного программирования;
-
результатами сравнительного анализа разработанных методов с аналогичными подходами к АОП;
-
результатом улучшения метрики интегрированной оценки качества исходного кода целевого приложения после проведения АОП-рефакторинга;
4) позитивным опытом внедрения и эксплуатации ПО, разработанного с применением предложенных методов.
Научная новизна работы заключается в том, что разработанная технология бесшовного расширения функциональности облачных веб-приложений на платформе Microsoft Azure с помощью подсистемы применения аспектов Aspect.NET предложена впервые. Разработанная автором библиотека аспектов AzureLibrary впервые позволила расширить функциональность облачных веб-приложений, не затрагивая их исходный код, конфигурационные файлы или настройки проекта.
Кроме того, разработанная в ходе исследования методика интеграции сквозной функциональности отличается от ранее созданных методик использования АОП своей бесшовностью применения. Это позволяет получать веб-приложения с высокой производительностью, которые легко сопровождать, и они не будут привязаны к конкретному АОП-инструменту, как это имеет место в альтернативных методиках АОП-программирования для платформы Microsoft .NET.
Таким образом, в данной работе рассмотрен принципиально новый подход к разработке облачных веб-приложений на платформе Microsoft Azure. Его преимуществами перед существующими технологиями являются: бесшовное добавление функциональности к веб-приложениям, высокая производительность, улучшение качества исходного кода и возможность использования существующих сторонних библиотек для реализации сквозной функциональности.
Теоретическая и практическая значимость работы. В рамках диссертационного исследования разработана методика для бесшовного расширения функциональности облачных веб-приложений на платформе Microsoft Azure с помощью АОП-инструмента Aspect.NET. Предложенный способ интеграции Aspect.NET в среду программирования Microsoft Visual Studio повышает удобство создания аспектов для платформы Microsoft.NET. Разработанный набор АОП-рефакторингов облачных ASP.NET веб-приложений демонстрирует повышение качества исходного кода целевого приложения за счет принципа “разделяй и властвуй”. Продемонстрированный в диссертации метод использования в аспектах стороннего решения Microsoft Enterprise Library Integration Pack дает возможность применять существующие библиотеки, компоненты и веб-сервисы для реализации сквозной функциональности, упрощая сами аспекты.
Практическая ценность заключается в реализации предложенных модификаций в Aspect.NET, создании библиотеки аспектов AzureLibrary и примеров ее применения. Также разработаны примеры, иллюстрирующие эффективность предложенного набора АОП-рефакторингов.
Так коэффициент сопровождаемости кода целевых приложений, подвергнутых АОП-рефакторингу улучшился на 3-25%. В проекте с Orchard CMS АОП-рефакторинг с помощью 6 аспектов повысил коэффициент сопро-
вождаемости целевых классов на 5-12%. Таким образом, доказан существенный технический эффект использования предложенных алгоритмов и методов при написании и сопровождении программных продуктов. Сведения о практическом использовании полученных автором диссертации научных результатов приведены в актах о внедрении программных принципов и библиотек, разработанных в рамках исследования (см. в приложении к диссертации).
Положения, выносимые на защиту
1. Разработана и реализована библиотека аспектов AzureLibrary
для расширения облачных веб-приложений следующими видами функцио
нальности: перенаправление протоколирования в хранилище отладочной ин
формации Microsoft Azure, кэширование в распределенном облачном кэше
информации, получаемой из SQL Azure, и обработки исключений. Примене
ние AzureLibrary и Aspect.NET приводит к добавлению новой функциональ
ности без какой-либо модификации целевого проекта.
-
Предложена методика “замещающего” аспектного наследника, который позволяет перехватывать обратные вызовы методов от инфраструктуры Microsoft Azure, поддерживающая возможность бесшовного применения аспектов в Aspect.NET. Также предложено раздельное хранение целевой и ас-пектной конфигурации, а для этого разработан алгоритм по их слиянию при компиляции аспектного проекта. Данные предложения реализованы в программном комплексе Aspect.NET.
-
Найден способ интеграции компоновщика аспектов Aspect.NET в Microsoft Visual Studio для обеспечения возможности публикации, а также локальной и удаленной отладки в облаке Azure АОП-программ.
-
Разработан метод бесшовной интеграции сквозной функциональности библиотеки Microsoft Enterprise Library Integration Pack for Azure в целевое приложение на примере аспектов логгирования (Logging Application Block), автоматического масштабирования облачного приложения (Autoscaling Application Block), реакции на исключительные ситуации (Transient Fault Handling). Это позволило расширить функциональность облачных приложений с помощью указанной библиотеки. Данные аспекты также реализованы автором в рамках библиотеки AzureLibrary.
-
Разработана и протестирована методика улучшения индекса сопрово-ждаемости (Maintanability Index) целевых классов с помощью проведения их АОП-рефакторинга. Спроектирован набор из 5 аспектно-ориентированных рефакторингов на основе Aspect.NET для классов облачных веб-приложений. Проведенные эксперименты над типичными веб-приложениями (N2CMS и Orchard CMS) показали улучшение индекса сопровождаемости целевых классов на значения от 2 до 25%.
Все полученные результаты являются новыми.
Апробация результатов. Основные результаты и выводы диссертационной работы докладывались и обсуждались на следующих научных конфе-
ренциях и семинарах: 1) конференция “Технологии Microsoft в теории и практике программирования”, 2011, СПбГПУ, Санкт-Петербург; 2) вторая межвузовская научная конференция по проблемам информатики “СПИСОК-2011”, 2011, СПбГУ, Санкт-Петербург; 3) всероссийская научная конференция по проблемам информатики “СПИСОК-2012”, 2012, СПбГУ, Санкт-Петербург; 4) конференция “Технологии Microsoft в теории и практике программирования”, 2012, СПбГПУ, Санкт-Петербург;
-
межвузовский конкурс-конференция “Технологии Microsoft в теории и практике программирования”, 2013, СПбГПУ, Санкт-Петербург;
-
межвузовская научная конференция по проблемам информатики “СПИСОК-2013”, 2013, СПбГУ, Санкт-Петербург; 7) всероссийская научная конференция по проблемам информатики “СПИСОК-2014”, 2014, СПбГУ, Санкт-Петербург; 8) international conference on numerical analysis and applied mathematics 2014 (ICNAAM-2014), 2014, Rhodes, Greece; 9) всероссийская научная конференция по проблемам информатики “СПИСОК-2016”, 2016, СПбГУ, Санкт-Петербург.
Структура и объем диссертации. Диссертационная работа состоит из введения, шести глав, заключения, библиографического списка, приложения. Работа изложена на 150 страницах машинописного текста, содержит 7 рисунков, 3 таблицы, 58 листингов, 3 акта о внедрении и список литературы из 132 наименований.
История развития облачных технологий (Amazon AWS и Microsoft Azure)
Как можно видеть, возможности IaaS предоставляются на уровне инфраструктуры и не затрагивают уровень приложения. Поэтому любое приложение может быть перенесено в облако без всяких изменений, используя модель IaaS. Также она оптимальна для заказа виртуального сервера и развертывания на нем своей базы данных, если нет необходимости в дорогостоящей (но стабильной и надежной) облачной базе данных от провайдера.
Итак, услуги по модели IaaS оказываются большим числом провайдеров, что приводит к её минимальной стоимости для клиента. Однако надо учитывать, что при этом он освобождается только от сложностей управления оборудованием, но не администрирования своих виртуальных серверов. В случае, если на физическом сервере откажет процессор, диск или память, провайдер их заменит, но вся настройка и сопровождение операционной системы, базы данных и вебсервера лежит на плечах клиента. Объединение своих виртуальных серверов для создания отказоустойчивых веб-приложений с распределением нагрузки (web-farms), установка обновлений прикладного программного обеспечения, антивирусная защита — всё это лишь примеры проблем, которые неявно повышают конечную стоимость облачного решения. При модели PaaS (Platform as a Service) клиент развертывает свои веб-приложения на аппаратной и программной инфраструктуре (операционная система, веб-сервер, среда выполнения, различные каркасы приложений) провайдера. Клиент сохраняет полный контроль над своими приложениями и может частично конфигурировать платформу, например, через веб-портал или переменные окружения. Таким образом, провайдер берет на себя администрирование всей облачной инфраструктуры, в то время как клиент сосредоточен только на своем приложении. Именно такой подход уменьшает временной разрыв между разработкой веб-приложения, его тестированием и публикацией в облаке, устраняя одновременно неспецифичные для бизнеса затраты на поддержание инфраструктуры. В качестве примера можно привести “Web Apps” — PaaS платформа Microsoft Azure, где клиент имеет возможность воспользоваться шаблонами готовых веб-приложений (CMS, интернет-магазины, блоги и пр.), а потом редактировать их прямо в облаке (с помощью Visual Studio Online [102]), связав с такими облачными сервисами, как кэширование, база данных, очередь сообщений, мониторинг, диагностика и пр.
В качестве другого примера модели PaaS, стоит упомянуть HDInsight — платформу для развертывания в облаке Microsoft Azure высокопроизводительных приложений, созданных на каркасе Apache Hadoop [12]. Его задачей является распределение элементарных задач по узлам кластера, а потом сведение их вместе для получения результата (парадигма MapReduce [58]). Со стороны платформы AWS аналогом является Amazon Elastic MapReduce [6]
Несмотря на удобство модели PaaS, абстрагированность от уровня инфраструктуры приводит к ограничению клиента в выборе инструментов разработки. Например, Web Apps не поддерживает веб-сервисы на языках C++, Perl или Smalltalk. В другой технологии — Google AppEngine, облачном сервисе хостинга веб-приложений на серверах Google, поддерживаются только языки Python, Java, Go или PHP. Более того, модель PaaS позволяет реализовать только внешнюю сторону (фронтенд, front-end) веб-приложения, оставляя для внутренней стороны (бэкенда, back-end) необходимость заказывать виртуальные серверы по модели IaaS. К бэкенду можно отнести отдельные приложения, которые перерабатывают каким-то образом данные для сайта: архивирование, индексирование, конвертация, построение отчетов и т.п. и не взаимодействуют с конечным пользователем.
Поэтому совместное применение моделей PaaS и IaaS далеко не редкость, а наличие API по управлению облачной конфигурацией дает возможность применять услуги от разных провайдеров. К примеру, для фронтенда облачного сайта с музыкой можно применить Azure Web Apps (PaaS), а сервер для индексирования авторов, треков и альбомов (на основе Java-приложения ElasticSearch [97]) будет на отдельной виртуальной машине Microsoft Azure (IaaS), в то время как хранилищем выбрать (из-за низкой стоимости) Google Cloud Storage [37, 127]
Бизнес-модель SaaS (Software as a Service) — это модель аренды веб-приложения, которая подразумевает его развертывание на облачном оборудовании компании разработчика [119]. Множество пользователей работают с этим приложением через Интернет или терминальный доступ. С экономической точки зрения такая модель наиболее выгодна для обеих сторон: разработчики поддерживают одну версию программного обеспечения на наиболее подходящем оборудовании, распределяя её по множеству пользователей. Клиенты в свою очередь экономят на техническом облуживании, получая на привычном устройстве необходимый сервис в течение только такого срока, когда это реально необходимо. Предсказуемость расходов, защита от нелицензионного использования и экономия на масштабах делают SaaS всё более популярной моделью распространения такого программного обеспечения, как почта, офисные редакторы (Google Docs), системы управления и создания сайтов (CRM) и даже среды разработки (Visual Studio Online). Однако модель SaaS не применима в случае таких типов программного обеспечения, которые требуют индивидуальной адаптации под требования пользователя (напр. системы автоматизации торговли), взаимодействия со специализированным оборудованием заказчика (автоматизация производства), возможность работы без Интернет-соединения (например, сбор данных с датчиков), а также критичны к вопросам контроля за распространением личных данных (государственные службы). Без доработки под индивидуальные требования и размещения программного обеспечения из указанных областей в частных облаках заказчика эти системы будут не применимы для ряда клиентов, но в этом случае нарушается требование SaaS “одна версия — для всех клиентов”.
Применение контейнера управления зависимостями Microsoft Unity для АОП на платформе .NET
Веб-сервисы — это самодостаточные программные компоненты, сконцентрированные на решении одной задачи и доступные через Интернет или виртуальную сеть.
Каждый веб-сервис объявляет открытый интерфейс, через который с ним могут работать системы, запущенные на различном оборудовании или операционных системах. Стандартизация протокола доступа к веб-сервисам позволила создавать слабосвязанные и кроссплатформенные приложения. Такой подход называется компонентно-ориентированной разработкой (Component-Based Software Development, CBSD) [95]. Несмотря на то, что его применение позволяет инкапсулировать различную функциональность в одном модуле, в случае “сквозной” функциональности вызовы этого модуля будут распределены по целевому коду. Авторы FuseJ предлагают объединить принципы АОП и CBSD в одном фреймворке для платформы Java, позволяющем бесшовно составить приложение из веб-сервисов и обеспечивающим возможность стыковать их аспектно-ориентированные образом [94]. Бесшовность в данном случае заключается в том, что программные компоненты разрабатываются как обычные классы, без учета того, будут ли они использованы аспектно-ориентированным образом.
Конструирование веб-сервисов в FuseJ основано на описании интерфейсов. Каждый веб-сервис (service) в FuseJ должен декларировать как свой интерфейс, который предоставляется его клиентам (provides), так и ожидаемый интерфейс (expects) другого веб-сервиса, который будет необходим для реализации.
Согласно приведенному описанию, фреймворк FuseJ во время выполнения программы перехватит все вызовы исходного (source) метода (задаваемого в блоке for), подставит вместо них целевой (target) метод (определяемый в блоке connect). В том случае, когда их сигнатуры не совпадают, FuseJ сопоставляет аргументы с одинаковым порядковым номером и типом, а остальные определяет из блока where. Дополнительно в блоке when можно использовать булевские функции Java для указания динамических условий, при которых будет произведена замена.
Специфицированные таким образом сервисы и коннекторы предписывают создать веб-сервисы, которые можно использовать как ожидаемые при создании других, обеспечивая повторное использование в спецификациях FuseJ. Связывание различных сервисов в рамках коннекторов позволяет быстро заменять одни реализации другими, однако преимущества данного подхода возникают только при программировании веб-сервисов, так как результирующие после FuseJ классы нельзя явно вызывать из Java-кода, например, для создания библиотеки классов. Подход FuseJ имеет сходные черты с IoC-контейнером Spring, в обоих случаях сопоставление интерфейсов и реализаций описывается бесшовным образом в отдельных сущностях — коннекторах FuseJ или XML-файлах Spring. Преимуществом FuseJ является возможность декларативно комбинировать одни веб-сервисы для создания других. По сравнению с аспектами в AspectJ и Aspect.NET, FuseJ отделяет реализацию аспекта (класс веб-сервиса) от правил его внедрения (коннектор). Таким образом, аспект не имеет никаких сведений о том, в какой точке внедрения он будет выполняться и поменять её поведение он может только через ожидаемый интерфейс. Это повышает связанность аспекта и предсказуемость его действий. Тем не менее, FuseJ может перехватывать только открытые методы, а на целевой проект накладываются дополнительные требования: его разработка должна производиться на основе интерфейсов, что затрудняет бесшовное применение аспектов к унаследованному коду. Также по сравнению со статическим применением аспектов, использование FuseJ приводит к дополнительным накладным расходам.
Паттерн управления зависимостями (Inversion of control, IoC) призван переложить ответственность за создание объектов на специальный контейнер. Если программа изначально спроектирована с выделением интерфейсов для всех операций, которые в дальнейшем могут эволюционировать, то прямое инстанцирование конкретных классов (через оператор new) приводит к жесткой связности между различными компонентами. Когда приходит время подставить ссылку на другой класс, реализующий тот же интерфейс, то приходится вручную находить все соответствующие места в коде и менять вызовы конструкторов. Всё это нарушает принцип проектирования “открыт для расширения, закрыт для модификации” OCP [59] и выходом будет разрыв зависимости между интерфейсом и его реализацией некой фабрикой, контейнером. Набор соответствий между интерфейсами и реализациями может быть задан как в коде, так и в XML-файле, что позволяет расширять приложение, не затрагивая существующие компоненты. Большинство IoC-контейнеров позволяет также сопоставлять интерфейсы и объекты, созданные вне контейнера. Более того, если IoC-контейнер будет возвращать ссылку не на объект целевого типа, а на прокси-объект, инкапсулирующий в себе данный объект, то появляется возможность перехвата вызовов к методам целевого класса по паттерну “Перехватчик” (Interceptor) [49]. Такая возможность перехвата вызовов представляет собой простейшую АОП-функциональность.
Ввиду актуальности данной проблемы, в настоящее время разработано множество IoC-контейнеров для платформы Microsoft .NET (Castle Windsor [128], Autofac [104], NInject [16], Spring.NET и т.д.). Компания Microsoft также предлагает свое решение Unity, которое являетсякода одним из функциональных блоков Microsoft Enterprise Library. Несмотря на разные способы управления зависимостями, все IoC-контейнеры служат одной цели и, без ущерба для понимания, можно рассмотреть лишь контейнер Unity [30].
Замещение аспектом целевого класса для перехвата событий
При АОП-разработке может потребоваться перехватить вызов данного обработчика для добавления текста в этот элемент. Метод LogButton_Click вызывается средой ASP.NET и у компоновщика нет доступа к вызывающему коду, чтобы обернуть его вызовом действий аспекта. В этом случае PostSharp предлагает применять правило внедрения OnMethodBoundaryAspect, при котором действия аспекта вставляются внутри тела целевого метода. Однако, если потребуется получить доступ к защищенным полям или методам целевого класса, придется использовать рефлексию .NET. Более оптимальное решение здесь — применить паттерн “Декоратор” [111] и создать наследника класса Default с переопределенным целевым методом LogButton_Click [114]:
Специальный пользовательский атрибут ReplaceBaseClass предписывает компоновщику Aspect.NET заменить целевой класс своим аспектным наследником. Для этой цели автором разработан следующий алгоритм, реализованный в компоновщике аспектов. 1. Заменить в исходной сборке все вызовы методов базового целевого класса (в том числе и конструкторы) на вызовы методов его наследника в аспектной сборке. 2. Принудительно объявить виртуальными те методы целевого класса, которые переопределены в замещающем его наследнике. Если они закрыты (private), то сделать их защищенными (protected). 3. Если вызов этих методов в исходной сборке производится с помощью MSIL-инструкции call или ldftn, заменить их на callvirt и ldvirtftn соответственно. 4. Объединить с помощью инструмента ILRepack [69] (из проекта Mono.Cecil) аспектную сборку и целевую. 5. Присвоить какое-нибудь служебное имя базовому целевому классу, а его первоначальное имя — замещающему наследнику из аспекта.
Подобное создание декораторов (но во время выполнения программы) лежит в основе IoC-контейнеров. Преимуществами такого подхода является простота подмены классов для пользователя, а также использование только штатного синтаксиса языка .NET. Теперь с помощью аспекта можно: уточнять поведение любого метода целевого класса, реализовывать в нем дополнительные интерфейсы, накладывать различные пользовательские атрибуты и т.п. По сравнению с обобщенным введением интерфейса в PostSharp мы теряем возможность декларативно вводить интерфейсы в целевые классы, однако получаем возможность использовать их члены в аспекте. Вычислительная сложность такого алгоритма O(N) , гд е N — количество MSIL-инструкций в исходной сборке. Поскольку в компоновщике аспектов Aspect.NET эти операции объединены с операциями вставки аспектов (также сложностью O(N)), общая асимптотическая сложность компоновки аспектов не увеличилась. Следует отметить, что данное решение всё же нетипично для АОП, где аспект описывается максимально изолированно от целевого класса, в то время как наследование предполагает сильную связь. В то же время, выразительные средства АОП решают ограниченный круг задач и, если есть возможность решить задачу более элегантным способом, стоит им воспользоваться. Косвенно это подтверждается действиями команды PostSharp, которая взяла курс на создание инструментов (PostSharpToolkits [79]), предназначенных для решения специфичных задач (напр. многопоточности и диагностики). Применение для тех же целей исключительно аспектов PostSharp вызывает практические затруднения.
Бесшовное расширение бизнес-логики нефункциональными требованиями с помощью сторонних библиотек (напр. Microsoft EL) заключается в создании отдельного проекта в виде библиотеки классов (dll), добавлению к нему аспектных классов, а также интеграции в него сторонней библиотеки через менеджера зависимостей Nuget. В процессе интеграции в зависимости аспектного проекта будут добавлены необходимые ссылки и, возможно, будет создан конфигурационный XML-файл с настройками сторонней библиотеки. После слияния компоновщиком Aspect.NET аспектной сборки и целевой, объекты сторонней библиотеки будут обращаться к конфигурационному файлу целевого проекта, в котором отсутствуют необходимые настройки. Пользователю приходится вносить изменения в целевой конфигурационный файл самостоятельно, что затрудняет его редактирование, ведь теперь все возможные настройки всех аспектов и целевого проекта содержатся в одном файле. Особенно такая ситуация критична в веб-приложениях, поскольку их файл web.config содержит достаточно много узлов и назвать “бесшовным” такое применение аспектов нельзя. Microsoft Visual Studio предлагает свою технологию по трансформации web.config файла при сборке или публикации проекта [28]. В обозревателе проекта (solution explorer) можно раскрыть узел web.config и получить доступ к файлам web.Debug.config и web.Release.config. В них с помощью XML-атрибутов xdt:Transform и xdt:Locate задается трансформация web.config при сборке в режиме Debug или Release. Но в нашем случае необходимо трансформировать целевой web.config только при внедрении соответствующего аспекта и оставить его неизменным при запуске целевого проекта без аспектов. К тому же, расстановка XML-атрибутов вручную может привести к ошибкам.
Итак, сформулируем проблему по бесшовному слиянию целевой и аспектной конфигурации. Есть два проекта, в каждом из них есть свой конфигурационный файл web.config. Необходимо предложить решение, которое бы автоматически обеспечивало слияние аспектных настроек с целевыми, но при этом сами файлы с настройками оставались бы неизменными. Сокращенные примеры исходных и результирующего файла приведены ниже (Листинг 28. Аспектный web.config, Листинг 29. web.config, Листинг 30. Результирующий web.config).
Кэширование в аспекте результатов операций, сессии и ответа сервера
Теперь рассмотрим привязку действий аспекта, связанного с ролью, к переадресованным вызовам методов базового класса RoleEntryPoint.
В том случае, если обращения к методам сервисного объекта Microsoft Azure содержатся внутри переопределенных методов роли и их необходимо перенести в действия аспекта, следует привязать их точки внедрения к переадресованным вызовам методов базового класса.
Предположим, в переопределенном методе роли OnStart() происходит инициализация сервисного объекта Microsoft Azure. Тогда следует перенести эту инициализацию в действие, которое будет вставлено, например, перед вызовом RoleEntryPoint.OnStart(). Здесь не подходит решение с определением в аспекте наследника роли, переопределением у него метода OnStart() и подменой им своего базового класса с помощью пользовательского атрибута ReplaceBaseClass. Дело в том, что среда Microsoft Azure автоматически создает экземпляры ролей, требуя при этом, чтобы непосредственным базовым классом роли был класс Microsoft.WindowsAzure.ServiceRuntime.RoleEntryPoint. В большинстве случаев внутри переопределенных методов роли вызываются методы базового класса, поэтому мы можем привязать вызов действия аспекта к нему.
Иногда управление службой производится на основе веб-интерфейса. В этом случае код разметки основной страницы с данными (.aspx) перемешан с разметкой веб-интерфейса службы. Если мы выделим этот веб-интерфейс службы в отдельный .ascx компонент, то сможем повторно использовать его на других страницах. Предположим, что облачная веб-роль реализуется по принципам ASP.NET MVC [106]: Контроллер (определения понятий Контроллер, Модель и Вид см. в разделе 1 данной главы) заполняет Модель данными и передает её Виду (т.е. .aspx странице) для визуального отображения. Тогда, чтобы выделить из Вида отдельный .ascx компонент, необходимо выполнить следующие действия: 1. Перенести данные, требуемые для управления службой из общей модели в отдельную модель и сохранить её класс в проекте аспекта; 2. Выделить управляющие элементы веб-интерфейса службы в .ascx компонент и связать его с новой моделью (AscxControlViewModel); 3. Скопировать этот .ascx компонент в проект аспекта; 4. Показать содержимое .ascx компонента на .aspx странице Вида через подстановку команды %= Html.Action("AscxControlView") % в то место, где раньше находилась разметка веб-интерфейса управления службы. При этом AscxControlView — название этого компонента; 5. Создать аспектный производный класс для Контроллера и определить в нем метод для обработки команды AscxControlView:
В заключение рассмотрим получение информации от аспекта и управление им через “пустые” private свойства в целевом коде.
Зачастую сервисы Microsoft Azure используются для получения какого-либо значения, например, для вывода пользователю на .aspx-странице текущего количества одновременно запущенных экземпляров веб-роли. Или же это значение используется для управления службой, например, устанавливается требуемое число экземпляров веб-роли. Данное поведение полностью соответствует концепции свойств в .NET, и имеет смысл заменить вызовы методов сервиса Microsoft Azure на его пустое свойство “представитель”. Сами вызовы будут перенесены в аспект, действия которого привяжутся к get_ и set_ методам свойства и подменят их на этапе компиляции (с помощью правила %instead %call).
Для оценки полученных результатов использовалась интегральная метрика Maintainability Index, которая встроена в Microsoft Visual Studio и определяет удобство сопровождения исходного кода отдельных классов и проекта в целом. Так, например, выделение из целевых классов учебного примера [106] функции кэширования в отдельный аспект позволило увеличить для них эту метрику качества на 33%. Для целевых классов другого примера [33] аспектное управление конфигурацией дало прирост этого индекса на 24%. Следует отметить, что такой выигрыш наблюдается только у конкретных классов, но экономия в масштабах целого приложения будет не столь существенна.
Аналогично проекту по демонстрации преимуществ АОП-рефакторинга системы JHotDraw [52] на основе AspectJ [101], получить информацию о применимости АОП-рефакторинга на базе Aspect.NET для реальных приложений можно из студенческих проектов Н. Волкова и А. Михайловой, ко т о р ы е рассматривали N2CMS [85, 110] и Orchard CMS [122, 86]. Данные приложения с открытым кодом по созданию и управлению сайтами работают на платформе ASP.NET и, следовательно, могут быть перенесены в облако Microsoft Azure. В первом проекте проведен рефакторинг 3 классов, их метрики приведены ниже, на рис. 7 и рис. 8.
Данный коэффициент имеет значение от 0 до 100, которое обозначает относительную легкость сопровождения кода. Чем больше значение, тем легче код сопровождать (вносить в него изменения, добавлять новую функциональность, удалять устаревшие блоки, искать ошибки и т.д.). Чтобы ускорить обнаружение проблемных фрагментов кода, могут использоваться цветовые индикаторы. Зеленый рейтинг указывает на значение индекса в диапазоне от 20 до 100, что означает, что код удобно поддерживать. Желтый рейтинг указывает на значение индекса в диапазоне от 10 до 19, что означает, что код можно поддерживать. Красный рейтинг указывает на значение индекса в диапазоне от 0 до 9, что означает, что код сложно поддерживать [118]. Значения указанных коэффициентов до и после преобразования приведены ниже (Таблица 2 и Таблица 3 соответственно).