Schon mal was von Aspektorientierung gehört? Nein? Kein Wunder, denn die aspektorientierte Programmierung führt ein ziemliches Schattendasein, obwohl sie in vielen Fällen äußerst praktisch sein kann. Besonders Aufgaben wie Profiling, Logging und Berechtigungen, die in rein objektorientiertem Code viel Aufwand machen würden, lassen sich aspektorientiert sehr elegant umsetzen.

Objektorientierung++

Glücklicherweise versucht die Aspektorientierung nicht das Rad komplett neu zu erfinden, sondern versteht sich eher als Erweiterung zur normalen Objektorientierung. Es gibt einige Probleme die mit der herkömmlichen Objektorientierung nicht trivial (ohne große Mengen an redundanten Code) lösbar sind, da es beispielsweise keine Möglichkeit gibt von außen in das Verhalten von Objekten einzugreifen. An dieser Stelle führt die aspektorientierte Programmierung das Konzept der Aspekte ein, die bestimmtes Verhalten in den gesamten Programmcode “einweben” können. Die Probleme die damit gelöst werden nennen sich Cross-Cutting Concerns, da sie sich über die gesamte Programmlogik erstrecken und nicht gekapselt werden können. Musterbeispiele für solche Cross-Cutting Concerns sind, wie bereits oben genannt Profiling, Logging oder Berechtigungen.
In der Aspektorientierung benutzt man Point-Cuts um alle Stellen im Programm zu definieren an denen bestimmte Aspekte umgesetzt werden müssen. Ein Aspekt wird in der Regel durch einen Funktionsaufruf realisiert, der an ganz bestimmten Point-Cuts aufgerufen wird. Diese Funktionen nennt man Advice. Um ein Advice aufzurufen, wird der Programmfluss an dem Point-Cut unterbrochen und alle Advices werden ausgeführt. Abschließend lässt man die Advices von einer Hilfsmethode (oder je nach Sprache von einem Compiler) an den von den Point-Cuts definierten Punkten einbinden. Dieser Vorgang nennt sich “Weaving”.

Profiler

Am besten lassen sich die Vorteile der aspektorientierten Programmierung an einem praktischen Beispiel zeigen. Unser Ziel ist es einen Profiler zu schreiben, der bei einem gegebenen Objekt die Laufzeiten aller Funktionsaufrufe misst und auf der Console ausgibt. Diesen Profiler wollen wir dann benutzen um das HTML5-Canvas zu profilen. Als Werkzeug verwende ich jQuery-AOP, eine Bibliothek die Hilfsfunktionen für die aspektorientierte Programmierung bietet.
Nach dem Einbinden von jQuery und jQuery-AOP, definieren wir zuerst einen Point-Cut und einen passenden Advice. Der Point-Cut “zeigt” auf alle Methoden des Objekts das wir überwachen wollen. Der Advice wird bei jedem Funktionsaufruf ausgeführt und führt die eigentliche Zeitmessung durch. Beim Weaving benutzen wir die Funktion around(), um festzulegen dass alle Funktionen in den Advice eingebettet werden sollen.

var ctx = document.getElementById("some-canvas").getContext("2d");
// Point-Cut definieren.
var pointCut = { target: ctx, method: /.*/ };
// Advice definieren.
var advice = function(invocation) { 
    var t1 = Date.now();
    var ret = invocation.proceed();
    console.log(invocation.method + ": "  + (Date.now() - t1) + " ms");
    return ret;
}
// Weave
jQuery.aop.around(pointCut,advice);
// Laufzeiten messen
ctx.fillStyle = "rgb(200,0,0)";             // fillRect: 1 ms
ctx.fillRect (10, 10, 55, 50);              // fillRect: 1 ms
ctx.beginPath();                            // beginPath: 1 ms
ctx.moveTo(30, 30);                         // moveTo: 2 ms
ctx.lineTo(150, 150);                       // lineTo: 0 ms
ctx.bezierCurveTo(60, 70, 60, 70, 70, 150); // bezierCurveTo: 1 ms
ctx.lineTo(30, 30);                         // lineTo: 0 ms
ctx.fill();                                 // fill: 0 ms