A számítástechnikában az aspektusorientált programozás (AOP) egy olyan programozási paradigma, amelynek célja a modularitás növelése azáltal, hogy lehetővé teszi a kereszthivatkozások szeparálását (SoC). Ez úgy történik, hogy kiegészítő viselkedést ad a meglévő kódhoz (advice), önmagában a kód módosítása nélkül, ehelyett külön megjelöli, hogy melyik kódot módosítják egy „pointcut” specifikációval, például „naplózza az összes függvényhívást, amikor a függvény neve »set«-tel kezdődik”. Ez lehetővé teszi az üzleti logika szempontjából a nem központi viselkedés (például naplózás) hozzáadását a programhoz a funkcionalitás alapját képező kód túlzsúfolása nélkül. Az AOP alapja az aspektusorientált szoftverfejlesztésnek.

Az AOP programozási módszereket és eszközöket tartalmaz, amelyek támogatják a vonatkozások modulációját a forráskód szintjén, míg az "aspektusorientált szoftverfejlesztés" egy teljes mérnöki tudományágat jelent.

Az aspektusorientált programozás magában foglalja a program logikájának különálló részekre bontását (úgynevezett vonatkozások, koherens funkcionális területek). Szinte az összes programozási paradigma támogatja a vonatkozások bizonyos szintű csoportosítását és beágyazását különálló, független entitásokba absztrakciók (például függvények, eljárások, modulok, osztályok, metódusok) biztosításával, amelyek felhasználhatók ezeknek a vonatkozásoknak az implementálására, absztrakciójára és összeállítására. Néhány vonatkozás „átvág” számos absztrakción egy programon belül, és meghiúsítja a végrehajtás ezen formáit. Ezeket a vonatkozásokat cross-cutting (keresztülvágó) vagy horizontális vonatkozásoknak (vagy szimplán kereszthivatkozás) nevezik.

A naplózás egy kereszthivatkozási problémát szemléltet, mivel a naplózási stratégia szükségszerűen érinti a rendszer minden naplózott részét. A naplózás ezzel keresztezi az összes naplózott osztályt és metódust.

Minden AOP implementációnak vannak olyan átfogó kifejezései, amelyek mindegyik vonatkozást egységbe zárják. Az implementációk közötti különbség a biztosított konstrukciók erejében, biztonságában és használhatóságában rejlik. Például az olyan megszakítók, amelyek meghatározzák a keresztmetszet korlátozott formájának kifejezésére szolgáló metódusokat, a típusbiztonság vagy a hibakeresés támogatása nélkül. Az AspectJ-nek számos ilyen kifejezése van, melyeket beilleszthet egy speciális osztályba, egy aspektusba. Például egy aspektus megváltoztathatja az alapkód viselkedését (a program nem aspektusú részét), ha tanácsot (kiegészítő viselkedést) alkalmaz a különféle csatlakozási pontokban (a program pontjai), amelyeket egy mennyiségi meghatározás, vagy lekérdezés határoz meg, melyet pointcutnak nevezünk (amely észleli, hogy egy adott csatlakozási pont megegyezik-e). Egy aspektus binárisan kompatibilis szerkezeti változtatásokat is végrehajthat más osztályokban, például tagok vagy szülők hozzáadásával.

Története Az AOP-nak számos közvetlen előzménye van, A1 és A2: reflexiós és metaobjektum protokollok, tárgyorientált programozás, Kompozíciós Szűrők és Adaptív Programozás."Adaptive Object Oriented Programming: The Demeter Approach with Propagation Patterns" Karl Liebherr 1996 presents a well-worked version of essentially the same thing (Lieberherr subsequently recognized this and reframed his approach).

Gregor Kiczales és a Xerox PARC kollégái kifejlesztették az AOP kifejezett fogalmát, majd ezt követték az AspectJ AOP Java kiterjesztésével. Az IBM kutatócsoportja egy eszközi megközelítést alkalmazott a nyelvi tervezési megközelítés felett, és 2001-ben javaslatot tett a Hyper/J és a Concern Manipulation Environment környezetre, amelyek még nem voltak széles körben elterjedtek.

A cikk példái az AspectJ-t használják.

A Microsoft Transaction Server kiszolgálót tekintik az AOP első nagyobb alkalmazásának, amelyet az Enterprise JavaBeans követett.

Motiváció és alapkoncepciók Általában egy aspektus szét van szórva vagy összekeveredve, ami megnehezíti a kód kezelhetőségét és megértését. Ez abban valósul meg, hogy egy függvényt (például naplózás), több független függvény használhat, teljesen független rendszerekben, különböző forrásnyelvekben. Ez azt jelenti, hogy a naplózás megváltoztatásához szükség lehet az összes érintett modul módosítására. Ezek a szempontok nem csak azon a rendszereknek a fő funkciójában keveredhetnek össze, amelyekben kifejeződnek, hanem akár egymással is. Ezért, az egyik kereszthivatkozás megváltoztatása hatással lehet a többi funkcióra.

Például, vegyünk egy banki alkalmazást, egy nagyon egyszerű koncepcióval, ami az egyik számláról a másikra utal összeget:Note: The examples in this article appear in a syntax that resembles that of the Java language. void transfer(Account fromAcc, Account toAcc, int amount) throws Exception { if (fromAcc.getBalance() < amount) throw new InsufficientFundsException();

fromAcc.withdraw(amount); toAcc.deposit(amount); } Ez az átviteli módszer azonban figyelmen kívül hagyja azokat a bizonyos szempontokat, amelyeket egy telepített alkalmazás igényelne: hiányzik a biztonsági ellenőrzés, annak ellenőrzésére, hogy a jelenlegi felhasználó rendelkezik-e engedéllyel e művelet végrehajtásához; egy adatbázis-tranzakciónak be kell építenie a műveletet a véletlen adatvesztés elkerülése érdekében; a diagnosztika érdekében a műveletet be kell jegyezni a rendszernaplóba.

A példa kedvéért egy verzió, amely ezeket az új vonatkozásokat implementálja így nézhet ki: 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."); } Ebben a példában egyéb érdekek keveredtek össze az alapvető funkcionalitással (néha üzleti logikai vonatkozásnak nevezik). A tranzakciók, a biztonság és a naplózás mind a kereszthivatkozásokat szemléltetik.

Most fontoljuk meg, mi történik, ha hirtelen meg kell változtatnunk (például) az alkalmazás biztonsági szempontjait. A program aktuális verziójában a biztonsággal kapcsolatos műveletek több metóduson keresztül lettek létrehozva, egy ilyen változtatás komoly erőfeszítéseket igényelne.

Az AOP megpróbálja ezt a problémát megoldani azáltal, hogy lehetővé teszi a programozónak, hogy kifejezze ezeket a kereszthivatkozásokat önálló modulokban, úgynevezett aspektusokban (szempontokban). A szempontok tartalmazhatnak adviceokat (a program meghatározott pontjaihoz csatolt kódot) és típusközi deklarációkat (strukturális tagok hozzáadva más osztályokhoz). A biztonsági modul például tartalmazhat olyan adviceokat, amelyek biztonsági ellenőrzést hajtanak végre a bankszámla elérése előtt. A pointcut meghatározza azokat az időpontokat (csatlakozási pontok), amikor egy bankszámlához hozzáférhetünk, és az advice törzsében szereplő kód határozza meg a biztonsági ellenőrzés végrehajtásának implementációját. Így mind az ellenőrzés, mind a területek egy részen kezelhetők. Ezenkívül egy jó pointcut előrejelzi a program későbbi változásait, tehát ha egy másik fejlesztő új metódust hoz létre a bankszámla eléréséhez, az advice az új módszerre vonatkozik annak végrehajtásakor.

A fentebb említettek példájára egy naplózás megvalósítása egy aspektusban: 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.");

// Other crosscutting code. } Az AOP kapcsán gondolhatunk egy hibakeresési eszközre, vagy akár egy felhasználói szintű kellékre. Az advicet tartalékolhatjuk azokra az esetekre, amikor nem sikerül egy funkciót megváltoztatni (felhasználói szint), vagy pedig nem akarjuk megváltoztatni a függvényt az élesen futó alkalmazásban (hibakezelés)

Csatlakozási pontok modellje Az aspektusorientált nyelv tanáccsal kapcsolatos komponense meghatározza a csatlakozási pontot (JPM). A JPM három dolgot határoz meg:

Mikor futhat az advice? Ezeket csatlakozási pontoknak nevezzük, mivel ezek egy futó program pontjai, ahol további viselkedés hasznos módon csatlakoztatható. A csatlakozási pontnak címezhetőnek és érthetőnek kell lennie egy átlagos programozó számára, hogy hasznos legyen. Valamint stabilnak kell, hogy maradjon a lényegtelen programváltozások között is, hogy egy aspektus is szintén stabil maradjon ilyen változások hatására. Számos AOP implementáció támogatja a metódus végrehajtását és a mező hivatkozásokat, referenciákat csatlakozási pontként. A csatlakozási pontok (pointcuts) meghatározásának (vagy számszerűsítésének) módja. A pointcut meghatározza, hogy egy adott csatlakozási pont megegyezik-e. A leghasznosabb pointcut nyelvek olyan szintaxist alkalmaznak, mint az alapnyelv ( például az AspectJ Java aláírásokat használ) és lehetővé teszik az újbóli felhasználást az elnevezés és a kombináció révén. A csatlakozási ponton futó kód megadásának eszköze. Az AspectJ meghívja ezt az advicet és futtathatja azt a csatlakozási pontok előtt, után és körül. Egyes implementációk támogatják egy metódus definiálását egy másik osztályban lévő aspektuson belül.

A csatlakozási pont modellek összehasonlíthatók meghatározásaik, valamint ezekben a pontokban engedélyezett műveleteik és a kifejezhető szerkezeti fejlesztéseik, és a kitett csatlakozási pontjaik alapján.

Az AspectJ csatlakozási pont modellje

Egyéb potenciális csatlakozási pont modellek Más típusú JPM is létezik. Az összes advice nyelv meghatározható a JPM alapján. Például az UML feltételezett nyelvén a következő JPM lehet:

A csatlakozási pontok mind a modell elemei. A pointcutok olyan logikai kifejezésekre vonatkoznak, amelyek a modell elemeit egyesítik. A befolyásolás eszköze ezeken a pontokon az összes illeszkedő csatlakozási pont megjelenítése.

Típusközi deklarációk A típusközi deklarációk lehetőséget adnak a modulok felépítését érintő kereszthivatkozások kifejezésére. Ezek más néven nyílt osztályok és kiterjesztési metódusok, amelyek lehetővé teszik a programozók számára, hogy egy helyen deklarálják egy másik osztály tagjait vagy szüleit, általában azért, hogy egy problémára vonatkozó kód egészét egy aspektusben összevonják. Például, ha egy programozó a visitor felhasználásával valósította meg a megjelenítés-frissítést, egy visitor (látogató) mintát használó típusú típusközi deklaráció az AspectJ-ben így nézhet ki: aspect DisplayUpdate { void Point.acceptVisitor(Visitor v) { v.visit(this);

// other crosscutting code... } Ez a kódrészlet hozzáadja az acceptVisitor metódust a Point osztályhoz.

Fontos követelmény, hogy minden strukturális kiegészítés kompatibilis legyen az eredeti osztállyal, hogy a meglévő osztály kliensei továbbra is működjenek, kivéve, ha az AOP megvalósítás azt várja el, hogy minden klienst folyamatosan ellenőrizzen.

Implementáció Az AOP programok kétféleképpen befolyásolhatják a többi programot, az alapul szolgáló nyelvektől és a környezettől függően:

Egy kombinált program készül, amely eredeti nyelven érvényes és megkülönbözhetetlen a hétköznapi programtól a végső interpreterig (fordító). A végső fordító vagy a környezet frissül az AOP funkciók megértéséhez és megvalósításához.