Laden...

Aspektorientierte Programmierung

Erstellt von Snowwolf3000 vor 18 Jahren Letzter Beitrag vor 16 Jahren 5.619 Views
Snowwolf3000 Themenstarter:in
140 Beiträge seit 2004
vor 18 Jahren
Aspektorientierte Programmierung

Hallo,
wollt mal fragen ob ihr schon Erfahrungen mit aspektorientierter Programmierung habt, obs jemand schon einsetzt (dann wahrscheinlich eher in Java als C#) usw.

Für alle die mit den Begriff noch nichts anfangen können: http://wwwse.fhs-hagenberg.ac.at/se/berufspraktika/2002/se99047/contents/german/aop.html oder unter Google gibt es jede Menge zu "AOP".

Versuchs aber mal kurz mit Hilfe eines Beispiels kurz zu erläutern:
In den heutigen Programmen gibt es einige Aspekte die sich den eigentlichen Gedanken der objektorientierten Progammierung wiedersetzen. Ziel ist ja möglichst alles in kleine, unabhängige Stücke zu zerlegen. Allerdings gibt es einige Aspekte bei denen das nicht vernünftig geht wie bei Logging, Validierung, Fehlerbehandlung usw. Man hat das praktisch in jeder Klasse (bzw. Methode) und das absolut redundant. Mithilfe der aspektorientierten Programmierung kann man das nun von den eigentlichen Code trennen.
Konkret sieht das folgendermaßen aus (idealisiert dargestellt):

Erstmal ohne AOP:


	public class TestObject
	{
		...
		public int MathFkt1(int a, int b)
		{
                      log.write("Starte MathFkt1");
                      return a+b;		
		}

		public int MathFkt2(int a, int b)
		{
                      log.write("Starte MathFkt2");
                      return a*b;		
		}
	}

Und so mit AOP:


	public class TestObject
	{
		...
		public int MathFkt1(int a, int b)
		{
                      return a+b;		
		}

		public int MathFkt2(int a, int b)
		{
                      return a*b;		
		}
	}

	public class LogAOP: Aspect
	{
        ...
		[IncludeMethods("TestObject", "MathFkt1")] //Zielfunktion
        [IncludeMethods("TestObject", "MathFkt2")] //Zielfunktion
		[Advice(AdviceTypes.Before)] //führe das aus bevor die Funktion aufgerufen wird			
        public void logFkt()
		{
			 log.write("Starte " + FktName);			
		}
    }

Die LogAOP Klasse merkt wenn die Funktion MathFkt1 oder 2 aufgerufen wird. In diesen Fall wird dann zuerst logFkt aufgerufen und erst dann die konkrete Funktion.

Das Ergebnis ist letzlich das Gleiche. Der Code ist aber kürzer(zumindest in der eigentlichen Klasse) und die Log-Funkton leicher wartbar, weil sie nur einmal vorkommt.

Hoffe das war jetzt halbwegs verständlich. Falls nicht fragt einfach nach. Könnt jetzt natürlich auch noch ein paar Links zu konkrekten Implementierungen posten, meine bisherige Erfahrungen damit usw. Allerdings hab ich jetzt schon viel mehr geschrieben als ich eigentlich wollte und ich bin mir nicht sicher ob das für euch intressant ist.

Gruß,
Snowwolf

4.506 Beiträge seit 2004
vor 18 Jahren

Hallo Snowwolf3000!

Also ich find das cool!

Ich muss auch Applikationen schreiben, in denen Logging groß geschrieben werden muss, da es sich um Windows-Services handelt, daher ist mir eine solche Verfahrensweise natürlich auf jeden Fall von Nutzen.

Ich werd das mal näher betrachten, doch konkret im Falle des Logging, dann sieht die Methode aus Deinem von Dir genannten Beispiel aber so aus:



...
        [IncludeMethods("TestObject", "MathFkt1")] //Zielfunktion
        [IncludeMethods("TestObject", "MathFkt2")] //Zielfunktion
        ...
        [IncludeMethods("TestObject", "MathFkt112")] //Zielfunktion
        [IncludeMethods("TestObject", "MathFkt113")] //Zielfunktion
        [Advice(AdviceTypes.Before)] //führe das aus bevor die Funktion aufgerufen
...

😉

Ciao
Norman-Timo

A: “Wie ist denn das Wetter bei euch?”
B: “Caps Lock.”
A: “Hä?”
B: “Na ja, Shift ohne Ende!”

S
8.746 Beiträge seit 2005
vor 18 Jahren

Hmmm, mich wundert nur die Art und Weise der Deklaration der Aspekte.

Hier wird ja nicht den Methoden oder Klassen selbst der Aspekt mitgegeben, sondern diese werden in speziellen Aspect-Klassen definiert. Das mindest den Vorteil der Kapselung doch wieder enorm. Was die Wartbarkeit angeht ebenso.

Da scheint mir Spring.NET besser.

Snowwolf3000 Themenstarter:in
140 Beiträge seit 2004
vor 18 Jahren

@norman_timo
Bisher hatten alle Implementierungen einen * Operator. Brauchst also nicht alle Funktionen angeben. 😉

@svenso
Also was ich der Einfachheit unterschlagen hab: Zumindest in der Implementierung die ich mir angeschaut habe, musste man der Zielklasse (hier: TestObject) auch noch die verwendeten Aspekte mit angeben.
Dadurch deine bedenken bezüglich Kapselung/Wartbarkeit beseitigt?

Ach ja und was ist eigentlich Spring.net?

S
8.746 Beiträge seit 2005
vor 18 Jahren

Original von Snowwolf3000

@svenso
Also was ich der Einfachheit unterschlagen hab: Zumindest in der Implementierung die ich mir angeschaut habe, musste man der Zielklasse (hier: TestObject) auch noch die verwendeten Aspekte mit angeben.
Dadurch deine bedenken bezüglich Kapselung/Wartbarkeit beseitigt?

Naja, nicht so ganz. Ich muss jeder Methoden den Aspekt (entspricht einer Klasse) angeben und dann in der Aspekt-Klasse nochmal die Methoden? Zugegebenermaßen mag dies ein Feature sein, da die Implementierung nicht merh Klassen-global sondern methdenspezifisch definiert wird. Im Normalfall möchte ich aber über einer Methode nur [Logging] sagen und gut ist. Aber vielleicht geht das ja auch und die explizite Angabe ist optional. Werd mir AOP.NET mal genauer ansehen. Fürs Tracing ist es genau das was ich immer gesucht hab.

*EDIT* Nochmal nachgeshaut: Spring.NET erfordert wohl auch die beidseitige Referenzierung, hier aber XML-Config-Files, was natürlich auch charmant ist.

Ach ja und was ist eigentlich Spring.net?

Das ist ein Architekturframework aus der Java-Welt, jetzt nach .NET portiert. Ist u.a. eine Lösung für sogenannte "Inversion of Control"-Container (für hochdynamisch konfigurierbare Systeme, sowas wie eine Super-Plugin-Technik). Bietet aber nebenbei auch AOP-Features und weitere schöne Funktionen.

P
939 Beiträge seit 2003
vor 18 Jahren

Inversion of Control (IoC) ist ein schöner Ansatz, nicht nur interessant im Zusammenhang mit einem speziellen Container oder Framework. Es ist auch ein einfaches Prinzip, das man beim Klassendesign im Hinterkopf haben sollte.

Prinzip: Eine Komponente A benötigt zur Funktion eine andere Komponente B. A holt oder instanziiert B jedoch nicht selbst, sondern bekommt die benötigte Kompoente von aussen in einer Eigenschaft gesetzt.

Vorteil: das Klassendesign wird modularer. Klassen/Komponenten bleiben unabhängig und können leichter wiederverwendet werden. Alles ist austauschbar. Wenn Interfaces verwendet werden, können sogar ganze, zugrundeliegende Technologien getauscht werden.

Und ganz wichtig, das Prinzip vermeidet die viel zu oft eingesetzten, unsäglichen Singletons und statischen Variablen.

Gruss
Pulpapex

S
8.746 Beiträge seit 2005
vor 18 Jahren

Ist das nicht eher Dependency Inversion? Wird zwar häufig mit IoC gleichgesetzt, aber DI ist m.E. eher ein Teilbereich der gesmten IoC.

Bei IoC geht ja auch die gesamte Ablaufsteuerung komplett an das Framework über.

Snowwolf3000 Themenstarter:in
140 Beiträge seit 2004
vor 18 Jahren

So will garnicht erst behaupten, dass ich das mit diesen Dependency Inversion wirklich verstanden hab. 🙂 Also erzähl ich mal kurz so wie ich denke das es ist und ihr sagt mir ob ich recht habe (eigentlich wollt ich ja über AOP reden aber egal):

Also ich erstell von einen Objekt verwendete Objekte nicht mehr direkt, sondern überlass den IoC-Object diese Arbeit. In Spring ist das nur eine XML-Datei.
Vorteil ist wenn ich nur gegen Interfaces programmiere (sonst funktioniert es doch nicht???), kann ich relativ leicht ein Objekt austauschen. Das gibt es ja schließlich in der XML nur einmal. Weiteren Vorteil seh ich jetzt nicht. Gibt es noch mehr?

Hab ich das jetzt richtig verstanden und falls ja verwendet ihr das auch produktiv?

S
8.746 Beiträge seit 2005
vor 18 Jahren

Die Bindung zwischen Modulen kann ja auch als Aspekt berachtet werden. Anstelle die Abhängigkeit in den Modulen selbst zu definieren (und aufzubauen) wird dies einer Dritt-Instanz überantwortet, die üblicherweise per XML konfiguriert wird (der Container). Alle Maßnahmen, die im Zuge der Bindung erfolgen müssen, werden von der Dritt-Komponente (inkl. Fehlerverhalten und Management) vorgenommen. Auch der Zeitpunkt der Bindung selbst wird nicht von der Anwendung sondern vom Container bestimmt (Steuerung).

IoC wäre demnäch die allgemeinere Form dieser Umkehrung der Steuerung, während DI sich auf den konkreten Fall der Bindung beschränkt.

Wenn man sich das mal schematisch vorstellt, dann steht in herkömmlichen Systemen der Anwendungscode in der Mitte und wird von den diversen Frameworks umrahmt. Bei IoC dreht sich das um und das (IoC-) Framework steht in der Mitte und die eigentliche Anwendung liegt in Form von Modulen vor, die in das Framework eingebunden werden.

So zumindest mein Verständnis.

S
8.746 Beiträge seit 2005
vor 18 Jahren

Nochmal zum Einsatz-Zweck: Ich würde IoC nicht generell verwenden. Ich denke, der Vorteil liegt in der extrem losen Kopplung der Module. Der Nachteil aber in der höheren Komplexität, die dem Gesamtsystem innewohnt (gilt eigentlich für alle Patterns, die den Code erstmal (!) "komplizierter" machen).

Aber wie immer bei Frameworks reduziert sich die Komplexität mit der Erfahrung, da die Benutzung des Frameworks immer die gleiche ist.

L
113 Beiträge seit 2004
vor 18 Jahren

ich hab keine ahnung ob das schon erwähnt wurde, aber im aktuellen dotnet-magazin ist auch ein kurzer artikel über aspektorientierte entwicklung drin.
also wer interesse hat kann ja mla reingucken.

2.891 Beiträge seit 2004
vor 17 Jahren

Um zum Thema mal etwas "Werbung" zu machen: [Artikel] Aspektorientierte Programmierung mit Rapier-Loom.NET

Gruß
dN!3L

M
110 Beiträge seit 2007
vor 16 Jahren

Hallo,

AOP ist eine feine Sache. Ich befasse mich gerade mit PostSharp.

Gruss

Mirko

Mappen statt hacken mit Invist , dem .NET O/R Mapper - Code Generator