AOP

You might also like

Download as ppt, pdf, or txt
Download as ppt, pdf, or txt
You are on page 1of 49

ЕВОЛУЦИЈА СОФТВЕРА

ПОДРЖАНА АСПЕКТНО-
ОРИЈЕНТИСАНИМ
ПРОГРАМИРАЊЕМ
Ментор: Драган Бојић
Аутор: Саша Мисаиловић

Пролеће 2008
Садржај
• Мотивација
• Раздвајање одлика
• Принципи АОП
• АОП Алати - AspectJ
• Аспектуална рефакторисања
• Коментари
Пример
class Student {
Map<Subject, Grade> grades;

Grade getGrade(Subject subject) {


Grade result = grades.get(subject);
return result;
}
}
Пример – бележење
class Student {
Map<Subject, Grade> grades;

Grade getGrade(Subject subject) {


Grade result = grades.get(subject);
Logger.log(“Accessed subjects list for student “ +
studentName);
return result;
}
}
Пример – аутентикација
class Student {
Map<Subject, Grade> grades;

Grade getGrade(Subject subject) {


AuthService.checkPermissions(session);
Grade result = grades.get(subject);
Logger.log(“Accessed subjects list for student “ +
studentName);
return result;
}
}
Пример – обрада изузетака
class Student {
Map<Subject, Grade> grades;

Grade getGrade(Subject subject) {


try {
AuthService.checkPermissions(session);
Grade result = grades.get(subject);
Logger.log(“Accessed grade for “ + subject + “ for student “ +
studentName);
return result;
} catch (AuthenticationException e) {
// handle exception
} finally {
// handle common case - authentication
}
}
Пример - трансакције
class Student {

Grade getGrade(Subject subject) {


try {
AuthService.checkPermissions(session);
TransactionManager.startTransaction(this);
Grade result = getSubjectsTable().getEntry(subject);
TransactionManager.endTransaction(this);
Logger.log(“Accessed subjects list for student “ +
studentName);
return result;
} catch (AuthenticationException e) {
// handle exception
} finally {
// handle common case - authentication
}
}
}
Пример – додатна обрада изузетака
class Student {
Grade getGrade(Subject subject) {
try {
AuthService.checkPermissions(session);
TransactionManager.startTransaction(this);
Grade result = getSubjectsTable().getEntry(subject);
TransactionManager.endTransaction(this);
Logger.log(“Accessed grade for “ + subject + “ for student “ + studentName);
return result;
} catch (AuthenticationException e) {
// handle exception
} catch TransactionException e)
// handle exception
} finally {
// handle common case – authenticatoin
// handle common case - transaction
}
}}
Пример – коначан изглед
class Student {
Grade getGrade(Subject subject) {
try {
AuthService.checkPermissions(session);
TransactionManager.startTransaction(this);
Grade result = getSubjectsTable().getEntry(subject);
TransactionManager.endTransaction(this);
Logger.log (“Accessed grade for “ + subject + “ for student “ + studentName);
return result;
} catch (AuthenticationException e) {
// handle exception
} catch TransactionException e) class Student {
// handle exception Grade getGrade(Subject subject) {
Grade result = grades.get(subject);
} finally { return result;
// handle common case – authenticatoin }
// handle common case - transaction }
}
}}
Пример – коначан изглед
class Student {
Grade getGrade(Subject subject) {
try {
AuthService.checkPermissions(session);
TransactionManager.startTransaction(this);
Grade result = getSubjectsTable().getEntry(subject);
TransactionManager.endTransaction(this);
Logger.log (“Accessed grade for “ + subject + “ for student “ + studentName);
return result;
} catch (AuthenticationException e) {
// handle exception
} catch TransactionException e)
// handle exception
} finally {
// handle common case – authenticatoin
// handle common case – transaction
}
}}
Садржај
• Мотивација
• Раздвајање одлика
• Принципи АОП
• АОП Алати - AspectJ
• Аспектуална рефакторисања
• Коментари
Раздвајање одлика
Separation of concerns

• Идентификујемо одлике које су међусобно


независне и обрађујемо их као засебне
компоненте
• Један од основних принципа развоја софтвера
– Једноставније разумевање проблема
– Већа могућност одржавања и проширивања
– Поновна употребљивост делова програма
– Побољшана поузданост
• Подршка методологија програмирања:
– Процедуре и функције, библиотеке
– Објекти и класе, пакети
Раздвајање одлика
• Едсгар Дајкстра (1974. “О улози научне
мисли”):
[…]It is what I sometimes have called "the
separation of concerns", which, even if not
perfectly possible, is yet the only available
technique for effective ordering of one's thoughts,
that I know of. This is what I mean by "focusing
one's attention upon some aspect": it does not
mean ignoring the other aspects, it is just doing
justice to the fact that from this aspect's point of
view, the other is irrelevant.
Прожимајуће одлике
Crosscutting concerns

• Неке одлике се не могу локализовати у


једном модулу, већ се њихова
имплементација преплиће кроз хијерархију
декомпозиције система
• Неке одлике (а) не представљају основну
карактеристику модула и/или (б) нису
предвиђене у време пројектовања
• Циљ: Сваки модул треба да обавља
искључиво своју основну функционалност
Прожимајуће одлике
Логовање y org.apache.tomcat
Прожимајуће одлике
• Пресликавање из захтева у имплементацију
није бијективно
• Проблеми у имплементацији:
– Расејавање кода(scattering)
– Мршење кода (tangling)
• Декомпозициона тиранија
– Предности има декомпозиција по основним
(пословним) захтевима. Остали (административни)
захтеви се декомпонују у зависности од примарне
декомпозиције
– Одражава се на цео животни циклус софтвера
Прожимајуће одлике
• Проблеми : • Примери
– Расејавање – Контрола приступа
– Мршење
– Трансакције
Component Component Component – Праћење извршавања
(tracing & logging)
– Управљање сесијом
– Кеширање
– Обрада изузетака
– Policy enforcement
– Тестирање
–…
Прожимајуће одлике
• Издвајање кода секундарних одлика
у засебне модуле:
– Флексибилност
– Прегледност aspects
component component component
– Независност

• Сваки модул
представља
независну
одлику

• Модул се зове аспект


Садржај
• Мотивација
• Раздвајање одлика
• Принципи АОП
• АОП Алати - AspectJ
• Аспектуална рефакторисања
• Коментари
Аспектно-оријентисано
програмирање
• Раздваја примарне одлике од секундарних
– Постоји посебан модул, аспект, који представља
секундарне одлике и начин повезивања са
модулима примарних одлика
• Омогућава додавање особина (делова стања и
понашања) модулу који имплементира
примарну одлику
• Представља надградњу објектно-
оријентисаног програмирања
– Сви концепти из ОО су неизмењени!
Сродан приступ
Пројектни образац Декоратер

BufferedReader in = new BufferedReader(new FileReader("foo.in"));


Сродан приступ
Пројектни образац декоратер
• Мора се узети у обзир
• Флексибилно решење приликом иницијалног
• Решава проблем дизајна система или се
додавања новог стања оригинални систем мора
и новог понашања за рефакторисати
објекте • Мора се експлицитно
инстанцирати на свим
местима у коду у којима
је потребан
• Компликовано
искључивање/промена
додатне могућности
• Да ли се сме користити за
додавање сигурности?
Сродан приступ
Пројектни образац Пресретач
• Пресретач (Interceptor) class TargetClass {
– Образац за конкурентне и
мрежне програме TargetClassState state;
– Омогућава додавање
List<Interceptor> executeEntry;
одговорности основним
објектима током извршавања List<Interceptor> executeExit;
програма
void execute() {
• Циљни објекат на notify(executeEntry);
одређеним местима // method body, change state
оглашава докле је notify(executeExit);
извршавање стигло }
– тачке пресретања
void notify(List<Interceptor> event)
• Пријављени пресретачи могу for( Interceptor i : event )
да у том тренутку изврше i.report(state);
промену стања циљног }
објекта
Сродан приступ
Пројектни образац Пресретач
class TargetClass {
• Потенцијални недостаци:
TargetClassState state; – Тачке пресретања мора да
List<Interceptor> executeEntry; дефинише експлицитно
List<Interceptor> executeExit; програмер циљне класе
void execute() { – Програмер клијентског
notify(executeEntry); кода мора ручно додати
// method body, change state
notify(executeExit);
пресретаче, или да
} користи апстрактну
фабрику
void notify(List<Interceptor> event)
{ – Губи се на перформансама
for( Interceptor i : event ) уколико на некој тачки
i.report(state);
} пресретања не постоји
ниједан пресретач
Аспектно-оријентисано програмирање
• Join-point модел за повезивање одлика
• Кључни појмови:
– Join point – локација у програму која се може
идентификовати (нпр. улаз/излаз из методе)
– Pointcut – скуп више Join point-a који имају заједничку
особину (нпр. припадност класи, заједничко име)
– Advice – програмски кôд који имплементира секундарне
одлика
– Introduction – додатни поља и методи који су потребни
за имплементирање секундарних одлика
– Aspect – реализује секундарне одлике,
• идентификацијом места у програму (помоћу Pointcut-a)
• где треба извршити акције (наведене у Advice-у)
• и додавање потребних метода и поља (наведене
Introduction-ом) потребних за извршење акције
Особине АОП
• Сав специфичан код аспекта се наводи на једном
месту
• Секундарне одлике
– Лако се могу прикључити/развезати од примарног кода
– Прикључују се само уколико су потребне
• Нису потребне ручне промене кода
• Може се додати у било којој фази рада на систему (у
било којој верзији)
• Скуп места на којима треба извршити специфични
код аспекта се наводи имплицитно, унутар аспетка
• Оригинални код нема знања о аспектима и о
њиховим специфичностима (нити зависи од њих!)
– Могућност поновног коришћења
Критика АОП
• Мења семантику језика?
– Разбија локализацију секвенце кода
• Еволуција оригиналног кода може довести до
проблема при коришћењу аспекта
• Промена понашања туђег (3rd party) кода
• Имплементације концепата се доста разликују међу
алатима и језицима
• Џејмс Гослинг о АОП-у:
“I basically like the concept, but I don’t think that the research
community has really figured out how to encapsulate those in a
mechanism that really works for people. Its like giving them a
chainsaw without any safety instructions.”
Садржај
• Мотивација
• Раздвајање одлика
• Принципи АОП
• АОП Алати - AspectJ
• Аспектуална рефакторисања
• Коментари
АОП Алати
• Постоји велики број алата за различите језике који на
различите начине имплементирају АО парадигму
• Јава AspectJ
– Проширење програмског језика Јава
– Интеграција са Eclipse радним окружењем
• Постоји још алата за Јаву: HyperJ, GluonJ…
• Постоје алати за С#: Aspect#, PostSharp…
• AspectC , за процедурални језик C,
• AspectF# за функционални језик F#
• Окружења попут Spring и JBoss користе концепте АОП
АОП Алати
• АО може да се примени на
– Нивоу класе (type level)
– Нивоу објекта (instance level)
• Плетење (weaving)- Комбиновање АО кода
са ОО кодом може да се примени
– Статички – у време превођења
• Над изворним кодом
• Над међукодом/извршним кодом
– Динамички – у време извршавања
AspectJ
• http://www.eclipse.org/aspectj/
• Проширење програмског језика Јава
– Нове кључне речи (aspect, pointcut…)
– Компатибилан byte code, извршава се на свакој JVM
– Могућност статичког и динамичког плетења
• У време превођења - посебан преводилац (ajc), подржава Јаву 5 (и 6)
• У време учитавања класе, помоћу анотација или XML докумената
• Подршка у Eclipse радном окружењу
– http://www.eclipse.org/ajdt/
– Едитор: истицање синтаксе, обележавање join points, допуна
кода, ...
– Преводилац – превођење и покретање програма
– Дебагер – интегрисан (обележавање кода који се извршава...)
AspectJ – проширење језика Јава
• Aspect:
– Нови конструкт језика, налик класи, садржи остале елементе
• Pointcut
– Идентификују жељене Join Point-е (нпр. део имена)
– Врсте Join points:
• Позив метода или конструктора
• Извршавање метода или конструктора
• Приступ или промена вредности поља
• Иницијализација класа и објеката
• Извршавање руковаоца изузетака
– Синтакса попут регуларних израза; врши се pattern matching
• Advice – наводе се у аспекту, уз одговарајући pointcut
– Место извршавања: before, after, around
– Код који представља тело advice-a
• Introduction – поља и методи у аспекту
AspectJ - пример
• Уколико желимо да постигнемо:
class C {
void m1(int i) {
Logger.log(“C.m1(int) started”);
// execute operation body m1…
Logger.log(“C.m1(int) finished”);
}
int m2() {
Logger.log(“C.m2() started”);
// execute operation body m2…
Logger.log(“C.m2() finished”);
return …
}
// …
}
AspectJ - пример
class C {
void m1(int i) { /* execute operation body m1… */ }
int m2() {/* execute operation body m2… */; return … }
}

aspect Logging {
pointcut c_m() : execution(void C.m1(int)) || execution(int C.m2());
// modifier_pattern ret_type_pattern type_pattern.id_pattern(..))
pointcut c_mx() : execution (* C+.m*(..));

before() : c_m() { Logger.log(thisJoinPoint.getSignature() + " started"); }


after() : c_mx() { Logger.log(thisJoinPoint.getSignature() + " finished"); }
}
AspectJ - имплементација
• Две фазе у превођењу код ajc:
– Front-end: генерише Јава .class фајлове, регуларне за
обичне класе, а са анотацијама за аспекте да представи
додатне елементе као што су pointcut и advice
– Back-end: примењује трансформације које упарују Join
points са advice-ом, на основу задатог pointcut-a;
инструментизује класe у којима постоји join point тако
што умеће позив advice методе.

*C.class,
C.java, Logger.java C.class, Logger.class, Logger.class,
@AspectLogging.class AspectLogging.class
Logging.aj
AspectJ - имплементација
• Елементи АОП се преводе у елементе ООП,
који се могу покренути у извршном окружењу:
– Аспект се преводи у класу
– Pointcut се представља анотацијом која садржи
правило за упаривање са Join Point-има; анотација
припада аспекту.
– Advice се представља као метод класе која настаје
од аспекта; место примене advice-а се обележава
посебном анотацијом
• Статичка инструментација на нивоу класе
– Инструментизује се byte code - BCEL библиотека
– Може се извршавати на било којој Јава VM
AspectJ - пример
class C {
void m1(int i) { /* execute operation body m1… */ }
int m2() {/* execute operation body m2… */; return … }
}

aspect Logging {
pointcut c_m() : execution( void C.m1(int)) || execution(int C.m2());
pointcut c_mx() : execution (* C+.m*(..));

before() : c_m() { Logger.log(thisJoinPoint.getSignature() + " started"); }


after() : c_mx() { Logger.log(thisJoinPoint.getSignature() + " finished"); }
}
AspectJ – имплементација пример
@aspect(“Logging”)
@pointcut(“c_m”, “execution( void C.m1(int)) || execution(int C.m2())”)
public class AspectLogging {
@advice(before, “c_m”)
public static void before_adv_1(java.lang.reflect.Method m) {
Logger.log(m.getSignature() + “ started”);
}
//…
}
class C {
void m1() {
AspectLogging.before_adv_1(C.class.getMethod(“m1”, new Class []{int.class}));
// code of m1…
AspectLogging.after_adv_1(C.class.getMethod(“m1”, new Class []{int.class}));
}
}
Садржај
• Мотивација
• Раздвајање одлика
• Принципи АОП
• АОП Алати - AspectJ
• Аспектуална рефакторисања
• Коментари
АОП у еволуцији софтвера
• Додавање нових одговорности постојећим класама
– Креирање нових аспеката и повезивање са класама
– Смањене међузависности између модула

• Рефакторисање постојећих секундарних одговорности


– Смањује се распршеност и умршеност кода
– Систематска подршка за делимично имплементиране
одговорности
– После рефакторисања
• одговорности се ефикасно могу проширити на класе у којима нису
постојале
• одговорности се ефикасно могу изменити

• Међутим, нека од постојећих ОО рефакторисања могу бити


опасна и морају се прилагодити (нпр. промена имена методе!)
Екстраховање позива метода
• [Fowler] Код који се понавља се смешта у засебан метод, а
на ранијим местима кода се наводи позив тог метода
– Није АО, важи на основу једне класе, позиви зависе од
постојања метода у датој класи

• [АО рефакторисање] Код који се понавља се тражи на


нивоу целог пројекта:
– Тело екстрахованог метода се смешта у аспект (introduce)
– Сва места на којима је пронађен позив методе се идентификују
помоћу pointcut-a
– За тај pointcut се додељује advice који позива екстраховану
методу, која је сад у аспекту, а позив у оригиналној класи се
брише

• Оригиналне класе постају независне од функционалности


коју је обезбеђивао екстраховани метод
Екстраховање позива метода
Екстраховање имплементације
интерфејса
• Замењује апстрактну класу аспектом
• Ефективно, омогућава вишеструко
наслеђивање
– Све дуплиране (идентичне) имплементације се
такође рефакторишу аспектом
• Али, све класе на које се односи нови
аспект постају зависне од њега (не могу се
користити као ОО класе)
Екстраховање руковања изузецима
• Проблем: На више места у клијентском коду се позива метода
која може бацити неке изузетке; на свим местима врши се
идентична обрада!
• Предлог: Обрада изузетка за тај позив методе се премешта у
аспект.
– Pointcut тог аспекта је сваки позив методе
– Advice тог аспекта се извршава када метод баци неки изузетак
– Око позива методе остаје само подразумевани
try {…} catch (Throwable t) { throw new RuntimeException(t); } блок
• Особине:
– Обрада изузетка је локализована; промена у аспекту се одражава
на све означене позиве
– Код на месту позива је једноставнији за праћење
– Треба обратити пажњу на случај када за неке позиве метода треба
урадити другачију обраду изузетака
Замена редефинисања метода
advice-ом
• Додавање нових /промењених одговорности
постојећим класама:
– Класа се наследи; у наслеђеној класи се
редефинишу методе
– Пројектни обрасци: декоратер и сл...
• Аспект се такође може користити за додавање
нове одговорности:
– Методи којима треба додати одговорност се
наведу у pointcut-у, a у advice-у се наводи нови код
(нпр. позив посматрача – observer-a)
– Ефекат сличан као код пројектног обрасца
Пресретач
Policy Enforcement
• Ефикасна котрола исправности кода
– Ефективно, проширује се функција компајлера
• Евиденција
– У време превођења
– У време извршавања

• Пример:
aspect DetectConsoleUsage {
declare warning : get ( * System.out)
|| get ( * System.err)
: “Consider using Logging.log() instead

of System.out and System.err”;


}
Садржај
• Мотивација
• Раздвајање одлика
• Принципи АОП
• АОП Алати - AspectJ
• Аспектуална рефакторисања
• Коментари
Закључак
• Аспектно оријентисано програмирање је техника која
помаже да се независне одлике сместе у засебне
модуле
– Смањује расејавање и мршење кода
– Једноставније пресликавање из спецификације у
имплементацију
• АОП уводи неколико принципа који се надограђују на
принципе постојећих програмских парадигми
– Може се применити на ОО, процедуралне или
функционалне програме
– Постоји велики број алата за различите програмске језике
• АОП омогућава већу флексибилност, прегледност и
независност компоненти у систему
Литература
• Ramnivas Laddad, AspectJ in Action: Practical Aspect-
Oriented Programming, Manning, 2003.
• Tzilla Elrad, Robert E. Filman and Atef Bader, Aspect-
Oriented Programming, Communications of the ACM,
Vol. 44, No. 10, October 2001, pp. 29-32.
• Adrian Colyer, Andy Clement, George Harley,
Matthew Webster, Eclipse AspectJ: Aspect-Oriented
Programming with AspectJ and the Eclipse AspectJ
Development Tools, : Addison Wesley Professional, 2004

You might also like