A few years ago, when I discovered AOP, Didier Danse told me about an AOP framework he was liking for .NET : PostSharp by Gaël Fraiteur. So I started to try it, and simply felt in love with this tool.
I do not want here to explain how to use it (I will try to post some examples about that in the future) but for now, I just want to tell you my story about PostSharp, and why I really started to use it.
The context
A few years ago, I was writing data oriented tests : typically, I was inserted some data, checking the behavior of my web app and then cleaning my data. And so my tests started to look like this :
[TestMethod]
public void Mytest()
{
try
{
InsertSomeData();
InsertSomeOtherData();
DoMyTest();
}
finally
{
CleanMyOtherData();
CleanMyData();
}
}
It was working, but was a bit too verbose and my test code was "lost among noise".
Kind of AOP using the .NET framework
I was not knowing AOP at that time but I was sure I was able to do something different. I read the book of Jason Bock called "Applied .NET Attributes" and I discovered the ContextBoundObject and I turn my code to this :
[TestMethod]
[InsertSomeData]
[InsertSomeOtherData]
public void Mytest()
{
DoMyTest();
}
Much better and elegant. My attributes were doing the stuff of inserting and deleting and there were no more noise in my test.
But dealing with messages and sinks is not so simple and has a lot of limitation. Above all, all this stuff is done at runtime and impose you to inherit from ContextBoundObject. Possible for my tests, but no further application for my production code.
The revelation
It's at this moment that one of my colleague has done a thesis about AOP and that I met Didier Danse. He told me about PostSharp and I started to test it. And quickly I had migrated all my attributes into PostSharp. And of course I had in the meanwhile extended their capabilities for keeping my test very declarative:
[TestMethod]
[InsertSomeData]
[InsertSomeOtherData]
[ExecuteThisTestSeveralTimeAs("user1", "user2", "user3")]
[IgnoreThisTestIfDbVersionIsInferiorTo(35)]
public void Mytest()
{
DoMyTest();
}
I was no longer injecting (asking PostSharp to inject) code into my test, but also modifying its metadata attributes ! I was indeed adding some IgnoreAttribute to my code at postcompilation if my test was not relevant to my current test context. This was alllowing me not only to reduce the number of test I had to write, but also to keep a very simple test result file without any inconclusive test.
My present
And I started to see so many possible applications in my code - without any performance penalty as every aspet I was thinking to would be woven at compilation time. (Well indeed there is a small performance penalty as PostSharp inject some additional method call but this is practically negligeable in practice. Note moreover that PostSharp 2.0 will just remove this extra overhead !)
My next step was when I wanted to do some performance investigation in my code. Usually, I add some Stopwatches in my code to capture the execution time and log that to a file. But in my case, I wanted to instrument many many methods that were calling each other. Ok... Let's do an assembly attribute and work with "OnMethodInvocationAspect" and using some filtering on my class names and method names !
In a few lines of code, I had instrumented thousands of methods (but only the one I wanted to). Pretty awsome.
What about now ?
Postsharp is now a key feature of my designs. How could I make a clean INotifyPropertyChanged without it ?
I would not say PostSharp is transparent to use. There is of course a learning cost and a vocabulary, specially if you do not know AOP by itself. But this learning cost is quite small compared to the productivity you can obtain in your development.
In my view, it's the best way to create some cross-cutting functionality in a very elegant and efficient way ! And when you want to enforce some design rules in your code, working declaratively is a dream ! Specially when you can work at interface level !