Аспектно-ориентированное программирование: различия между версиями
Содержимое удалено Содержимое добавлено
ESSch (обсуждение | вклад) викификация |
|||
Строка 1:
{{wikipedia|Аспектно-ориентированное программирование}}
'''Аспе́ктно-ориенти́рованное программи́рование''' (в дальнейшем АОП) — это методика программирования в рамках [[
== История ==
Если вы когда-нибудь работали над кодом со сквозной функциональностью, вам известны проблемы, связанные с ограничением модульности. Поскольку «поперечное» поведение реализуется разрозненно, разработчики находят такое поведение затруднительным в осмысливании, реализации и изменении. Код для ведения журналов, например, переплетается с кодом, отвечающим в основном за что-либо другое. В зависимости от масштаба и сложности crosscutting-отношения степень запутанности может быть более или менее значительной.
Строка 15 ⟶ 16 :
AOП дополняет объектно-ориентированное программирование, обогащая его другим типом модульности, который позволяет локализовать код реализации crosscutting логики в одном модуле. Такие модули обозначаются термином аспекты, от аспектно-ориентированного программирования. За счет отделения аспектно-ориентированного кода работа с crosscutting- отношениями упрощается. Аспекты в системе могут изменяться, вставляться, удаляться на этапе компиляции и, более того, повторно использоваться.
== AspectJ ==
[[w:AspectJ|AspectJ]] — аспектно-ориентированное расширение языка [[w:Java|Java]], предложенное [[w:Xerox PARC|Xerox PARC]]. Представим его на примере программы для журналирования событий, реализованной на AspectJ. Этот пример взят из системы с открытым кодом Cactus, упрощающей тестирование Java-компонентов на стороне сервера. Каркас Cactus разработан для поддержки процесса отладки с помощью трассировки вызовов всех методов. Версия 1.2 Cactus была написана без
<source lang="java">
Строка 51 ⟶ 53 :
</source>
Проанализируем этот пример и посмотрим, какие действия осуществляет аспект. Первое, на что нужно обратить внимание — это объявление аспекта. Оно подобно [[:w:|объявлению класса]] и, так же как класс, определяет тип Java. Кроме того, аспект содержит конструкции ''pointcut'' и ''advice''.
=== Конструкция ''pointcut'' и точки соединения ===
Прежде всего, рассмотрим, что представляет собой '''join point''' ({{lang-ru|точка соединения}}). Точки соединения — это однозначно определенные точки при выполнении программы. Так под точками соединения в AspectJ подразумеваются: вызовы [[:w:ru:Метод (языки программирования)|методов]], точки обращения к членам класса и исполнение блоков [[:w:ru:Обработка исключений|обработчиков исключений]] и т. д. Точки соединения могут, в свою очередь, содержать другие точки соединения. Например, результат вызова метода может передаваться каким-то другим методам. А pointcut является языковой конструкцией, которая отбирает множество точек соединения на основании определенного критерия. В приведенном выше примере первый pointcut под именем <code>publicMethods</code> выбирает исполнения всех <code>public</code> методов в пакете org.apache.cactus. Подобно
=== Конструкция advice ===
Строка 66 ⟶ 68 :
</source>
Этот advice использует класс <code>Logger</code>, методы <code>entry</code> и <code>exit</code> которого выглядят следующим образом:
<source lang="java">
Строка 75 ⟶ 77 :
</source>
В приведенном примере классу <code>logger</code> передается String, образованная от <code>thisJoinPoint</code>, специального объекта, разрешающего доступ к контексту времени выполнения, в котором исполняется точка соединения. В данном, используемом Cactus-ом аспекте, advice применяет этот объект для извлечения параметров метода, передающихся в каждый зарегистрированный вызов метода. «След» вызова метода (с применением аспекта) в log-файле выглядит следующим образом:
<pre>
Строка 85 ⟶ 87 :
=== Advice типа around ===
В примере Cactus определены advice типа <code>before()</code> и <code>after()</code>.
Advice третьего типа <code>around()</code> дает возможность разработчику аспектов управлять передачей управления на точку соединения. При этом используется специальный синтаксис <code>proceed()</code>.
Следующий advice вызывает (или не вызывает) исполнение метода <code>say</code> из класса <code>Hello</code> в зависимости от генерируемого случайного числа (random):
<source lang="java">
Строка 104 ⟶ 106 :
=== Программирование в AspectJ ===
Теперь, когда мы представляем себе, что такое код аспекта, зададим вопрос: «Как заставить приведенный выше код работать?».
Чтобы аспекты могли оказывать воздействие на обычный, основанный на классах код, эти аспекты должны быть «вплетены» в модифицируемый ими код. Чтобы осуществить это в AspectJ, надо [[:w:ru:Компилятор|откомпилировать]] код класса и аспекта ajc-компилятором. ajc может функционировать как полноценный компилятор, генерируя действующий код класса, так и как [[:w:ru:препроцессор|препроцессор]], генерируя .java файлы компилируемые стандартными средствами Java (со ссылкой на небольшой run-time JAR).
Для компиляции в AspectJ необходимо явно задать исходные файлы (и для аспектов, и для классов), подлежащие включению в данную компиляцию — ajc не использует classpath, в отличие от javac. Это имеет определенный смысл, поскольку каждый класс стандартного приложения Java является, в некотором смысле, изолированным [[:w:ru:Компонент (программирование)|компонентом]]. Для корректной работы классу требуется всего лишь присутствие других классов, на которые он ссылается. Аспекты же представляют совокупное поведение, перекрывающее множество классов. Поэтому
Задавая файлы для компиляции, можно также включать и отключать различные аспекты системы на этапе компиляции. Например, включая или исключая описанный ранее аспект для регистрации, разработчик приложения может добавлять или удалять трассировку метода системы Cactus.
Существенное ограничение '''текущей версии''' AspectJ состоит в том, что ее компилятор может вводить аспекты только в код, для которого есть исходный текст. Иными словами, невозможно использовать ajc для включения advice в уже откомпилированные классы. Разработчики AspectJ представляют это ограничение как временное, и на Web-сайте AspectJ можно найти подтверждение того, что в будущей версия (официально — версия 2.0) будут допустимы модификации на уровне [[:w:ru:Байт-код|байт-кода]].
=== Обзор возможностей AspectJ ===
Строка 143 ⟶ 145 :
===== Наследование в стиле mix-in =====
AspectJ позволяет добавлять члены в интерфейсы (аналогично добавлению в классы), что относится к наследованию в стиле mix-in a la C++.
Если мы хотим ввести в общее употребление аспект, рассмотренный в предыдущем разделе, таким образом, чтобы стало возможным многократное использование кода <code>timestamp</code> для множества объектов, следует определить интерфейс с именем
<source lang="java">
Строка 172 ⟶ 174 :
<source lang="java">declare parents: ValueObject||BigValueObject implements TimestampedObject;</source>
После того как определены операции, поддерживаемые интерфейсом
<source lang="java">
Строка 186 ⟶ 188 :
</source>
Заметьте, что ''pointcut'' определяет аргументы, используемые в ''advice'' типа ''after()'' — в данном случае, это
''Pointcut this()'' определяет все точки соединения, где исполняемый в настоящее время объект имеет тип, заданный в скобках. Несколько других типов значений могут быть связаны с аргументами advice, такие как аргументы метода, исключения при исполнении метода и результат вызова метода.
Строка 204 ⟶ 206 :
==== Обработка ошибок ====
Есть множество [[:w:ru:Обработка исключений|обрабатываемых исключений]] в языке [[w:ru:Java|Java]]. Зачастую создаются такие методы, которые наверняка не должны вызывать исключений, и, возможно, они не будут происходить ни у кого из потенциальных пользователей метода. Мы не призываем игнорировать возможные исключения, но тяжело отслеживать присутствие исключений во всех вызовах метода. Есть разные искусные способы использования блоков try/catch, чтобы все-таки решить эту задачу, но самый элегантный — это declare soft в AspectJ. Рассмотрим пример работы с базой данных:
<source lang="java">
Строка 225 ⟶ 227 :
}</source>
Если не использовать AspectJ или объявлять исключение в каждой сигнатуре метода, то пришлось бы встраивать блоки try/catch для обработки <code>SQLException</code>, генерируемого почти каждым методом [[w:Java Database Connectivity|JDBC]] [[w:Интерфейс программирования приложений|API]]. Язык
<source lang="java">
Строка 253 ⟶ 255 :
=== Инструментальная поддержка ===
Xerox подготовил [[w:
Использование открытого кода означает также, что исходный код AspectJ был предметом серьезного общественного обсуждения, прежде чем появиться на рынке.
В AspectJ релиз включены несколько инструментальных средств. Это свидетельствует о твердых обязательствах авторов AspectJ в части создания дружественного по отношению к разработчикам средства. Инструментальная поддержка чрезвычайно важна для аспектно-ориентированных систем, поскольку программные модули могут зависеть от других модулей, о наличии которых они не знают.
Строка 259 ⟶ 261 :
=== Заключение ===
Стоит ли использовать AspectJ? Гради Буч описывает
Разумеется, для AspectJ есть некоторая «кривая обучения». Как в любом языке или расширении языка программирования, в нем есть свои тонкости, которые необходимо освоить, прежде чем задействовать всю мощь этого средства. Однако, «кривая обучения» не слишком крутая — по прочтении руководства пользователя и после проработки нескольких примеров можно составлять полезные аспекты. AspectJ воспринимается естественно, поскольку скорее заполняет пробел в знаниях по программированию, чем придает им новое направление.
Способность AspectJ к «модулированию немодулируемого» должна найти достойное применение. Если вы пока не готовы использовать AspectJ в полном объеме для разработки, его на первых порах можно легко применить в отладке, не упуская благоприятных возможностей, предоставляемых этим расширением.
=== Ссылки ===
* {{cite web
* [http://www.aspectj.org AspectJ.org] — официальный ресурс AspectJ▼
| url = http://www.aspectj.org
* [http://www.aosd.net aosd.net] — портал поклонников аспектно-ориентированного программирования▼
| title = <s>AspectJ.org</s>
| lang = en
| accessdate = 27.10.2010
}}
* {{cite web
| url = http://www.aosd.net
| title = aosd.net
| lang = en
| accessdate = 27.10.2010
▲
}}
== [[Лисп]] ==
{{Эпиграф|В Лиспе, если охота аспектно-ориентированного программирования, нужно лишь настругать немного макросов, и готово. В Java, нужен Грегор Кичалес, создающий новую фирму, и месяцы и годы попыток заставить всё работать.}}
{{Подпись|— [http://www.norvig.com/ Петер Норвиг]}}
Строка 275 ⟶ 288 :
[…]
[[Категория:
[[Категория:Java]]
|