Aspectgeoriënteerd programmerenAspectgeoriënteerd programmeren (AOP, of Aspect Oriented Development, AOD) is een uitbreiding op de bekende manieren van programmeren, waarbij het mogelijk wordt om een stuk code A "in te lassen" in een ander stuk code B zonder dat B een zichtbare verwijzing heeft naar A. Hoewel deze uitbreiding toegepast kan worden op alle bekende vormen (paradigma's of paradigmata) van programmeertalen, past het concept qua structuur het beste bij het objectgeoriënteerde paradigma. Het is belangrijk op te merken dat aspectgeoriënteerd programmeren niet een paradigma is dat andere paradigmata vervangt. AOP is bedoeld als een strikte uitbreiding op bestaande programmeertechnieken. OverzichtAspectoriëntatie is bedoeld als antwoord op een probleem waar alle "klassieke" paradigma's mee kampen, namelijk de vraag hoe om te gaan met de zogeheten crosscutting concerns: handelingen die door het hele programma heen uitgevoerd moeten worden. Typische voorbeelden hiervan zijn logging en beveiliging: op vrijwel ieder punt in een gemiddeld programma bestaat de behoefte aan de mogelijkheid om zaken naar een log weg te schrijven om fouten te traceren en zeer veel programma's moeten op verschillende punten controleren of de gebruiker van het programma wel gerechtigd is om de opgevraagde handeling uit te voeren. De "klassieke" paradigma's hebben hiervoor geen makkelijke oplossing en vallen daarom terug op het meerdere malen opnemen van precies dezelfde code op iedere plaats waar dezelfde handeling uitgevoerd wordt. Met als resultaat dat een verandering aan de uitvoering van een dergelijk crosscutting concern betekent dat door het hele programma heen code moet worden aangepast. Als oplossing hiervoor biedt AOD (Aspect Oriented Development) de mogelijkheid een stukje code te schrijven dat op een groot aantal, door de programmeur te definiëren punten, ingevoegd wordt. Dit invoegen gebeurt zonder dat de geschreven code waarin ingevoegd wordt, aangepast wordt op de invoeging (dat er op een gegeven plaats iets ingevoegd wordt, kan men dus niet zien aan de programmacode). Om dit voor elkaar te krijgen, geeft de programmeur extern aan de programmacode een aantal punten op waarin bepaalde code ingevoegd dient te worden. Een apart programma neemt de code van de programmeur en zijn aanwijzingen over invoegen en stelt daarmee een nieuw programma samen waarin de juiste code op de juiste plaats ingevoegd is. Er zijn in principe twee tijdstippen waarop het weven (het samenvoegen van code) kan plaatsvinden: tijdens de compilatie van code naar programma (dit wordt statisch weven genoemd) en tijdens het uitvoeren van het gecompileerde programma (dynamisch weven). In het eerste geval leeft de AOD-uitbreiding op de bestaande techniek in de compiler, in het tweede geval wordt de uitbreiding extern aangebracht via een preprocessor. GeschiedenisOm aspectoriëntatie mogelijk te maken, moet men beschikken over een aantal verschillende concepten (die verderop behandeld zullen worden). Deze concepten zijn allemaal los van elkaar ontwikkeld en bestudeerd vanaf de jaren 1980. De samenvoeging van deze concepten tot "aspectgeoriënteerd programmeren" gebeurde waarschijnlijk voor het eerst midden jaren 1990 aan het Xerox PARC. Uit die hoek komt ook de term aspect, voor het eerst gehoord in 1996. Vanuit het PARC komt ook AspectJ (een project van Gregor Kiczales), een van de bekendste programmeertalen (een uitbreiding op Java) waarin statisch weven verwerkt zit. Sinds het jaar 2000 heeft AOD een grotere bekendheid gekregen, mede door het opnemen van AspectJ in de opensourcegemeenschap als onderdeel van Eclipse. Sinds 2003 is het echt 'hot' en wordt AOD op meerdere manieren geïmplementeerd, bijvoorbeeld als onderdeel van het Spring-framework door middel van dynamisch weven. De werkingTerminologieDe introductie van aspectoriëntatie brengt zijn eigen terminologie met zich mee. Hoewel er nog niet echt "vaste regels" zijn, worden de volgende termen wel vrij algemeen gebruikt in de literatuur aangaande AOD:
Invoegpunten en puntsnede-selectieZoals elders opgemerkt, werkt aspectoriëntatie door het invoegen van stukken code (adviezen) in andere stukken code. De plaatsen waar adviezen ingevoegd kunnen worden, worden invoegpunten genoemd. In principe is er een invoegpunt direct voor en direct na ieder statement in een gegeven programma: : {invoegpunt 0} statement_0; {invoegpunt 1} statement_1; {invoegpunt 2} : Formalisten zullen opmerken dat de locaties van invoegpunten overeenkomen met de plaatsen waar in een Hoare triple de asserties staan. Dit is uiteraard geheel niet toevallig; de assertie in het Hoare triple geeft de toestand van een programma weer tussen statements en komt dus overeen met de plaats waar een voorgaand statement geheel afgehandeld is. Vanaf dat punt kan het volgende statement beginnen en dat is dus ook precies het punt waar een alternatief statement tussengevoegd kan worden. Het is wel van belang om op te merken dat invoegpunten aangeduid worden in termen van het statement waar ze bij staan en niet in termen van asserties in de Hoarelogica; in het voorgaande voorbeeld is de aanduiding van invoegpunt 0 dus "het invoegpunt voor statement_0" en van invoegpunt 2 "het invoegpunt na statement_1". Het zal duidelijk zijn dat het aantal invoegpunten in een gegeven programma erg groot is: het aantal statements plus 1 (en het aantal statements in een klein programma is al gauw 10.000). Als er een advies is dat op meerdere invoegpunten ingevoegd moet worden, is het al gauw ondoenlijk om dat voor ieder invoegpunt individueel op te geven. Om die reden is het concept van een puntsnede ingevoerd: een verzameling van invoegpunten die allemaal tegelijk van een advies kunnen worden voorzien. Puntsneden zelf kunnen gedefinieerd worden met een opsomming van invoegpunten, maar dat is meestal om dezelfde reden ondoenlijk. Daarom voorziet ieder AOD-systeem in een manier om snel hele verzamelingen invoegpunten aan te duiden (dit wordt meestal filteren genoemd). Daarbij wordt meestal gekeken naar een aantal typische soorten invoegpunten die vaak interessant gevonden worden – bijvoorbeeld bepaalde methode-aanroepen of alle statements die een bepaalde variabele van waarde laten veranderen. Het is bijvoorbeeld gemeengoed in alle AOD-systemen om een puntsnede te definiëren die bestaat uit "alle invoegpunten voor aanroepen van alle methoden wier namen met set beginnen". Dergelijke selecties kunnen heel uitgebreid worden: "alle methoden die beginnen met setA, maar alleen in klassen wier naam zelf begint met Security of Timing maar niet als die klasse overerft van klasse Simpel of als de methode aangeroepen wordt vanuit methode moeilijk()" bijvoorbeeld. De meeste AOD-systemen implementeren dergelijke filtratie-systemen met behulp van reguliere expressies. Overigens wordt de selectie meestal gesplitst: een puntsnede wordt gedefinieerd in termen van statements, daarna wordt gezegd dat het advies ingevoegd moet worden voor al die statements. Het aanduiden van statements wordt namelijk makkelijker gevonden dan het aanduiden van de plaatsen tussen statements. Als eenmaal een puntsnede gedefinieerd is, kan aan die puntsnede een advies worden toegekend. Dat advies wordt dan ingevoegd op alle invoegpunten in de puntsnede. Merk daarbij op dat het meestal niet verboden is dat een invoegpunt in meerdere puntsneden is opgenomen, of dat aan een puntsnede meerdere adviezen worden toegekend. Het is dan ook vaak nodig zorgvuldig op te passen dat de uiteindelijke volgorde van het uitvoeren van alle adviezen goed is (of ten minste om ervoor te zorgen dat individuele adviezen elkaar niet beïnvloeden). Een bijzondere toepassing van AOD is om de definities van klassen en dergelijke in een werkend programma aan te passen. Dit is een toepassing waarbij niet alleen enkele, losse statements ingevoegd worden bij een invoegpunt, maar waarbij extra variabelen of zelfs hele extra methodes ingevoegd worden. Deze toepassing van AOP wordt doorgaans een introductie genoemd. Het wevenNadat vastligt welke invoegpunten interessant zijn (door gebruik van puntsneden) en welke adviezen erin ingevoegd moeten worden, volgt de toepassing van een weefproces om "normale" code en adviezen samen te voegen tot een werkend programma. Voor dit weven bestaan verschillende modellen die destijds opgesomd zijn door Gregor Kiczales en zijn team:
De eerste drie varianten zijn vormen van statisch weven, waarbij de weving uitgevoerd wordt als het programma vertaald en samengesteld wordt tot uitvoerbare code. De eindgebruiker merkt niets van het weven. Deze methode van weven levert over het algemeen een generieker systeem op, omdat fijnmazige weving (bijvoorbeeld op alle statements die een variabele aanpassen) moeilijker door te voeren is en veel tijd kost. Om die reden wordt dergelijke weving het liefst uitgevoerd op een moment dat de eindgebruiker het niet merkt. De eerste methode lijkt op het macromechanisme van de programmeertaal C en past de leesbare broncode aan. Om die reden zijn er groepen die vinden dat deze methode niet "echt AOD" is. De laatste twee methoden zijn vormen van dynamisch weven, waarbij het weven plaatsvindt als de eindgebruiker het programma gebruikt. Het nadeel van deze methode is dat het opstarten of uitvoeren van het programma langzamer wordt. Om die reden voorzien dynamische weefsystemen vaak alleen in invoegpunten waarvan maar een beperkt aantal aanwezig is en die ook nog makkelijke aanpassingen aan het programma opleveren: rond de aanroep van een methode bijvoorbeeld. Daarbij komt ook nog eens dat de meeste dynamische methoden een aangepaste omgeving vereisen; in het geval van Java een aparte JVM bijvoorbeeld om de vierde methode toe te kunnen passen. Het grote voordeel is echter dat de weving aangepast kan worden zonder het hele programma opnieuw te hoeven compileren. De laatste paar jaren is er echter nog een methode in opkomst, bedacht door Cohen en Gil, een soort variant van de vijfde methode, die goed werkt op populaire systemen als de JVM en de .NET-omgeving. Deze methode maakt gebruik van een dynamische proxyklasse, een kindklasse van een klasse waarin advies ingevoegd moet worden, die tijdens de uitvoering van het programma gegenereerd kan worden. De proxy beschikt uiteraard over dezelfde methoden als de klasse die van advies voorzien moet worden, door overerving. Advies bij de aanroep van de methoden kan echter als volgt ingevoegd worden:
Het resultaat is een soort combinatie van de vierde en vijfde methode. Het nadeel is dat er maar een gelimiteerde selectie van invoegpunten mogelijk is, omdat de bestaande code niet aangepast kan worden anders dan door overerving. Maar het is niet erg duur qua benodigde tijd en redelijk makkelijk in te passen in bestaande systemen. Het Spring Framework gebruikt deze methode bijvoorbeeld. ToepassingAspectoriëntatie kan worden toegepast om crosscutting concerns te implementeren in code zonder dezelfde code op meerdere plaatsen te moeten herhalen. Daarmee maakt AOP het mogelijk om de structurering van een programma te verbeteren en daarmee ook de onderhoudbaarheid ervan. Typische voorbeelden van dergelijke crosscutting concerns zijn logging, toegangscontrole, transactionaliteit en databasetoegang. Voor diverse objectgeoriënteerde programmeertalen zijn één of meerdere AOD-preprocessoren gebouwd:
AfwegingenAlhoewel AOD bepaalde voordelen heeft zijn er ook nadelen aan te wijzen. Of het in de toekomst een standaard feature van elke taal wordt valt derhalve nog af te wachten. Wellicht kunnen de problemen die het oplost straks op een andere manier aangepakt worden die de voorkeur geniet. Voordelen
Nadelen
Externe link
Bronnen, noten en/of referenties
|