авторефераты диссертаций БЕСПЛАТНАЯ БИБЛИОТЕКА РОССИИ

КОНФЕРЕНЦИИ, КНИГИ, ПОСОБИЯ, НАУЧНЫЕ ИЗДАНИЯ

<< ГЛАВНАЯ
АГРОИНЖЕНЕРИЯ
АСТРОНОМИЯ
БЕЗОПАСНОСТЬ
БИОЛОГИЯ
ЗЕМЛЯ
ИНФОРМАТИКА
ИСКУССТВОВЕДЕНИЕ
ИСТОРИЯ
КУЛЬТУРОЛОГИЯ
МАШИНОСТРОЕНИЕ
МЕДИЦИНА
МЕТАЛЛУРГИЯ
МЕХАНИКА
ПЕДАГОГИКА
ПОЛИТИКА
ПРИБОРОСТРОЕНИЕ
ПРОДОВОЛЬСТВИЕ
ПСИХОЛОГИЯ
РАДИОТЕХНИКА
СЕЛЬСКОЕ ХОЗЯЙСТВО
СОЦИОЛОГИЯ
СТРОИТЕЛЬСТВО
ТЕХНИЧЕСКИЕ НАУКИ
ТРАНСПОРТ
ФАРМАЦЕВТИКА
ФИЗИКА
ФИЗИОЛОГИЯ
ФИЛОЛОГИЯ
ФИЛОСОФИЯ
ХИМИЯ
ЭКОНОМИКА
ЭЛЕКТРОТЕХНИКА
ЭНЕРГЕТИКА
ЮРИСПРУДЕНЦИЯ
ЯЗЫКОЗНАНИЕ
РАЗНОЕ
КОНТАКТЫ


Pages:   || 2 | 3 |
-- [ Страница 1 ] --

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

В. О. Сафонов

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

ПРОГРАММИРОВАНИЕ

Учебное пособие

Рекомендовано УМО в области инновационных междисциплинарных

общеобразовательных программ в качестве учебного пособия

по специальности 01.05.03 — математическое обеспечение

и администрирование информационных систем

С.-ПЕТЕРБУРГ

2011

УДК 004.4’2 ББК 32.811.7 С22 Печатается по постановлению Редакционно-издательского совета математико-механического факультета С.-Петербургского государственного университета Сафонов В. О.

С22 Аспектно-ориентированное программирование: учеб. посо бие. — СПб.: Изд-во С.-Петерб. ун-та, 2011. — 104 с.

ISBN 978-5-288-05188- Учебное пособие знакомит читателей с основами нового перспективного подхода к разработке программ — аспектно-ориентированным программирова нием (АОП), предназначенного для модуляризации и автоматизированного до бавления (weaving) в целевые приложения сквозной функциональности, напри мер, добавления в код целевой программы проверок безопасности, трассировки, действий по защите информации. АОП в настоящее время играет все более важ ную роль при разработке и модернизации современного программного обеспе чения — прежде всего, для организации надежных и безопасных вычислений (trustworthy computing). В учебном пособии дан обзор концепций, методов и ин струментов АОП и подробно описан разработанный под руководством автора современный инструмент АОП — система Aspect.NET, получившая широкое признание и используемая в 26 странах мира. Даны примеры аспектов и целевых приложений и практические рекомендации по использованию системы Aspect.NET. Автор учебного пособия и системы Aspect.NET — широко извест ный в России и в мире специалист в области информатики и инженерии про грамм.

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

ББК 32.811. © В. О. Сафонов, © Санкт-Петербургский государственный университет, ISBN 978-2-288-05188- ВВЕДЕНИЕ Данное учебное пособие посвящено аспектно-ориентированному программированию (АОП) [1] — новому перспективному направлению развития программирования, которое сложилось в середине 1990-х гг., но истоки которого были заложены гораздо раньше, еще в 1970-х — 1980-х гг.

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

Современной и актуальной технологии и платформе ООП, Java технологии, посвящена предыдущая книга автора [2].

Данное учебное пособие, по-видимому, является первой книгой по АОП на русском языке. В книге изложены в доступной для изуче ния форме принципы АОП, архитектура инструментальных средств АОП, в том числе — разработанный под руководством автора инстру ментарий АОП Aspect.NET [3], используемый в 26 странах мира. Рас смотрено применение АОП для решения различных задач — органи зации надежных и безопасных вычислений (trustworthy computing), контрактного проектирования (design by contract). Намечены перспек тивы развития и дальнейшего, все более широкого использования АОП и системы Aspect.NET.

К каждой главе книги даны контрольные вопросы для самопро верки (или проведения опроса студентов) и упражнения для самостоя тельной работы. Это позволяет использовать книгу как основу для фа культативного односеместрового спецкурса, спецсеминара или прак тических занятий (hand-on labs) для студентов ИТ-специальностей.

Рекомендуется использование книги для студентов старших курсов — с третьего по пятый (шестой), владеющих одним или несколькими языками программирования и основами технологии.NET и языка C#.

Книга основана на многолетнем опыте автора в области ИТ — выполнения научно-исследовательских работ, промышленных проек тов, международного сотрудничества в области разработки программ ного обеспечения, преподавания на математико-механическом факуль тета Санкт-Петербургского государственного университета. Основы АОП изложены в лекции 7 учебного курса автора «Архитектуры и мо дели программ и знаний» [4], опубликованном на академическом сайте Microsoft в 2009 г.

Автор является основателем и научным руководителем уникаль ной, первой в России и одной из ведущих в мире, научной школы по аспектно-ориентированному программированию, созданной на мате матико-механическом факультете СПбГУ. Автор выражает сердечную благодарность своим ученикам, участникам нашей научной школы по АОП: кандидатам физ.-мат. наук Дмитрию Григорьеву, Михаилу Гра чеву, Руслану Муханову, аспирантам Анне Когай, Доану Нгуен Вану, Денису Подорожкину, Денису Фролову и многим другим — за ориги нальные идеи в области АОП, реализацию системы Aspect.NET (авто ра — Дмитрий Григорьев и Михаил Грачев) и ее аналога для академи ческой версии.NET — системы AspectRotor (автор — Руслан Муха нов), реализацию библиотек аспектов для использования системы Aspect.NET в различных предметных областях (авторы — Анна Когай, Денис Подорожкин, Доан Нгуен Ван, Денис Фролов). Я благодарен также моим студентам, интересующимся АОП, в особенности — сту дентам-дипломникам Игорю Евдакову и Айбеку Саримбекову, реали зовавшим в 2010 г. в качестве своих дипломных работ поддержку вто рого языка — Visual Basic — в системе Aspect.NET.

По аспектно-ориентированному программированию и системе Aspect.NET опубликована широко известная в мире монография авто ра [1] на английском языке в издательстве John Wiley & Sons (2008 г.) и целый ряд статей и учебных материалов на русском и английском языках [5–17], которые могут быть использованы для дальнейшего изучения АОП и методов его практического использования в совре менном программировании.

Глава ПРЕДПОСЫЛКИ И ИСТОРИЯ АОП 1.1. АОП и сквозная функциональность Аспектно-ориентированное программирование (АОП) [1] — но вый перспективный подход к разработке программ. Суть данного под хода — поддержка разработки и модификации сквозной функциональ ности (cross-cutting concerns) в больших программных системах.

При проектировании, реализации и модификации любой про граммы ее архитектура полностью или частично описывается в виде иерархии модулей — классов, процедур, функций, реализующих раз личные функциональные возможности (функциональности) програм мы. Простейшая из таких возможностей — например, вычисление ка кой-либо математической функции по известной формуле, — может быть реализована всего одним модулем в классическом смысле этого слова — функцией, процедурой, статическим методом, макросом, — имеющим, по терминологии Г. Майерса [18], функциональную проч ность. Более сложная по семантике функциональность реализуется в виде иерархии классов, библиотеки функций и др. Такова, например, любая компонента большой программной системы, реализующая часть ее бизнес-логики, т. е. решающая конкретную задачу из прикладной области, — например, расчет зарплаты, расчет курсов акций, планиро вание распределения заданий между сотрудниками.

Такого рода функциональность в программе, реализация которой выразима в виде одного модуля или взаимосвязанной совокупности модулей, будем называть модульной функциональностью (modular concern).

Как показывает анализ архитектуры программных систем, суще ствует также сквозная функциональность (cross-cutting concerns). Дан ное понятие объединяет такие виды функциональных возможностей, идей, принципов, методов, реализация которых принципиально не осуществима в виде лишь одной иерархии взаимосвязанных модулей, а, в дополнение к ним, требует вставки в физически рассредоточенные точки программы фрагментов нового кода (либо исполнения новых фрагментов кода в рассредоточенных точках целевой программы, без их явной вставки). Как правило, фрагменты кода, реализующие новую сквозную функциональность, являются исполняемыми конструкциями (операторами), чаще всего — вызовами, однако они могут быть и опи саниями (определениями) данных, также являющихся частью реализа ции рассматриваемой сквозной функциональности.

1.2. Типичные классы задач, решаемые АОП Типичные классы задач, решение которых требует реализации сквозной функциональности, относятся к надежному и безопасному программированию (trustworthy computing) [1, 12]:

безопасность (security) — аутентификация пользователей и программ;

авторизация (проверка полномочий кода или пользователя для выполнения тех или иных действий);

криптографические операции над данными с целью обеспечения их конфиденциальности и т. д.;

надежность (reliability) — проверка выполнения предусловий и постусловий в модулях и инвариантов в классах;

обработка ошибок и др.;

безопасность многопоточного выполнения кода (multi threaded safety) — синхронизация по ресурсам или по событиям, выде ление критических участков кода, взаимное исключение доступа к ним и др.;

протоколирование и профилирование работы программы (logging and profiling) — трассировка начала и окончания выполнения каждой функции (каждого метода), вывод их аргументов и результа тов, сбор и вывод статистической информации об исполнении различ ных фрагментов программы и т. д.

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

Выполнение данной нетривиальной модификации существующей программной системы требует глобального анализа всего исходного кода программы, размер которого может составлять несколько десят ков тысяч или даже несколько миллионов строк. Если подобные дей ствия выполняются вручную, с использованием возможностей исполь зуемой при разработке универсальной интегрированной среды, напри мер, Visual Studio.NET или Eclipse, но без применения каких-либо спе циализированных технологий и инструментов, — то весьма велик риск внесения в программу ошибок. Например, разработчик может вставить в код лишь вызов операции закрытия семафора, но по каким-либо при чинам забыть вставить парную ей «синхронизирующую скобку» — вызов операции открытия семафора после модификации ресурса, что может привести к тупику (deadlock) при исполнении программы, кото рый впоследствии весьма сложно обнаружить и устранить.

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

АОП расширяет традиционную концепцию модуля по Майерсу [18] понятием аспекта (aspect). Аспект — это реализация сквозной функциональности, выполненная в виде специального модуля, содер жащего фрагменты кода (действия аспекта), активируемые в заданных точках целевой программы как часть новой функциональности. Опре деление аспекта содержит также спецификацию разреза (pointcut) кода целевой программы — совокупности правил поиска в ней точек при соединения (join points) аспекта к целевой программе, для последую щего применения (внедрения, weaving) в найденных точках действий аспекта (слово weave буквально означает ткать, плести). Внедрение аспекта — способ его использования как новой разновидности модуля, в отличие от традиционных модулей «по Майерсу», используемых путем их явного вызова.

Основатель АОП — Г. Кичалес (G. Kiczales), Университет Британ ской Колумбии, Канада [19], а наиболее популярный инструмент АОП для платформы Java — разработанная под его руководством система AspectJ [20], первая версия которой была создана в 1995 г. в фирме Xerox Palo Alto Research Corporation, США. Подробный обзор подхо дов к АОП и инструментов АОП приведен в монографии [1].

Для российских специалистов особенно важен тот факт, — как мне довелось убедиться, пока недостаточно известный современным специалистам по АОП в США и Канаде, — что подход к разработке программ, близкий к АОП, был предложен еще в конце 1970-х годов проф. А. Л. Фуксманом (Ростовский университет) [21] под названием технология рассредоточенных действий, сокращенно — РД-техно логия (другое название, использованное автором подхода, — техноло гия вертикального слоения). Согласно данной технологии, вертикаль ный слой (срез) — совокупность рассредоточенных действий, фраг ментов кода, реализующих некоторую расширяющую функцию, а про цесс разработки и модификации программы представляет собой по следовательность операций добавления или изменения расширяющих функций.

Даже при беглом изложении основных идей РД-технологии оче видно ее сходство с АОП. Более того, даже в самом названии моно графии [21] присутствует слово аспект. К сожалению, РД-технология не получила своего коммерческого воплощения, но осталась в истории отечественного и мирового программирования пионерской идеей, пре емственная связь АОП с которой несомненна.

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

Ежегодно проводится конференция Aspect-Oriented Software Development [22]. Обучающие курсы (tutorials) и исследовательские доклады по АОП неизменно входят в программу широко известных в мире конференций в области ИТ, например, OOPSLA. Имеются сотни инструментов АОП для платформ Java и.NET, расширения средствами АОП языков программирования C, C++, JavaScript, PHP и многих дру гих [1].

В России АОП пока недостаточно распространено, несмотря на то, что его концепции известны уже более 15 лет. Созданы русскоя зычные страницы Web-энциклопедии Wikipedia и краткий wiki учебник по АОП на русском языке [23]. Литература по АОП на рус ском языке, как правило, ограничивается переводами и обзорами зару бежных работ [24]. Но уже (кроме работ нашей научной школы по АОП) появляются исследования молодых авторов, посвященные при менению известных инструментов АОП (например, JBoss [25]) в раз личных областях — например, для разработки графических пользова тельских интерфейсов [26]. Отечественная монография [27], посвя щенная методам расширения программ, определяет концепцию рас средоточенного набора, весьма близкую идеям технологии вертикаль ного слоения и АОП.

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

Вопросы к главе 1. Что такое аспектно-ориентированное программирование?

2. Что такое модульная и сквозная функциональность?

3. Приведите примеры типичных задач организации надежных и безо пасных вычислений (trustworthy computing).

4. Почему использование традиционных интегрированных сред для вставки рассредоточенных действий в программу может оказаться ненадежным и привести к ошибкам? Приведите конкретный пример.

5. Что такое аспект?

6. Что такое поперечный разрез (pointcut)?

7. Что такое точка присоединения (join point)?

8. Что такое применение (внедрение) аспекта?

9. Кто был основателем АОП и какая система АОП была разработана под его руководством?

10. В чем основная идея технологии рассредоточенных действий (РД технологии) — предшественника АОП — и кто был ее автором?

11. Что такое вертикальный слой (срез) и какова родственная связь дан ной концепции с концепцией аспекта в АОП?

Упражнения к главе 1. Проанализируйте и сформулируйте отличия объектно-ориентиро ванного программирования от аспектно-ориентированного програм мирования.

2. Скачайте и инсталлируйте инструмент АОП AspectJ, изучите его и пропустите прилагаемые к нему примеры целевых приложений и ас пектов.

3. Скачайте и инсталлируйте инструмент АОП JBoss, изучите его и про пустите прилагаемые к нему примеры целевых приложений и аспек тов.

4. Проанализируйте, является ли нарушением принципов модульного программирования по Майерсу вставка в класс дополнительного оп ределения поля, которое видимо только извне использующему его ас пекту.

Глава ОСНОВНЫЕ КОНЦЕПЦИИ АОП 2.1. Подходы к концепциям АОП и к его реализации Согласно определению АОП в Wikipedia [23], «программные па радигмы аспектно-ориентированного программирования (АОП) и ас пектно-ориентированной разработки программ (АОРП) предназначе ны для разделения функциональностей (separation of concerns), прежде всего — сквозных функциональностей (cross-cutting concerns), и явля ются расширением концепций модуляризации. АОП обеспечивает это преимущественно путем реализации расширений используемого языка программирования;

АОРП использует сочетание языка, окружения и метода».

Авторы статьи по АОП в Wikipedia противопоставляют концеп ции АОП и АОРП. В частности, если буквально следовать классифика ции, предложенной в [23], то и AspectJ, и Aspect.NET относятся к ин струментам АОРП, а не АОП. Однако в данной работе будем исполь зовать единый, более распространенный термин АОП, чтобы не ус ложнять терминологию и обеспечить более общую точку знения на данный круг проблем. На наш взгляд, разделение на АОП и АОРП не вполне целесообразно — на данном этапе развития АОП объединение идей и усилий различных школ более важно, чем их противопоставле ние.

Таким образом, аспектно-ориентированное программирование (aspect-oriented programming) — это технология разработки сквозной функциональности (cross-cutting concern) в виде специализированных модулей — аспектов (aspects), с целью ее последующего внедрения (weaving) путем активизации фрагментов кода аспекта — действий (advices) в выделенных инструментом АОП в целевой программе точ ках присоединения (join points). Спецификация точек присоединения, задаваемая в определении аспекта либо в виде отдельного модуля, на который могут ссылаться различные аспекты, получила название раз рез (pointcut). Чтобы пояснить суть решаемых проблем, рассмотрим типичную структуру современной программной системы (рис. 2.1).

Рис. 2.1. Типичная структура программной системы Как видно из схемы, программа состоит из совокупности реализа ций модульных функциональностей (modular concerns) и сквозных функциональностей (crosscutting concerns), причем последние, — на пример, проверки безопасности, — реализованы в виде совокупностей рассредоточенных фрагментов (вставок) кода в различные модули программы. Реализация сквозных фунциональностей показана различ ными оттенками цвета. Таким образом, программная система пред ставляет собой некий «слоеный пирог» из фрагментов реализации сквозных функциональностей.

Основная идея АОП проиллюстрирована на рис. 2.2:

Рис. 2.2. Разделение сквозных функциональностей в АОП АОП предлагает методы раздельного описания специальных мо дулей — аспектов, каждый из которых реализует некоторую сквозную функциональность (аспекты показаны справа), и инструменты для по следующего применения аспектов в одном или нескольких целевых приложений.

По сути дела, аспект можно представлять себе как совокупность правил вида Условие - Действие, где Условие специфицирует разрез целевой программы, а Действие задает фрагмент кода, активизируе мый в целевой программе при выполнении данного условия.

Процесс компоновки модулей в АОП изображен на рис. 2.3.

Рис. 2.3. Процесс компоновки модулей в АОП Помимо основной задачи реализации и внедрения новой сквозной функциональности, АОП решает две других не менее важных задачи:

аспектизация (aspectizing [5], aspect-oriented refactoring [28], aspect mining [29]) — выделение аспектов из не аспектно-ориен тированных программ, с целью их последующего многократного ис пользования;

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

Спецификация (определение) аспекта в АОП может быть выпол нена на специальном метаязыке АОП, как это делается, например, в нашей в системе Aspect.NET, — либо в терминах расширений базового языка программирования конструкциями АОП, как в системе AspectJ, которая по существу является реализацией аспектно-ориентирован ного расширения языка Java.

При использовании метаязыка АОП возникает проблема его ото бражения в базовый язык реализации, которая в Aspect.NET решается путем конвертирования конструкций метаязыка Aspect.NET.ML в оп ределения введенных нами специализированных атрибутов АОП (custom attributes).

При втором подходе возникает зависимость инструмента АОП от базового языка и всех его изменений. Например, код на языке AspectJ требует для компиляции специализированного компилятора ajc, вхо дящего в состав системы AspectJ, и при любом изменении базового языка Java приходится вносить соответствующие изменения в компи лятор ajc.

Но самое существенное, с концептуальной точки зрения, в том, что при расширении базового языка средствами АОП традиционные для ООП понятия, конструкции и взаимосвязи (классы, поля, объекты, наследование) «сосуществуют» в одном расширенном языке с гораздо более общими по своей природе метапонятиями АОП (аспект, разрез, действие аспекта, внедрение, точка присоединения). При этом у поль зователей возникает целый ряд проблем, которые можно охарактери зовать как «проблемы концептуальной путаницы» (conceptual confusion): могут ли аспекты наследоваться от классов, классы — от аспектов, как при этом изменяется семантика программы и т. д. Все это лишь затрудняет использование АОП, а не облегчает его, так как и без того непростой базовый язык реализации оказывается и вовсе за путанным, что может вообще оттолкнуть пользователей от освоения и использования АОП.

На наш взгляд, АОП и его концепции относятся к мета-уровню методологии программирования, спецификации программ и их транс формаций, — более высокому, чем уровень конкретных известных программных парадигм: процедурное, объектно-ориентированное, функциональное программирование и др. АОП решает в общем виде задачи трансформации программ с целью добавления или модифика ции в них сквозной функциональности, а также спецификации таких трансформаций. При этом методы и подходы, характерные для АОП, на наш взгляд, практически не зависят от концепций базового языка реализации. Хотя при описании разрезов и правил внедрения и ис пользуются понятия базового языка, но, по своей природе и семантике, суть преобразований, выполняемых в АОП, — например, вставка пе ред всеми вызовами модуля (в классическом смысле) с заданным име нем некоторого нового кода, — не зависит от базового языка реализа ции и воплощенной в нем парадигмы. Для процедурных языков Фор тран, Паскаль и Си, либо для объектно-ориентированных языков C++, Java или C#, суть АОП-преобразований программ аналогична;

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

С данной точки зрения, весьма важна также разработка методов формальной спецификации аспектов и их формальной верификации [1], которая в настоящий момент далека от своего решения.

Следует также отметить концептуальную связь АОП и инженерии знаний. Спецификацию аспекта можно рассматривать как представле ние знаний о методе решения задачи (concern) и о методе преобразова ния целевой программы с целью расширения ее функциональности решением рассматриваемой задачи, описанным в виде аспекта. Даже сама форма определения аспекта в любой системе поддержки АОП — совокупность правил вида Условие - Действие, — напоминает про дукционную систему, где набор продукций (знаний) содержит как зна ния о требуемых преобразованиях целевой программы (Условие), так и знания о способе решения задачи аспектом (Действие). С данной точ ки зрения, представляет несомненный интерес исследование и пред ставление аспектно-ориентированных знаний, которое только начина ется. В частности, в нашей группе ведутся исследования по интегра ции системы Aspect.NET c другой нашей системой — Knowledge.NET [30], инструментарием представления знаний для платформы.NET, содержащим средства представления и использования онтологий, фреймов и наборов правил.

2.2. Модели использования аспектов (join point models) С точки зрения семантики и реализации, существующие инстру менты АОП [1] различаются своими моделями внедрения (join point models) — способами реализации аспектов и их внедрения. Основное различие имеет место между статическим и динамическим внедрением.

Инструменты АОП со статическим внедрением осуществляют преобразования целевой программы либо на уровне исходного кода, либо на уровне промежуточного кода (например, байт-кода Java, уни версального промежуточного кода CIL платформы.NET или какого либо собственного внутреннего представления, используемого только данным инструментом АОП), — либо, наконец, на уровне платформ но-зависимого объектного кода (native code). Используется также под ход, основанный на внедрении аспекта на этапе just-in-time компиля ции — динамической компиляции метода из промежуточного кода в платформно-независимый объектный код при первом его вызове.

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

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

На наш взгляд, идеальный инструмент АОП должен обеспечивать гибкое сочетание статической и динамической моделей. С этой точки зрения, наиболее развитой является система AspectJ.

Вопросы к главе 1. Что такое АОП и АОРП?

2. В чем основная проблема сложности программной системы как сово купности рассредоточенных реализаций сквозных фукнкционально стей?

3. Какие методы решения данной проблемы предлагает АОП?

4. Из каких правил состоит определение аспекта, какова их структура, в чем их смысл и как они применяются к целевой программе?

5. Каковы другие основные задачи АОП, кроме раздельного описания аспектов и поддержки инструментов их внедрения?

6. Что такое аспектизация?

7. Что такое метаязык АОП и как он используется в определении аспек та?

8. В чем идея метода реализации АОП как расширения существующего языка программирования и какая широко известная система АОП реализована подобным образом?

9. Какой метод отображения конструкций метаязыка АОП в базовый язык реализации аспектов используется в системе Aspect.NET?

10. Какие концептуальные проблемы возникают при реализации АОП методом расширения базового языка программирования?

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

12. Какова концептуальная связь и в чем сходство АОП и инженерии знаний?

13. Что такое модель внедрения аспектов (join points model) и какие ос новные из таких моделей Вы знаете?

14. В чем суть, достоинства и недостатки статического и динамического внедрения аспектов?

Упражнения к главе 1. Разработайте в системе AspectJ (см. упражнения к главе 1) простей ший аспект, вставляющий перед вызовом каждого метода в целевую программу вывод строки «Hello!», и примените его к целевому Java приложению.

2. Проанализируйте метод обработки системой AspectJ целевого прило жения и аспекта: исходный код (.aj) - байт-код (.class) - байт-код программы с внедренным аспектом - исполнение программы с вне дренным аспектом.

3. Исследуйте другие возможности AspectJ: визуализацию аспектов, от ладку аспектов и др.

4. Сформулируйте примеры известных Вам классов проблем и разно видностей функциональностей в программах, которые по своей сути являются сквозной функциональностью (например, проверки безо пасности).

5. Спроектируйте информационную систему, хранящую анкетные дан ные студентов, по принципам АОП: какие модули необходимо вклю чить в ядро системы, какие сквозные функциональности необходимо будет реализовать для этой системы?

6. Как Вы считаете, для чего лучше подходит АОП — для начального проектирования и разработки большой программной системы или для модернизации и сопровождения системы с уже существующим кодом реализации? Мотивируйте свое мнение конкретными аргументами.

Глава ОБЗОР ИНСТРУМЕНТОВ АОП 3.1. AspectJ и AspectWerkz Система AspectJ [10, 31], как уже отмечалось, — самый популяр ный и широко используемый инструмент АОП, фактически являю щийся де-факто стандартом АОП — как набор базовых терминов АОП, так и набор функциональностей АОП. Первая версия AspectJ была разработана в 1995 году основателем АОП Грегором Кичалесом (Gregor Kiczales) и его группой в фирме Xerox PARC. Это произошло в тот же самый год, когда была выпущена первая версия Java (1.0). В настоящий момент системе AspectJ 16 лет — она достигла «юноше ского возраста», как и Java-технология. На данный момент уже накоп лен большой опыт обучения системе AspectJ и ее использования во всем мире. Наша система Aspect.NET намного «моложе»: ее принципы разработаны в 2003 — 2004 гг., а первый действующий прототип поя вился в 2005.

AspectJ — это АОП-расширение языка Java, или «аспектно ориентированная Java». Текущая версия AspectJ доступна как один из проектов с открытым исходным кодом, входящих в Eclipse foundation.

AspectJ доступен как в виде отдельного продукта, так и в форме, ин тегрированной в среды Eclipse и NetBeans — наиболее популярные интегрированные Java IDE. На наш взгляд, наиболее удобно использо вать AspectJ в форме, интегрированной в среду Eclipse (AspectJ Development Tools — AJDT [32]), благодаря удобным особенностям среды Eclipse Java IDE — относительно быстрому развертыванию и удобному пользовательскому интерфейсу. После инсталляции среды Eclipse, для того, чтобы инсталлировать ее расширение (plug-in), под держивающее AspectJ, достаточно скачать архив AJDT, распаковать его и скопировать его содержимое в поддиректории features и plugins дерева директорий, созданного в результате инсталляции среды Eclipse.

Основные компоненты архитектуры системы AspectJ:

ajc — компилятор AspectJ. Он компилирует исходный код на языке AspectJ (языке Java, расширенном средствами АОП) в Java байткод, «понятный» обычной виртуальной машине Java(JVM, запус каемой командой java). Компилятор ajc доступен как в командном ре жиме, с большим набором опций, так и через интегрированную среду ajdoc — утилита, аналогичная утилите javadoc из JDK, кото рая генерирует гипертекстовую HMTL-документацию в стиле javadoc по исходному коду аспектно-ориентированной программы, написан ной на языке AspectJ. Документация содержит описание структуры сквозных функциональностей, использованных в программе ajbrowser — браузер AspectJ, графический пользовательский интерфейс для визуализации аспектов, их взаимосвязей и структуры сквозных функциональностей в программе. Браузер AspectJ позволяет вызвать компилятор ajc для компиляции программ на AspectJ. Однако (в отличие от Aspect.NET) в браузере AspectJ отсутствует функциональ ность для выбора или отмены выбора точек присоединения аспектов AspectJ ant tasks — инструмент поддержки процесса сборки программ для популярного инструмента сборки программ на Java — Apache ant [33], аналога утилиты make AspectJ load-time weaver — «внедряющий загрузчик классов», утилита, выполняющая «отложенное» внедрение аспектов при загруз ке в JVM соответствующего класса. Возможна разработка и добавле ние в систему внедряющих агентов времени загрузки (load-time weaving agents), решающих ту же задачу. AspectJ также поддерживает внедрение во время компиляции (выполняемое после того, как компи лятор ajc транслирует единицу компиляции AspectJ) и внедрение после компиляции (при котором в качестве входной информации для внедре ния аспектов используются готовый бинарный класс-файл или jar архив).

Язык AspectJ включает разнообразные возможности АОП и до сих пор используется в качестве критерия полноты реализованных возмож ностей АОП для многих инструментов АОП, разработанных позже него (включая и нашу систему Aspect.NET). Основные возможности AspectJ:

определения аспектов, именованные объявления разрезов (pointcuts) и межтиповые объявления (inter-type declarations). Определения аспектов содержат объявления советов (advice declarations), которые, в свою очередь, могут использовать конструкции вида thisJoinPoint для обра ботки информации о точках присоединения в целевых приложениях.

Заметим, что в системе Aspect.NET вместо, на наш взгляд, неудачного термина совет используется термин действие (аспекта).

Определения аспектов в AspectJ являются новой разновидностью модулей, в которых инкапсулирована некоторая сквозная функцио нальность, которая может быть использована путем внедрения (weaving) в целевую программу. Например: протоколирование (logging);

проверки безопасности (security checks). Пример определе ния аспекта на языке AspectJ:

aspect Logging { //Aspect that Introduces logging behavior pointcut AnyCall (): // Named pointcut call (void MyClass.*(..));

before(): AnyCall () { System.out.println ("Hello " + thisJoinPoint) } after(): AnyCall () { System.out.println ("Bye" + thisJoinPoint) } } // Logging Данный аспект вводит функциональность для протоколирования в класс MyClass. Перед каждым вызовом каждого метода M он исполняет совет, который выводит сообщение вида: Hello M, — а после каждого вызова M — совет, который выводит аналогичное завершающее сооб щение: Bye M. Для демонстрационных целей в аспект включено опреде ление именованного разреза AnyCall, хотя в столь простом аспекте мож но было бы ограничиться использованием анонимного разреза:

before(): call (void MyClass.*(..)){... } В реализациях советов использован объект thisJoinPoint, который связывает совет с точкой присоединения в целевой программе и пре доставляет разнообразные возможности для обработки контекста точ ки присоединения. В примере использована лишь простейшая из них — неявный вызов метода thisJoinPoint.toString(), который возвра щает фактическое имя целевого метода, найденного с помощью разре за. Разрезы могут быть также параметризованными, приватными и абстрактными.

Аспекты в языке AspectJ могут наследоваться от других аспектов или классов. Это вполне «в духе Java», хотя можно поспорить о том, безопасна ли эта возможность, модульна ли она или нет, может ли она вызвать «концептуальную путаницу». Предпочитаем здесь не «судить»

решение, принятое пионерами АОП.

Аспекты могут также вводить в другие классы новые межтипо вые объявления (inter-type declarations):

aspect MyAspect { int MyClass.VisibleFromMyAspectOnly;

...

} В данном примере аспект MyAspect добавляет новое поле с име нем VisibleFromMyAspectOnly в класс MyClass. Это поле, в соответст вии с его именем, видимо только из данного аспекта, хотя фактически становится частью класса MyClass. В языке Java добавление подобной функциональности, в самом деле, полезно. Однако, что касается.NET, подобная возможность для пошаговой разработки классов уже реали зована в.NET 2.0 под названием частичные классы (partial classes):

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

Аспекты в AspectJ могут быть также определены как привилегиро ванные (privileged). Такие аспекты имеют доступ к приватным полям целевого класса. Это — правильное решение, так как сквозная функ циональность, добавляемая или расширяемая аспектом, может вклю чать приватные данные класса. Например, приватные поля могут ин капсулировать некоторый общий ресурс, совместно используемый параллельными потоками, а аспект может быть разработан с целью добавления МП-безопасности в целевой класс.

Советы в AspectJ, определенные в аспектах, которые внедряются в целевые программы, могут быть применены перед (before), после (after) или в окрестности (around) точки присоединения (последний вариант фактически означает вместо — instead). В советах типа after может быть уточнена фактическая точка присоединения. Например, код:

after()returning (int result):

call (int MyClass.M ()) { … } означает, что совет активируется после каждого возврата из вызова метода M в классе MyClass, а результат вызова автоматически при сваивается аргументу совета result и может быть проанализирован в теле совета. Аналогичным образом, возможно также уточнение точки активации совета при генерации исключения во время некоторого вы зова, с последующей обработкой исключения.

В свою очередь, разрезы в AspectJ могут быть разнообразных ви дов и могут классифицировать различные виды точек присоединения в Java-программах достаточно тонкими способами: call — вызов неко торого метода;

execution — исполнение тела метода initialization — инициализация объекта;

staticinitialization — инициализация статиче ских полей класса;

set — присваивание полю;

get — извлечение значе ния поля;

handler — вызов обработчика исключения некоторого класса или его подкласса, и т. д. Если иметь в виду, что все эти варианты уточнений могут использоваться в любой комбинации с советами типа after, before или around, можно оценить по достоинству разнообразие возможностей отслеживания и обработки различных моментов испол нения Java-программы с помощью механизма советов в AspectJ.

Начиная с версии AspectJ 1.5, благодаря слиянию AspectJ с дру гим проектом по АОП для платформы Java — AspectWerkz [35], в AspectJ доступна альтернативная форма определения аспектов и их частей с помощью аннотаций, реализованных в Java 1.5. Система AspectWerkz сама по себе не является расширением языка Java средст вами АОП. Это инструмент, поддерживающий определения аспектов с помощью аннотаций. В синтаксисе AspectWerkz, аннотация вида:

@aspect Logging...

имеет семантику, сходную с обычным определением аспекта Logging на языке AspectJ, рассмотренным выше.

В данном разделе дан обзор лишь наиболее основных возможно стей AspectJ. В работе [31] и документации по AJDT [32] они описаны более подробно.

Система AspectJ поддерживается некоторыми крупными компа ниями — разработчиками программного обеспечения, которые под держивают Java-технологию — IBM, Oracle и др. Она оказала огром ное влияние на многих Java-программистов и исследователей в облас ти АОП, включая специалистов моей группы и меня лично. На каждой крупной конференции по АОП и технологиям программирования в программу включается обучающий курс по AspectJ.

Считаю, что система AspectJ имеет большое будущее. Эта система наверняка будет использоваться все большим и большим числом раз работчиков программного обеспечения на Java.

Однако, по-моему, возможности AspectJ гораздо более сложны для изучения и использования, тем сам базовый язык Java. Особую сложность системе AspectJ придают: тонкая и изощренная классифи кация различных видов точек присоединения, — например, вызов ме тода (call) или исполнение метода (execution);

разнообразные языковые возможности, не «ортогональные» друг другу;

смешение базовых кон цепций и конструкций Java и АОП. Многие опытные разработчики Java-программ, включая меня лично, высоко ценят мощность и исто рическую роль AspectJ, испытывают глубокое уважение к его авторам и осознают, что AspectJ может быть применен (и фактически уже при меняется) как в промышленности, так и в исследованиях. Поистине бесценное значение AspectJ в том, что он воплощает в себе первый практически ориентированный и успешно применяемый подход к АОП. Но усложненная «кухня» из множества способов определения и внедрения аспектов в AspectJ может быть воспринята как слишком сложная большинством практиков разработки программного обеспе чения. На мой взгляд, пользователей AspectJ можно разделить на две большие группы: первая — опытные Java-программисты, решающие сложные проблемы проектирования, реализации и сопровождения программ и уверенные в том, что АОП и AspectJ помогут им решить эти проблемы;

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

3.2. Другие подходы к АОП и к проблеме разделения функциональностей Разделение функциональностей (separation of concerns) [35] — одна из базовых концепций программирования, впервые сформулиро ванная Дейкстрой (1974). С общей точки зрения, все подходы к про граммированию и парадигмы разработки программ — модульное про граммирование, объектно-ориентированное программирование (ООП), абстрактные типы данных, аспектно-ориентированное программиро вание — могут рассматриваться как различные методы разделения функциональностей в программах. Например, ООП — это метод раз деления функциональностей в виде иерархий классов;

модульное про граммирование — в виде библиотек модулей;

АОП — это метод раз деления сквозных функциональностей в виде аспектов.

Кроме АОП, существует целый ряд сходных методов, исполь зующих несколько другую терминологию, но также предназначенных для разделения сквозных функциональностей. По-видимому, наиболее общий из таких подходов был предложен исследовательской группой фирмы IBM [36] и основан на концепциях гиперпространства (hyperspace) и многомерного разделения функциональностей (multi dimensional separation of concerns). Данный подход явился основой для второй из наиболее известных в мире (после AspectJ) систем АОП — HyperJ [37], ныне доступной через сайт проектов IBM alphaWorks.

HyperJ — АОП-расширение Java, как и AspectJ, однако система HyperJ гораздо более сложна в использовании. По моему личному опыту, весьма сложной (даже, можно сказать, чересчур усложненной) задачей является разработка, модификация и понимание конфигурационных файлов в системе HyperJ. Видимо, именно подобные сложности стали причиной того, что проект HyperJ был прекращен. Однако данный подход сам по себе интересен для изучения и анализа.

Авторы определяют свою основную концепцию многомерного разделения функциональностей как «гибкое и пошаговое разделение, модуляризация и интеграция программных артефактов на основе лю бого числа функциональностей» [36]. В качестве основных целей сво его подхода они формулируют следующие:

Инкапсуляцию всех видов функциональностей в программной системе одновременно.

Пересечение и взаимодействие функциональностей.

Повторную модуляризацию (remodularization) по требованию для инкапсуляции новых функциональностей в любой момент времени.

Основная концепция и конструкция для достижения многомерно го разделения функциональностей — это гиперпространство (hyperspace) — пространство функциональностей, состоящее из ги пермодулей (hypermodules) — модулей, реализующих конкретные функциональности. Основная идея, связанная с функциональностями, состоит в том, что они группируются в различные измерения (dimensions). Каждое измерение — это набор функциональностей, ко торые не имеют ничего объего друг с другом, т. е. не пересекаются.

Модуль (unit), точка в гиперпространстве (т. е. в модели архитектуры программной системы в целом), проектируется в точности на одну функциональность в каждой размерности. Гипермодули, в свою оче редь, являются базовыми строительными блоками программной сис темы. Каждый гипермодуль состоит из гипервырезок (hyperslices) — совокупностей модулей, специфицируемых в терминах функциональ ностей в гиперпространстве, а правило композиции (composition rule) специфицирует, какм образом следует интегрировать гипервырезки.

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

Даже краткое описание данного подхода показывает, что он бази руется на сложных многомерных геометрических структурах. Более простые — одномерные — геометрические аналоги могут быть ис пользованы при рассмотрении одной из базовых концепций програм мирования — уровней абстракции (по Дейкстре). Каждый уровень абстракции n — это горизонтальный слой из определений модулей данного уровня, в реализации которых могут быть использованы толь ко модули уровня n-1. Двумерная геометрическая модель получается, если к уровням абстракции добавить вертикальные слои (по Фуксма ну). В каждом из этих подходов каждый модуль получает свои «коор динаты» — одну или две. С данной точки зрения, подход IBM к мно гомерному моделированию функциональностей можно рассматривать как обобщение подходов Дейкстры и Фуксмана. Подобная модель, безусловно, интересна с теоретической точки зрения, однако она до сих пор не подтвердила свою практическую применимость, в отличие от подхода AspectJ. Усложненные геометрические аналоги близки к стилю мышления математиков в процессе их теоретических исследо ваний, однако, к сожалению, геометрические концепции не столь близки большинству других людей, включая программистов. По на шему мнению, геометрические аналоги не вполне подходят для описа ния программных архитектур, так как возникает проблема переисполь зования модулей, при котором тот же самый модуль может получить другие горизонтальную и вертикальную (или многомерные) координа ты. По мнению автора, графы, в частности, деревья, являются гораздо более подходящим формализмом для этой цели.

Многомерное разделение функциональностей базируется на еще одном, более раннем подходе к композиции программ — субьектно ориентированном программировании (subject-oriented programming — SOP) [39]. Субъект (subject) в данном подходе — это семантически взаимосвязанная совокупность классов и их фрагментов в объектно ориентированной системе, реализующих некоторую сквозную функ циональность. Объектно-ориентированная система строится из не сольких субъектов, в соответствии с правилами композиции, специфи цирующими способы интеграции субъектов. Такой подход предназна чен для разработки систем как наборов функциональностей, причем код каждой из них хранится отдельно. Поддержка SOP для C++ была реализована в середине 1990-х гг. как расширение известной интегри рованной среды IBM VisualAge.

Адаптивное программирование (adaptive programming) [39] — еще один широко известный подход к разделению функционально стей, предложенный Либергерром (Lieberherr) и реализованный его группой в системе DemeterJ, поддерживающей адаптивное програм мирование для Java. Адаптивное программирование — это метод про ектирования и разработки объектно-ориентированной программной системы с изменяющимися иерархией классов и взаимосвязями мето дов. Основная идея адаптивного программирования в следующем. Ме тод не должен быть жестко привязан (hardwired) к деталям иерархии классов, иначе при любом изменении проекта или реализации системы потребуются значительные модификации кода. Каждый класс должен быть реализован с использованием минимальной информации об ие рархии классов. Общие стратегии обхода иерархии классов должны быть специфицированы на специальном высокоуровневом языке под названием DEMETER, в соответствии с «законом Деметры», глася щим, что каждый должен взаимодействовать только со своими непо средственными друзьями (весьма полезный принцип в современных условиях, не правда ли?). Например [39], если программная система предназначена для автоматизации иерархии организационных струк тур в области высшего образования (министерство образования, уни верситет, факультет, отделение, преподаватель), она может содержать метод для ответа на вопрос вида: «Сколько всего преподавателей есть в наших университетах?» Вместо очевидной реализации данного за проса, с явным посещением всех уровней иерархии, данную операцию следует реализовать в системе DEMETER как состоящую из двух час тей: оператор обхода (traversal clause) — обойти всю иерархию, от министра образования до преподавателя) и обертка преподавателя (teacher wrapper) — при достижении узла, который представляет пре подавателя, увеличить число преподавателей на единицу.


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

Abstract

data types), предложенных Лисков [20], относительно инкапсуляции деталей конкретного представления в итераторах (iterators) — высокоуровневых операциях поэлементно го обхода сложных структур данных. Программа на языке DEMETER затем должна быть оттранслирована в язык Java или C++. Благодаря предложенным принципам, объектно-ориентированные программы становятся более адаптируемыми к изменениям и эволюции.

Композиционные фильтры (composition filters) [41] — это подход к конструированию реализаций множественных сквозных функцио нальностей, предложенный группой из университета Твенте, Голлан дия. Модель композиционных фильтров предназначена для объектно базированных систем (систем ООП без наследования классов), функ циональность которых основана на передаче сообщений между объек тами. Интерфейсная часть — видимое другим поведение объекта — определяется как набор композиционных фильтров — входного и вы ходного наборов фильтров. Интерфейсная часть имеет модульную структуру и не зависит от языка реализации. Она пишется на простом декларативном языке спецификаций (т. е. в стиле «что», а не «как»).

Реализационная часть, написанная на каком-либо конкретном языке реализации, например, на Java, определяет два вида методов — регу лярные методы и условия (последний термин означает запросы со стояния объекта, не изменяющие этого состояния). Для спецификации сквозной функциональности используется супернакладывающее пред ложение (superimposition clause). Данная модель была реализована для трех языков Smalltalk, C++ и Java.

Интересный с практической точки зрения подход, получивший название графы функциональностей (concern graphs) [42], предложен и реализован в системе FEAT Робилларом и Мэрфи (Robillard and Murphy). В нем модели программ рассматриваются как помеченные ориентированные графы — форма, которая, на наш взгляд, гораздо более адекватна, чем многомерные геометрические структуры, для описания взаимосвязей в программной системе. Система FEAT, как и AspectJ, реализована как расширение (plug-in) к популярной интегри рованной среде Eclipse. Система FEAT позволяет визуализировать реализации функциональностей и их компоненты явным образом — например, для каждого метода увидеть, из каких других методов он вызывается и какими другими методами он перегружен. Система по зволяет пользователю построить полный граф функциональностей (concern graph) программной системы в терминах ее типов, методов и полей и их взаимосвязей. Более того, она позволяет обнаруживать не сколько видов несогласованностей в исходных кодах. Все это весьма полезно для лучшего понимания пользователями структуры и функ циональностей программной системы и для их модификации, требуе мых в процессе разработки. Графы функциональностей в системе FEAT помогают пользователям решать до сих пор одну из наиболее сложных задач разработки и сопровождения программ — понимания и модификации существующего программного кода.

В заключении данного краткого обзора (более полный приведен в работе [1]) кратко перечислим другие близкие интересные подходы к разработке и модификации программ:

интенциональное программирование (intentional programming) [43] — подход, основанный на идее отражения в исходном коде про граммной системы исходных намерений (intentions) разработчиков системы, выраженных на соответствующем уровне абстракции генерационное программирование (generative programming) [44] — подход, основанный, по словам его авторов, «на моделирова нии и реализации семейств систем таким образом, что заданная систе ма может быть автоматически сгенерирована из спецификации, напи санной на одном или несскольких текстовых или или графических языков, ориентированных на предметную область».

Возвращаясь к АОП и его инструментам, в заключение данной главы отметим, что в настоящее время инструменты АОП реализованы для многих традиционных и современных языков и платформ: Java, C, C++, JavaScript, C#.NET, VB.NET, Cobol, Perl, PHP, Lua, Python, Ruby, XML и т. д. Web-страница АОП в Wikipedia [45] и сайт по АОП [22] содержат описание сотен разнообразных инструментов АОП.

Вопросы к главе Каково назначение системы AspectJ?

1.

Каковы основные компоненты архитектуры AspectJ?

2.

Что такое определение аспекта в AspectJ?

3.

Что такое объявление разреза в AspectJ?

4.

Что такое межтиповые объявления в AspectJ?

5.

Какие модели внедрения аспектов используются в AspectJ?

6.

Что такое привилегированные аспекты в AspectJ?

7.

Какая альтернативная форма определения аспектов с помощью анно 8.

таций введена в AspectJ при его интеграции с системой AspectWerkz?

В чем, по-Вашему, сложности использования AspectJ?

9.

Что такое уровень абстракции?

10.

Что такое разделение функциональностей?

11.

Каковы основные принципы системы HyperJ?

12.

Что такое субьектно-ориентированное программирование?

13.

Что такое адаптивное программирование?

14.

Что такое генерационное программирование?

15.

Что такое интенциональное программирование?

16.

Что такое граф функциональностей (в системе FEAT)?

17.

Упражнения к главе 1. Скачайте и инсталлируйте систему AspectJ в составе интегрирован ной среды Eclipse 2. Разработайте в системе AspectJ аспект протоколирования, который в начале вызова каждого метода M выводит сообщение Hello M, а в конце каждого вызова — сообщение Bye M. Затем добавьте к этому аспекту вывод значений аргументов метода и его результата.

Глава ПРИНЦИПЫ И АРХИТЕКТУРА СИСТЕМЫ ASPECT.NET 4.1. История и принципы Aspect.NET Знакомство автора с АОП началось в 2001 г. с номера журнала Communications of the ACM [46], посвященного АОП. Содержание его статей позволило мне неожиданно для себя увериться в том, что фак тически я уже являюсь сторонником АОП, так как развивал и исполь зовал аналогичные принципы разработки программ в течение всей своей профессиональной деятельности.

В частности, цели ТИП-технологии [47], разработанной автором в 1980-х гг. и использованной нашим коллективом в течение ряда лет для разработки компиляторов и экспертных систем, состояли, выража ясь современным языком, в поддержке шаблонов проектирования и реализации операций над сложными структурами данных в виде пре допределенного набора уровней абстракции (уровень представления, уровень определения, концептуальный уровень) и вертикальных срезов (интерфейс генерации/удаления, интерфейс доступа, интерфейс мо дификации, интерфейс вывода), — реализуемых в виде информацион но прочного [18] многовходового модуля — технологического инст рументального пакета (ТИП). Использование (внедрение) ТИП путем вызова его абстрактных операций, в отличие от внедрения аспекта в АОП, не было автоматизировано, не опиралось на какие-либо инстру менты, отсутствовал метаязык определения разрезов и правил внедре ния ТИП, однако элементами технологической дисциплины ТИП технологии были семантические рекомендации по использованию операций ТИП [47] и мнемонические обозначения точек использова ния (присоединения) ТИП в виде комментариев, например:

%List% p := Cons (1, Nil);

что облегчало локализацию с помощью редактора или текстовых фильтров в исходном коде программы всех фрагментов (действий) ТИП. Таким образом, ТИП-технология [47], как и технология верти кального слоения [21], была шагом вперед на пути к АОП.

Как известно, значительную трудность для большинства про граммистов при сопровождении больших программных систем пред ставляют выделение и модификация сквозной функциональности. Для исправления ошибки или недоработки в программе (например, отсут ствие синхронизирующих скобок при модификации общего ресурса), программисту приходится, используя средства универсальной интег рированной среды, во-первых, найти в программе все вызовы опера ции изменения ресурса — например, SetResource (NewValue), — во вторых, заключить все эти вызовы в синхронизирующие скобки — например, вставить вызов операции Wait (Semaphore) перед каждым вызовом SetResource, а вызов операции Signal (Semaphore) — после каждого вызова SetResource. Указанные групповые модификации кода выполняются средствами текстового редактора интегрированной сре ды. При этом, в лучшем случае, в среде автоматизирован поиск всех вызовов заданного метода (например, в виде одной из опций функции refactoring), — либо и такая возможность отсутствует, и для поиска приходится использовать сторонние утилиты типа grep. Для надежно сти и безопасности вставки кода синхронизирующих скобок универ сальная среда разработки не обеспечивает никакой поддержки, кроме базовых возможностей редактора (Copy / Paste). Таким образом, си туация, когда программист вставил в код только вызов Wait, но забыл вставить вызов Signal, не контролируется технологией разработки.

Рассмотрим, как описанная выше задача решается в АОП, в сис теме Aspect.NET — с помощью определения и внедрения простого аспекта:


%aspect SemaphoreBrackets public class SemaphoreBrackets { %before %call *.SetResource %action public static void WaitAction () { Wait (Semaphore);

} %after %call *.SetResource %action public static void SignalAction () { Signal (Semaphore);

} } // SemaphoreBrackets Аспект SemaphoreBrackets состоит из двух действий — WaitAction и SignalAction, статических методов, вызовы которых, со гласно правилам внедрения аспекта, вставляются в код целевой про граммы соответственно, перед каждым вызовом и после каждого вы зова метода SetResource.

Строки исходного кода аспекта, начинающиеся знаком процента (%), представляют собой аспектно-ориентированные аннотации, или, иначе говоря, конструкции метаязыка АОП — Aspect.NET.ML, являю щегося частью нашей системы. Весь остальной код — это обычный, синтаксически и семантически правильный код определения класса на C#. Конструкции метаязыка Aspect.NET.ML конвертируются в опре деления специализированных атрибутов (custom attributes).NET на языке C#. Этап конвертирования является первым шагом процесса сборки проекта в Visual Studio. Например, код на метаязыке Aspect.NET.ML:

%before %call *.SetResource %action будет конвертирован в следующий код на C#:

[AspectAction("%before %call *.SetResource")] — код, аннотирующий метод SetResource экземпляром специализиро ванного атрибута АОП AspectAction (действие аспекта).

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

System.Console.WriteLine ("Target method name=" +% TargetMemberInfo.Name);

Аналогичным образом, возможна обработка («захват») аргумен тов и результатов целевого метода;

объекта, к которому применяется метод в целевой программе;

имени файла и номера строки точки при соединения аспекта в целевой программе и т. д.

Пользователь Aspect.NET имеет возможность для разработки оп ределения нового аспекта использовать любой из двух видов проекта Visual Studio.NET, которыми Aspect.NET расширяет стандартный на бор типов проектов Visual Studio, — Aspect.NET.ML module (код на метаязыке АОП) и Aspect.NET modulе — код на C#, в котором специа лизированные атрибуты АОП можно задавать непосредственно и, та ким образом, разрабатывать аспекты «в атрибутах», не используя ме таязыка АОП вообще. Однако, в отличие от конструкций АОП в AspectJ, конструкции метаязыка Aspect.NET.ML очень просты и могут быть быстро освоены с помощью примеров и шаблонов кода, введен ных в Visual Studio для проектов типа Aspect.NET.ML module.

Полученный в результате конвертирования исходный код на C# (VB) компилируется в универсальный промежуточный код CIL плат формы.NET стандартными средствами Visual Studio. Бинарный код сборки (файл переносимого кода, portable executable, платформы.NET) несет в себе информацию не только о коде класса, но и о принадлеж ности его фрагментов (действий, реализуемых методами) аспекту SemaphoreBrackets. Это не препятствует работе стандартных утилит.NET (например, отладчика), но позволяет системе Aspect.NET, ис пользуя атрибуты, «понимать» аспекты, представленные в виде двоич ных кодов сборок. Использование атрибутов АОП более надежно, чем распространенная во многих других инструментах АОП спецификация аспектов в виде отдельных XML-файлов.

Вставка кода действий аспекта в Aspect.NET выполняется автома тически подсистемой внедрения аспектов (weaver). При этом гаранти руется надежность и полнота выполнения данной групповой модифи кации: Aspect.NET не может «случайно забыть» выполнить вставку какого-либо действия аспекта. Подсистема внедрения аспектов вызы вается через интегрированную среду — Aspect.NET Framework, яв ляющуюся частью (add-in) универсальной интегрированной среды Visual Studio.NET. Для обработки сборок.NET подсистема внедрения аспектов использует инструментарий Microsoft Phoenix [48], предна значенный для создания платформно-зависимых частей (back-ends) компиляторов и разработки всевозможных утилит обработки про грамм. Пользователем Phoenix, в рамках программы Phoenix Academic Program [29], наша группа, по приглашению Microsoft Research, явля ется с 2003 года.

Среда Aspect.NET Framework обеспечивает открытие аспектов, представленных двоичными сборками, запоминание открытых аспек тов для последующих открытий той же целевой программы в Visual Studio, визуализацию аспектов, вызов подсистемы внедрения, визуали зацию точек присоединения аспектов в целевой программе, а также пробный запуск одним нажатием кнопки полученного в результате внедрения аспектов двоичного кода сборки.NET.

Aspect.NET, единственный из известных на данный момент инст рументов АОП, обеспечивает режим внедрения аспектов, управляемо го пользователем (user-controlled weaving). Перед фактическим вне дрением аспектов пользователь имеет возможность просмотреть все найденные Aspect.NET потенциальные точки присоединения аспекта в исходном коде целевой программы, проанализировать возможный эф фект внедрения действий аспекта в каждую из этих точек, отменить (deselect) те из них, внедрение в которые нежелательно, и лишь затем выполнить внедрение аспекта. Таким образом, наша система позволяет избежать самой серьезной опасности, которую таит в себе АОП как мощный механизм групповых преобразований кода, — «слепого», бесконтрольного изменения поведения программы, последствия кото рого нетрудно предвидеть.

Вопреки распространенной точке зрения о неэффективности при менения АОП, в отличие от «ручной» вставки аналогичных фрагмен тов кода, Aspect.NET не ухудшает эффективность результирующей программы [1]. Вставки или замены выполняются на уровне бинарного кода сборки (assembly). При этом, как правило, кроме самих вызовов действий аспекта, в код целевой программы не вставляется никакого дополнительного «инструментовочного» кода, т. е. результат внедре ния аспекта в сборку ничем не отличается от результата ее аналогич ной ручной модификации. Полученная сборка может использоваться всеми универсальными инструментами.NET — общей средой под держки выполнения (CLR), отладчиком, профилировщиком (profiler) и т. д.

Суммируя сказанное, отметим, что наша система Aspect.NET ис пользует и развивает наиболее важные черты архитектуры.NET — открытость;

ориентацию на многоязыковое программирование на ос нове единого промежуточного кода MSIL;

применение пользователь ских атрибутов (custom attributes) для аннотирования и расширения программ (в Aspect.NET, как мы уже видели, атрибуты используются для аннотирования методов информацией об аспектах, которым они принадлежат).

4.2. Архитектура Aspect.NET Аспект в системе Aspect.NET определяется как исходный код класса (в наиболее общем виде — код единицы компиляции) на языке C# или Visual Basic (в будущем — на любом другом языке, реализо ванном в.NET), аннотированный конструкциями нашего метаязыка АОП (называемого Aspect.NET.ML) с целью выделения частей опреде ления аспекта.

Определение аспекта сосстоит из следующих частей:

заголовок аспекта (aspect header);

(необязательные) данные аспекта (aspect data) — как прави ло, приватные поля;

модули аспекта (aspect modules) — методы или функции;

правила внедрения аспекта (aspect weaving rules), которые, в свою очередь, состоят из условий внедрения (weaving conditions) и дей ствий (actions), которые, в соответствии с заданными правилами, должны быть внедрены (woven) в целевую сборку.

В Aspect.NET 2.2 поддерживается возможность определения ас пектов на языках Aspect.NET.ML и C#, либо на языках Aspect.NET.ML и Visual Basic, либо только на C# (Visual Basic) «в атрибутах», без ис пользования метаязыка. Поддержка всех остальных основных языков, реализованных в.NET (Managed C++, F# и др.) планируется в бли жайших следующих версиях.

Сразу отметим, что структура метаязыка Aspect.NET.ML и его се мантика не привязаны к конкретному языку реализации, что позволит использовать одни и те же спецификации аспектов на Aspect.NET.ML в сочетании с различными языками их реализации. Подобная языковая независимость метаязыка АОП — важный принцип Aspect.NET.

Правила внедрения аспекта определяют точки присоединения (join points) в целевой программе, в которые должны быть добавлены действия аспекта. Именно действия аспекта, в конечном счете, опре деляют его функциональность.

Препроцессоры (конверторы) Aspect.NET преобразуют аннотации АОП в определения специализированных атрибутов АОП (AOP custom attributes), специально спроектированных для Aspect.NET, на языках C# (VB). Атрибуты АОП помечают классы и методы как части опре деления аспекта (см. рис. 4.1). Далее, соответствующий штатный ком пилятор Visual Studio.NET (для Aspect.NET 2.2 — компилятор с языка C# или VB) преобразует специализированные атрибуты АОП в мета данные (metadata) аспектной сборки (aspect assembly), которые, со гласно общим принципам архитектуры.NET, хранятся в сборке вместе с ее кодом на промежуточном языке MSIL.

Точки присоединения в Aspect.NET определяются по правилам внедрения, которые либо являются частью определения аспекта, либо определены в отдельном модуле — наборе правил (rule set).

В Aspect.NET 2.2 наборы правил не реализованы;

их реализация пла нируется в следующих версиях.

Правила внедрения содержат:

условия (conditions), определяющие точку вызова действия ас пекта относительно конкретной точки присоединения в целевой про грамме: before — перед точкой присоединения;

after — после точки присоединения;

instead — вместо кода (вызова), являющегося точкой присоединения;

контекст (context) вызова действия аспекта: ключевое слово call — вызов некоторого метода в целевой программе;

assign — при сваивание переменной (полю) в целевой программе;

use — использова ние переменной (поля);

за ключевым словом следует шаблон (wildcard) для поиска в целевой программе контекста вызова действия аспекта.

Рис. 4.1. Архитектура Aspect.NET В Aspect.NET 2.2 реализованы точки присоединения вида call (вы зов). Реализация других видов точек присоединения планируется в следующих версиях. Практика показала, что именно точки присоеди нения типа call наиболее важны, и практически любую необходимую АОП-трансформацию программы можно выразить в терминах внеде ний аспектов в такие точки.

Процесс внедрения аспекта состоит из двух фаз: сканирования (scanning) — поиска потенциальных точек внедрения в целевой про грамме, — и собственно внедрения (weaving) вызовов действий аспекта в найденные точки присоединения.

Одним из важнейших принципов Aspect.NET, в отличие от мно гих других инструментов АОП, является возможность внедрения, управляемого пользователем (user-controlled weaving). По завершении фазы сканирования, Aspect.NET позволяет пользователю отметить (select) или отменить отметку (deselect) любой из найденных потен циальных точек внедрения, используя Aspect.NET Framework GUI. Это позволяет избежать синдрома «слепого внедрения» (blind weaving) без какого-либо контроля его результатов, что могло бы сделать результи рующий код целевой программы неясным или вообще ошибочным и затруднить его отладку. Таким образом, в Aspect.NET окончательный выбор, внедрять или не внедрять аспект в ту или иную точку присое динения, остается за пользователем.

Пользователь может определять аспекты либо в форме Aspect.NET.ML, либо непосредственно в терминах специализирован ных атрибутов на языке C# (или VB), без использования метаязыка.

Aspect.NET Framework поддерживает два соответствующих типа про ектов для определения аспектов.

Основные компоненты Aspect.NET — подсистема внедрения (weaver), конвертор метаязыка (meta-language converter) и Aspect.NET Framework — и их взаимосвязь изображены на риc. 4.2.

Рис. 4.2. Компоненты Aspect.NET Очень важно, что результат работы Aspect.NET — двоичная сбор ка (assembly) модифицированной целевой программы — является, с точки зрения обычных пользователей и инструментов.NET, не связан ных с АОП, совершенно стандартной сборкой и может обрабатываться любым штатным инструментом.NET.

Более подобное описание метаязыка определения аспектов Aspect.NET.ML и методы практического использования Aspect.NET в среде Visual Studio даны в последующих двух главах 5 и 6.

Вопросы к главе 1. Что такое ТИП-технология и каково ее назначение?

2. Сформулируйте проблемы разработки и модификации сквозной функциональности.

3. Как решаются эти проблемы с помощью АОП и Aspect.NEТ?

4. Что такое Aspect.NET.ML и как он используется в системе Aspect.NET?

5. Как используются в системе Aspect.NET специализированные атри буты (custom arrtibutes)?

6. Что такое конвертор Aspect.NET.ML в определения атрибутов и како во его назначение?

7. Какие языки определения аспектов поддержаны в текущей версии Aspect.NET?

8. Что такое Aspect.NET Framework?

9. Из каких основных компонент состоит система Aspect.NET, каким образом они взаимодействуют между собой и с интегрированной сре дой Visual Studio?

Упражнения к главе 1. Скачайте Aspect.NET 2.2 и используемый в нем инструмент — Phoenix RDK March 2007. Инсталлируйте (поверх Visual Studio 2005) сначала Phoenix RDK, затем — Aspect.NET. Ссылка на Phoenix RDK дана на странице проекта Aspect.NET: http://www.aspectdotnet.org. Там же прочтите все другие требования (pre-requisites) к окружению для инсталляции и использования Aspect.NET и выполните их (проверьте, что они выполнены).

2. Пропустите все примеры целевых приложений и аспектов, постав ляемых вместе с Aspect.NET 2.2. Проанализируйте результаты.

3. Пропустите все примеры аспектов, опубликованные на странице про екта Aspect.NET, из книги [1]. Проанализируйте результаты.

4. Разработайте аспект, заменяющий реализации всех методов на за глушки, единственной функцией которых является вывод имени вы зываемого метода.

5. Разработайте аспект, заменяющий каждый вызов метода void M() на его «обертку», вызывающую тот же самый метод, но обрабатываю щую все возможные исключения, которые могут возникнуть при вы зове данного метода. В случае генерации исключения аспект должен его перехватывать и выводить в стандартный вывод сообщение с именем возникшего исключения, после чего должна продолжаться нормальная работа программы.

Глава МЕТАЯЗЫК СПЕЦИФИКАЦИИ АСПЕКТОВ ASPECT.NET.ML 5.1. Синтаксис и семантика Aspect.NET.ML Рассмотрим подробнее синтаксис и семантику конструкций мета языка АОП — Aspect.NET.ML, соответствующих версии Aspect.NET 2.2. Синтаксические определения приведены в расширенной форме Бэкуса-Наура (РБНФ). Ключевые слова Aspect.NET.ML (например, %aspect) даны жирным шрифтом. Метасимволы РБНФ, например:

[]*|.

(точка обозначает конец синтаксического правила) также даны жир ным шрифтом.

Каждая конструкция метаязыка — это АОП-аннотация, конверти руемая на этапе сборки аспекта в определения специалилированных атрибутов АОП на соответствующем языке реализации (C# или VB).

Структура и семантика метаязыка не зависят от языка реализации, т. е. при реализации аспекта на C# или VB метаязык используется один и тот же. В этом — один из важнейших принципов Aspect.NET, под держивающий многоязыковое АОП (см. главу 9). Насколько нам из вестно, в настоящее время Aspect.NET — единственная система, под держивающая многоязыково аспектно-ориентированное программиро вание.

Заметим, что в системе Aspect.NET возможно использование не посредственно АОП-атрибутов для определения аспектов, без исполь зования метаязыка Aspect.NET.ML.

Заметим также, что метаязык Aspect.NET.ML спроектирован та ким образом, что, если «забыть об АОП» — удалить или закомменти ровать конструкции метаязыка которые при этом должны быть в от дельных строках исходного кода, — то получившийся код будет син таксически и семантически правильным исходным кодом на языке реализации аспекта (C# или VB). В этом — также один из основных принципов Aspect.NET и наша принципиальная позиция. Наша систе ма не «навязывает» новые конструкции АОП;

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

5.2. Определение аспекта Синтаксис AspectDefinition = %aspect AspectName CSharpClassDefinitionWithModulesAndActions.

AspectName = Id.

Семантика Определение аспекта начинается с его заголовка — ключевого слова %aspect, за которым следует имя аспекта. За заголовком следует тело аспекта, которое может быть любым определением класса на язы ке C#. Имя класса должно совпадать с именем аспекта.

Заголовок класса (class AspectName) может отсутствовать. В таком случае он автоматически генерируется конвертором Aspect.NET.ML.

Класс, реализующий определение аспекта, должен содержать оп ределения модулей (после ключевого слова %modules) и правил вне дрения (после ключевого слова %rules).

Модули аспекта (раздел modules не обязателен), как правило, должны быть приватными методами класса.

Заметим, что такой подход отличается от подхода AspectJ. Мы не вводим в Aspect.NET новую разновидность конструкции в сам язык C#, а вместо этого предоставляем простые и наглядные аннотации к коду на C#, объясняющие пользователям и самой системе Aspect.NET, что данный код определения класса должен рассматриваться как ас пект. Мы считаем, что такой подход гораздо проще, не создает колли зий аспектов и классов на уровне языка реализации, а в будущих вер сиях Aspect.NET он позволит нам использовать аналогичные АОП аннотации для кода на других языках платформы.NET, например, на Managed C++ (в версии 2.2 уже возможно использовать второй язык реализации — VB.NET).

5.3. Правила внедрения аспекта Синтаксис AspectWeavingRulesSection = %rules WeavingRule +.

WeavingRule = WeavingRuleCondition WeavingRuleAction.

WeavingRuleCondition = WeavingRuleConditionClause [ '||' WeavingRuleConditionClause ] *.

WeavingRuleConditionClause = WeavingContext JoinPointKind MethodPattern.

WeavingContext = %before | %after | %instead.

JoinPointKind = %call.

MethodPattern = MethodNameFilter [ MethodArgumentTypes ] [ Restrictions ].

MethodArgumentTypes = ' (' '..' | CLRType [', ' CLRType]* ') '.

MethodNameFilter = [ public | private | *] [static] [CLRType| *] MethodNameWildCard.

Restrictions = Restriction [ '&&' Restriction ] *.

Restriction = %args '(' arg'[' IntLiteral ']' [ ', ' arg'[' IntLiteral ']' ] * ')' | %args '(..)' | %[ '!' ]within '(' TypeNameWildCard')' | %[ '!' ]withincode '(' MethodNameWildCard ')'.

WeavingRuleAction = %action PublicStaticMethodDef.

Примеры 1) %after %call * %action public static void SayBye () { System.Console.WriteLine("Bye");

} Данное правило внедрения обеспечивает следующую функцио нальность: после каждого вызова каждого метода в целевой программе вставляется вызов статического метода (действия) SayBye(), который выводит сообщение «Bye» на консоль. Таким образом, применение подобного рода правил внедрения существенно упрощает реализацию протоколирования целевых программ.

2) %instead %call *BankAccount.withdraw(float)&&args(..) %action public static float WithdrawWrapper (float amount) { BankAccount acc = (BankAccount)TargetObject;

if (isLicenceValid (TargetMemberInfo.Name)) return acc.withdraw(amount);

Console.WriteLine ("Withdraw operation is not allowed");

return acc.Balance;



Pages:   || 2 | 3 |
 





 
© 2013 www.libed.ru - «Бесплатная библиотека научно-практических конференций»

Материалы этого сайта размещены для ознакомления, все права принадлежат их авторам.
Если Вы не согласны с тем, что Ваш материал размещён на этом сайте, пожалуйста, напишите нам, мы в течении 1-2 рабочих дней удалим его.