Научная статья на тему 'Средства аспектно-ориентированного программирования для разработки Web-приложений в системе Aspect.NET'

Средства аспектно-ориентированного программирования для разработки Web-приложений в системе Aspect.NET Текст научной статьи по специальности «Компьютерные и информационные науки»

CC BY
375
120
i Надоели баннеры? Вы всегда можете отключить рекламу.
Ключевые слова
АСПЕКТНО-ОРИЕНТИРОВАННОЕ ПРОГРАММИРОВАНИЕ / АОП / ASPECT.NET / WEBПРИЛОЖЕНИЕ / MICROSOFT.NET / ASP.NET / ASPECT-ORIENTED PROGRAMMING / AOP / WEB-APPLICATION

Аннотация научной статьи по компьютерным и информационным наукам, автор научной работы — Нгуен Ван Доан, Сафонов Владимир Олегович

Описаны методы применения аспектно-ориентированного программирования для задач разработки Web-приложений на платформе Microsoft.NET. Разработаны аспекты для поддержки Web-программирования в системе Aspect.NET. Проанализированы эффективность и производительность применения этих аспектов в Web-приложениях.

i Надоели баннеры? Вы всегда можете отключить рекламу.
iНе можете найти то, что вам нужно? Попробуйте сервис подбора литературы.
i Надоели баннеры? Вы всегда можете отключить рекламу.

Aspect-oriented programming tools for Webapplications development in the Aspect.NET system

At prezentWeb-programming plays an important role in sphere of software development. Day to day web applications quickly develop and gradually replace desktop applications. They are the future of theWeb, software applications, network architectures, and even computers and operating systems. Therefore, application of aspect-oriented programming in Web-programming is wary important in the society of software development. It allows developers to reduce time, cost and complexity of development, to simplify the maintenance of Web-based products and amending them, to create reliable and secure Web-applications. The paper suggests methods of application of aspect-oriented programming for the tasks of Web-applications development in Microsoft.NET platform. Aspects that support Web-programming are developed in the Aspect.NET system to simplify the process of creation and maintenance of Web-applications.

Текст научной работы на тему «Средства аспектно-ориентированного программирования для разработки Web-приложений в системе Aspect.NET»

Сер. 10. 2011. Вып. 1

ВЕСТНИК САНКТ-ПЕТЕРБУРГСКОГО УНИВЕРСИТЕТА

УДК 004.432.4

Ван Доан Нгуен, В. О. Сафонов

СРЕДСТВА АСПЕКТНО-ОРИЕНТИРОВАННОГО ПРОГРАММИРОВАНИЯ ДЛЯ РАЗРАБОТКИ WEB-ПРИЛОЖЕНИЙ В СИСТЕМЕ ASPECT.NET

Введение. Аспектно-ориентированное программирование (АОП) [1] - перспективный подход к инженерии программ, предназначенный для разработки сквозной функциональности (cross-cutting concerns) - идей, методов, функциональных возможностей, реализуемых и модифицируемых в ходе разработки программ, которые принципиально, по своей природе, не могут быть реализованы одной обобщенной процедурой (generalized procedure) - тесно взаимосвязанной совокупностью модулей (например, иерархией классов), а требуют для своей реализации совокупности рассредоточенных действий (tangled actions), которые должны быть добавлены в различные части существующего программного кода целевого приложения, для того чтобы новая сквозная функциональность заработала [2]. Иначе говоря, сквозная функциональность - это новая функциональность, реализация которой рассредоточена по коду приложения. Тем самым, АОП позволяет систематически добавлять и модифицировать новую функциональность, в том числе и относящуюся к Web-программированию. Подробное описание АОП дано в работах [1-3].

В настоящее время Web-программирование играет важную роль в сфере разработки программного обеспечения (ПО). Web-приложения (Web applications) быстро развиваются и постепенно заменяют приложения для настольной системы (desktop applications). Развитие Web-приложений является важной тенденцией эволюции компьютерных технологий, операционных систем, сетевых архитектур и прикладных программ [4]. Применение АОП в Web-программировании, как будет показано в статье, позволяет разработчикам снизить время, стоимость и сложность разработки, упростить сопровождение Web-продуктов и внесение в них изменений, создавать надежные и безопасные Web-приложения.

В настоящей статье рассмотрено применение АОП в Web-программировании для платформы Microsoft.NET. Web-программирование для настоящей платформы реализуется с помощью технологии ASP.NET [5], а АОП для платформы .NET - в системе Aspect.NET [6], разработанной в лаборатории Java-технологии

Нгуен Ван Доан — аспирант кафедры информатики математико-механического факультета Санкт-Петербургского государственного университета. Научный руководитель: доктор технических наук, проф. В. О. Сафонов. Количество опубликованных работ: 6. Научные направления: аспектноориентированное программирование, языки программирования, Java технология, .NET. E-mail: ngvdoanbk@yahoo.co.uk.

Сафонов Владимир Олегович — доктор технических наук, профессор кафедры информатики математико-механического факультета Санкт-Петербургского государственного университета. Количество опубликованных работ: 110. Научные направления: аспектно-ориентированное программирование, языки программирования, компиляторы, инженерия знаний, Java-технология, .NET, надежное и безопасное программирование, параллельное программирование. E-mail: vosafonov@gmail.com.

© Ван Доан Нгуен, В. О. Сафонов, 2011

математико-механического факультета СПбГУ под руководством проф. В. О. Сафонова. Цели статьи - анализ методов применения АОП, реализованного в системе Aspect.NET, для разработки и модификации ASP.NET-приложений, а также выделение некоторых типичных задач Web-программирования, к которым можно применить АОП.

1. Особенности ASP.NET. ASP.NET - технология создания Web-приложений и Web-сервисов, разработанная компанией Microsoft. Она служит составной частью платформы Microsoft.NET и развитием более старой технологии Microsoft ASP. Хотя название технологии ASP.NET происходит от Microsoft ASP, она значительно отличается от последней. Microsoft полностью перестроила ASP.NET, основываясь на общей системе поддержки выполнения программы Common Language Runtime (CLR), которая служит основой Microsoft.NET. Преимущество технологии ASP.NET - в более высокой степени абстракции, построенной над стандартным HTML-кодом: использование объектно-ориентированной парадигмы, поддержка нескольких языков программирования, динамическая компиляция страницы при первом запросе к странице, наличие универсальной библиотеки классов, содержащей тысячи готовых для использования в проектах решений - Microsoft .NET Framework.

Важная особенность ASP.NET - технология разделения кода, которая позволяет разработчику отделить код программной логики от кода представления, т. е. поместить код программной логики страницы в файл .cs или .vb, отдельно от кода собственно страницы, размещаемого в .aspx-файле. Эта технология называется Code-Behind. Таким образом, дизайн страницы может быть изменен, не затрагивая кода страницы, что позволяет разделить ответственность за внешний вид и работу страницы между дизайнером и программистом.

В Microsoft Visual Studio.NET существуют два типа ASP.NET-проектов [7]: ASP.NET Web-сайт (ASP.NET Web Site) и ASP.NET Web-приложение ( ASP.NET Web Application). Основное различие между ними и детальное сравнение данных типов ASP.NET-проектов описаны в [7]. Microsoft Visual Studio.NET 2005 по умолчанию не включает в себя шаблон ASP.NET Web-приложения. Для работы с этим шаблоном необходимо установить Service Pack 1 [8]. В отличие от версии 2005, Microsoft Visual Studio.NET 2008 по умолчанию поддерживает оба этих типа ASP.NET-проектов. В текущей версии (2.1) Aspect.NET применим только к ASP.NET Web-приложениям. Все примеры аспектов, которые будут рассмотрены в п. 5, были разработаны в среде Microsoft Visual Studio.NET 2008 с использованием новой версии Aspect.NET, которая будет выпущена в ближайшее время, и внедрены в ASP.NET Web-приложения.

2. Взаимодействие Aspect.NET с ASP.NET. Aspect.NET - это языково-независимая визуальная среда разработки АОП-приложений для Microsoft.NET, реализованная как расширение (add-in) Microsoft Visual Studio.NET 2005. С помощью Aspect.NET пользователь может определять, внедрять и оценивать результаты внедрения аспектов в своих проектах.

Наиболее разумным решением при описании аспектов была бы возможность использовать как метаязык, так и атрибутные спецификации, чтобы скомбинировать преимущества этих подходов. Преимуществом метаязыка является лаконичное описание сложных аспектов, а пользовательских атрибутов - совместимость с существующими инструментами для разработки на платформе .NET. Система Aspect.NET использует оба подхода. Определению аспекта на метаязыке Aspect.NET.ML соответствует специальный тип проекта, который затем может быть сконвертирован в класс аспекта

с соответствующими атрибутными аннотациями или напрямую в сборку аспекта. Такая скомпилированная сборка аспекта затем применяется для внедрения.

Представим более детальный сценарий взаимодействия Aspect.NET с ASP.NET:

1. Пользователь описывает аспекты на метаязыке (или на языке C# с использованием специализированных атрибутов АОП), загружает исходные коды целевого Web-приложения (в виде обычного «ASP.NET Web Application» проекта MS Visual Studio) в редактор и компилирует коды программной логики страниц (code-behind) в целевую сборку.

2. Редактор конвертирует описания аспектов (если аспекты описаны на метаязыке) в классы и АОП пользовательские атрибуты, комбинируя их затем в общую аспектную сборку.

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

4. Подсистема внедрения аспектов формирует и возвращает обратно редактору XML-файл с информацией о координатах точек внедрения в целевой сборке и исходном тексте.

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

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

На рис. 1 представлена организация среды АОП-разработки Aspect.NET для ASP.NET-приложения.

Процесс работы пользователя с Aspect.NET реализуется следующим образом. Создаются сборки с аспектами, как результат компиляции классов аспектов с атрибутными аннотациями или компиляции специальных проектов (template projects) на метаязыке Aspect.NET. После загрузки пользовательского ASP.NET Web-приложения в Visual Studio в Aspect.NET Editor можно выбрать эти сборки с аспектами для внедрения в данный проект и запустить режим сканирования для получения списка доступных точек внедрения (рис. 2).

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

3. Некоторые задачи Web-программирования, допускающие решение с помощью АОП. При создании ASP.NET-приложений разработчики сталкиваются с задачами, решение которых может потребоваться во многих модулях кода приложения. Эти задачи для Web-приложений являются примерами сквозной функциональности. Приведем список некоторых типичных задач подобного рода, для которых были разработаны аспекты в системе Aspect.NET: протоколирование (logging), безопасность (authentication, authorization, impersonation), криптография строки запроса (Query String), криптография cookie-файлов, кодирование гипертекста (Html Encoding), расширение пользовательского Web-интерфейса. Отмеченные нами задачи

Рис. 1. Организация среды АОП-разработки Aspect.NET для ASP.NET-приложения

Рис. 2. Получение списка доступных точек внедрения

были выбраны, так как, во-первых, их решение необходимо в реальном процессе разработки Web-приложений, во-вторых, они требуют решения в виде реализации сквозной функциональности приложения (за счет возможного повторения их реализации в разных местах кода Web-приложения), а АОП - наиболее подходящая технология для разработки подобных реализаций. В дальнейшем рассмотрим также другие задачи, например: расширение событий мониторинга (Custom Health Monitoring Events), проверка безопасности (Security Checking), валидация XML-документов (XML Validation) и т. д.

Протоколирование (или ведение протокола) - хронологическая запись с различной (настраиваемой) степенью подробности сведений о происходящих в системе событиях, обычно в некоторый файл. Эта задача типичная и может быть решена с помощью АОП.

Безопасность Web-приложений является важной задачей Web-программирования. Безопасность ASP.NET-приложений основана на трех операциях: аутентификация, авторизация и олицетворение (impersonation) - предоставление серверному процессу ASP.NET прав доступа клиента. ASP.NET предоставляет удобные механизмы для реализации этих операций [5, 9]. При разработке Web-приложений при необходимости осуществляются программно действия аутентификации и авторизации пользователей или действия олицетворения некоторого фрагмента кода в Web-приложениях с Windows-аутентификацией. Эти действия могут повторяться в различных модулях приложения.

Один из способов передачи информации между страницами в Web-приложениях -через строки HTTP-запросов (Query Strings). Строка HTTP-запроса - часть унифицированного указателя ресурса (URL), который содержит данные для передачи в Web-приложения. Например, если URL-адрес запроса: http://vnn.vn/news.aspx?name= asp.net&author=abc, то значение строки запроса равно name=asp.net&author=abc. Во многих ситуациях информация URL-запроса, соответствующая переданным пользователем данным, не содержит проблем, связанных с тем, что пользователь может видеть или модифицировать ее. Но в других ситуациях строка запроса содержит информацию, которую пользователям запрещено визуализировать. Поэтому необходимо решить задачу криптографии строки запроса.

Один из способов хранения данных на стороне пользователя в Web-приложениях -использование cookie-файлов. Cookie - небольшой фрагмент данных, созданный Web-сервером и хранимый на компьютере пользователя в виде файла, который Web-клиент (обычно Web-браузер) каждый раз пересылает Web-серверу в HTTP-запросе при попытке открыть страницу соответствующего сайта. Поскольку cookie-файлы могут содержать конфиденциальную информацию (имя пользователя, условия доступа и т. д.), их содержимое не должно быть доступно другим, следовательно, необходимо решить задачу криптографии их содержимого.

В Web-приложениях часто необходимо представлять статическую информацию на страницах, т. е. информацию, которую пользователи не могут изменить. К данным Web-приложениям относятся главным образом Web-приложения, публикующие новости, например http://gazeta.ru. Проблема, касающаяся данной информации, в следующем: она может содержать в себе символы, которые браузеры неправильно отображают, например пробел, меньше (<), больше (>), амперсанд (&) и кавычки ("). Поэтому необходимо кодировать их в Html-эквиваленты, например символ “<” кодируется в “ &lt;”. Таким образом, необходимо реализовать функциональность кодирования гипертекста при задании текста для элементов управления вида Label, LinkButton, HyperLink, CheckBox, ListItem, RadioButton.

При сопровождении Web-приложений разработчики сталкиваются с проблемой расширения пользовательского интерфейса разработанного Web-приложения, например, следующего содержания: добавить карту Google в Web-страницах; добавить ссылку на некоторый сайт; добавить рекламные элементы; добавить элементы типа сообщения после некоторого действия. При этом приходится изменять код приложения: например, если необходимо добавить элементы типа сообщения после действий какой-либо бизнес-логики, разработчики сначала разрабатывают элемент сообщения (в частности, в виде окна), затем после каждого действия (или в конце их выполнения) создают динамически этот элемент сообщения и вносят его в нужный контейнер на странице.

Исходя из того, что реализация рассмотренных задач может повторяться и рассредоточиваться во многих местах Web-приложения, возникает идея применения АОП для решения указанных задач при разработке ASP.NET-приложений. С помощью АОП каждая задача (или функциональность) реализуется в аспекте в виде набора действий (actions), затем определяются условия внедрения для присоединения данных действий к нужным нам точкам выполнения Web-приложения, после чего запускается подсистема внедрения (weaver) аспектов системы Aspect.NET. Действия аспекта будут автоматически добавляться подсистемой внедрения в точки присоединения (т. е. в нужные нам точки выполнения), определенные условиями внедрения аспекта. При этом изменения целевого Web-приложения выполняются на уровне MSIL-кода.

4. Существующие решения задач Web-программирования. В настоящее время существует значительное число реализаций АОП [3] для платформы Microsoft.NET. Рассмотрим краткий обзор существующих АОП-инструментариев для .NET.

LOOM.NET [10] реализует как динамическое внедрение (с помощью системы внедрения Rapier-LOOM.NET), так и статическое внедрение аспектов (с помощью системы внедрения Gripper-LOOM.NET). Основной целью проекта является помощь в разработке и улучшении динамического реконфигурируемого многопоточного программного обеспечения. Система внедрения аспектов Rapier-LOOM.NET используется для генерации и внедрения динамических COM-объектов. Аспекты в LOOM.NET определены через классы аспектов. LOOM.NET реализует некоторые AspectJ-подобные функции для коммерческой версии .NET и для Mono [11].

AspectDNG [12] - многоязычная система внедрения аспектов, которая работает на уровне MSIL. Она позволяет разработчику внедрить любые .NET 1.1 или .NET 2.0 сборки. Идею проекта AspectDNG дала технология AspectJ, и он разработан на C#. Благодаря тому, что система внедрения аспектов работает с MSIL-кодом, аспекты и целевые приложения могут быть написаны на любом языке .NET. AspectDNG не имеет подходящего языка спецификации аспектов и IDE.

Aspect# [13] - инструментарий АОП для C#. Он состоит из простого (не-XML) языка спецификации аспектов и механизма аспектов (системы внедрения аспектов). Aspect# тоже не имеет IDE.

PostSharp [14] является пост-компилятором для платформы .NET. Он работает как трансформатор MSIL-кода и использует пользовательские атрибуты (custom attributes). Этот инструмент может быть полезен для многих целей, в том числе АОП. На основе PostSharp для АОП была разработана система внедрения аспектов PostSharp Laos. Аспект в PostSharp должен быть определен через специальный тип пользовательских атрибутов, который может быть применен с любым классом или методом для расширения их функциональности.

Weave.NET [15] - проект и инструмент АОП, ориентированный на язык-неза-висимые аспекты - аспекты MSIL-уровня. Ввод для системы внедрения аспектов

представляет собой набор .NET-сборок и один XML-файл спецификации правил внедрения аспектов. Процесс внедрения выполняется во время загрузки.

Wicca [16] является фреймворком АОП (AOP framework), который реализует различные виды стратегий внедрения: статическое и динамическое внедрение на уровнях исходного кода и MSIL-кода. В частности, внедрение на MSIL-уровне в Wicca поддерживается Phx.Morph, основанным на инфраструктуре внутреннего компилятора Microsoft’s Phoenix (так же, как система внедрения аспектов Aspect.NET). Динамическое внедрение в Wicca реализуется с использованием других технологий и инструмента Microsoft: Microsoft Managed Debugger (mdbg). Внедрение на уровне исходного кода C# реализуется с помощью wcs, представляющего собой компилятор исходного кода и систему внедрения аспектов.

Перечисленные выше инструменты АОП для .NET содержат много оригинальных подходов к реализации АОП. Но существующие инструменты АОП для .NET имеют следующие недостатки:

1) отсутствие многоязычной совместимости, зависимость от C# или MSIL. Большинство инструментов АОП для .NET связано только с С#, так что они не применяют должным образом одну из главных особенностей .NET: многоязычную совместимость. Единственный подход, применяемый для достижения совместимости в некоторых других инструментах АОП для .NET, зависит от MSIL;

2) отсутствие правильного языка спецификации аспектов. Большинство проектов предпочитает применять С#, MSIL, и .NET «как есть», четкое определение аспектов как С#-классов, унаследованных от некоторых специфических «классов реализации основного аспекта» с применением пользовательских атрибутов или файлов конфигурации аспекта. Они просто моделируют АОП и AspectJ-функции в языке реализации более низкого уровня;

3) слишком много XML;

4) отсутствие GUI манипуляции аспектами и визуализации аспектов. Поскольку большинство инструментов АОП для .NET еще находится в ранней стадии разработки, они лишь предоставляют АОП, поддерживающее API и файлы конфигурации в формате XML. Они не имеют GUI для манипуляции аспектами, их визуализации, отладки и т. д.;

5) отсутствие интеграции в Visual Studio.NET и другие IDE для .NET.

Подход, которому следует Aspect.NET, основан на следующих основных идеях:

1) статическое внедрение аспектов. Внедрение аспектов реализуется путем инжек-ции бинарного MSIL-кода;

2) язык нейтральных АОП-аннотаций (метаязык АОП) - Aspect.NET.ML;

3) использование пользовательских атрибутов (custom atributes) для представления аспектов для .NET;

4) межъязыковые аспекты (cross-language aspects interoperability);

5) интеграция в технологии и инструменты Microsoft для разработки ПО: Microsoft Visual Studio.NET и Microsoft Phoenix;

6) GUI для визуализации, модификации, добавления, удаления и внедрения аспектов;

7) разработка аспектизатора - инструмента для выделения аспектов из существующих не аспектно-ориентированных приложений и преобразования их в аспектноориентированные.

Более подробно детали Aspect.NET описаны в [3].

Как видно из изложенного, существует значительное число инструментариев АОП для .NET, однако пока они не были применены для решения задач Web-программирования. Теперь рассмотрим более традиционные, основанные на ООП, решения некоторых задач из вышеперечисленных задач Web-программирования, а затем покажем, как они могут быть решены с помощью АОП и в чем преимущество применения АОП для их решения.

Рассмотрим задачу криптографии строки запроса. В [5] (раздел Cryptography) авторы демонстрируют интересный пример шифрования строки запроса. Создается класс EncryptedQueryString, который выполняет функциональность криптографии строки запроса. При шифровании создается объект этого класса с помощью конструктора без аргументов, потом добавляются необходимые данные для строки запроса и, наконец, вызывается метод ToString() для шифрования введенных данных:

EncryptedQueryString QueryString = new EncryptedQueryString();

QueryString.Add("MyData", MyData.Text);

QueryString.Add("MyTime", DateTime.Now.ToLongTimeString());

QueryString.Add("MyDate", DateTime.Now.ToLongDateString());

Response.Redirect("QueryStringRecipient.aspx?data=" + QueryString.ToString());

При расшифровке создается объект класса EncryptedQueryString, аргументом конструктора которого являются зашифрованные данные строки запроса: EncryptedQueryString QueryString = new EncryptedQueryString(Request.QueryString["data"]), и для получения расшифрованных данных вызывается код myDataText = QueryString["My-Data"].

Теперь рассмотрим, как реализуется безопасность в ASP.NET-приложениях. Безопасность ASP.NET реализуется двумя подходами: реконфигурируемая безопасность (configurable security) и программируемая безопасность (programmatic security). Реконфигурируемая безопасность связана с доступом к URL страницы Web-сайта, т. е. конфигурируется URL безопасность в файле web.config Web-приложения. При этом действия аутентификации, авторизации и олицетворения выполняются по странице. Более подробно реконфигурируемая безопасность описана в [5, 9]. Программируемая безопасность связана с проверкой права доступа в коде приложения. Возможны следующие опции для программной безопасности:

1. Явная проверка безопасности с использованием IPrincipal интерфейса (объект User - объект класса, реализующего интерфейс System.Security.Principal.IPrincipal и является свойством объекта страницы System.Web.UI.Page):

1.1. Аутентификация: if (User.Identity.IsAuthenticated) { ... };

1.2. Авторизация (проверка роля):

if (User.Identity.IsAuthenticated && User.IsInRole("Admin")){ ... }.

2. Использование PrincipalPermission класса для проверки безопасности:

2.1. Аутентификация:

PrincipalPermission pp = new PrincipalPermission(null, null, true);

pp.Demand();

//equivalent with the check: if (User.Identity.IsAuthenticated)

//Do business action

2.2. Авторизация (проверка роля):

PrincipalPermission pp = new PrincipalPermission(null, "Admin", true);

pp.Demand();

//Do business action

3. Олицетворение кода с правами доступа аутентифицированного пользователя:

WindowsIdentity windowsID = User.Identity as WindowsIdentity;

if (windowsID != null) {

WindowsImpersonationContext wiContext = windowsID.Impersonate();

//Do something here with permission of authenticated user wiContext.Undo();

}

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

Другие задачи обычно реализуются в отдельном модуле или в наборе модулей; при необходимости разработчик вызывает данные модули в нужных ему точках выполнения кода. Проблема возникает, когда необходимо применить данные модули во многих точках выполнения приложения, например при вызове метода шифрования и метода расшифровки строки запроса или при использовании программируемой безопасности многократно в разных точках выполнения приложения. При этом размер кода увеличивается за счет повторения и рассредоточения кода вызова (реализации) задачи (или функциональности). Возможна также ситуация модификации разработанного Web-приложения для добавления новой сквозной функциональности, такая как, например, рассмотренные нами задачи: кодирование гипертекста (информация отображена на страницах неправильно из-за того, что данные в базе данных содержат специальные символы - пробел, меньше и т. д.), криптография cookie-файлов или выдача сообщений в браузере при выполнении какой-либо бизнес-логики. При этом для реализации новой функциональности приходится изменять код приложения вручную, реализуя ее в модулях и добавляя код их вызова вручную в нужные точки выполнения приложения.

5. Реализация аспектов поддержки Web-программирования.

5.1. Протоколирование. Предположим, что в нашем приложении существует точка выполнения, в которой вызывается некоторый метод, названный DoSomething-(string arg, int num). Теперь создаем аспект протоколирования, примененный к этой точке и названный WebLoggingAspect.

Используем для протоколирования известную библиотеку log4net [17]. Для этого необходимо добавить в проект аспекта (например, WebAspect) ссылку (Reference) на сборку log4net.dll. Затем добавим в начало файла WebLoggingAspect.cs следующий код: using log^net;. Добавим в наш аспект статическое свойство для работы с протоколированием:

private static ILog logger; public static ILog Logger { get {

if (logger == null) {

log4net.Config.XmlConfigurator.Configure(

new FileInfo(AppBinPath + "\\WebAODLog.log4net")); logger = LogManager.GetLogger("WebAODLog");

return WebLoggingAspect.logger;

iНе можете найти то, что вам нужно? Попробуйте сервис подбора литературы.

}

}

В файле конфигурации WebAODLog.log4net необходимо создать logger с названием WebAODLog. Конфигурирование log4net описано в работе [17]. Файл конфигурации WebAODLog.log4net необходимо поместить в папку bin Web-проекта. Теперь добавим действия протоколирования в аспект, которые выполнят трассировку начала и окончания выполнения метода DoSomething():

[AspectAction("%before %call *.DoSomething(..)")] public static void BeforeLog()

{

Logger.Info("Start call method: " + TargetMemberInfo.Name);

}

[AspectAction("%after %call *.DoSomething(..)")] public static void AfterLog()

{

Logger.Info("The end of method: " + TargetMemberInfo.Name);

}

Эти действия вызываются перед и после вызова метода DoSomething() и выдают информацию о вызываемом (целевом) методе. Такие действия можно применить к нужным точкам выполнения. Причем условия внедрения необходимо записать так, чтобы они соответствовали нашим точкам выполнения (см. [2]).

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

public class BusinessLogic {

virtual public void DoSomething() { }

virtual public void DoSomethingWithAdminRole(string a0, int a1) { } virtual public void DoImpersonationTask() { }

}

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

Действие аутентификации:

[AspectAction("%instead %call BusinessLogic.*")] public static void AuthenticationAction() {

IPrincipal User = HttpContext.Current.User;

if (User.Identity.IsAuthenticated) {

MethodInfo method = (MethodInfo)TargetMemberInfo;

else { //Throw exception or do other action }

}

Условие внедрения "%instead %call BusinessLogic.*" означает, что вместо вызова любого метода класса BusinessLogic вызывается действие аспекта AuthenticationAction(). В этом действии проверяем, аутентифицирован ли пользователь с помощью свойства IPrincipal.Identity.IsAuthenticated. Если пользователь аутентифицирован, то разрешается выполнить действие целевого объекта, т. е. вызов целевого метода объекта класса BusinessLogic с помощью рефлексии (Reflection). Если нет, то либо выбрасывается исключение, либо выполняется другое действие.

Действие авторизации:

[AspectAction("%instead %call *.DoSomethingWithAdminRole(..) " +

"&& %args(..)")] public static void AuthorizationAction(string a0, int a1) { IPrincipal User = HttpContext.Current.User; if (User.Identity.IsAuthenticated && User.IsInRole("Administrator")) {

MethodInfo method = (MethodInfo)TargetMemberInfo; method.Invoke(TargetObject, new object[] { a0, a1 });

}

else { //Throw exception or do other action }

}

Здесь действие аспекта AuthorizationAction() вызывается вместо вызова методов DoSo-methingWithAdminRole() любого класса (%instead %call *.DoSomethingWithAdminRole()). В этом действии мы проверяем, аутентифицирован ли пользователь с помощью свойства IPrincipal.Identity.IsAuthenticated, и является ли он администратором (User.IsInRo-le("Administrator")). Если пользователь аутентифицирован и является администратором, то ему разрешается выполнить действие целевого объекта, т. е. вызов метода DoSomethingWithAdminRole() целевого объекта с помощью рефлексии (Reflection). Если нет, то либо выбрасывается исключение, либо выполняется другое действие. Олицетворение:

[AspectAction("%instead %call *Imperson*")] public static void ImpersonationAction() {

WindowsIdentity windowsID =

HttpContext.Current.User.Identity as WindowsIdentity; if (windowsID != null) {

WindowsImpersonationContext wiContext = windowsID.Impersonate();

MethodInfo method = (MethodInfo)TargetMemberInfo; method.Invoke(TargetObject, null); wiContext.Undo();

}

else { //Throw an exception or do another task }

Условие внедрения "%instead %ocall *Imperson*" означает, что вместо вызова любого метода, удовлетворяющего регулярному выражению *Imperson* (т. е. имя которого содержит Imperson) вызывается действие аспекта ImpersonationAction(). В этом действии мы проверяем, является ли режим аутентификации Windows Authentication. Если да, то олицетворим наш метод, иначе можем выбросить исключение или выполнить другую задачу.

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

5.3. Криптография строки запроса. Создадим аспект CryptoQueryStringAspect. В него добавим наши действия RedirectAction() (действие шифрования) и GetQuery-StringAction() (действие расшифровки).

Действие шифрования:

[AspectAction("%instead %call HttpResponse.Redirect(string) " +

"&& %args(arg[0])")] public static void RedirectAction(string Query) {

string[] SplittedQuery = Query.Split(new char[] { ’?’ }); string RedirectPage = SplittedQuery[0]; string ClearQueryString = SplittedQuery[1];

byte[] EncryptedData = SymEncryption.Encrypt(ClearQueryString); string NewQuery = RedirectPage + "?data=" + GetString(EncryptedData); HttpContext.Current.Response.Redirect(NewQuery);

}

Условие внедрения аспекта "%instead %call HttpResponse.Redirect(string) && %args(arg[-

0])" означает, что вместо вызова метода HttpResponse.Redirect() вызывается действие аспекта RedirectAction(string Query). То есть фактически Aspect.NET подменяет метод HttpResponse.Redirect() на действие аспекта RedirectAction() в точках выполнения, где вызывается HttpResponse.Redirect(), и при подмене аргумент действия аспекта передается аргументом целевого метода. В этом действии мы реализуем шифрование строки запроса ClearQueryString симметричным алгоритмом шифрования (Symmetric encryption: SymEncryption). Здесь, кроме симметричного алгоритма, можно использовать любые методы шифрования, например Windows data protection API (DPAPI) [5]. После шифрования строки запроса необходимо преобразовать ее в строку (string) для передачи в URL-запрос. Один из подходов - использование статического метода Convert.ToBase64String(), который создает Base64-закодированную строку. Но Base64-строка содержит символы, не допустимые в строке запроса. Поэтому преобразуем ее в шестнадцатеричную строку с помощью метода GetString() [5]. Наконец, перенаправляем новый URL-запрос с зашифрованной строкой запроса вызовом метода HttpResponse.Redirect().

Действие расшифровки:

[AspectAction("%instead %call HttpRequest.get_QueryString()")] public static NameValueCollection GetQueryStringAction() {

HttpRequest Request = (HttpRequest)TargetObject;

NameValueCollection EncryptedQS = Request.QueryString; byte[] EncryptedData = GetBytes(EncryptedQS["data"]); string ClearQueryString =

SymEncryption.DecryptToString(EncryptedData);

string[] SplittedQS = ClearQueryString.Split(new char[] { });

NameValueCollection DecryptedQS = new NameValueCollection(); foreach (string SingleData in SplittedQS) { int Index = SingleData.IndexOf(’=’);

DecryptedQS.Add(

HttpUtility.UrlDecode(SingleData.Substring(0, Index)), HttpUtility.UrlDecode(SingleData.Substring(Index + 1)));

}

return DecryptedQS;

}

Условие внедрения аспекта "%instead %call HttpRequest.get_QueryString()" означает, что вместо вызова метода HttpRequest.get_QueryString() (т. е. при обращении к свойству QueryString объекта класса System.Web.HttpRequest) вызывается действие аспекта GetQueryStringAction(). В приведенном коде извлекается зашифрованная строка запроса из URL-запроса, которая передается в метод GetBytes() [5], чтобы получить зашифрованные данные в виде массива байтов byte[] EncryptedData = GetBytes(EncryptedQS-["data"]);. После этого вызывается метод для расшифровки данных string ClearQuery-String = SymEncryption.DecryptToString(EncryptedData);. Расшифрованная строка типа string анализируется, и ее данные передаются в объект DecryptedQS, который возвращается в конце действия.

В нашем Web-приложении код для получения данных от строки запроса следующий:

NameValueCollection QueryString = Request.QueryString; lbMsg.Text = "mydata = " + QueryString["mydata"];

5.4. Криптография cookie-файлов. Допустим, в Web-приложении используются следующие фрагменты кода для работы с Куки:

Создание Куки:

HttpCookie cookie = new HttpCookie("MyCookie"); cookie["Faculty"] = "Mat-Mex"; cookie["University"] = "SPBU"; cookie.Expires = DateTime.Now.AddDays(1);

Response.Cookies.Add(cookie);

Получение информации из Куки:

HttpCookie cookie = Request.Cookies["MyCookie"]; if (cookie != null) {

string Faculty = cookie["Faculty"]; string University = cookie["University"];

}

Создадим аспект CryptoCookieAspect. В него добавим наши действия EncryptCookie-Action() (действие шифрования) и DecryptCookieAction() (действие расшифровки).

Действие шифрования:

[AspectAction("%before %call HttpCookieCollection.Add(HttpCookie) " +

"&& %args(arg[0])")] public static void EncryptCookieAction(HttpCookie cookie) {

string value = cookie.Value;

cookie.Value = GetString(SymEncryption.Encrypt(value));

В этом действии определяем условие внедрения аспекта "%before %call HttpCookieCollec-tion.Add(HttpCookie) && %args(arg[0])" аспекта для присоединения этого действия к точкам выполнения, где добавлены Куки в ответ сервера. Условие означает, что перед вызовом метода HttpCookieCollection.Add(HttpCookie) (т. е. перед Response.Cookies.Add-(cookie)) вызывается действие аспекта EncryptCookieAction() и аргумент действия аспекта передается аргументом целевого метода. В данном действии реализуем шифрование содержимого Куки.

Действие расшифровки:

[AspectAction("%instead %call HttpCookieCollection.get_Item(string) " + "&& %args(arg[0])")] public static HttpCookie DecryptCookieAction(string name) {

HttpCookie cookie = HttpContext.Current.Request.Cookies[name]; byte[] EncryptedData = GetBytes(cookie.Value); string value = SymEncryption.DecryptToString(EncryptedData); return new HttpCookie(name, value);

}

Условие внедрения аспекта "%instead %call HttpCookieCollection.get_Item(string) && %args(arg[0])" означает, что вместо вызова метода HttpCookieCollection.get_Item(string) (т. е. вместо вызова Request.Cookies["MyCookie"]) вызывается действие аспекта Decrypt-CookieAction(). Аргумент действия аспекта передается аргументом целевого метода. В этом действии реализуем расшифровку содержимого Куки.

5.5. Кодирование гипертекста (Html Encoding). Допустим, что в нашем приложении существует точка выполнения, в которой необходимо установить текст для элемента управления Label:

lbArticleBody.Text = strTextIsFromDB;

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

Создадим аспект, названный HtmlEncodingAspect. Добавим в него действие HtmlEn-codeAdvice(), которое будет добавлено в данной точке выполнения:

[AspectAction("%instead %call Label.set_Text(string) && %args(arg[0])")] public static void HtmlEncodeAdvice(string text) {

Label label = (Label)TargetObject;

string encodedText = HttpContext.Current.Server.HtmlEncode(text); encodedText = encodedText.Replace(" ", "&nbsp;"); label.Text = encodedText;

}

В этом действии после вызова метода HtmlEncode() добавлен код для преобразования последовательности пробелов в последовательность "&nbsp;". После этого получим закодированный текст для нашего элемента управления. Условие внедрения

аспекта "%instead %call Label.set_Text(string) && %args(arg[0])" означает, что вместо вызова метода установки текста для элемента управления Label (Label.set_Text()) вызывается действие аспекта HtmlEncodeAdvice(string text). Можно присоединить его к точкам выполнения, где текст установлен для других элементов управления (например, LinkButton, HyperLink, CheckBox, ListItem, RadioButton). При этом необходимо изменить условие внедрения так, чтобы оно соответствовало данным точкам выполнения (синтаксис условия внедрения описан в [2]), например, "%instead %call *.set_Text(string) && %args(arg[0])", т. е. при вызове метода установки текста объекта любого класса. В теле действия HtmlEncodeAdvice() необходимо проверить тип целевого объекта (TargetObject).

Теперь рассмотрим, как реализовать действие аспекта для декодирования. Добавим в аспект HtmlEncodingAspect следующее действие:

[AspectAction("%instead %call Label.get_Text()")] public static string HtmlDecodeAdvice() {

Label label = (Label)TargetObject; string encodedText = label.Text;

iНе можете найти то, что вам нужно? Попробуйте сервис подбора литературы.

encodedText = encodedText.Replace("&nbsp;", " "); return HttpContext.Current.Server.HtmlDecode(encodedText);

}

Условие внедрения аспекта "%instead %ocall Label.get_ Text()" означает, что вместо вызова метода Label.get_ Text() вызывается действие аспекта HtmlDecodeAdvice(). Кроме того, можно написать условие внедрения для вызова метода get_ Text() объекта класса LinkButton, HyperLink, CheckBox, ListItem, RadioButton и т. д.

5.6. Расширение пользовательского Web-интерфейса. При сопровождении Web-приложений разрабочики сталкиваются с проблемой расширения пользовательского интерфейса разработанного Web-приложения, например, следующего содержания: добавить карту Google в Web-страницах; добавить ссылку на некоторый сайт; добавить рекламные элементы; добавить элементы типа сообщения после некоторого действия. Предлагается выделить эту новую функциональность в аспекте, т. е. реализовать ее как действия аспекта, и определить условия внедрения для нужных точек присоединения. В действиях аспекта реализуем функциональность путем динамического добавления элементов управления в определенном контейнере, задаваемом в файле Web.config нашего Web-приложения.

Приведем простой пример аспекта, который добавляет элемент типа сообщения после денежных операций банка VP:

[AspectAction("%after %call VPBank.operate*")] public static void AddWarning() {

Page ActivePage = HttpContext.Current.Handler as Page;

WebControl Container = (WebControl)

ActivePage.FindControl(ContainerID); if (Container != null) {

BankWarning warning = (BankWarning)

ActivePage.LoadControl("BankWarning.ascx"); Container.Controls.Add(warning);

}

}

Здесь элемент управления типа сообщения BankWarning.ascx загружается динамически и добавляется в нужный нам контейнер Container, идентификатор которого задается в разделе appSettings в файле Web.config. Получим этот идентификатор (ID) через статическое свойство аспекта ContainerID (ContainerID = ConfigurationManager.App-Settings["ContainerID"];).

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

%instead %call VPBank.Accounts.BankAccount.withdraw(float) && args(..) && %withincode(VPBank.operate*)

Данное условие внедрения аспектов означает, что внутри кода методов, имена которых удовлетворяют VPBank.operate*, вместо вызова метода withdraw(float) класса BankAccount пакета VPBank.Accounts вызывается действие аспекта. Более подробно форма условий внедрения аспекта описана в [2].

При поддержке или расширении приложения необходимо принимать во внимание влияние разработанных аспектов, т. е. учитывать условия внедрения аспектов, которые могут быть изменены. В свою очередь, Aspect.NET предоставляет возможность «вручную» отметить какую-либо потенциальную точку присоединения либо отменить ее отметку, исключив тем самым ее из дальнейшего процесса внедрения. Это позволяет избежать «слепого», неконтролируемого внедрения аспектов - одной из самых серьезных опасностей, которые таит в себе АОП - мощное «оружие», управляющее групповыми модификациями кода. Описываемая возможность Aspect.NET - внедрение, управляемое пользователем, - позволяет сделать процесс внедрения аспектов более безопасным и разумным. Однако оно не обязательно: если какого-либо пользователя это затрудняет, он может внедрять аспекты автоматически, нажатием кнопки Weave aspects. Отметим еще раз, что подобная возможность отсутствует во всех других известных нам, даже весьма популярных, инструментах АОП.

7. Эффективность и производительность применения АОП. Рассмотрим эффективность и производительность применения АОП для реализации задач Web-программирования в системе Aspect.NET. В. О. Сафонов [3] доказал, что применение АОП с использованием Aspect.NET улучшает продуктивность разработчиков ПО, на основе оценки трудоемкости с помощью модели COCOMO [18]. Для оценки проанализируем случай использования действий внедрения %before и %after.

Пусть s - объем исходного кода оригинального приложения. Предположим, что мы должны реализовать новую функциональность добавлением некоторых фрагментов кода перед и после всех вызовов метода P в коде всего приложения. Пусть a - объем кода, добавленного после вызовов P, и b - объем кода, добавленного перед вызовами P, c -число вызовов P во всем коде приложения. Если требуемая функциональность реализуется вручную без использования Aspect.NET, тогда объем полученного кода будет вычислен по формуле

s* = s + (а + b) * с.

Так как в Aspect.NET реализуется внедрение аспекта на уровне бинарного кода (MSIL) после компиляции целевого приложения и аспекта, в случае применения

Aspect.NET для реализации новой функциональности объем полученного кода приложения равен сумме объема его оригинального кода и объема кода аспекта:

в* = в + а + Ь.

Тогда объем результирующего кода приложения в случае без применения Aspect.NET будет больше объема улучшенного кода приложения с применением Aspect.NET на следующую сумму:

= [в + (а + Ь) * с] — (в + а + Ь) = (а + Ь)(с — 1).

Согласно базовой модели СОСОМО, суммарная трудоемкость Е (в человеко-месяцах) в случае без применения Aspect.NET будет определяться по формуле

Ер

аЬ

в + (а + Ь)с

1000

Ьь

в случае применения Aspect.NET - так:

ЕЛвре^М ЕТ =

аЬ

в + а + Ь 1000

Ьь

Очевидно, что ЕрШп, > ЕлВреЫМЕТ.

Время разработки будет вычисляться таким образом:

Тр1а1п = сЬ \Ер1агп] и ТЛзреЫМЕТ = сЬ \ЕЛвре^.ЫЕТ] Поскольку Ер1агп > ЕЛвреЫ^М ЕТ , то Тр1а1п > ТЛвре^.МЕТ.

Число разработчиков будем рассчитывать по формулам ^(1еурШп =

(1ь

N А3рес1_ N ЕТ грА

__ EAspect.NET

эрееЬ N ЕТ

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

1.2

Ер

3.6

5+(а+Ь)с

1000

-|0.32

и ЕЛ

вресЬ.Ы ЕТ

3.6 (

1000

Тр1а1п

2.5 \Ер1агп] . и Тлвресг МЕТ = 2.5 [ЕлэресЬ.МЕТ]

0.32

Для более конкретного примера будем считать, что наш проект небольшой: в = 1000 строк кода, а = 1, Ь = 1 (объем кода вставки является наименьшим возможным) и с = 100. В этом случае приблизительно Ер1агп = 4.48 человеко-месяцев и Елвресг.МЕТ = 3.6 человеко-месяцев (т. е. применение Aspect.NET помогает управлению проектом сократить примерно один человеко-месяц - четверть трудоемкости проекта), Тр1агп = 4.04 месяцев и ТлРвесг.МЕТ = 3.77 месяцев (т. е. применение Aspect.NET уменьшает время разработки примерно на 0.27 месяцев - 8 дней), число разработчиков:

^йеьр1агп 1.11 чел. и NdevЛspect.N ЕТ °.95 чел.

Теперь рассмотрим производительность исполнения приложения с применением Aspect.NET для реализации задач ^^Ь-программирования. Измерим время выполнения задач ^^Ь-программирования, который вызываются 10 000 раз, для обоих случаев без и c применением Aspect.NET. Например, для задачи аутентификации без применения Aspect.NET код для измерения времени выполнения следующий:

DateTime StartTime;

DateTime EndTime;

StartTime = DateTime.Now;

for (int i = 0; i < 10000; i++) {

if (User.Identity.IsAuthenticated) {

DoSomething();

}

}

EndTime = DateTime.Now;

TimeSpan Tsp = EndTime.Subtract(StartTime); Response.Write("Execution time: " + Tsp.Ticks / 10000 +

" milliseconds");

В случае применения Aspect.NET код для измерения времени выполнения будет таким:

DateTime StartTime;

DateTime EndTime;

StartTime = DateTime.Now;

for (int i = 0; i < 10000; i++) {

DoSomething();

}

EndTime = DateTime.Now;

TimeSpan Tsp = EndTime.Subtract(StartTime); Response.Write("Execution time: " + Tsp.Ticks / 10000 +

" milliseconds");

Были реализованы аналогичные измерения для всех задач, кроме расширения пользовательского интерфейса, на портативном компьютере Intel Core 2 CPU 1.83GHz, 2Gb Ram. Для каждой задачи измерение было произведено 100 раз. Были получены среднее время (в миллисекундах) выполнения задач Web-программирования и среднеквадратические погрешности (таблица).

Среднее время выполнения задач Web-программирования

Task Approach Average Time Standard Deviation

Logging OOP 8462.35523 133.259911

AOP 8488.0567 142.441413

Authentication OOP 31.591807 2.046801

AOP 32.071834 2.129242

Authorization OOP 37.392139 3.006206

AOP 37.922111 2.921416

Impersonation OOP 312.807891 8.891007

AOP 309.227687 8.819479

Cryptography Query String OOP 2693.55406 19.174604

AOP 2689.65384 13.069407

Cryptography Cookie OOP 2571.1471 25.477749

AOP 2547.1457 23.789024

Html Encoding OOP 28.211614 2.426656

AOP 28.731642 3.149908

iНе можете найти то, что вам нужно? Попробуйте сервис подбора литературы.

По полученным результатам измерения легко видеть, что время выполнения задач Web-программирования без и с применением Aspect.NET примерно одинаково. Поэтому можно заключить, что производительность исполнения Web-приложения после внедрения аспектов с помощью Aspect.NET не хуже производительности такого

Web-приложения без применения АОП, никакой избыточный инструментальный код не внедрен и не выполнен. То есть при использовании АОП для разработки Web-приложений в системе Aspect.NET производительность не изменилась, а объем кода и трудоемкость уменьшились, код приложения упростился. Например, для задачи аутентификации без применения Aspect.NET код следующий:

if (User.Identity.IsAuthenticated)

{

DoSomething();

}

В случае применения Aspect.NET код будет таким:

DoSomething();

Можно удалить if в данном контексте при условии, что метод DoSomething() аннотируется атрибутом [PrincipalPermission(SecurityAction.Demand)], например:

[PrincipalPermission(SecurityAction.Demand)] public void DoSomething() {

}

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

Изменение кода в аспекте, действительно, влияет на поведение результирующего Web-приложения, однако оно касается только той сквозной функциональности, для которой разрабатывался аспект. Добавление действий аспекта выполняется в точках присоединения, которые находятся вокруг целевых методов (перед ними - %before, после них - %after, вместо них - %instead), поэтому оно не влияет на архитектуру программы, т. е. не изменяет ее. Добавление новой функциональности методом, отличным от АОП, тоже выполняется, отталкиваясь от целевых методов. Предположим, что реализация некоторой новой функциональности требует изменения архитектуры приложения. При этом добавление данной функциональности без использования АОП тоже изменит архитектуру программы.

Теперь проанализируем недостатки реализации рассмотренных нами задач Web-программирования без применения АОП:

1) код реализации каждой задачи (функциональности) может повторяться во многих точках выполнения, в разных модулях Web-приложения, это ведет к увеличению объема кода времени и стоимости разработки;

2) необходимо редактировать исходный код приложения для изменения или добавления каждой функциональности;

3) усложняются сопровождение и развитие Web-приложения. Появление дополнительных требований в будущем может привести к переработке текущего варианта реализации, которая скорее всего затронет большинство существующих модулей.

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

по сравнению с реализацией задач без применения АОП имеет следующие преимущества:

1) использование синтаксиса определения условия внедрения аспекта [2] позволяет описать множество точек присоединения, в которые необходимо добавить функциональность наших задач;

2) действия аспекта будет автоматически добавляться на уровне MSIL-кода подсистемой внедрения (weaver) в точки присоединения (т. е. в нужные нам точки выполнения), определенные условиями внедрения аспекта. Таким образом, не требуются «ручные» вставки кода реализации функциональности в этих точках выполнения, благодаря чему уменьшаются объем кода, вероятность программных ошибок, время и стоимость разработки;

3) никакие изменения исходного кода в целевом Web-приложении не требуются. Необходимо лишь реализовать наши задачи в виде аспектов, определить условия их внедрения и запустить подсистему внедрения аспектов системы Aspect.NET;

4) упрощаются сопровождение, изменение и расширение Web-приложения. Новые требования (новая функциональность) реализуются в аспектах, затем внедряются в целевое Web-приложение. Изменение функциональности осуществляется также в коде реализации аспектов;

5) Web-приложения полностью работоспособны без применения аспектов. При этом функциональность, реализованная в аспектах, отсутствует в целевых Web-приложениях;

6) обеспечивается повторная используемость кода: разработанные аспекты могут внедряться в разные Web-приложения, требующие функциональности аспектов.

8. Отладка аспектов и оценка их влияния на Web-приложения. Подсистема внедрения аспектов Aspect.NET сопровождает каждое свое изменение в целевой сборке соответствующим обновлением отладочной информации в pdb-файле. Это дает возможность при отладке анализировать исходный код бизнес-логики, переходя в нужных местах к исходным кодам внедренного аспекта. Если же пользователю требуется полный исходный код результирующего приложения, то можно использовать утилиту .NET Reflector, которая путем полной декомпиляции сборки дает возможность получить исходный код, а также поддерживать возможность его. Комбинация таких двух подходов позволяет отладить аспекты. В дальнейшем в Aspect.NET планируется реализация специализированного отладчика в терминах аспектов.

Изменение кода аспекта влияет на поведение результирующей бизнес-логики. Однако оно касается только той сквозной функциональности, для которой разрабатывался аспект. Фактически, при применении АОП и Aspect.NET в аспекте содержится реализация сквозной функциональности всей программы. Таким образом, ее становится удобно сопровождать. В свою очередь, Aspect.NET предоставляет удобные возможности по оценке влияния аспектов на бизнес-логику:

1) имеется удобная система просмотра точек применения аспектов в исходном тексте бизнес-логики;

2) так как вся работа ведется в среде Microsoft Visual Studio, для тестирования результирующей сборки и аспектов можно использовать все ее возможности;

3) возможно исследование исходного кода результирующей сборки с помощью утилиты .NET Reflector.

Более подробное рассмотрение методов тестирования аспектов выходит за рамки данной статьи. В работе [19] дан подробный обзор технологий модульного тестирования аспектов для платформы Java, основанных на использовании системы AspectJ.

Заключение. В статье предложены методы применения аспектно-ориентированного программирования для задач разработки Web-приложений на платформе Microsoft.NET. Разработаны аспекты в системе Aspect.NET, которые упрощают процесс создания и сопровождения Web-приложений: аспект протоколирования, аспект безопасности, аспект криптографии строки запроса, аспект криптографии cookie-файлов, аспект кодирования гипертекста, аспект расширения пользовательского Web-интерфейса. Проанализированы эффективность и производительность применения этих аспектов в Web-приложениях. Код разработанной библиотеки аспектов опубликован на сайте проекта Aspect.NET [6].

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

Литература

1. Web-сайт по аспектно-ориентированной разработке программ. URL: http://aosd.net.

2. Сафонов В. О. Практическое руководство по системе аспектно-ориентированного программирования Aspect.NET // Компьютерные инструменты в образовании. 2008. № 2. С. 12—20.

3. Safonov V. O. Using aspect-oriented programming for trustworthy software development. Hoboken, New Jersey: Wiley Interscience, John Wiley & Sons, 2008. 338 p.

4. Rakesh Pai. Web Applications — The Wave of the Future. URL: http://piecesofrakesh.blogspot. com/2005/01/web-applications-wave-of-future.html.

5. Matthew MacDonald, Mario Szpuszta. Pro ASP.NET 3.5 in C# 2008. New York: Apress, 2008. 1498 p.

6. Web-сайт проекта Aspect.NET. URL: http://www.aspectdotnet.org.

7. Introduction to Web Application Projects. URL: http://msdn.microsoft.com/en-us/library/aa730880 (VS.80).aspx.

8. Microsoft Visual Studio 2005 Team Suite Service Pack 1. URL: http://www.microsoft.com/down-loads/details.aspx?familyid=bb4a75ab-e2d4-4c96-b39d-37baf6b5b1dc&displaylang=en.

9. Building Secure ASP.NET Applications: Authentication, Authorization, and Secure Communication. URL: http://msdn.microsoft.com/en-us/library/aa302388.aspx.

10. LOOM.NET Web pages. URL: http://www.rapier-loom.net.

11. Mono. URL: http://www.mono-project.com.

12. AspectDNG Web pages. URL: http://aspectdng.tigris.org.

13. Aspect# Web pages. URL: http://sourceforge.net/projects/aspectsharp.

14. PostSharp Web pages. URL: http://www.postsharp.org.

15. Weave.NET. URL: http://www.dsg.cs.tcd.ie/dynamic/?category_id=-26.

16. Wicca and Phx.Morph Web site. URL: http://www.cs.columbia.edu/~eaddy/wicca.

17. Log4net project. URL: http://logging.apache.org/log4net.

18. Boehm B. Software Engineering Economics. New York: Prentice Hall, Englewood Cliffs, 1981. 767 p.

19. Nicholas Lesiecki. Unit test your aspects. URL: https://www.ibm.com/developerworks/java/libra-ry/j-aopwork11.

Статья рекомендована к печати проф. В. Ю. Добрыниным.

Статья принята к печати 14 октября 2010 г.

i Надоели баннеры? Вы всегда можете отключить рекламу.