Analysis of storage and display frameworks based on aspect-oriented technologies

A set of recommendations for the use of dependency injection and aspect-oriented programming in software development is proposed. The influence of their use on the process of design, development, testing, further support and architecture of a software product is analysed.Prombles in programming 2013...

Ausführliche Beschreibung

Gespeichert in:
Bibliographische Detailangaben
Datum:2025
Hauptverfasser: Glybovets, M.M., Gorochovskiy, S.S., Lysenko, І.M.
Format: Artikel
Sprache:Ukrainian
Veröffentlicht: PROBLEMS IN PROGRAMMING 2025
Schlagworte:
Online Zugang:https://pp.isofts.kiev.ua/index.php/ojs1/article/view/777
Tags: Tag hinzufügen
Keine Tags, Fügen Sie den ersten Tag hinzu!
Назва журналу:Problems in programming
Завантажити файл: Pdf

Institution

Problems in programming
id pp_isofts_kiev_ua-article-777
record_format ojs
resource_txt_mv ppisoftskievua/06/8cced8d1eb2e6dfbc79951fb31901b06.pdf
spelling pp_isofts_kiev_ua-article-7772025-08-27T13:11:22Z Analysis of storage and display frameworks based on aspect-oriented technologies Аналіз каркасів зберігання й відображення на базі аспектно-орієнтованих технологій Glybovets, M.M. Gorochovskiy, S.S. Lysenko, І.M. UDC 004.4 УДК 004.4 A set of recommendations for the use of dependency injection and aspect-oriented programming in software development is proposed. The influence of their use on the process of design, development, testing, further support and architecture of a software product is analysed.Prombles in programming 2013; 2: 41-53 Запропоновано набір рекомендацій використання ін’єкції залежностей і аспектно-орієнтованого програмування у розробці програмного забезпечення. Проаналізовано вплив їх використання на процес проектування, розробки, тестування, подальшої підтримки та архітектуру програмного продукту.Prombles in programming 2013; 2: 41-53 PROBLEMS IN PROGRAMMING ПРОБЛЕМЫ ПРОГРАММИРОВАНИЯ ПРОБЛЕМИ ПРОГРАМУВАННЯ 2025-08-27 Article Article application/pdf https://pp.isofts.kiev.ua/index.php/ojs1/article/view/777 PROBLEMS IN PROGRAMMING; No 2 (2013); 41-53 ПРОБЛЕМЫ ПРОГРАММИРОВАНИЯ; No 2 (2013); 41-53 ПРОБЛЕМИ ПРОГРАМУВАННЯ; No 2 (2013); 41-53 1727-4907 uk https://pp.isofts.kiev.ua/index.php/ojs1/article/view/777/829 Copyright (c) 2025 PROBLEMS IN PROGRAMMING
institution Problems in programming
baseUrl_str https://pp.isofts.kiev.ua/index.php/ojs1/oai
datestamp_date 2025-08-27T13:11:22Z
collection OJS
language Ukrainian
topic
UDC 004.4
spellingShingle
UDC 004.4
Glybovets, M.M.
Gorochovskiy, S.S.
Lysenko, І.M.
Analysis of storage and display frameworks based on aspect-oriented technologies
topic_facet
UDC 004.4

УДК 004.4
format Article
author Glybovets, M.M.
Gorochovskiy, S.S.
Lysenko, І.M.
author_facet Glybovets, M.M.
Gorochovskiy, S.S.
Lysenko, І.M.
author_sort Glybovets, M.M.
title Analysis of storage and display frameworks based on aspect-oriented technologies
title_short Analysis of storage and display frameworks based on aspect-oriented technologies
title_full Analysis of storage and display frameworks based on aspect-oriented technologies
title_fullStr Analysis of storage and display frameworks based on aspect-oriented technologies
title_full_unstemmed Analysis of storage and display frameworks based on aspect-oriented technologies
title_sort analysis of storage and display frameworks based on aspect-oriented technologies
title_alt Аналіз каркасів зберігання й відображення на базі аспектно-орієнтованих технологій
description A set of recommendations for the use of dependency injection and aspect-oriented programming in software development is proposed. The influence of their use on the process of design, development, testing, further support and architecture of a software product is analysed.Prombles in programming 2013; 2: 41-53
publisher PROBLEMS IN PROGRAMMING
publishDate 2025
url https://pp.isofts.kiev.ua/index.php/ojs1/article/view/777
work_keys_str_mv AT glybovetsmm analysisofstorageanddisplayframeworksbasedonaspectorientedtechnologies
AT gorochovskiyss analysisofstorageanddisplayframeworksbasedonaspectorientedtechnologies
AT lysenkoím analysisofstorageanddisplayframeworksbasedonaspectorientedtechnologies
AT glybovetsmm analízkarkasívzberígannâjvídobražennânabazíaspektnooríêntovanihtehnologíj
AT gorochovskiyss analízkarkasívzberígannâjvídobražennânabazíaspektnooríêntovanihtehnologíj
AT lysenkoím analízkarkasívzberígannâjvídobražennânabazíaspektnooríêntovanihtehnologíj
first_indexed 2025-09-17T09:21:39Z
last_indexed 2025-09-17T09:21:39Z
_version_ 1850410144901365760
fulltext Інструментальні засоби та середовища програмування © М.М. Глибовець, С.С. Гороховський, І.М. Луценко, 2013 ISSN 1727-4907. Проблеми програмування. 2013. № 2 41 УДК 004.4 М.М. Глибовець, С.С. Гороховський, І.М. Луценко АНАЛІЗ КАРКАСІВ ЗБЕРІГАННЯ Й ВІДОБРАЖЕННЯ НА БАЗІ АСПЕКТНО-ОРІЄНТОВАНИХ ТЕХНОЛОГІЙ Запропоновано набір рекомендацій використання ін’єкції залежностей і аспектно-орієнтованого про- грамування у розробці програмного забезпечення. Проаналізовано вплив їх використання на процес проектування, розробки, тестування, подальшої підтримки та архітектуру програмного продукту. Вступ Ін’єкція залежностей (ІЗ) і аспект- но-орієнтоване програмування (АОП) дві технології, які набули значної популяр- ності останнім часом. Хоча ці технології не пов’язані одна з одною, обидві мають спільне застосування щодо поліпшення проектування, впровадження та супрово- ду програмного забезпечення шляхом створення деякого базису, який зменшує зв'язок між об'єктами і, відповідно, до- зволяє здійснити розбиття на окремі мо- дулі так званої наскрізної функціональнос- ті [1 – 3]. Уточнимо, що ми розуміємо під ви- словом використанням ІЗ і АОП для прое- ктування програмного забезпечення: в яких областях може ефективно застосо- вуватися; який вплив на дизайн програ- мної системи здійснюється з точки зору загальної модульності та архітектури про- грами. Що означає вислів використання ІЗ і АОП для розробки програмного забезпе- чення? Нас буде цікавити визначення впливу зазначених підходів на побудову проекту з точки зору можливих змін і по- дальшої підтримки та організації тесту- вання модулів, особливо автомати- зованого. Одним з найбільш використову- ваних програмних каркасів з відкритим кодом для Java платформ є Spring Framework (SF). Цей каркас робить ко- мерційну розробку програмних засто- сувань простішою, особливо у порівнянні з J2EE [4]. Програмне забезпечення (ПЗ), розроблене з його допомогою не повин- но залежати від API програмного каркасу. Тому SF підтримує інтеграцію з цілим ря- дом інших рішень, таких як Hibernate та каркасами об’єктно-реляційного від об- раження, а також веб-каркасами такими, як Struts. Це дозволяє використовувати тільки потрібні в даний момент розроб- ки SF разом з іншими, вже існуючими, рі- шеннями. SF надає чималу функціональність, розподілену на модулі, які можуть бути розглянуті як окремі повноцінні програмні каркаси. Серед таких модулів присутні: каркаси доступу до даних, керування тран- закціями і безпеки підтримки віддаленого керування, обміну повідомлень і тестуван- ня, контейнер інверсії контролю. Останній і забезпечує конфігурацію компонентів програми за допомогою ІЗ і АОП. Мета даної роботи – аналіз і оцінка наслідків введення і використання ІЗ та АОП з практичної точки зору в реальному проекті. Таким проектом будемо вважати обмежений як у часі, так ресурсами про- ект, що має нечітко сформульовані специ- фікації та мінливі вимоги. 1. Ін'єкції залежностей (Dependency Injection) Ін'єкції залежностей походять з концепції інверсії контролю. Основна ідея інверсії контролю – це досягнення слабкі- шого зв’язування модулів і створення са- мих модулів системи придатними до по- вторного багаторазового використання шляхом делегування контейнерові або кар- касу відповідальності за потік керування у застосуванні [5], тобто, інвертування по- току управління у порівнянні з тради- ційною архітектурою. Звідси і назва. Ін’єкція залежності (Dependency Injection) Інструментальні засоби та середовища програмування 42 є особливою формою інверсії контролю. Термін Dependency Injection був введений Мартіном Фаулером в 2004 році [6]. Використання ІЗ програмного кар- касу призводить до усунення обов'язку створення, поєднання і компонування об'єктів клієнтами або самими службами. Вони будуть передані програмному кар- касу. Тому потік керування інвертується. Замість відповідальності об'єкта за отри- мання необхідної йому служби з вико- ристанням паттерну фабрика [7], локатора служб (service locator) чи самостійного створення служби, об’єкт може мати ар- гумент, що містить посилання і авто- матично встановлюється програмним кар- касом під час створення об’єкта. Існує три типи стилів ін’єкції за- лежностей: ін’єкція під час створення (constructor injection), відкладена ін’єкція (setter injection) та ін’єкція через інтерфейс (interface injection). Різниця між ними виз- начається в тому, як вони надають об’єкту посилання на його залежності. В першому випадку посилання на залежності нада- ються через конструктор класу, тобто під час створення об’єкта. У відкладеній ін’єкції об’єкт надає спеціальний метод для зберігання посилань на залежності, який використовує каркас. У останньому варіанті об’єкт реалізує інтерфейс, що має метод для отримання посилання на залеж- ність. Наведемо приклад використання ІЗ. Приведені приклади дуже обмежені, але достатні для того, щоб стисло проілюстру- вати використання ін’єкції залежностей. Розглянемо клас, потрібний для представлення автомобіля. Характеристи- ки автомобіля, такі як вага, розміри, тип двигуна отримуються із зовнішнього дже- рела і присвоюються об’єкту. Класи, що читають характеристики, всі реалізують інтерфейс DataReader. Об’єкт автомобіль може виглядати так (приведені лише реле- вантні частини коду): public class Car { private DataReader reader; ... // інші параметри, що належать автомобілю public Car() { DataReader reader = new DataFileReader("cardata.txt"); } } Неважко помітити, що об’єкт авто- мобіль створює свою залежність –Data- Reader – явно, через оператор «new». Більш гнучким підходом було б викорис- тання паттерна фабрика. Змінимо клас автомобіль, щоб він використовував ІЗ через конструктор. Клас тепер виглядає так: public class Car { private DataReader reader; ... // інші параметри, що належать автомобілю public Car(DataReader reader) { this.reader = reader; } } Значуща різниця у цьому варіанті класу полягає у наданні залежності класу автомобіль. Клас сам не знає, і не повинен знати, який саме тип зчитувача даних(data reader) він отримує. Якщо ж використовувати відкладе- ну ІЗ, то зчитувач даних (data reader) буде надаватися через спеціальний метод, вже після створення об’єкта. public class Car { private DataReader reader; ... // other variables representing the car public Car() { } public void setReader(DataReader reader) { this.reader = reader; } } При використанні ІЗ жоден з класів (Car чи DataReader) не зобов’язаний знати про існування іншого чи явно викликати один одного. Клас автомобіль (Car) просто приймає об’єкт зчитувача даних і не пот- Інструментальні засоби та середовища програмування 43 ребує додаткової логіки створення об’єкта зчитувача даних. Це дозволяє класу авто- мобіль зосередитися на значущій «бізнес логіці», а не створювати громіздку і не- гнучку інфраструктуру отримання та інте- грування залежностей [8]. Приведені приклади не пояснюють, як ІЗ налаштовується. Це залежить від ви- користовуваного каркасу побудови ІЗ та може бути зроблено за використання кон- фігураційних файлів, анотацій або програ- мно. Далі розглянемо приклад викорис- тання каркасу ІЗ в SF. В цьому випадку, для попереднього прикладу слід налаштувати зв’язки об’єктів. У каркасі SF найбільш пошире- ний спосіб конфігурування зв’язків – це використання xml-файлів [9]. Починаючи з версії 2.5, також стало можливо викорис- тання анотації для конфігурування ІЗ. У нашому прикладі класи Data- Reader та Car потребують конфігурування. Наведемо приклад частини XML- конфігурації: <bean id="filereader" class=" com.masterproject.di.DataFileReader"> <constructor-arg value="cardata.txt"/> </bean> <bean id="car" class="com.masterproject.di.Car"> <property name="reader" ref="filereader"/> </bean> Атрибут «Id» використовується для ідентифікації об’єкта, або як його ще часто називають в термінології SF – bean. Атри- бут «class» показує, якого класу слід ство- рити об’єкт. У нашому прикладі екземпляр класу DataFileReader створюється з вико- ристанням ін’єкції через конструктор для вказування файлу з даними. Об’єкт Car використовує відкладену ІЗ для автоматичного отримання посилан- ня на зчитувач даних (file reader) після власного створення. Це досягається завдя- ки використанню посилання на об’єкт з «id» filereader. Наступний фрагмент коду показує як отримати посилання на екземпляр класу Car використовуючи BeanFactory. package com.masterproject.di; import org.springframework.beans.factory.BeanFact ory; import org.springframework.beans.factory.xml.XmlB eanFactory; import org.springframework.code.io.FileSystemReso urces; public class Example { public static void main(String[] args) throws Exception { BeanFactory factory = new XmlBeanFactory(new FileSystemResource ("config.x ml")); Car car = (Car) factory.getBean("car"); car.doStuff(); } } Використання getBean() методу BeanFactory об’єкта з попередньо визначе- ним аргументом id, призводить до отри- мання посилання на екземпляр класу Car. Коли об’єкт визначено, межі за за- мовчуванням встановлюються в позицію – singleton. Це означає існування лише одно- го спільного екземпляра класу для всіх на- ступних викликів і посилань. Протилеж- ним цьому є значення межі – prototype, за якою новий об’єкт класу буде створювати- ся кожного разу коли посилання буде отримано. Також існують додаткові типи меж. Наприклад, можливим є налаштувати об’єкт на існування протягом життєвого циклу HTTP запиту або сесії. Spring-контейнер також підтримує автоматичне зв’язування визначених об’єктів. Використання автоматичного зв’язування дозволяє вирішити, як об’єкти мають бути пов’язані шляхом вивчення Інструментальні засоби та середовища програмування 44 самих класів, використовуючи імена або типи атрибутів. За допомогою нього дося- гається відчутне зменшення або навіть ві- дмова від зв’язування, основаного на XML конфігуруванні. Недоліком такого підходу до зв’язування об’єктів є відсутність на- глядної картини зв’язків між об’єктами (не існує явної конфігурації). Програмний каркас SF дозволяє по- єднати автоматичне та явне зв’язування об’єктів. Можна використовувати й інші по- пулярні Java каркаси ін’єкцій залежностей. Наприклад, Guice – каркас ін’єкції залеж- ностей з відкритим кодом для Java 5, роз- роблений Google. Він явно використовує анотації для зв’язування залежностей. Програмний каркас PicoContainer замість анотацій чи XML-файлів надає спеціалізо- ваний API для програмної конфігурації об’єктів. EJB 3 підтримує ін’єкцію залеж- ностей двох типів; ін’єкцію атрибутів кла- су та ін’єкцію через спеціальний метод (setter injection) [10]. При ін’єкції атрибутів класу контейнер зберігає посилання на за- лежність у приватному атрибуті класу без використання якогось публічного методу. Ін’єкція залежностей стала настіль- ки невід'ємною частиною Spring Framework, що з достатньою впевненістю можна стверджувати, що без неї розробка в рамках даного каркасу майже не можли- ва, хіба, що лише при використанні окре- мих модулів Spring Framework. Всі класи в Spring Framework спроектовані так, що ві- дбувається ін’єкція залежності, де це лише можливо. Використання ін’єкції залежностей жодним чином не впливає на бізнес-логіку програмного застосування чи об'єктно- орієнтований дизайн класів. Натомість, воно відкриває альтернативний спосіб отримати посилання на залежні об'єкти. Саме через це, потрібні лише незначні, а часто і взагалі ніякі модифікації до загаль- ного дизайну системи для того, щоб пе- рейти на використання ін’єкції залежнос- тей. Якщо з певних причин каркас, що під- тримує ін’єкцію залежностей не може бути використаний, то концепція і проектний взірець (паттерн) можуть бути з великою користю задіяні у проектуванні класів. Реалізація класів з інтерфейсами, спроектованими для підтримки setter- і constructor-ін’єкцій та створення цих кла- сів, використовуючи паттерн типу фабри- ка, принесе чимало користі, яку можна по- рівняти з користю від використання ін’єкції залежностей, але в цьому випадку немає потреби використовувати повноцін- ний каркас. Загалом, при використанні ін’єкції залежностей зменшується кількість шаб- лонного програмного коду, адже зникає потреба у створенні і дублюванні коду, який здійснює пошук або створює залежні об'єкти. Це пояснюється тим, що залежно- сті, як правило, передаються через setter- методи або в конструктор класу, на відмі- ну від їх створення, ініціалізації та отри- мання через методи пошуку або викорис- товуючи фабрики. Менша кількість шаблонного про- грамного коду призводить до вищого сту- пеню зв'язності (cohesion) об'єктів, що, зві- сно, завжди є бажаним. В цьому випадку програмний код фокусується менше на пи- таннях інфраструктури, таких як створен- ня і отримання залежних об'єктів, і більше на виконання задач застосування. Напри- клад, можна встановити всі зовнішні зале- жності певного об'єкта лише подивившись на сигнатуру конструктора та публічних setter-методів. Варто окремо відзначити потенцій- ну небезпеку одночасного використання традиційного способу отримання залежно- стей і ін’єкції залежностей. У такому ви- падку дуже легко не помітити залежності, які можна ідентифікувати, лише уважно переглянувши реалізацію метода та лише проаналізувати сигнатури методів або конфігурацію ін’єкції залежностей. Ін’єкція залежностей пропагує ди- зайн слабше поєднаних класів, адже їхні залежності отримуються ззовні, на проти- вагу створенню або отриманню залежнос- тей, використовуючи інфраструктурний програмний код, що знаходиться в самому об'єкті. Лише це само по собі робить мож- ливу зміну класу легшою. Прикладом, коли потрібна зміна програмного коду, може бути ситуація, коли змінюються залежності. Наприклад, Інструментальні засоби та середовища програмування 45 колекція даних змінюється з одного типу даних на інший. Зміни в класі потенційно простіші у системі, що побудована з вико- ристанням ін’єкції залежностей, у порів- нянні з традиційним підходом до проекту- вання. Особливо це проявляється, коли ін’єкція залежностей використовується ра- зом з концепцією проектування за інтер- фейсом. Причиною простішої реалізації можливих змін в цьому випадку є передача залежності ззовні і єдиний «контракт» між залежністю і об'єктом, що реалізує логіку, та те, що використовує цю залежність ли- ше інтерфейс. Якщо залежність змінюєть- ся, але все ще використовується поперед- ній інтерфейс, то щодо об'єкта слід здійс- нювати незначні зміни або взагалі не про- водити змін. Очевидно, що модульне тестування також виграє від використання ін’єкції залежностей. Загалом менш зв’язані об’єкти легше тестувати модулями, але якщо присутні залежності, то вони мають бути замінені на об’єкти-макети. Об’єкт-макет – це об’єкт, що симу- лює поведінку справжнього об’єкта, адже використання справжніх об’єктів непрак- тичне в модульних тестах. Існує декілька причин використання об’єктів-макетів. Прикладом можуть бути об’єкти зі специ- фічними станами, які дуже складно відт- ворити (наприклад, помилки мережі) або вони занадто повільні (певні запити до ба- зи даних). У модульному тестуванні веб- застосувань загальноприйнятою практи- кою є використання об’єктів-макетів, що репрезентують HTTP запит. Ін’єкція залежностей дозволяє легку заміну реальних об’єктів макетами, де це необхідно. Якщо б залежності були не так легко досяжні, то їх заміна була б склад- ною операцією. 2. Аспектно-орієнтоване програмування Наразі, об’єктно-орієнтоване про- грамування (ООП) є де-факто стандартом для більшості нових проектів розробки програмного забезпечення [10]. ООП запо- чаткувало об'єктну абстракцію і полегшує моделювання загальної поведінки та інка- псулювання цієї поведінки модульним способом. Модульність робить систему гнучкішою, легшою у підтримці й швид- шою у розробці [11]. На жаль, і ООП не забезпечує прийнятного дизайну і ефективної розробки наскрізної функ- ціональності, тобто такої функціональнос- ті, що «прошиває» всю систему, як, напри- клад, безпека [9]. Це часто призводить до компро- місів, коли програмний код для певної за- дачі розсіюється по кількох модулях, що призводить до заплутаного програмного коду і одразу робить реалізацію як са- мої задачі, так й всіх модулів, що зале- жать від даної реалізації, складнішими у розробці та подальшій підтримці. Повто- римо, що таку функціональність назива- ють наскрізною (cross-cutting), оскільки вона перетинає різні модулі. Організацію реалізації такої функціональності прагне спростити АОП, шляхом надання способу відокремлення функціональності в моду- льні аспекти. Для подальшого ознайомлення із аспектно-орієнтованим програмуванням, використаємо приклад, що спрощено опи- сує систему адміністрування готелем. Сис- тема адміністрування використовується персоналом готелю для бронювання кім- нат для гостей, резервування столиків у ресторані, і тому подібне. На перший погляд модуль (або клас), відповідальний за бронювання но- мерів, здається досить тривіальним. Спочатку перевіряється, чи є віль- ний номер на потрібний період. Якщо но- мер вільний протягом проміжку часу, що цікавить клієнта, то далі потрібно зарезер- вувати номер на вказаний термін. Варто зауважити, що не кожен з персоналу готе- лю повинен мати змогу здійснювати бро- нювання номерів. Тобто необхідна додат- кова перевірка для гарантування, що пото- чний виконавець авторизований для здійс- нення даної процедури. Окрім, кожна опе- рація має бути записана у спеціальний жу- рнал та збережена в базі даних, щоб потім була можливість переглянути, хто, що і коли робив. Потрібно зберігати й іншу статистичну інформацію для менеджменту готелю. Інструментальні засоби та середовища програмування 46 Додавання викликів функцій пере- вірки прав користувача та здійснення облі- кового запису в журнал є відносно прос- тою задачею, але варто розуміти важливий момент – додавання цих викликів поро- джує залежності на зовнішні модулі, чим перетворюють модуль резервування номе- рів жорстко залежним від інших частин системи. До того ж знижується зв’язність (внутрішній взаємозв’язок між частинами) модуля, адже система резервування номе- рів тепер мусить відповідати за автентифі- кацію користувача та ініціювати створення облікового запису про виконану дію. Схема, показана на рис. 1, як мо- дуль для резервування викликає методи модулів ведення обліку. Рис. 1. Схема викликів У аспектно-орієнтованому програ- муванні таку наскрізну функціональність, як перевірка прав користувачів на вико- нання певних дій та здійснення записів до журналу обліку можна помістити у окремі модулі – аспекти. Аспект може налашто- вуватися на автоматичне виконання, керу- ючись набором простих правил, що заби- рає відповідальність за виконання відпо- відних задач з окремого модуля, класу чи функції, до яких він буде застосований. Наприклад, аспект перевірки прав користувача може бути автоматично вико- наний перед кожним викликом функції з ім’ям, що починається зі слова “book” (на- приклад, bookRoom(…)). Тобто, відповідна функція буде виконана лише за умови, що користувач має відповідні права на вико- нання. Схема із рис. 2 демонструє проце- дуру резервування номерів із застосуван- ням аспектно-орієнтованого підходу. Вве- дені аспекти визначають коли і як здійс- нювати виклики до АРІ модулів обліку та безпеки. Використання аспектно-орієнтова- ного програмування у даній системі приз- вело до зменшення розпорошення програ- много коду та зробило його менш заплута- ним. В цьому випадку модуль бронювання номерів лише містить програмний код, який має відношення лише до процесу бронювання. Це призвело до меншої взає- мозалежності модулів, більш зрозумілого їх наповнення, а отже і покращило моду- льність системи. Рис. 2. Використання АОП для покращення ведення обліку та аутентифікації користувачів Інструментальні засоби та середовища програмування 47 Для докладнішого обговорення АОП, деякі терміни потребують детальні- шого пояснення. Це терміни рекомендація (аdvice), точка з’єднання (join point), зріз точки (рointcut), аспект (аspect), ціль (target), зв’язування (weaving). Рекомендація описує, що саме пот- рібно робити, коли застосовується аспект. Вона містить програмний код, який забез- печує виконання дій, що мають бути за- стосовані. Наприклад, якщо мета аспекта полягає у веденні журналу обліку подій, які виконуються у застосуванні, рекомен- дація буде містити програмний код, що призведе до запису відповідного рядка у файл облікових записів. Рекомендація може бути виконана до або після точки з’єднання. Вона може замінити програмний код точок з’єднання, або навіть пропустити його виконання. Точки з’єднання – це всі можливі місця виконання рекомендації у програм- ному коді. Вони називаються точками з’єднання, оскільки представляють місця в програмному коді, де рекомендації (advices) можуть бути під’єднанні (або пі- дключені). Можливими точками під’єднання можуть бути виклики методів, створення об’єктів або місця зміни атрибутів об’єктів. Різні типи точок з’єднання, що підтримуються, варіюються залежно від використання різних аспектно-орієнтова- них програмних каркасів. У прикладі ведення журналу обліку, точками з'єднання будуть всі можливі міс- ця у програмному коді, де може бути ви- кликана рекомендація ведення обліку. Зріз точки визначає, де рекоменда- ція має бути виконана, вказуючи набір то- чок з'єднання. Як правило, зрізи точок вка- зують точки з'єднання шляхом переліку відповідних назв класів або процедур явно, або використовуючи шаблони регулярних виразів. Різні варіанти зрізів точок варію- ються між різними імплементаціями про- грамних каркасів [12]. Деякі з них надають можливість створення динамічних зрізів точок, які залежать від рішень прийнятих під час виконання, наприклад, застосуван- ня рекомендації у певній ситуації може залежати від значення певного параметру. Продовжуючи приклад з журналом обліку подій, зріз точки вирішує, коли має бути створений обліковий запис (з-поміж усіх можливих точок з'єднання). Напри- клад, це може відбуватися, коли виклика- ється будь-яка процедура з іменем, що по- чинається зі слова “book”. Найчастіше вживаними типами зрі- зів точок є “до”, “після” і “навколо”. Перші два викликаються за мить до і після ви- клику певної процедури, а рекомендація “навколо” інкапсулює виклик процедури і, таким чином, надає можливість виконати програмний код до і після, включаючи можливість пропуску виклику процедури взагалі. Центральний елемент, у якому ре- комендація і точки з'єднання поєднуються, називається аспектом. Окрім перелічених аспектно-орієнтованих специфічних дета- лей, аспект може містити змінні, процеду- ри і внутрішні класи, точно так як і зви- чайні Java класи. Аспект у прикладі про журнал облі- ку подій визначає все довкілля процесу ведення обліку: де облік має бути застосо- ваним (зріз точки), коли і як запис обліку має бути здійснений (рекомендація). Ціль – це об’єкт, до якого аспект має бути застосований. Зв’язування пред- ставляє процес поєднання аспектів і об’єктів-цілей у завершену систему. Аспе- кти «сплітаються» у об’єкти у вказаних точках з'єднання. Зв’язування може бути виконано у декілька способів: під час ком- піляції чи під час виконання. Для уточнення АОП розглянемо на- вмисно спрощений приклад, що не містить складної бізнес-логіки, а це дозволить з легкістю простежити потік виконання. Наша головна мета – показати відмінність АОП від «чистого» ООП. Головний клас прикладу – Room мі- стить метод bookRoom(int i), що приймає на вхід ціле число (номер кімнати) і бро- нює відповідну кімнату у готелі. Головний метод просто робить два виклики для де- монстрації потоку виконання під час вико- нання bookRoom() метода. Інструментальні засоби та середовища програмування 48 public class Room { public void bookRoom(int id) { System.out.println("Roo m " + id + " booking logic performed"); } public static void main(String[] args) { Room room = new Room(); room.bookRoom(1); room.bookRoom(0); } } Далі маємо Logging аспект, що здійснює збереження облікового запису до і після виклику метода bookRoom(int i) класу Room. Зріз точки ведення обліку ви- значає, що створення запису буде від- буватися до і після виконання усіх пуб- лічних методів класу Room, назви яких починаються з “book”, незалежно від зна- чення, яке поверне метод, і параметрів, які він приймає. Дві точки з'єднання визначе- но для виконання до і після того, як викли- кається зріз точки створення облікового запису. public aspect Logging { public pointcut logging(): call(public* com.Room.book*(*)); before(): logging() { System.out.println( "Entering: " + thisJoinPointStaticPart.getSign ature().getName() ); } after(): logging() { System.out.println( "Exiting: " + thisJoinPointStaicPart. getSignature().getName () ); } } Аспект перевірки прав користувача на виконання певної операції має схожий зріз точки, але він застосовує рекоменда- цію «навколо» і лише умовно продовжує виконання початкового виклику. Дуже спрощений програмний код у прикладі міг би бути замінений на логіку, що перевіряє, чи має поточний користувач дозвіл на ре- зервування певного номера. Якщо корис- тувач дозволу не має, то виклик до метода, що здійснює резервування, не відбудеться (як показано у приклад, і коли параметр «і» дорівнює 0). public aspect Security { public pointcut access(): call(public* com.Room.book*(int)); void around(int i): access() && args(i) { if (i == 0) { System.out.print ln("Blocked call when i == " + i); return; } else { proceed(i); } } } Виконання цього тривіального при- кладу за допомогою AspectJ згенерувало такий результат: Entering: bookRoom Room 1 booking logic performed Exiting: bookRoom Entering: bookRoom Blocked call when i == 0 Exiting: bookRoom Для кожного виклику створюється запис у журнал обліку подій, варто зверну- ти увагу, що для кожного виклику аспек- том створюються два записи Logging – до і після виконання. У випадку, коли виклика- ється метод bookRoom(int i) з аргументом i=0, він блокується аспектом перевірки прав користувачів. Архітектура. Порівняно з ін’єкцією залежностей АОП має великий вплив на проектування та розробку застосування. З концепцією поділу розрізненої функціона- Інструментальні засоби та середовища програмування 49 льності на аспекти архітектура застосуван- ня з використанням АОП значно від- різняється від використання лише загаль- ноприйнятого ООП. При успішному використанні АОП, наскрізна функціональність, яка раніше була розсіяна по всій системі, у значній мірі може бути зосереджена в аспекті та буде застосована там, де це необхідно. Це призводить до двох важливих результатів. Програмний код, що викликає наскрізну функціональність, може бути видалений з об’єктів. У цьому випадку можна сфокусу- вати об’єкти лише на логіці застосування і таким чином досягти вищої зв’язності (cohesion) кожного окремого об’єкта. З ін- шого боку, реалізація і запуск наскрізної функціональності зосереджується у аспек- тах, а отже у випадку необхідності внесен- ня змін до програмного коду наскрізної функціональності, потрібно лише змінити відповідний аспект, а не всі (у найгіршому випадку) місця у системі, де ця функціона- льність використовувалася. Ще одним ти- повим прикладом наскрізної функціональ- ності є ведення обліку подій у системі. АОП привносить новий підхід до проектування. Важливо пам’ятати, що АОП є доповненням до ООП. Розробник має колізію вибору – яка функціональність підходить для реалізації за допомогою ас- пекту, а яка ні. Базуючись на досвіді проектування застосувань, ми пропонуємо використову- вати два підходи до ідентифікації аспектів. Перший підхід полягає у ідентифі- кації наскрізної функціональності під час аналізу вимог до застосування і початково- го етапу проектування архітектури. Цей підхід включає ідентифікацію бізнес- аспектів, що пронизують різні модулі. Другий підхід полягає у розробці модулів і об’єктів у традиційний спосіб з подальшою переробкою окремої функці- ональності на аспекти, коли стане зрозу- міло, що ця функціональність є наскріз- ною, наприклад, якщо програмний код повторюється у багатьох місцях системи; об’єкти перероблюються в такий спосіб, що вони використовуватимуть аспект, а не повторюватимуть той самий програм- ний код. Зазначимо, що доволі легко засто- совувати аспекти для типових рішень, які описані у багатьох наукових статтях як приклади: безпека, облік і керування тран- закціями. При виборі використання АОП, як правило, обирається другий варіант. Існує кілька причин такого вибору. По-перше, завжди легше робити щось «звичним способом» порівняно до впрова- дження чогось нового, та ще й за умови, що розробник не має значного досвіду ро- боти з цим новим. По-друге, більшість проблем проектування не нові й тому вже існують перевірені часом вирішення біль- шості з них. Така ситуація часто виникає при використанні Spring Framework. Незважа- ючи на те, що Spring Framework має влас- ну AOP підтримку, вже існує чимало при- датних способів вирішення проблем без використанням АОП. Аналогічне можна сказати і щодо використання паттернів проектування (design patterns). Як правило, краще вико- ристовувати перевірені паттерни замість впровадження аспектно-орієнтованого ви- рішення. Однак однозначної думки тут не існує. Наприклад, у роботі [7] досліджува- лися 23 паттерни Gang-of-Four. Вони були реалізовані як з використанням об'єктно- орієнтованих, так і аспектних рішень. Піс- ля порівняння зроблено висновок, що бі- льшість аспектно-орієнтованих рішень по- кращили поділ пов'язаної з паттернами функціональності. Та в праці [13] зазнача- ють, що тільки чотири з 23 взірців мають значне повторне використання у проектах. Потрібно брати до уваги і те, що хоча кращий поділ функціональності може бути досягнутий шляхом використання аспектно-орієнтованих рішень, у деяких випадках це може призвести до збільшен- ня розміру програмного коду і складнішо- го дизайну системи. У таких випадках за- гальноприйнятий підхід може виявитися бажаним. Зрозуміло, що АОП є відносно но- вим способом проектування застосувань у порівнянні до ООП і коли розробник стає досвідченішим у застосуванні аспектно- орієнтованих рішень, бажання натомість Інструментальні засоби та середовища програмування 50 застосовувати традиційні рішення через те, що вони більш вивчені, поступово змен- шуватиметься. Підтримка. З точки зору підтрим- ки застосування, при використанні АОП фундаментальним постає питання: чи лю- дина, що змінює програмний код (не автор програмного коду), має досвід і достатні знання з АОП. Може виявитися, що еле- ментарного перегляду класів і аналізу програмного коду в кожному з методів стане недостатнім для розуміння заміни потоку виконання програмного коду аспе- ктами. Намагання зрозуміти, чи варто від- лагоджувати (debug) таку систему без дос- татнього розуміння того, які саме аспекти застосовуються, може виявитися пробле- матичним. У такій ситуації важливу роль відіг- рають середовища програмної розробки (IDE), які підтримують аспектно- орієнтоване програмування. Вони суттєво спрощують намагання зрозуміти, де і як застосовуються аспекти. Навіть для спеці- алістів зі значним досвідом у АОП вони надають значну допомогу при інтерпрета- ції складних умовних зрізів (pointcuts). Як ми вже зазначали раніше, при використанні АОП, програмний код, що реалізує логіку наскрізної функціонально- сті, можна видалити з усіх методів і нато- мість розташувати в окремий модуль – ас- пект. Це призводить до кращої зв’язності класів і робить їх можливі подальші зміни легшими. Полегкість зумовлюють дві при- чини: програмного коду у кожному з кла- сів стає менше і він стає більш сфокусова- ним, а відповідальність за виклик логіки наскрізної функціональності перенесена з методів класу до аспектів. Однією з найбільших переваг аспек- тно-орієнтованого підходу є значне полег- шення змін програмного коду наскрізної функціональності. Якщо взяти за приклад ведення журналу обліку подій системи, то виклики методів створення записів можуть бути розкидані за багатьма класами. І якщо виникає потреба привнесення змін до про- грамного коду створення записів, то у най- гіршому випадку буде необхідна зміна про- грамного коду, що викликав методи ство- рення записів, за всією системою. Зрозумі- ло, що це збільшує ймовірність появи по- милок і просто вимагає чимало часу та зу- силь при умові наявності великої кількості програмного коду в системі. При використанні АОП такі зміни ізолюються у аспекті, що відповідає за внесення записів до журналу і таким чи- ном поєднує у собі як логіку зберігання, так і визначення способу та часу його ви- клику зрізами (pointcuts). Варто зазначити, що існує ризик неправильності призначення аспекту при зміні класів, до яких він застосовується. Зрізи можуть бути визначені за допомогою назв методів і тому при зміні класу розро- бник має дотримуватися домовленості що- до назв методів. Тому бачиться абсолютно необхідним для розробника, що змінює програмний код, знати про використані аспекти, навіть, коли зміни жодним чином не стосуються наскрізної функціональнос- ті. Ігнорування цього може призвести до помилок виконання програмного коду, які буде надзвичайно складно знайти. Тестування. У традиційній архіте- ктурі наскрізну функціональність немож- ливо тестувати з модульних тестів (unit test), бо ця функціональність розсіяна, і тому не є модулем. При аспектно- орієнтованій архітектурі наскрізна функці- ональність зібрана у аспекти, тобто ми ма- ємо окремі модулі. Варто зазначити, що модульне тес- тування аспектів не таке просте, як тесту- вання простих класів, адже, логіка, яку ви- конує аспект, завжди застосовується до цільового об’єкта. Під час розробки засто- сування були ідентифіковані три різні під- ходи до тестування. Найпростішим способом такого тестування вважають модульний тест об’єктів, до яких застосовані аспекти. В цьому випадку ми певною мірою отри- муємо інтеграційний тест, адже одноча- сно тестуються не аспектно-орієнтовані класи й аспекти, що застосовуються до цих класів. Написання такого модульного тесту нескладне, адже він за своєю природою нічим не відрізняється він інших модуль- них тестів. Варто відзначити, що додатко- ва увага має бути приділена перевірці ре- Інструментальні засоби та середовища програмування 51 зультатів виконання тесту. Він повинен мати негативний результат як при умові неправильного виконання логіки класу, так і за умови, що аспект працює неправильно. Недоліком інтеграційного тестування вважають неізольоване тестування аспекту. Тому, якщо тестування цільового об’єкта дає негативний результат, то і тестування аспекту також поверне негативний резуль- тат, навіть за умови, що аспект відпрацьовує коректно. Можливим рішенням бачиться тут використання макету цільового об’єкта, до якого застосовується аспект. З точки зору аспекту, такий макет нічим не відрізняється від інших цільових об’єктів. Створення макету цільового об’єкта має на меті звузити наповнення макета лише до програмного коду, що допомагає перевірити потік виконання і коректний виклик рекомендацій у правильних точках з’єднання. Тобто макет не повинен містити іншої логіки, подібної до тієї, що містять звичайні цільові об’єкти. Перевагою використання макета ці- льового об’єкта є те, що логіка аспекту може бути протестована ізольовано. Недо- ліком можна назвати, те, що потенційно має бути створена чимала кількість маке- тів цільових об’єктів, якщо аспекти засто- совуються до багатьох об’єктів. Третій підхід полягає у делегуванні логіки аспекту в окремі класи і вже потім виконувати модульне тестування цих кла- сів. Цей підхід перевіряє логіку, що вико- нується всередині аспекту, але не може перевірити, коли рекомендації виклика- ються визначеннями точок зрізів. Тому цей підхід може дуже вдало поєднуватися з використанням макетів цільових об’єктів. Недоліком підходу вважається незручність або складність виокремлення логіки в окремі класи. 3. Каркаси аспектно- орієнтованого програмування У залежності від використовувано- го програмного каркаса, що підтримує аспектно-орієнтоване програмування, на- бір підтримуваних можливостей може різнитися. Ця різниця включає у себе, те, які типи точок з'єднання можуть бути застосовані, які зрізи точок визначені і, як та коли відбувається зв’язування. Вказані відмінності розглянемо на прикладі най- більш використовуваних каркасів Spring [9], AspectJ [14], EJB 3 (Enterprise JavaBeans) [10]. Каркас Spring AOP використовуєть- ся для підтримки аспектно-орієнтованого програмування у SF. Він дозволяє розроб- никам створювати власні аспекти простим і легким способом та надає декларативні комерційні сервіси (головним чином керу- вання транзакціями) у самому каркасі [9]. Spring AOP не являється, і не планувався бути таким, повномасштабним AOP карка- сом як AspectJ. Рекомендація (advice) у Spring має синтаксис стандартного Java класу, а зрізи точок описані в XML конфігураційних фа- йлах або з допомогою анотацій. Зв’язува- ння у Spring відбувається під час виконан- ня шляхом загортання об’єкта-цілі у проксі клас. Коли відбувається виклик проксі клас позиціонується як ціль і перехоплює виклики, де рекомендація має бути засто- сована. Через це відпадає потреба у спе- ціальному процесі компіляції, все є чистою Java і застосування може бути напряму ви- користано у J2EE веб-контейнері або сер- вері застосувань. Найпомітніший недолік Spring AOP – це підтримка лише точок з’єднання ме- тодів. Доступні типи рекомендацій: • Before – виконується перед мето- дом, але не може запобігти виконанню методу, хіба що у випадку виникнення помилки; • After return – виконується після нормального виконання метода; • After throwing – виконується якщо виконання метода завершилося помилкою; • After (finally) – завжди виконуєть- ся після виконання метода; • Around – огортає точку з’єднання і може показувати різну поведінку до і після запуску метода. Можливий варіант, коли рекомендація вирішить пропустити вико- нання метода взагалі. Якщо потрібні детальніші рекомен- дації, ніж ті, що надаються точками з’єднання методів, то також існує можли- вість використовувати AspectJ в межах Spring Framework. Інструментальні засоби та середовища програмування 52 AspectJ – найпоширеніший стандарт для аспектно-орієнтованого програмуван- ня [15]. Перша загальнодоступна версія AspectJ була презентована в 2001. Нині AspectJ – проект з відкритим програмним кодом у Eclipse Foundation [3]. AspectJ – це розширення Java для опису зрізів точок і способів їх використання. Java використо- вується для розробки внутрішніх concerns. Будь-яка Java програма є прийнят- ною AspectJ програмою і AspectJ компіля- тор генерує стандартні Java файли класів, що можуть бути виконані будь-якою Java віртуальною машиною. AspectJ підтримує compile-time зв’язування, post-compile зв’язування (зв’язування аспектів у вже зкомпільовані класи) і load-time зв’язуван- ня (LTW). При load-time зв’язуванні Java віртуальна машина використовує заванта- жувач класів. EJB 3 (Enterprise JavaBeans), части- на JavaEE 5, підтримує аспектно- орієнтоване програмування з точки зору використання перехоплювачів (inter- ceptors). Підтримка AOP обмежена [10]. Перехоплювачі – це об’єкти, які ав- томатично виконуються, коли метод викли- кається у EJB об’єкті. Типи точок зрізів, що підтримуються: around рекомендація, яка дозволяє налаштування гнучкої поведінки як на початку метода, так і після нього, з можливістю реакції як на результат що по- вернув метод, так і на можливу помилку, до якої призвело виконання методу. Висновки У роботі проаналізовано викорис- тання ін’єкції залежностей і АОП при роз- робці складних програмних проектів. Ін’єкція залежностей легка у вико- ристанні та розумінні і не вимагає суттє- вих змін архітектури класів певного за- стосування. Однак вона привносить пат- терн проектування, що призводить до менш залежних модулів і меншої кількос- ті шаблонного, повторюваного програм- ного коду. Особливо вигідним є використання ін’єкції залежностей у тестуванні, особливо модульному. Зрозуміло, що модульне тесту- вання полегшується, якщо клас не відпові- дає за пошук або створення своїх залежнос- тей і ресурсів. Частково тому, що класи ста- ють менш зв’язаними між собою, але біль- шою мірою тому, що залежності легко мож- на підмінити об’єктами-макетами. Чимало програмних каркасів нада- ють підтримку ін’єкції залежностей. Саме тому використання ін’єкції залежностей досить легке і зрозуміле. Якщо з певних причин використання програмного карка- са, що підтримує ін’єкцію залежностей неможливе, може бути отримана певна ко- ристь від використання принципу інверсії контролю. Основна мета АОП полягає у роз- робці і підтримці наскрізної функціональ- ності у більш модульний спосіб порівняно з традиційним об’єктно-орієнтованим про- грамуванням. Це досягається впровадженням кон- цепції аспектів, що застосовуються до ці- льових об’єктів. Опис точки зрізу викорис- товується для визначення того коли, де і які зміни параметрів чи виклики методів ці- льових об’єктів перехоплюються програм- ним кодом з аспекту. Визначення від- бувається через процес, що має назву зв’язування (weaving). У випадку AspectJ зв’язування як правило, виконується з ви- користанням AspectJ компілятора. У ви- падку Spring AOP (підтримка АОП у Spring Framework) зв’язування відбувається під час виконання і тому не вимагає спе- ціального компілятора, тим самим дозво- ляючи легкий перехід на використання АОП. Щоб отримати відчутну перевагу від використання АОП варто перейти на дещо новий підхід до процесу проектуван- ня та розробки у порівнянні до традицій- ного ООП, для того, щоб ідентифікувати функціональність, яка претендує на місце в аспекті. Незважаючи на існування чималої кількості ситуацій, коли виграш від вико- ристання АОП беззаперечний, воно прив- носить певну складність, адже потік вико- нання програмного коду цільового об’єкта може бути змінено і це буде непомітно з програмного коду. Використання аспектів також вимагає зміни до процесу тестуван- ня, особливо модульного тестування. Інструментальні засоби та середовища програмування 53 1. Андон П., Дерецький В. Проблеми побудо- ви сервіс-орієнтованих прикладних інфор- маційних систем в semantic web середови- щі на основі агентного підходу // Пробле- ми програмування — 2006. – № 2 – 3 [спец. вип.]. – С. 493–502. 2. Андон Ф.И., Бабко Л.Д. Стандартизация инженерии систем и программных средств в Украине // Кибернетика и системный анализ. – 2009. – 45, № 6. – С. 144–148. 3. Aspectj проект Eclipse Foundation. http://www.eclipse.org/aspectj/. 4. Rod Johnson, Juergen Hoeller, Alef Arendsen, Thomas Risberg, Colin Sampaleanu Professional Java Development with the Spring Framework, Wiley Publishing Inc, July 8, 2005. – P. 1–6. 5. Ralph E. Johnson and Brian Foote. Designing reusable classes // Journal of Object-Oriented Programming. – 1988. – 1(2). – P. 22–35. 6. Martin Fowler. Inversion of Control Containers and the Dependency Injection pattern. http://martinfowler.com/articles/injection.html , 2004. 7. Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides. Design Patterns. Addison-Wesley Professional. – 1995. – P. 87–97. 8. Dhanji R. Prasanna. Dependency Injection. Manning Publications Co., Greenwich, CT, USA, 2008. – P. 19–20. 9. Rod Johnson. The Spring Framework – Reference Documentation. http://static.springframework.org/spring/docs/ 2.5.x/reference/. 10. Debu Panda, Reza Rahman, and Derek Lane. Ejb 3 in Action. Manning Publications Co., Грінвіч, CT, США. – 2007. – P. 146–150. 11. Parnas D.L. On the criteria to be used in decomposing systems into modules. – 1979. – P. 139–150. 12. Maximilian Storzer and Stefan Hanenberg. A classification of pointcut language constructs. In Software-engineering Properties of Languages and Aspect Technologies. 2005. 13. Alessandro Garcia, Cláudio Sant’Anna, Eduardo Figueiredo, Uirá Kulesza, Carlos Lucena, and Arndt von Staa. Modularizing design patterns with aspects: a quantitative study // In AOSD ’05: Proceedings of the 4th international conference on Aspect-oriented software development, 2005. – P 3–14. 14. Gregor Kiczales, Erik Hilsdale, Jim Hugunin, Mik Kersten, Jeffrey Palm, and William G. Griswold. An overview of aspectj. In ECOOP, Springer, 2001. – 2072, P. 327–353. 15. Gregor Kiczales, John Lamping, Anurag Menhdhekar, Chris Maeda, Cristina Lopes, Jean-Marc Loingtier, and John Irwin. Aspect- oriented programming // In Proceedings European Conference on Object-Oriented Programming, Springer-Verlag, Берлін, 1997. – 1241. – P. 220–242. Одержано 18.10.2012 Про авторів: Глибовець Микола Миколайович, доктор фізико-математичних наук, професор, декан факультету інформатики, Гороховський Семен Самійлович, кандидат фізико-математичних наук, доцент кафедри інформатики, Луценко Ігор Миколайович, магістр комп’ютерних наук, керівник команди розробників програмного забезпечення. Місце роботи авторів: Національний університет “Києво-Могилянська Aкадемія”, напрям наукових інтересів – розподілені системи інтелектуального типу, програмні системи підтримки електронного навчання 254070, Київ-70, вул. Сковороди, 2. Тел. (067) 209 0740,факс (044) 416 4515, E-mail: glib@ukma.kiev.ua gor@ukma.kiev.ua м. Київ, вул. Академіка Грекова 5\68, фірма Otto (GmbH & Co KG). Тел.: (050) 135 2319, E-mail: lutsenko.i@gmail.com http://www.eclipse.org/aspectj/ http://www.amazon.com/s/ref=ntt_athr_dp_sr_1?_encoding=UTF8&field-author=Rod%20%20Johnson&ie=UTF8&search-alias=books&sort=relevancerank http://www.amazon.com/s/ref=ntt_athr_dp_sr_2?_encoding=UTF8&field-author=Juergen%20%20Hoeller&ie=UTF8&search-alias=books&sort=relevancerank http://www.amazon.com/s/ref=ntt_athr_dp_sr_3?_encoding=UTF8&field-author=Alef%20%20Arendsen&ie=UTF8&search-alias=books&sort=relevancerank http://www.amazon.com/s/ref=ntt_athr_dp_sr_3?_encoding=UTF8&field-author=Alef%20%20Arendsen&ie=UTF8&search-alias=books&sort=relevancerank http://www.amazon.com/s/ref=ntt_athr_dp_sr_4?_encoding=UTF8&field-author=Thomas%20%20Risberg&ie=UTF8&search-alias=books&sort=relevancerank http://www.amazon.com/s/ref=ntt_athr_dp_sr_5?_encoding=UTF8&field-author=Colin%20Sampaleanu&ie=UTF8&search-alias=books&sort=relevancerank http://www.amazon.com/s/ref=ntt_athr_dp_sr_5?_encoding=UTF8&field-author=Colin%20Sampaleanu&ie=UTF8&search-alias=books&sort=relevancerank mailto:glib@ukma.kiev.ua mailto:gor@ukma.kiev.ua http://www.otto.com/ mailto:lutsenko.i@gmail.com