Аспектно-ориентирано програмиране

от Уикипедия, свободната енциклопедия
Направо към: навигация, търсене

В компютърните науки, аспектно-ориентираното програмиране (АОП) е парадигма на програмиране, която има за цел да повиши модулността, позволявайки изолирането на пресичащи функционални дялове. Това се постига чрез добавяне на допълнително поведение на съществуващия код, наречено ”адвайс” (на английски: advice), без промяна на самия код, като вместо това отделно се определя кой код ще бъде променен посредством задаване на пресечна точка (на английски: pointcut ), като например „отрази в регистъра всички извиквания на функции, в които името на функцията започва със "set". Това позволява към програмата да се добавят поведения, които не са централни за бизнес логиката (например записване в регистър), без да се повлиява на функционалността на основния код. АОП създава основа за разработка на аспектно-ориентиран софтуер.

АОП включва програмни методи и инструменти, които подпомагат разделянето на функционалните дялове в модули на ниво сорс код, докато „разработка на аспектно-ориентиран софтуер” се отнася за цялата инженерна дисциплина.

Аспектно-ориентираното програмиране изисква разбиване на програмната логика на отделни части (т.нар. функционални дялове, обособени функционални елементи от кода). Почти всички програмни парадигми предоставят някакво ниво на групиране и капсулация на функционални дялове в отделни, независими елементи посредством абстракции (напр. функции, процедури, модули, класове, методи), които могат да бъдат използвани за имплементация, превръщане в абстракция и съставяне на тези функционални дялове. Някои функционални дялове „пресичат” няколко абстракции в програмата и не се подчиняват на тези форми на имплементация. Тези функционални дялове се наричат пресичащи или хоризонтални функционални дялове.

Записването в регистър е пример за пресичащ функционален дял, тъй като стратегията за регистриране на данни по необходимост влияе на всяка отразявана в регистъра част на системата. По тази причина записването в регистър пресича всички отразявани в регистър класове и методи.

Всички имплементации на АОП имат пресичащи изрази, които капсулират всеки функционален дял на едно място. Разликата между имплементациите се крие в мощността, сигурността и използваемостта на предоставените конструкции. Например, интерсепторите (на английски: interceptors), определящи методите, които да въздействат на изпълнението на програмата, представляват ограничена форма на пресичане без значителна поддръжка на типова безопасност или дебъгване. AspectJ предлага множество такива изрази, които капсулира в специален клас, наречен аспект. Аспектът може да промени поведението на основния код (неаспектната част на програмата) посредством прилагане на адвайс (допълнително поведение) в различни съединени точки (на английски: join point), определени в квантификатор (quantification) или заявка, наречена пресечна точка (която проверява дали дадена съединена точка отговаря). Един аспект може също така да извърши бинарно-съвместими структурни промени в други класове, като добавяне на членове или родители.

История[редактиране | редактиране на кода]

AOП има няколко преки предшественици А1 и А2:[1] рефлексия и метаобектни протоколи, предметно-ориентирано програмиране, Композиционни Филтри и Адаптивно програмиране [2]. Грегор Кишалес и колегите му от Xerox PARC разработват първоначалната концепция за AOP, на базата, на която създават разширението AspectJ AOP за Джавa. Изследователският екип на IBM преследва инструменталния подход пред този с езиков дизайн и през 2001 година предлага Hyper J и Concern Manipulation Environment, които така и не успяват да придобият широка употреба. Примерите в тази статия използват AspectJ, тъй като това е най-широко разпространения език за AOP. Microsoft Transaction Server е считан за първото голямо приложение на AOP последвано от Enterprise JavaBeans.[3][4]

Мотивация и основни концепции[редактиране | редактиране на кода]

Обикновено един аспект е разпръснат или заплетен като код, което го прави труден за разбиране и поддръжка. Разпръснат въз основа на функцията (например разцепен), която се простира из множество отделни функции, които може да използват функцията му, в изцяло несвързани системи, различни изходни езици и други. Това означава, че за да се промени разцепеността му (logging) ще трябва да се променят всички засегнати модули. Аспектите стават заплетени не само с главната функция на системите, в които са изразени, но също и един с друг. Това означава, че при промяната на един трябва да се погрижим за цялостното разбиране на всички заплетени такива. В противен случай трябва да имаме някакви средства, с помощта на които ефекта предизвикан от промяната може да бъде заключен.

Например, да вземем едно банково приложение с концептуално прост метод за прехвърляне на сума от една сметка в друга:[5]

void transfer(Account fromAcc, Account toAcc, int amount) throws Exception {
  if (fromAcc.getBalance() < amount)
      throw new InsufficientFundsException();

  fromAcc.withdraw(amount);
  toAcc.deposit(amount);
}

Въпреки това, този метод за прехвърляне изисква да се вземат под внимание няколко неща, които работещо приложение би трябвало да има: липсва проверка на сигурността, която да установи, че текущия потребител е оторизиран да извърши операцията; транзакция чрез базата данни би трябвало да капсулова операцията с цел да предотврати случайна загуба на данни; за нуждите на диагностицирането операцията би трябвало да се записва в системния лог и тн. За да дадем пример, версия с всички тези нови функционалности би изглеждала така:

void transfer(Account fromAcc, Account toAcc, int amount, User user,
    Logger logger, Database database) throws Exception {
  logger.info("Transferring money...");
  
  if (!isUserAuthorised(user, fromAcc)) {
    logger.info("User has no permission.");
    throw new UnauthorisedUserException();
  }
  
  if (fromAcc.getBalance() < amount) {
    logger.info("Insufficient funds.");
    throw new InsufficientFundsException();
  }

  fromAcc.withdraw(amount);
  toAcc.deposit(amount);

  database.commitChanges();  // Atomic operation.

  logger.info("Transaction successful.");
}

В този пример други интереси станаха заплетени с основната функционалност (понякога ги наричат функционалност на бизнес логиката). Транзакции, сигурност, и логване – всички илюстрират напречно вкараната функционалност. Какво би се случило ако случайно трябва да сменим например функционалността засягаща сигурността на приложението ни. В настоящата версия на програмата, всички операции свързани със сигурността са разцепени из многобройните методи и подобна промяна би изискала огромни усилия. AOP опитва да разреши този проблем, като позволява на програмиста да изрази напречно вкарана функционалност чрез самостоятелни модули, наричани аспекти. Аспектите могат да съдържат адвайс (присъединен код за специфициране на определени точки в програмата) и междутипови декларации (структурни членове, добавени към други класове). Например, модул за сигурността може да включи адвайс, който изпълнява проверка на сигурността преди достъпа до банковата сметка. Пойнткътът определя колко пъти (колко съединени точки), някой може да получи достъп до банкова сметка, а кодът в тялото на адвайса определя как сигурността да бъде приложена. По този начин и двете – проверката и местата могат да се поддържат на едно място. Освен това един добър пойнткът може да предвиди по-късни промени в програмата, така че ако друг разработчик създаде нов метод за достъп до банковата сметка, адвайсът ще се приложи и на новия метод, когато той се изпълнява. Така че, за горния пример прилагаме разцепването в аспект:

aspect Logger {
  void Bank.transfer(Account fromAcc, Account toAcc, int amount, User user, Logger logger)  {
    logger.info("Transferring money...");
  }

  void Bank.getMoneyBack(User user, int transactionId, Logger logger)  {
    logger.info("User requested money back.");
  }

  // Друга напречно вкарана функционалност.
}

АОП може да се възприема като инструмент за дебъгване или като инструмент на ниво потребител. Адвайс би трябвало да бъде съхранен за случаите, когато не може да се накара функцията да се промени (потребителско ниво)[6] или не се иска да се променя функция на код в продукция (дебъгване).

Модели на съединени точки[редактиране | редактиране на кода]

Компонентът адвайс на аспектно – ориентирания език дефинира модели на съединени точки (МСТ). МСТ определят три неща:

  1. Кога адвайсът може да бъде пуснат. Наречени са съединени точки, защото те са точки на работеща програма, където допълнително поведение може да бъде полезно присъединено. За да бъде полезна, съединената точка трябва да може да бъде адресирана и разбрана от всеки обикновен програмист. Трябва също да бъде стабилна при незначителни промени в програмата, за да може всеки отделен аспект да бъде стабилен при такива промени. Много АОП имплементации поддържат метод за изпълнение и полеви препратки във вид на съединени точки.
  2. Пойнткът се нарича начина за определяне (или количествено определяне) на съединени точки. Пойнткътите определят дали дадена съединени точка съвпада. Най-полезните пойнткътите програмни езици използват подобен синтаксис на базовия език за програмиране (например използва Джава сигнатури) и позволяват повторна употреба чрез наименуване и комбиниране.
  3. Средство да се зададе на кода да тръгне по съединени точка. AspectJ нарича това адвайс и може да го пусне преди, след и около съединени точка. Някои имплементации също поддържат неща като дефиниране на метод по отношение на друг клас.

Моделите на съединени точки могат да бъдат сравнени на базата на изложените съединени точки, по какъв начин те са специфицирани, позволените им операции, и структурните подобрения, които могат да бъдат изразени.

Модел на съединени точки на AspectJ[редактиране | редактиране на кода]

Главна статия: AspectJ

  • Съединените точки в AspectJ включват извикването на метод или конструкция или изпълнението, инициализирането на клас или обект, достъпа до поле за четене и писане, обработка на изключения и т.н. Те не включват цикли, супер извиквания, хвърляне на клаузи, множество изявления и др.
  • Съединените точки са определят чрез комбинирането на обозначители на примитивни съединени точки (ОПСТ).

„Типова“ ОПСТ съвпада със съединена точка от определен тип (например изпълнението на метод) и обикновено взима за вход сигнатура като при Джава. Подобна пойнткът би изглеждала така:

 execution(*set*(*))

Този пойнткът съвпада с метод execution на съединена точка, ако името на метода започва със “set” и има точно един аргумент от какъвто и да е тип в него. „Динамични“ ОПСТ проверяват рънтайм видове и обвързват променливи. Например:

 this(Point)

Този пойнткът съвпада, когато обектът, който се изпълнява е инстанция на класа Point. Имайте предвид, че некласифицирано име на един клас може да бъде използвано и чрез нормалния вид търсене на Джава. „Обхват“ ОПСТ ограничава лексикално обхвата на съединените точки. Например:

within(com.company.*)

Този пойнткът съвпада с всяка съединена точка от всеки вид в пакета com.company. * е форма на заместващ символ, който може да бъде използван за съчетаване на много неща с еднаква сигнатура. Пойнткътите могат да бъдат съставяни и именувани за повторно използване.

 pointcut set() : execution(* set*(*) ) && this(Point) && within(com.company.*);

Този пойнткът съвпада със съединена точка на метод execution, ако името на метода започва със „set“ и this е инстанция на тип Point в пакет com.company. Moже да бъде реферирана като се използва името "set()".

  • Адвайс-а определя да пусне (преди, след или около) съединена точка (определена чрез пойнткът) определен код (специфициран като код в метод). АОП рънтайм извиква Адвайс-а автоматично, когато пойнткъта съвпада със съединената точка. Например:
after() : set() {
  Display.update();
}

Това на практика уточнява: "ако set() пойнткът съвпадне със съединената точка стартирай кода Display.update(), след като съединената точка се изпълни. "

Други потенциални модели на съединени точки[редактиране | редактиране на кода]

Има и други типове МСТ. Всички езици с адвайс могат да бъдат определени от гледна точка на техните МСТ. Например, предполагаем аспектен език за UML може да има следната МСТ:

  • Съединените точки за всички елементи от модела.
  • Пойнткътите са булеви изрази, комбиниращи елементите на модела.
  • Средствата за повлияване на тези точки са визуализиране на всички съвпадения на съединените точки.

Междутипови декларации[редактиране | редактиране на кода]

Междутиповите декларации предоставят начин за изразяване на влиянието на напречно вкараната функционалност (cross-cutting concerns) върху структурата на модулите. Познати и като отворени класове (open classes) с разширяващи методи (extension methods), те позволяват на програмистите на декларират на едно място всички членове или родителя на друг клас, обикновено с идеята да се комбинира целият код свързан с функционалността (concern) на един аспект. Например, ако програмист имплементира напречната функционалност display-update използвайки „посетители“, междутиповата декларация използваща дизайнерския шаблон „Посетител“ може да изглежда така в AspectJ:

  aspect DisplayUpdate {
    void Point.acceptVisitor(Visitor v) {
      v.visit(this);
    }
    // друг код...
  }

Този код добавя метода acceptVisitor към Point класа.

Изисква се всички структурни добавки да бъдат съвместими с оригиналния клас, така че клиентите на съществуващия клас да продължат да работят, освен ако аспектно-ориентираната имплементация може да очаква да контролира всички клиенти непрекъснато.

Имплементация[редактиране | редактиране на кода]

Аспектно-ориентираните програми могат да влияят на други програми по два различни начина в зависимост от езика и средата, на които са написани:

  1. създава се комбинирана програма, която е валидна на оригиналния език и за интерпретатора е точно като обикновена програма;
  2. интерпретаторът или средата се обновяват, за да разбират и да позволяват имплементирането на аспектно-ориентирани функции.

Трудността да се смени средата води до това повечето имплементации да създават съвместими комбинирани програми (начин 1). Това става чрез процеса уийвинг (weaving; на английски: weave – тъка, плета) – специален случай на програмна трансформация (program transformation). Аспектен уийвър (aspect weaver) чете аспектно-ориентирания код и генерира подходящ обектно-ориентиран код с добавените аспекти. Същият аспектно-ориентиран език може да се имплементира по различни уийвинг методи, така че семантиката на езика никога да не се разбира по отношение на уийвинг имплементацията. Само скоростта на имплементиране и лекотата на настройване и пускане в употреба (ease of deployment) се влияят от това кой метод е избран.

Системите могат да имплементират уийвинг на ниво сорс код (source-level weaving) като използват препроцесори (както С++ беше имплементиран оригинално в CFront), които изискват достъп до програмните файлове сърържащи кода. Въпреки това добре дефинираната бинарна форма на Java (Java's binary form) позволява на байткод уийвъри (bytecode weavers) да работят с всяка Java програма в .class формат. Байткод уийвърите могат да бъдат вкарани в употреба по време на компилация или, ако уийв моделът (weave model) е покласов, по време на зареждане на класовете. AspectJ започна да предлага уийвинг на ниво сорс код през 2001, покласов байткод уийвър през 2002 и поддръжка за развит уийвинг по време на зареждане след интеграцията на AspectWerkz през 2005.

Всяко решение, което комбинира програми по време на изпълнение (runtime) трябва да предоставя изгледи (views), които да разделят програмите правилно, така че да се запази модела на програмиста. Поддръжката на байткодът (bytecode) на Java за различни сорс код файлове позволява на всеки дебъгер (debugger) да обходи един правилно уийвнат (properly woven) .class файл в сорс код редактор. Въпреки това някои търд-парти декомпилатори (third-party decompilers) не могат да обработят уийвнат код, защото очакват код направен от Javac (компилаторът на Java), вместо всичките поддържани байткод формати (виж секция "Критика").

Уийвингът по време на пускане в употреба/настройване (deploy-time weaving) предлага друг подход.[7] Това предполага постпроцесиране, но вместо да се обновява генерирания код, този уийвинг подход създава подкласове (subclasses), за да добави промените чрез презаписване на методи (method-overriding). Вече съществуващите класове остават непроменени, дори по време на изпълнение. Така всички съществуващи инструменти (дебъгери, профилатори и др.) могат да бъдат използвани по време на разработка. Подобен подход вече се е доказал в имплементацията на много Java EE сървъри, като например WebSphere на IBM.

Терминология[редактиране | редактиране на кода]

Стардартната терминология в Аспектно-ориентираното програмиране включва:

Напречно вкарана функционалност (Cross-cutting concerns)
Въпреки че повечето класове в един обектно-ориентиран модел изпълняват една определена функция, те често споделят вторична функционалност с други класове. Например, може да искаме да добавим логване (logging) в класове от слоя за достъпване на данни или в класове от слоя за потребителския интерфейс, когато някоя нишка влезе или излезе от някой метод. Освен това, напречно вкараната функционалност може да е свързана със сигурността - например с контрол на достъпа (access control [8]) или контрол на потока от информация (information flow control [9]). Макар всеки клас да има различна функционалност, кодът, нужен за изпълнение на вторичната функционалност, често е идентичен.
Адвайс (Advice)
Това е парче допълнителен код, което искаме да добавим към много на брой различни методи. В примера, това е кодът за логване, който искаме да изпълняваме, когато някоя нишка влезе или излезе от метод.
Съединена точка (Join point)
Това е точката на пресичане на компонент и аспект. Тази точка от изпълнението на програмата позволява вмъкването на аспектна логика (на адвайс). Например, ако искаме да изпълняваме определено парче код (адвайс) всеки път, когато изпълнението достигне определена точка съединена точка). Примери за такава точка са: извикване на метод, "хвърляне" на ексепшън, достъпване на променлива.
Пойнткът (Pointcut)
Това е терминът даден на точка от изпълнението на приложението, в която трябва да се приложи напречно вкарана функционалност (cross-cutting concern). В примера, пойнткът е достигнат, когато нишка влезе в метод, и още веднъж, когато нишка излезе от метод. Накратко, пойнткът е група от съединени точки, асоциирана с определен адвайс.
Аспект (Aspect)
Комбинацията от пойнткът и адвайс се нарича аспект. В горния пример добавяме аспект за логване към нашето приложение като дефинираме пойнткът и слагаме правилния адвайс.
Уийвинг (Weaving)
Процесът на "инжектиране" на адвайси в кода на програмата чрез генериране на обектно-ориентиран код от аспектно-ориентиран код.
По време на изпълнението на програмата, когато се достигне до съединени точка от някой пойнткът се изпълнява определен адвайс, асоцииран с този пойнткът. Всеки адвайс може да е свързан с един или повече пойнткъти.

Сравнение с други парадигми на програмиране[редактиране | редактиране на кода]

Аспектите водят началото си от обектно-ориентираното програмиране и изчислителната рефлексия . АОП езиците имат функционалност подобна на мета-обект протоколите, но по-ограничена. Аспектите са тясно свързани с програмни концепции като субекти (на английски: subjects), миксини (на английски: mixins) и делегиране (на английски: delegation). Други начини за използване на аспектно-ориентирани парадигми за програмиране включват модела на Композиционни Филтри, както и Хиперслайсес-подходът (на английски: hyperslices). Още поне от 70-те години, разработчиците използват форми на прихващане и изпращане(на английски: interception and dispatch-patching), приличащи на някои от имплементационните методи за АОП, но тези методи никога не са имали написана на едно място семантиката, която осигурява кроскътинга (на английски: crosscutting), т.е. не са достигнали нивото на днешната програмна парадигма АОП.

Дизайнерите са разглеждали различни алтернативи за постигане на разделение на кода, като частичните типове [10] в C#, но при подобни подходи липсва механизъм за количествено определяне, който позволява достигането на няколко съединени точки (на английски: join point) на кода с едно декларативно изявление.

Макар на пръв поглед да не изглежда така, в тестването употребата на мокове или стъбове (на английски: mocks or stubs)[11] изисква употребата на АОП техники. За целите на тестването, сътрудничещите си обекти представляват кроскътинг дял (на английски: crosscutting concern). По този начин различните Mock-обектни рамки осигуряват тези функции.

Проблеми с усвояването[редактиране | редактиране на кода]

За програмистите е важно да умеят да четат програмен код и да го разбират, за да могат да предотвратяват грешки.[12] Дори с добро образование, разбирането на кроскътинг дяловете може да се окаже трудно без подходящо визуализиране - както на статичната структура, така и на динамичния поток на програмата. През 2002 г. AspectJ започва да предоставя IDE плъгини за поддръжка на визуализирането на кроскътинг дялове. Подобни функционалности вече са често срещани. Предвид силата на АОП, ако един програмист направи логическа грешка при кроскътинг-израз, това може да доведе до голям бъг в програмата. В същото време, друг програмист може да промени дадени съединени точки в една програма – например чрез преместване или преименуване на методи – по начин, който авторът на аспекта не е очаквал и това да има непредвидени последствия. Едно от предимствата на промяната на кроскътинг дялове е възможността един програмист лесно да влияе на цялата система. В резултат на това подобни проблеми представляват конфликт на отговорността за дадена грешка между двама или повече разработчици. Въпреки това, решението на тези проблеми би могло да е много по-лесно при наличието на АОП, тъй като само аспектът трябва да се промени, докато същите проблеми без АОП, могат да бъдат много по-сериозни.

Критика[редактиране | редактиране на кода]

Въпреки безспорните си положителни страни, АОП среща и известни критики. На първо място, аспектно-ориентираното програмиране е патентовано,[13] съответно не е безплатно за имплементация. Най-съществената критика срещу ефекта на АОП е, че цикълът е неясен, и е не само по-лош от “GOTO” оператора, но е и почти аналогичен на COMEFROM - създадения първоначално като шега оператор. За пример е дадено сравнение на COME FROM програма:

5 input x
10 print 'result is :'
15 print x

20 come from 10
25      x = x * x
30 return

с фрагмент от АОП с аналогична семантика:

main() {
    input x
    print(result(x))
}
input result(int x) { return x }
around(int x): call(result(int)) && args(x) {
    int temp = proceed(x)
//    return temp * temp
}

Всъщност, един пойнткът (на английски: pointcut) може да зависи от времето за изпълнение и това да го прави нестатично детерминиран. Това обстоятелство може да бъде смекчено, но не и преодоляно чрез статичен анализ и IDE (Интегрирана среда за разработка) поддръжка, показваща кои адвайси (на английски: advices - съвети - отнася се за допълнително добавено поведение към съществуващ код) биха съвпаднали. Сред общите критики е и мнението, че претенциите на АОП да подобрява „както модулността (на английски: modularity), така и структурата на кода“ са неоснователни. Според критиците, вместо това АОП подкопава тези цели и пречи на „независимата разработка и разбираемост на програмите“. По-конкретно, количественото определяне чрез пойнткъти е в разрез с модулността: по принцип, човек трябва да познава цялата програма, за да разсъждава върху динамичното изпълнение на аспектно-ориентирана програма. Освен това, докато целите на АОП (модулиране на кроскътинг дялове) са разбираеми, неговата дефиниция е неясна и трудно се отличава от други, вече установени техники. Всъщност, аспектите могат да се прилагат към себе си, което ще доведе до проблеми като парадокса на лъжеца. Технически насочените критики пък посочват количественото определяне на пойнткъти (дефиниране на мястото на изпълнение на адвайсите) като „изключително чувствително към промени в програмата“ – проблем известен още като “fragile pointcut problem” (на английски: „проблем на чупливите пойнткъти“). Проблемите с пойнткъти се считат за неразрешими - ако заменим количественото им определяне с експлицитни анотации, ще получим атрибутно-ориентирано програмиране (на английски: Attribute-oriented programming), което пък среща същите проблеми, за чието решение е създадено АОП.

Приложения[редактиране | редактиране на кода]

Следните езици за програмиране имат приложено АОП в самия език или като външна библиотекаː

Вижте също[редактиране | редактиране на кода]


Бележки и препратки[редактиране | редактиране на кода]

  1. Aspect-oriented programming. // European Conference on Object-Oriented Programming. Т. 1241. 1997, 220–242 с. DOI:10.1007/BFb0053381.
  2. "Adaptive Object Oriented Programming: The Demeter Approach with Propagation Patterns" Karl Liebherr 1996 ISBN 0-534-94602-X presents a well-worked version of essentially the same thing (Lieberherr subsequently recognized this and reframed his approach).
  3. Essential.NET: The common language runtime. Addison-Wesley Professional, 4 November 2002. ISBN 978-0-201-73411-9. с. 206. Посетен на 4 October 2011.
  4. Mastering Enterprise JavaBeans. John Wiley and Sons, 1 January 2005. ISBN 978-0-7645-8492-3. с. 285. Посетен на 4 October 2011.
  5. Бележка: Примерите в тази статия са със синтаксис подобен на Джава.
  6. Eмакс документация
  7. http://www.forum2.org/tal/AspectJ2EE.pdf
  8. B. De Win, B. Vanhaute and B. De Decker. Security through aspect-oriented programming. In Advances in Network and Distributed Systems Security 2002.
  9. T. Pasquier, J. Bacon and B. Shand. FlowR: Aspect Oriented Programming for Information Flow Control in Ruby. In ACM Proceedings of the 13th international conference on Modularity (Aspect Oriented Software Development) 2014.
  10. partial (Type) (C# Reference)
  11. Mocks and stubs[1]
  12. Edsger Dijkstra, Notes on Structured Programming, pg. 1-2
  13. Щатски патент 6 467 086 , link
  14. Многобройни: Afterthought, LOOM.NET, Enterprise Library 3.0 Policy Injection Application Block, AspectDNG, DynamicProxy, Compose*, Seasar.NET, DotSpect (.SPECT), Spring.NET (като част от функционалността му), Wicca and Phx.Morph
  15. ActionScript[2]
  16. Ada2012 Rationale
  17. Function Hooks
  18. Различни: AspectC++, FeatureC++, AspectC, AspeCt-oriented C, Aspicere
  19. Cobble
  20. ColdSpring
  21. Closer Project: AspectL.. // Посетен на 11 August 2015.
  22. infra - Frameworks Integrados para Delphi - Google Project Hosting. // Посетен на 11 August 2015.
  23. meaop - MeSDK: MeObjects, MeRTTI, MeAOP - Delphi AOP(Aspect Oriented Programming), MeRemote, MeService... - Google Project Hosting. // Посетен на 11 August 2015.
  24. Google Project Hosting. // Посетен на 11 August 2015.
  25. Emacs Advice Functions
  26. monad (functional programming) (Monads As a theoretical basis for AOP, CiteSeerX: 10.1.1.25.8262) and Aspect-oriented programming with type classes. A Typed Monadic Embedding of Aspects
  27. Многобройни: CaesarJ, Compose*, Dynaop, JAC, Google Guice (като част от функционалността му), Javassist, JAsCo (and AWED), JAML, JBoss AOP, LogicAJ, Object Teams, PROSE, The AspectBench Compiler for AspectJ (abc), Spring framework (as part of its functionality), Seasar, The JMangler Project, InjectJ, GluonJ, Steamloom
  28. Многобройни: Advisable, Ajaxpect, jQuery AOP Plugin, Aspectes, AspectJS, Cerny.js, Dojo Toolkit, Humax Web Framework, Joose, Prototype - Prototype Function#wrap, YUI 3 (Y.Do)
  29. Using built-in support for categories (which allows the encapsulation of aspect code) and event-driven programming (which allows the definition of before and after event handlers).
  30. AspectLua. // Посетен на 11 August 2015.
  31. MAKAO, re(verse)-engineering build systems. // Посетен на 11 August 2015.
  32. McLab. // Посетен на 11 August 2015.
  33. AspectML - Aspect-oriented Functional Programming Language Research. // Посетен на 11 August 2015.
  34. Adam Kennedy. Aspect - Aspect-Oriented Programming (AOP) for Perl - metacpan.org. // Посетен на 11 August 2015.
  35. Многобройни: PHP-AOP (AOP.io), Go! AOP framework, PHPaspect, Seasar.PHP, PHP-AOP, TYPO3 Flow, AOP PECL Extension
  36. "Whirl"
  37. Многобройни: PEAK, Aspyct AOP, Lightweight Python AOP, Logilab's aspect module, Pythius, Spring Python's AOP module, Pytilities' AOP module, aspectlib
  38. PLaneT Package Repository : PLaneT > dutchyn > aspectscheme.plt. // Посетен на 11 August 2015.
  39. AspectR README. // Посетен на 11 August 2015.
  40. AspectR - Simple aspect-oriented programming in Ruby. // Посетен на 11 August 2015.
  41. Dean Wampler. Home. // Посетен на 11 August 2015.
  42. gcao/aspector. // GitHub. Посетен на 11 August 2015.
  43. AspectS
  44. MetaclassTalk: Reflection and Meta-Programming in Smalltalk. // Посетен на 11 August 2015.
  45. WEAVR
  46. aspectxml - An Aspect-Oriented XML Weaving Engine (AXLE) - Google Project Hosting. // Посетен на 11 August 2015.
Криейтив Комънс - Признание - Споделяне на споделеното Лиценз за свободна документация на ГНУ Тази страница частично или изцяло представлява превод на страницата „Aspect-oriented programming“ в Уикипедия на английски. Оригиналният текст, както и този превод, са защитени от Лиценза „Криейтив Комънс - Признание - Споделяне на споделеното“, а за съдържание, създадено преди юни 2009 година — от Лиценза за свободна документация на ГНУ. Прегледайте историята на редакциите на оригиналната страница, както и на преводната страница. Вижте източниците на оригиналната статия, състоянието ѝ при превода, и списъка на съавторите.